FreeRTOS的学习

发布时间:2023年12月26日

1.创建函数和删除

  1. 动态创建为FreeRTOS分配的堆栈(方便),而静态创建为人为分配空间。
  2. 任务中必须有while(1)否则只会执行一次
  3. 任务中的延时要用??? ? ? ?vTaskDelay(500); 延时期间执行其它任务
    1. 任务中的延时使用的是软件延时,即还是让CPU等待来达到延时的效果。使用RTOS的优势就是能充分发挥CPU的性能,永远不让它闲着。任务如果需要延时,也就不能再让CPU空等来实现延时的效果。RTOS中的延时叫作阻塞延时,即任务需要延时时,会放弃CPU的使用权,CPU可以去做其他的事情,当任务延时时间到,重新获取CPU使用权,任务继续运行,这样就充分地利用了CPU的资源,而不是空等
      当任务需要延时而进入阻塞状态时,那CPU在做什么?如果没有其他任务可以运行,RTOS都会为CPU创建一个空闲任务,这个时候CPU就运行空闲任务。在FreeRTOS中,空闲任务是系统在启动调度器时创建的优先级最低的任务,空闲任务主体主要是做一些系统内存的清理工作。

  4. 任务创建后马上就执行,一个MCU能够支持多少任务,取决于RAM空间的大小。
  5. 进入临界区,不使用任务调度,退出临界区,开始任务调度
  6. 关于堆栈大小可以使用这个函数:
    xGetFreeStackSpace任务栈历史剩余最小值
动态创建任务
#define Led2_PRIO        1		       /* 任务优先级 */		
#define Led2_STACK_SIZE   128          /* 任务堆栈大小*/		
TaskHandle_t    Led2_task_handler;      /* 任务句柄 */		
void Led2Task(void *argument);          /* 任务函数声明 */	

    xTaskCreate((TaskFunction_t         )   Led2Task,				  /* 任务函数 */
                (char *                 )   "Led2",		              /* 任务名字 */
                (configSTACK_DEPTH_TYPE )   Led2_STACK_SIZE,	       /* 堆栈大小 */
                (void *                 )   NULL,	   				   /* 入口参数 */
                (UBaseType_t            )   Led2_PRIO,	               /* 任务优先级 */
                (TaskHandle_t *         )   &Led2_task_handler );      /* 任务句柄 */
任务函数
void Led2Task(void *argument)
{
  /* USER CODE BEGIN LedTask */
  /* Infinite loop */
  for(;;)
  {
    LED2_ON;
	vTaskDelay(500);
	LED2_OFF;
	vTaskDelay(500);
  }
  /* USER CODE END LedTask */
}
?
创建和删除任务

? ? ? ?vTaskDelete(task1_handler); ? ? ? ? //填写任务句柄

// 删除任务
    if(task1_handler!= NULL)
    {
        printf("删除start_task任务\r\n");
        vTaskDelete(task1_handler);         //填写任务句柄
        task1_handler = ZERO;
    }

//创建任务
	if(Led2_task_handler == NULL)
    {
	   xTaskCreate(Led2Task,"Led2",Led2_STACK_SIZE,             
       ZERO,Led2_PRIO,&Led2_task_handler );     
    }

vTaskDelete(null);		            Delete your own tasks		
保护任务:
// 保护任务
    taskENTER_CRITICAL();               /* 进入临界区 */
    /* 被保护的代码 */
    taskEXIT_CRITICAL();                /* 退出临界区 */ 
静态创建:

? ? ? ? 静态创建时,任务句柄作为返回值。

#define Led3_PRIO        osPriorityLow             /* 任务优先级 */		
#define Led3_STACK_SIZE   128					   /* 任务堆栈大小*/		
TaskHandle_t    Led3_task_handler;				    /* 任务句柄 */	
StackType_t     Led3_task_stack[Led3_STACK_SIZE];	/* 任务堆栈*/	
StaticTask_t    Led3_task_tcb;						/* 任务控制块*/	
void Led3Task(void *argument);					   /* 任务函数声明 */		


Led3_task_handler = xTaskCreateStatic( (TaskFunction_t )   Led3Task,		  /* 任务函数 */
                                       (char *         )   "Led3",    		  /* 任务名字 */
                                       (uint32_t       )   Led3_STACK_SIZE,	  /* 堆栈大小 */
                                       (void *         )   NULL,			  /* 入口参数 */
                                       (UBaseType_t    )   Led3_PRIO,	    /* 任务优先级* /
                                       (StackType_t *  )   Led3_task_stack,	  /* 任务堆栈 */
                                       (StaticTask_t * )   &Led3_task_tcb );  /* 任务名字 */

2.任务挂起和恢复

  1. 任务优先级越大,优先程度越高,中断优先级数值越小,优先级越高。中断中优先级恢复任务中 , 中断优先级在5—15级

????????vTaskSuspend(TaskHandle_t xTaskToSuspend)? ? //任务挂起? ——任务句柄

? ? ? ? ?vTaskResume(TaskHandle_t xTaskToResume)??? //任务恢复? ——任务句柄

????????xTaskResumeFromISR(TaskHandle_t xTaskToResume)?? //中断中任务恢复? ——任务句柄

挂起任务与恢复任务:
vTaskSuspend(LedHandle);  

vTaskResume(LedHandle);  

3.中断:

? ? STM32 总共有16个优先级(0—15)? ? ?

  1. 中断优先级在5—15级的中断中才能调用FreeRTOS中的函数,小于5的中断无法使用。且要使用尾部为FromISR的函数。
  2. 对 5—15 等级中断的管理
  3. vTaskDelay(500); 会打开中断
	portENABLE_INTERRUPTS();        //开启中断
    portDISABLE_INTERRUPTS();       //关闭中断

5.临界段代码保护:

什么是临界段:
????????临界段,用一句话概括就是一段在执行时不能被中断的代码段。在FreeRTOS中,临界段最常出现的地方就是对全局变量的操作。全局变量就像是一个靶子,谁都可以对其开枪,但是有一人开枪,其他人就不能开枪,否则就不知道是谁命中了靶子。
那么什么情况下临界段会被打断?一个是系统调度,还有一个就是外部中断。在FreeRTOS中,系统调度最终也是产生PendSV中断,在PendSV Handler中实现任务的切换,所以还是可以归结为中断。既然这样,FreeRTOS对临界段的保护最终还是回到对中断的开和关的控制。

作用:? 防止中断和任务调度的打断。

应用方面:

  1. 通信时候,IIC SPI
  2. 系统自身需求
  3. 用户需求

特点:

  1. 成对使用
  2. 主要通过关闭和开启中断实现,和开启和关闭任务调度器
  3. 被保护的代码一定要短
  4. 关闭中断,即所有中断都不能执行;而关闭任务调度器,可以任务无法抢占,而可以中断可以打断。
//开启和关闭任务调度器
vTaskSuspendAll() ;
{
        … …	/* 内容 */
}
xTaskResumeAll()	;



// 代码中使用,关闭所有中断
taskENTER_CRITICAL() ;
{
        … …	/* 临界区 */
}
taskEXIT_CRITICAL()	;


// 中断中使用,关闭所有中断
uint32_t  save_status;
save_status  = taskENTER_CRITICAL_FROM_ISR();
{
        … …	/* 临界区 */
}
taskEXIT_CRITICAL_FROM_ISR(save_status );

6.列表和列表项

文章来源:https://blog.csdn.net/JasonKyro/article/details/135209428
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。