cancel
Showing results for 
Search instead for 
Did you mean: 

usb host channel interrupt register is always zero after a transaction

ko
Associate
Posted on March 05, 2016 at 21:14

I use stm32f105's usb otg interface in forced host mode. When I issued a bulk in transaction, after some nak returned (which is ok), keep retrying, then data came, this first transaction completed successfully. Then I halted the channel, enabled it again for another transaction, and the channel interrupt register value was always zero, no data, no nak, no ack, no error, and program stuck there.

This code is part of the program:

void OTG_FS_IRQHandler() 
// Only rfxlvl interrupt unmasked
{
usb_gregs->GINTMSK = 0; 
//mask rfxlvl
USB_OTG_GRXFSTS grxsts;
grxsts.d32 = usb_gregs->GRXSTSP;
if
(grxsts.b.pktsts == 2)
{
u8 numword = (grxsts.b.bcnt + 3) / 4;
u32* fifo = usb_fifo0 + grxsts.b.chnum * USB_OTG_DATA_FIFO_SIZE;
if
(!usb_state || (usb_state && usb_channel != grxsts.b.chnum))
{
for
(u8 i = 0; i < numword; i++)
*fifo;
}
else
{
for
(u8 i = 0; i < numword; i++)
*rxbuff++ = *fifo;
rxnumbyte = grxsts.b.bcnt;
usb_state = 0;
}
}
usb_gregs->GINTMSK = 1 << 4; 
//unmask rfxlvl
}
u16 bulkin(u32* buff, u16 len)
{
u16 ret = 0;
USB_OTG_HCINTn hcint;
USB_OTG_HCTSIZn hctsiz;
u16 numpacket = len / MPS;
usb_gregs->GINTSTS = 0xffffffff;
usb_hc3regs->HCINT = 0xffffffff;
hctsiz.d32 = usb_hc3regs->HCTSIZ;
hctsiz.b.pktcnt = numpacket;
hctsiz.b.xfersize = numpacket * MPS;
//
usb_hc3regs->HCTSIZ = hctsiz.d32;
rxbuff = buff;
usb_channel = 3;
while
(!(usb_hc3regs->HCINT & 1)) //check for XFRC

{
usb_state = 1;
usb_hc3regs->HCINT = 0xffffffff;
usb_hc3regs->HCCHAR = MPS | (1 << 31) | (device_address << 22) | (1 << 11) | (2 << 18) | (1<<15); 
//max packet size 64 byte, chenable, endpoint 2
while
(!(hcint.d32 = usb_hc3regs->HCINT)); 
//issue in token, any flag? <<<ALWAYS ZERO, PROGRAM STUCK
if
(hcint.b.nak)
{
cn++;
continue
;
}
else
if
(hcint.b.ack)
{
while
(usb_state);
ret += rxnumbyte;
rxbuff = (u8*)buff + ret;
}
else
while
(1);
}
if
(!(usb_hc3regs->HCINT & (1 << 1)))
usb_hc3regs->HCCHAR = MPS | (1 << 31) | (1 << 30) | (device_address << 22) | (1 << 11) | (2 << 18) | (1<<15); 
// halt channel
while
(!(usb_hc3regs->HCINT & (1 << 1)));
return
ret;
}

The program stuck at

while
(!(hcint.d32 = usb_hc3regs->HCINT));

beacause HCINT always zero. Why is this happening ? I'm willing to provide any additional information. EDIT: I solved it after some weeks pulling my hair out. The problem come from this code:


 

hctsiz.d32 = usb_hc3regs->HCTSIZ;
hctsiz.b.pktcnt = numpacket;
hctsiz.b.xfersize = numpacket * MPS;
//
usb_hc3regs->HCTSIZ = hctsiz.d32;

The idea for this code is when a bulk transfer is divided to many packets, the core will automatically alternate the data pid for us while transfering. This code keep the last data pid, just change packet count and transfer size. So before the first transfer this register content is 0x0. After the first transfer complete, for some reason the core changes the 31 bit to 1, and the second transfer will fail because this bit is not at its reset value. Fix this and it works like a charm. Hope this help somebody out there.
0 REPLIES 0