Hi,
I have a code for USB mass storage device on atmel AT91SAM7SE512 target. The code is based on Keil\ARM\Boards\Atmel\AT91SAM7X-EK\RL\USB\RTX_Memory .
When connecting my device to a PC and saving a file - I see that at some point, messages are sent to endpoint task from ISR (isr_mbx_send...) but not received by the endpoint task (os_mbx_wait...). Some save sessions are passed successfully, but most sessions behave as described above...
Any idea what may be the problem...?
Thanks
Since isr_mbx_send does not return any value, you might not know, if the message has been send.
http://www.keil.com/support/man/docs/rlarm/rlarm_isr_mbx_send.htm
If the mailbox is full, the kernel ignores the message since it cannot be put into the mailbox. Thus before sending a message using isr_mbx_send, you must use the os_mbx_check function to check if the mailbox is full. [There is failure in the manual, it should be isr_mbx_check.]
Do you check the mailbox with isr_mbx_check?
Currently I check the mailbox with os_mbx_check (as done in the mentioned reference code) and according to the return value - mailbox is available... When should I use os_mbx_check and when isr_mbx_check..?
In an ISR, you should use isr_mbx_send() and obviously then also isr_mbx_check().
I'm using now isr_mbx_check but there is no change in the behavior.
Can you post the code of the ISR and the receiving function?
The ISR code:
/* Endpoint Interrupts */ for (n = 0; n < USB_EP_NUM; n++) { if (isr & (1 << n)) { csr = pUDP->UDP_CSR[n]; /* Setup Packet Received Interrupt */ if (csr & AT91C_UDP_RXSETUP) { pEpEvent = _alloc_box (USB_MsgPool); /* allocate memory */ if (pEpEvent){ pEpEvent->bCnt = USB_ReadEP(n, pEpEvent->bData); /* read the setup packet */ pEpEvent->wEvent = USB_EVT_SETUP; /* set event */ if (isr_mbx_check (USB_EPMbx[n]) == 0) _free_box (USB_MsgPool, pEpEvent); else isr_mbx_send (USB_EPMbx[n], pEpEvent); } Udp_ep_clr_flag(pUDP,n,AT91C_UDP_RXSETUP); } /* Data Packet Received Interrupt */ bkm = RX_DATA_BK[RxDataBank[n]]; if (csr & bkm) { pEpEvent = _alloc_box (USB_MsgPool); /* allocate memory */ if (pEpEvent){ pEpEvent->bCnt = USB_ReadEP(n, pEpEvent->bData); /* read the data packet */ pEpEvent->wEvent = USB_EVT_OUT; /* set event */ // Save isr_mbx_check result for debug mbxCheck = isr_mbx_check (USB_EPMbx[n]); if (mbxCheck == 0){ _free_box (USB_MsgPool, pEpEvent); mbxErr++; // Debug } else { isr_mbx_send (USB_EPMbx[n], pEpEvent); // Debug- count the bulk out (EP 2) data messages if ((pEpEvent->bCnt == 64) && (n==2)) EP_2_Count_Sent++; } } Udp_ep_clr_flag(pUDP,n ,bkm); if (DualBankEP & (1 << n)) { RxDataBank[n] ^= 1; } } /* Data Packet Sent Interrupt */ if (csr & AT91C_UDP_TXCOMP) { Udp_ep_clr_flag(pUDP,n ,AT91C_UDP_TXCOMP); if (TxDataBank[n]) { //pUDP->UDP_CSR[n] |= AT91C_UDP_TXPKTRDY; Udp_ep_set_flag(pUDP,n,AT91C_UDP_TXPKTRDY); TxDataBank[n] = 0; } pEpEvent = _alloc_box (USB_MsgPool); if (pEpEvent){ pEpEvent->wEvent = USB_EVT_IN; if (isr_mbx_check (USB_EPMbx[n]) == 0) _free_box (USB_MsgPool, pEpEvent); else isr_mbx_send (USB_EPMbx[n], pEpEvent); } } /* STALL Packet Sent Interrupt */ if (csr & AT91C_UDP_STALLSENT) { if ((csr & AT91C_UDP_EPTYPE) == AT91C_UDP_EPTYPE_CTRL) { pEpEvent = _alloc_box (USB_MsgPool); if (pEpEvent){ pEpEvent->wEvent = USB_EVT_IN_STALL; if (isr_mbx_check (USB_EPMbx[n]) == 0) _free_box (USB_MsgPool, pEpEvent); else isr_mbx_send (USB_EPMbx[n], pEpEvent); } } Udp_ep_clr_flag(pUDP,n ,AT91C_UDP_STALLSENT); } } }
The receiver task code:
void USB_EndPoint2 (void) __task { T_USB_EP_EVENT *pEpEvent; USB_EPMbx[2] = USB_EP2Mbx; /* store Mbx in array */ os_mbx_init (USB_EP2Mbx, sizeof(USB_EP2Mbx)); /* initialize the mailbox */ for (;;) { os_mbx_wait (USB_EP2Mbx, (void **)&pEpEvent, 0xFFFF); /* Wait for an Event */ memcpy (BulkBuf, pEpEvent->bData, pEpEvent->bCnt); /* store received data from mailbox */ BulkLen = pEpEvent->bCnt; // Debug - update counters if ((BulkBuf[15] == 0x2A) && (BulkLen == 31)) { printf("\n --> BulkOut zero counter %d (writeCount = %d) ", bufOutCount, writeCount); bufOutCount = 0; writeCount = 0; } else if (BulkLen == 64) bufOutCount++; MSC_BulkOut(); _free_box (USB_MsgPool, pEpEvent); /* free memory allocated for message */ } }
In the error case - I eventually receive Bus reset from host and then I print the session counters: CBW.dDataLength = 29184, - Length of data that was sent (/64 = 456) EP_2_Count_Sent = 420, - Number of bulks sent by ISR bufOutCount = 388, - Number of bulks received by receiver task writeCount = 388, - Number of bulks handled by SW mbxErr = 0 , - No mailbox request errors mbxCheck = 28 - Number of available mailbox entries
(Each Bulk is 64 bytes)
May it be possible, that
pEpEvent = _alloc_box (USB_MsgPool);
fails and therefore the message is not even created. There is no error checking for this case, as far as I see.
The next line checks that aloccation was successfull ( if (pEpEvent){...). If allocation failes - the mailbox send code is not activated... See that my counter is promoted only after successfull allocations and when mailbox is available