我目前正在为ARM Cortext M4 MCU上的项目开发一些软件,其中需要执行三个总体主要任务:
1) Init_all.c - Must run first and ONLY once at startup
2) Task1.c - Runs infrequently; Once every 10 seconds
3) Task2.c - Must run most frequently
我决定尝试使用FreeRTOS,以查看通过简单的无限While(1)
循环使用FreeRTOS调度是否有好处
根据我到目前为止从文档中所读的内容(如果我输入错了,请纠正我)
1)FreeRTOS根据优先级运行任务-如果没有将中断或停止条件编码为优先级最高的任务,任何优先级较低的任务将从不排队并运行
2)如果在无限for(;;)
循环中未放置任何内容,则该任务将仅运行一次(循环外的代码说一次初始化外围设备)
由于FreeRTOS按优先级选择任务并对其进行排队,所以我在分配和创建任务时想到的最初解决方案是:
1) Init_all.c - Highest priority; for(;;) loop only contains code to trigger LED
2) Task1.c - Second highest priority **but** I include a 10 second interrupt vTaskDelay( xDelay10000ms ) right at the start of the for(;;) loop
3) Task2.c - Lowest priority
对此进行测试,如果遵循FreeRTOS逻辑,我应该期望永远不会看到Task1.c或Task2.c排队,因为Init_all.c任务永远不会结束,因为它具有触发LED的代码在for(;;)
循环中。
哪个使我想到了我的问题:实施上述方法时,发现了两个令人费解的发现:
观察1:
1)运行Init_all.c任务
2)跟在Task1.c之后,然后它被中断并立即停止10秒钟。
3)在此期间,Task2.c一直运行到10秒钟为止。然后Task1.c接管vTaskDelay( xDelay6000ms )
中断后运行代码。
所有这一切,Init_all.c仍在运行,但idk处于队列的什么位置。 LED确实确实会每秒触发一次,但又一次完全混淆了为什么什至Init_all.c任务还在运行。
Task1.c的代码如下,以提供更好的说明:
// Task1.c
void Task1(void const * argument)
{
// Timer interrupt
const TickType_t xDelay10000ms = pdMS_TO_TICKS( 10000 );
for( ;; )
{
/** Immediately block this task for 10secs upon starting it **/
vTaskDelay( xDelay10000ms );
( code below to execute AFTER the Task1 resumes from the interrupt )
}
观察2:
Task2需要1秒钟才能运行,因此理论上应该在10秒窗口(由中断指定)中运行10次。
但是,我看到一个奇怪的结果,Task2有时运行9次,然后运行10次。
我误解了FreeRTOS概念吗?谢谢!代码如下:
Init_all.c任务:
void StartDefaultTask(void const * argument)
{
init_sensor1();
init_sensor2();
init_sensor3();
init_sensor4();
for( ; ; )
{
GREEN_LED_ON();
osDelay(50);
GREEN_LED_OFF();
osDelay(1000);
}
}
任务1:
void Task1(void const * argument)
{
// Timer interrupt
const TickType_t xDelay6000ms = pdMS_TO_TICKS( 6000 );
// All Initialisation
for( ;; )
{
// Timer interrupt this task to ensure apptasks.c finishes first?
vTaskDelay( xDelay6000ms );
takesensor1data();
takesensor2data();
}
}
任务2:
void Task2(void const * argument)
{
// Timer interrupt
const TickType_t xDelay6000ms = pdMS_TO_TICKS( 6000 );
// All Initialisation
for( ;; )
{
takesensor3data();
takesensor4data();
}
}
答案 0 :(得分:0)
Init_all.c-必须首先运行,并且只能在启动时运行一次
在此页面上搜索“守护程序任务启动挂钩”:https://www.freertos.org/a00016.html
2)如果在无限for(;;)循环中没有放置任何内容,则该任务将仅运行一次(循环外的代码说一次初始化外围设备)
如果执行此操作,则必须在执行结束时删除该任务(调用vTaskDelete(NULL))。 https://www.freertos.org/implementing-a-FreeRTOS-task.html
关于您的主要问题-您没有显示init任务的代码,因此无法说明。但是,通常这种系统是由事件驱动的,因此大多数任务大部分时间都处于阻塞状态(不使用任何CPU,因此可以执行优先级较低的任务)。
答案 1 :(得分:0)
我怕你的观察是错误的
如果较低优先级的任务没有交出控制权,或者中断例程没有唤醒较高优先级的任务,则该任务可能会较新地获得控制权。
这里的队列中没有类似位置的东西。它不是Linux或Windows。