CC3000一直进入中断
这种情况偶尔会发生。
运行了一段时间时候,具体多长时间确定,感觉也没规律。
中断出现的频率是54us左右(示波器观察)。
进入中断之后
sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ; /* IRQ line goes down - we are start reception */ ASSERT_CS(); // Wait for TX/RX Compete which will come as DMA interrupt SpiReadHeader(); sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; SSIContReadOperation();
在SpiReadHeader();中会收到10个字节02 00 ff 00 00 00 00 00 00 00而且每次都是这十个。
在SSIContReadOperation中
if (!SpiReadDataCont()) { // All the data was read - finalize handling by switching to the task // and calling from task Event Handler SpiTriggerRxProcessing(); }
会进入SpiTriggerRxProcessing。
最终进入
void SpiReceiveHandler(void *pvBuffer) { tSLInformation.usEventOrDataReceived = 1; tSLInformation.pucReceivedData = (unsigned char *)pvBuffer; if(tSLInformation.usRxEventOpcode == HCI_EVNT_RECVFROM) { if(!hci_unsolicited_event_handler()) { rt_sem_release(g_event_semaphore); } } else hci_unsolicited_event_handler(); }
上面这段被我改了下用在rtthread里。
watch看到tSLInformation.usRxEventOpcode 的值是 0x1003,查看了定义这个应该是HCI_EVNT_SEND。
之后进入hci_unsolicited_event_handler()中
hci_unsolicited_event_handler(void) { unsigned long res = 0; unsigned char *pucReceivedData; if (tSLInformation.usEventOrDataReceived != 0) { pucReceivedData = (tSLInformation.pucReceivedData); if (*pucReceivedData == HCI_TYPE_EVNT) { // In case unsolicited event received - here the handling finished if (hci_unsol_event_handler((char *)pucReceivedData) == 1) { // There was an unsolicited event received - we can release the buffer // and clean the event received tSLInformation.usEventOrDataReceived = 0; res = 1; SpiResumeSpi(); } } } return res; }
*pucReceivedData的值是0直接退出。
之后就是一直进行这个循环。
由于程序不是很好调试,tSLInformation.usRxEventOpcode 的值是 0x1003。还没找到在哪个send的地方出现的这种情况,待下次补充。
望根据上述信息能否判断我这个是什么问题。谢谢。
没有人配到过类似的情况吗。
除了上面的情况
在hci_event_handler中
while (1) { if (tSLInformation.usEventOrDataReceived != 0) { pucReceivedData = (tSLInformation.pucReceivedData); if (*pucReceivedData == HCI_TYPE_EVNT) { //未执行 } else { pucReceivedParams = pucReceivedData; STREAM_TO_UINT8((char *)pucReceivedData, HCI_PACKET_ARGSIZE_OFFSET, ucArgsize); STREAM_TO_UINT16((char *)pucReceivedData, HCI_PACKET_LENGTH_OFFSET, usLength); // Data received: note that the only case where from and from length // are not null is in recv from, so fill the args accordingly if (from) { STREAM_TO_UINT32((char *)(pucReceivedData + HCI_DATA_HEADER_SIZE), BSD_RECV_FROM_FROMLEN_OFFSET, *(unsigned long *)fromlen); memcpy(from, (pucReceivedData + HCI_DATA_HEADER_SIZE + BSD_RECV_FROM_FROM_OFFSET) ,*fromlen); } memcpy(pRetParams, pucReceivedParams + HCI_DATA_HEADER_SIZE + ucArgsize, usLength - ucArgsize); tSLInformation.usRxDataPending = 0; } tSLInformation.usEventOrDataReceived = 0; SpiResumeSpi(); // Since we are going to TX - we need to handle this event after the // ResumeSPi since we need interrupts if ((*pucReceivedData == HCI_TYPE_EVNT) && (usReceivedEventOpcode == HCI_EVNT_PATCHES_REQ)) { hci_unsol_handle_patch_request((char *)pucReceivedData); } if ((tSLInformation.usRxEventOpcode == 0) && (tSLInformation.usRxDataPending == 0)) { return NULL; } } }
一直进入if (tSLInformation.usEventOrDataReceived != 0)里面
然后*pucReceivedData != HCI_TYPE_EVNT进入else中。
0x1003 是HCI_EVENT_SEND,出现这种情况的时候,wifi connect还在吗?
wifi还是连接着的。
使用的情况是这样的。我在CC3000上建立一个tcp服务端。客户端连接到服务端,有些信息需要去通知所有的客户端。
我发现出现这种情况都是在这种位置。
for(k=1; k<(最大连接数); k++) //这里最大连接数取了8 { if(第k个socket是活跃的) //也就是有客户端连接。 send//发送数据 } 具体代码: for(k=1; k<8; k++) //report { if(g_sockets[k].status != SOC_NOT_INITED && k != udp_socket && k!= cloud_sd) { send(g_sockets[k].sd, s, xlen, 0); } }
k=0时是服务端的socket
我程序里有四个地方是有这种代码的。往不同的socket发送数据,没有延时。
有一个地方是往一个socket连续发送数据,也是没有延时,好像没有在那个地方出现过。
当然这种情况不是经常有,大部分时间是没问题的。但是如果出现一次,程序就没法继续跑了。
send判断一下返回值,看是不是有error,
send(g_sockets[k].sd, s, xlen, 0);
照你的方法在send之后判断了返回值。
不过出现这种情况之后就卡死在hci_event_handler(void *pRetParams, unsigned char *from, unsigned char *fromlen)中的while(1)里了。只能看到出错之前的send的返回值了。
出错之前send的返回值和你发送的buf长度是一致的吗?
卡死是因为send的command一致没有等到对应的event,但是你的代码又一直从spi接收到数据,把数据二进制dump出来看看。
是spi接收到的数据吗。
spi的接收到的数据是02 00 ff 00 00 00 00 00 00 00。一直无限接收到这十个数据。
你的应用层协议是怎么定义的?什么时候会接收数据?或者说什么时候client会发数据给server?02是data,也就是说你调用hci_send发送数据,正常应该是等待send的event回来,结果接收到的是数据,而SimpleLinkWaitEvent根本不会处理这种数据。
void SimpleLinkWaitEvent(unsigned short usOpcode, void *pRetParams) { // In the blocking implementation the control to caller will be returned only // after the end of current transaction tSLInformation.usRxEventOpcode = usOpcode; hci_event_handler(pRetParams, 0, 0); }
你的程序在send之前调用recv检查一下,看结果会怎么样
data不是是调用recv时才会收到吗。
程序里做了互斥的操作,就是从Multithreaded WiFi Application改过来的。在send没有返回时是不会调用recv的。
int send(long sd, const void *buf, long len, long flags) { int ret; rt_mutex_take(g_main_mutex, RT_WAITING_FOREVER); ret = c_send(sd, buf, len, flags); rt_mutex_release(g_main_mutex); return(ret); }
程序里有的是select去判断数据收到了没。只有select之后才会去recv。
程序里有四个地方是发给了所有的客户端。有两个就是和select在一个线程里,这个时候更不会出现互斥的情况了。可就是在这两个地方还是会有这种情况。
我的意思是说每次在调用send之前,都用select或者read检查一下。因为什么时候收到数据可能不是你协议能控制的。socket的recv buffer是一个,如果你调用send的时候,socket已经有数据到了,你没收,send 的event只能排在数据后面,在当前的逻辑,只能在while里死循环了。
cc3000的驱动程序里有个hci_unsolicited_event_handler函数,这个函数应该是处理主动上报的事件event。
hci_unsol_event_handler中列出的HCI_EVNT_UNSOL_BASE,HCI_EVNT_WLAN_UNSOL_BASE,HCI_EVNT_WLAN_ASYNC_PING_REPORT等,应该都不包含recv的event。
我理解是:
除了hci_unsol_event_handler里的事件event,其他的event应该都不会主动上报的。
比如HCI_EVNT_ACCEPT,HCI_EVNT_SELECT这些应该是调用了accept,select之后才会响应。
recv应该也是这样。
我的程序还在send中而且加了lock。当然包括recv,accept等等都是加了锁的。
在send函数运行时应该只会收到,HCI_EVNT_SEND,或者HCI_EVNT_SENDTO,也有可能是hci_unsol_event_handler里列出的事件(因为这些是主动事件可能出现在任何时刻)。应该是不会出现recv的事件吧。
程序虽然是一直进入中断的
在hci_unsolicited_event_handler中时
if (tSLInformation.usEventOrDataReceived != 0) { pucReceivedData = (tSLInformation.pucReceivedData); if (*pucReceivedData == HCI_TYPE_EVNT) { // In case unsolicited event received - here the handling finished if (hci_unsol_event_handler((char *)pucReceivedData) == 1) { // There was an unsolicited event received - we can release the buffer // and clean the event received tSLInformation.usEventOrDataReceived = 0; res = 1; SpiResumeSpi(); } } }
//-------------------------------
watch里看到
*pucReceivedData 的值是0
不符合if的条件。也就说明这不是一个unsolicited, event。
还有谢谢你提供的解决方法。但是有个问题。程序里有地方做recv的工作。
没必要在send之前都加一个recv,这是不是会减慢程序的运行速度.
另外有没有可能这个状况是刚好在
recv
send
这个顺序中我刚执行完recv就出现了呢。
那如果这样的话,这种解决方式也没有用,我现在考虑的是这到底是什么原因。
真的是只有我一个人碰到这种情况吗?
自己来顶下
你在程序里面是不是一直在调用select
是用的select读,不过都是在操作cc3000时都是上锁的,应该不会有冲突吧。
没有太明白你的问题,能否详细描述一下。
详细问题就是前面提到的有时会一直不停(远远小于0.5秒)在中断里,死在中断里之后的描述也在前面帖子里。
接收线程大概如下
timeout是0.5秒
ret = select(maxFD, &readsds, NULL, NULL, &timeout); // Polling instead of blocking here to process "accept" below
if(ret > 0)
{
for (index = 0; index < MAX_NUM_OF_SOCKETS; index++)
{
if (g_sockets[index].status != SOC_NOT_INITED && FD_ISSET(g_sockets[index].sd, &readsds))
{
rx_bytes = recv(g_sockets[index].sd, rx_buf, 1024, 0);
数据处理
}
}
}
所有的socket操作(recv , send等等)都有如下加锁过程。
int
select(long nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, struct timeval *timeout)
{
int ret;
rt_mutex_take(g_main_mutex, RT_WAITING_FOREVER);
ret = c_select(nfds, readsds, writesds, exceptsds, timeout);
rt_mutex_release(g_main_mutex);
return(ret);
}
主动上报的事件在另外一个线程
for(socket 在客户端socket列表中)
{
发送数据
send(g_sockets[k].sd, pdata, len);
}
网络操作大概如上。
你如果把锁拿掉会有这个问题吗?
CC3000SDK\CC3000 SDK\LM4F120H5QR\Multithreaded WiFi Application\Multithreaded WiFi Source\Source\Multithreaded WiFi Application
就是从这个工程移植 ,锁是为了解决多线程共享的问题,这和锁没关系吧。
我是想看一下原始的SDK在你的板子上有没有问题。
原始的SDK不知道是指哪个?我现在用的的是JORJIN的模块,他们给的demo是个单线程的例子,就从官网下了一个多线程例子改的。不过这个问题偶尔出现所以不好测试,暂时用复位的方式解决,就是想知道什么时候才会不停的中断,或者是我操作不当引起的。
我是指你的MCU是用的什么,如果是用的TI MCU的话可以直接用SDK里面的例程测试一下。
对于你的问题,你在MCU端收到中断之后能否先disable irq,处理irq, 然后在enable irq.