This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

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.