Other Parts Discussed in Thread: CC3200, CC3100
It seems that if I do not have a line of debug in my code, I can become stuck in hci_event_handler. I believe I have found the culprit to be a race condition in which tSLInformation.usRxEventOpcode is set too late - after the IRQ arrives. Unfortunately the SPI data receive handler performs a key check on this variable, (evnt_handler.c:639) which will scrap the received data if it hasn't been set. This happens if the interrupt happens before we get into the SimpleLinkWaitEvent call, (evnt_handler.c:816)
/* The following shows a race condition due to setting tSLInformation.usRxEventOpcode
too late. (Only code of note shown.)
CC3000 Host Driver: 1.11.1 */
/* Call to wlan_start */
wlan.c:256 wlan_start()
/* Stuff ... */
wlan.c:306 hci_command_send(HCI_CMND_READ_BUFFER_SIZE,
tSLInformation.pucTxCommandBuffer, 0);
wlan.c:307 SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0);
/* If an interrupt should happen before this point,
it will result in the host driver getting stuck
in a loop */
evnt_handler.c:816 tSLInformation.usRxEventOpcode = usOpcode;
/* The following is called after IRQ pin drops, SPI data read in */
wlan.c:219 void SpiReceiveHandler(void *pvBuffer)
wlan.c:224 hci_unsolicited_event_handler();
evnt_handler.c:673 if (hci_unsol_event_handler((char *)pucReceivedData) == 1)
evnt_handler.c:639 if ((event_type != tSLInformation.usRxEventOpcode)
&& (event_type != HCI_EVNT_PATCHES_REQ))
{
return(1);
}
/* Now considering what happens if this returns 1... */
evnt_handler.c:673 if (hci_unsol_event_handler((char *)pucReceivedData) == 1)
{
/* This ultimately causes this command to be
lost... */
tSLInformation.usEventOrDataReceived = 0;
res = 1;
SpiResumeSpi();
}
/* Once the IRQ finishes we continue processing */
evnt_handler.c:816 hci_event_handler(pRetParams, 0, 0);
/* Since we set this to zero, we loop on this
forever... */
while (1)
{
evnt_handler.c:241 if (tSLInformation.usEventOrDataReceived != 0)
Thoughts and suggested fixes?
From searching this forum I think there is a good chance the following posts are describing this problem.
http://e2e.ti.com/support/low_power_rf/f/851/t/305178.aspx
http://e2e.ti.com/support/low_power_rf/f/851/t/295158.aspx
http://e2e.ti.com/support/low_power_rf/f/851/t/292783.aspx
http://e2e.ti.com/support/low_power_rf/f/851/t/303733.aspx
EDIT for some clarification: My host is running a RTOS (ChibiOS) so rather than handling the interrupt in an ISR it is passed onto a thread. This problem can manifest itself in in the following way:
| CC3000 Control Thread | IRQ Processing Thread |
| Send SPI Command | |
| Receive Reply | |
| Unexpected opcode - delete data | |
| Set expected reply opcode |
My solution to this problem was to insert a wait in the IRQ processing thread, before the call to the registered processing callback is triggered. This wait will permit the control thread to execute a bit further, hopefully setting usRxEventOpcode:
