FreeRTOS(八)----调度器的开启与任务切换

目录

调度器的开启

任务切换


 

  • 调度器的开启

01-vTaskStartScheduler()

调度器负责给各个任务分配CPU资源,使得多任务并发执行,FreeRTOS提供的vTaskStartScheduler()用于开启调度器,一旦开启,整个系统就交给调度器负责。

                         

开启调度器的主要工作是进行任务创建、中断设置以及运行第一个任务,接下来的工作将由各个中断触发运行,比如SysTick中断里面进行调度器程序的运行,PenSVC中断里面进行上下文切换等等。

 

02- xTaskCreate() 

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,      
             const char * const pcName,      
             const uint16_t usStackDepth,     
             void * const pvParameters,      
             UBaseType_t uxPriority,        
              TaskHandle_t * const pxCreatedTask )
  •  pxTaskCode : 实现任务的主要功能的函数,其返回值是void 类型,参数是void * 类型
  • const pcName:任务名,其长度由宏 configMAX_TASK_NAME_LEN 决定,一般16
  • StackDepth : 堆栈的大小设置。实际大小是该值4倍,因为它是4字节大小。
  • pvParameters :需要传递给任务的参数,
  • uxPriority : 任务优先级,范围:0-configMAX_PRIORITIES
  • pxCreatedTask :创建成功后的任务句柄保存在这个参数里面,供其他API 使用。比如任务删除
  • 创建成功后,返回值为: pdPASS.   其他则为失败,可能的原因堆内存分配失败。
  • 由于任务需要ram 来进行堆栈的分配和存储,这部分自动从FreeRTOS 的堆中分配。由于这个函数需要系统来帮助任务做这些处理所以需要freertos 提供内存管理和分配,因此对于freeRTOS 来说需要提供一个内存管理文件,如heap_x.c ,同时宏configSUPPORT_DYNAMIC_ALLOCATION 需要定义为1.

Tist:

01.每次创建任务,pxCurrentTCB都会更新

02.开启调度器的主要工作是创建空闲任务、设置中断和开始第一个任务

 

  • 任务切换

在FreeRTOS具备了任务的内存资源——堆栈管理机制,能根据任务状态和优先级进行CPU执行的上下文切换,并提供了任务间通信渠道以实现必要的任务同步和互斥之后,多个任务可以协同起来工作了。在一个硬件中断(IRQ)产生以后,立即唤醒某个任务来处理这个事件是操作系统必须要支持的。从任务的角度来看,其实有很多任务是需要根据硬件上的事件(比如传输完成,设备就绪,接收到数据等)来被调度的,否则它将不停测试硬件设备状态寄存器标志位,浪费CPU时间。

 

任务切换的场合:

FreeRTOS任务的切换最终都是在PendSV中断服务函数(汇编代码实现的)中完成的,发生任务切换的场合有两种情况:

1) 执行一个系统调用

2) 系统滴答定时器(sysTick)中断

所谓的执行系统调用就是执行了taskYIELD()函数或者调用了taskYIELD的其他API函数;

taskYIELD()函数定义在task.h中:

#define taskYIELD()          portYIELD()

函数portELD定义在portmacro.h中:

#define portYIELD()

{
         portNVIC_INT_CTRL_REG=portNVIC_PENDSVSET_BIT;//步骤1
         __dsb(portSY_FULL_READ_WRITE);
         __isb(portSY_FULL_READ_WRITE);

}

步骤1表示通过向中断控制和状态寄存器ICSR的bit28写入1挂起PendSV来启动PendSV中断。这样就可以在PendSV中断服务函数中进行任务切换了。

中断级的任务切换函数为portYIELD_FROM_ISR()也是通过调用portYIELD来完成任务切换的。

 

第二个能产生任务切换的就是滴答定时器(SysTick)中断服务函数:

void SysTick_Handler(void)

{
         if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
         {
             xPortSysTickHandler();
         }
}

xPortSysTickHandler()的主要功能是向中断控制和状态寄存器ICSR的bit28写入1挂起PendSV来启动PendSV中断。这样就可以在PendSV中断服务函数中进行任务切换了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值