1、今天在调试串口任务时,碰到了一个问题:
调用vTaskSuspend挂起任务后,通过vTaskResume恢复任务,恢复的任务无法响应
2、具体如下:
1> 串口接收读取中断函数:
串口接收中断函数:通过设置(give)一个信号量标记,告诉串口接收主任务函数,可以进行接收串口数据了
串口接收主任务函数:等待信号量,接收数据,将数据送入队列
3、所做的测试如下:
在其他任务重,通过指令调试代码:
Print("test uart :\r\n");
Dis_TaskCmsdkISR_uart(); //挂起TaskCmsdkISR_uart任务
for(i=0;i<=9;i++)
{
//rxByte=uart0_read(DP_WaitForever);
rxByte=uart0_read_POLL(5000); //在这里接收和使用串口数据
Print("%02x ",rxByte);
}
EN_TaskCmsdkISR_uart(); //恢复TaskCmsdkISR_uart任务
DP_TaskSleep(1);
taskYIELD();
Print("rev uart 10bytes ok\r\n");
在运行EN_TaskCmsdkISR_uart()之后,发送其他调试指令,不能响应,如下:
按道理已经恢复任务了,应该可以响应正常的指令才对。
观察led任务,发现灯还可以闪烁,说明RTOS任务能正常切换,操作系统未被挂死。
4、分析:
1>查看挂起的任务Task_cmsdkISR_uart代码
代码长期都会处于等待信号量状态,所以在挂起任务时,肯定是出于等待信号量函数的那行;所以恢复任务时,会恢复到等待信号量的那行
2>挂起和恢复任务间的操作
我们可以看到,挂起任务后,我们会操作信号量去读取数据,这里会不会和挂起任务所使用的信号量冲突呢?那肯定会是冲突的,在不同任务调用同一资源,需要保护。
所以在任务恢复后,那个信号量的状态可能已经发生了变化,可能会导致Task_cmsdkISR_uart任务移植在那里等待,所以解决办法是:
a>给信号量加保护?
b>将信号量重新复位一下:
这里是这样做:
恢复任务后,重新give信号量,让他可以跳出当前foever等待的那个状态。
然后就可以正常接收数据了。
-----主要还是,这里中断使用问题:
这个提供的库,中断函数采用回调方式,当调用uart_read时,才会调用中断回调函数。
这里非阻塞方式读数据,当没数据时,会等待回调的那个中断函数响应,如果一直没,会一直等那里,跳不过那个forever;
而只有调用uart_read函数,才会有中断回调函数响应,在挂起/恢复后,那个中断give的信号量被使用后,形成了个死循环。