微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI WIFI设计交流 > CC3000一直进入中断

CC3000一直进入中断

时间:10-02 整理:3721RD 点击:

这种情况偶尔会发生。

运行了一段时间时候,具体多长时间确定,感觉也没规律。

中断出现的频率是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.

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top