请问一下FreeRTOS每个任务在创建时都会分配一个任务栈,那么为什么不直接使用裸机的栈区呢?
裸机,任务切换的时候,栈空间可能被覆盖
任务一:实现红色LED灯每一秒闪烁,并且串口5输出当前时间,输出格式(任务1:2019-10-07 10:10:14);任务二:实现绿色LED灭4秒亮1秒,并且每5秒使用串口5输出当前时间,输出格式(任务2:2019-10-07 10:10:14)
任务函数
char *timeFORMAT="ccyy-MM-dd hh:mm:ss";
char para[40];
void gettime(LPSYSTEMTIME lpsystime)
{
getSystemTimeInt(lpsystime);
DatetimeToStr(lpsystime,(int8_t*)timeFORMAT,(int8_t *)para);
Uart_SendData(E_UART5,(uint8_t *)para,strlen(para));
}//从系统中获取时间
void taskfunction1(void *pvParameters)
{
SYSTEMTIME stime1;
uint8_t thread1[5]={'t','a','s','k','1'};
uint8_t enter1[2]={'\r','\n'};
for( ;; )
{
GPIO_SetBits(GPIOE,GPIO_Pin_7);
GPIO_SetBits(GPIOD,GPIO_Pin_13);
vTaskDelay(1000);
GPIO_ResetBits(GPIOE,GPIO_Pin_7);
GPIO_ResetBits(GPIOD,GPIO_Pin_13);
vTaskDelay(1000);
Uart_SendData(E_UART5,thread1,5);
gettime(&stime1);
Uart_SendData(E_UART5,enter1,2);
}
}//任务1实现
void taskfunction2(void *pvParameters)
{
SYSTEMTIME stime2;
uint8_t thread2[5]={'t','a','s','k','2'};
uint8_t enter2[2]={'\r','\n'};
for( ;; )
{
GPIO_SetBits(GPIOE,GPIO_Pin_8);
GPIO_SetBits(GPIOD,GPIO_Pin_14);
vTaskDelay(1000);
GPIO_ResetBits(GPIOE,GPIO_Pin_8);
GPIO_ResetBits(GPIOD,GPIO_Pin_14);
vTaskDelay(5000);
Uart_SendData(E_UART5,thread2,5);
gettime(&stime2);
Uart_SendData(E_UART5,enter2,2);
}
}//任务2实现
主函数
int main (void)
{
struct rtc_time RTCtime={0,0,0,1,1,2019,1};//初始化RTC,注意这里不能定义指针,要定义数组
struct rtc_time NEWtime={0,13,15,17,10,2019,3};
RTC_CheckAndConfig(&RTCtime);
WriteTime(&NEWtime);//写入系统时间
Led_Init();
Sys_Init();
Door_Init();
Uart_Init(E_UART5,9600,UART_Parity_No);
xTaskCreate((TaskFunction_t )taskfunction1, //任务函数
(const char * )"task1", //任务名称
(uint16_t )128, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )1, //任务优先级
(TaskHandle_t* )NULL); //任务句柄
xTaskCreate((TaskFunction_t )taskfunction2,
(const char * )"task2",
(uint16_t )128,
(void* )NULL,
(UBaseType_t )1,
(TaskHandle_t* )NULL);
vTaskStartScheduler(); //开启任务调度
}
结果
回答:
FreeRTOS不能直接使用裸机的栈区是因为FreeRTOS采用了任务切换的机制,需要为每个任务分配独立的栈空间。这样可以保证每个任务运行时,都有自己独立的空间,避免了任务间数据的干扰,同时也保证了任务切换的正确性与可靠性。
如果想要查找就绪任务中优先级最高的,可以使用前导零指令__CLZ来更快速地计算。但是,在最大任务优先级configMAX_PRIORITIES超过32或者没有前导零指令__CLZ的内核时,需要在FreeRTOSConfig.h中添加宏定义#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0,并使用一种更通用的方法去查找就绪任务中优先级最高的。
对于事件标志组的操作,可以使用函数xEventGroupWaitBits等待事件标志被设置,第一个参数是事件标志组句柄,第二个参数表示等待24个事件标志位中的指定标志。如果第三个参数设置为pdTRUE,且在参数xTicksToWait设置的溢出时间内返回,那么相应被设置的事件标志位会被清零。如果第四个参数设置为pdTRUE,需要等待第二个参数uxBitsToWaitFor所指定的标志位全部被置1,函数才可以返回。对于事件标志组的位清除,可以使用函数xEventGroupClearBits,在任务中或者中断中都可以清除。