项目场景:
` 最近在准备找工作,没有实际的项目和经验,就买了几个模块结合FreeRTOS来拼凑拼凑整成一个项目——基于ESP8266的远程温度监控,使用MQTT协议和搭载FreeRTOS系统。
省流:vTaskDelay 的使用需要放在任务中,否则运行不了!
问题描述:
使用ESP8266时候,按照oneNET的例程移植到STM32上,能够很好的运行,但是把代码复制到FreeRTOS时候却一直初始化不了,等于说是卡在初始化了。下图为初始化函数摆放位置。
原因分析:
在使用串口函数一步一步的在每一个函数内外部设置打印信息后,初步发现问题是出在vTaskDelay 函数上,如下图所示
就是进入了延时函数vTaskDelay 之后就没出来。 分析: 进入延时函数查看问题(函数是官方的,不可能有问题,所以问题大概出在哪里任务没弄好或者其他冲突),发现延时函数有vTaskSuspendAll 函数和xTaskResumeAll 函数的,初步感觉到了问题应该是出在任务的调度上,所以就把ESP8266_Init 函数放在开启任务调度函数vTaskStartScheduler 后边,结果还是没有用,查资料后才知道任务调度函数后不执行后边的语句。 再接着看延时函数里面的后续函数时候发现prvAddCurrentTaskToDelayedList ,看着名字想起来了问题所在了:由于ESP8266_Init 函数在主函数内,而且里面还有延时函数,所以此时没有任务创建和运行,无法进行延时函数里面的任务阻塞。延时函数vTaskDelay 里的prvAddCurrentTaskToDelayedList 是将当前任务加入到延时列表中。所以任务都没有,何来的延时。更具体的后续函数和原理我也疏于学习就没有了解,就不分析了,直到这一步已经能够解决问题了。
延时函数部分内容:
void vTaskDelay( const TickType_t xTicksToDelay )
{
BaseType_t xAlreadyYielded = pdFALSE;
if( xTicksToDelay > ( TickType_t ) 0U )
{
configASSERT( uxSchedulerSuspended == 0 );
vTaskSuspendAll();
{
traceTASK_DELAY();
prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
}
xAlreadyYielded = xTaskResumeAll();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
总结:
由于目前主要任务是找工作而完成项目,对于更深层次的学习就只能在后边学了。目前对于FreeRTOS的掌握程度只是要求会移植会使用,满足项目的需求而已。 最后的解决方式:将ESP8266的初始化有关函数放在一个任务里,完成后删除该任务或者放在创建任务的函数中,例如:
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t )task1_task,
(const char* )"task1_task",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_TASK_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
xTaskCreate((TaskFunction_t )task2_task,
(const char* )"task2_task",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
ESP8266_Init();
while(OneNet_DevLink())
vTaskDelay(500);
OneNet_Subscribe(topics, 1);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
最后运行成功:
|