FreeRTOS每个任务在创建时都会分配一个任务栈问题

请问一下FreeRTOS每个任务在创建时都会分配一个任务栈,那么为什么不直接使用裸机的栈区呢?

裸机,任务切换的时候,栈空间可能被覆盖

  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7617140
  • 这篇博客也不错, 你可以看下1、FreeRTOS及源码下载/介绍
  • 除此之外, 这篇博客: FreeRTOS系统创建多任务中的 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入门教程内部机制讲解课程中的 4. 创建任务的函数简析小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    回答:

    FreeRTOS不能直接使用裸机的栈区是因为FreeRTOS采用了任务切换的机制,需要为每个任务分配独立的栈空间。这样可以保证每个任务运行时,都有自己独立的空间,避免了任务间数据的干扰,同时也保证了任务切换的正确性与可靠性。

    如果想要查找就绪任务中优先级最高的,可以使用前导零指令__CLZ来更快速地计算。但是,在最大任务优先级configMAX_PRIORITIES超过32或者没有前导零指令__CLZ的内核时,需要在FreeRTOSConfig.h中添加宏定义#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0,并使用一种更通用的方法去查找就绪任务中优先级最高的。

    对于事件标志组的操作,可以使用函数xEventGroupWaitBits等待事件标志被设置,第一个参数是事件标志组句柄,第二个参数表示等待24个事件标志位中的指定标志。如果第三个参数设置为pdTRUE,且在参数xTicksToWait设置的溢出时间内返回,那么相应被设置的事件标志位会被清零。如果第四个参数设置为pdTRUE,需要等待第二个参数uxBitsToWaitFor所指定的标志位全部被置1,函数才可以返回。对于事件标志组的位清除,可以使用函数xEventGroupClearBits,在任务中或者中断中都可以清除。