FreeRTOS内核源码解读之-------系统启动(一)

  • RTOS多任务运行
  • Cortex-M4对于多任务运行的硬件架构支持特性
    最近研究FreeRTOS的内核源码,产生了一个疑问?
//创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄  

//创建TASK1任务
    xTaskCreate((TaskFunction_t )malloc_task,             
                (const char*    )"malloc_task",           
                (uint16_t       )MALLOC_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )MALLOC_TASK_PRIO,        
                (TaskHandle_t*  )&MallocTask_Handler);   
    vTaskDelete(StartTask_Handler); //删除开始任务

只要通过FreeRTOS提供的任务创建函数API就能够运行我们应用层写的代码。换句话说,FreeRTOS是怎么找到我们写的代码,然后进行运行的呢?首先看一下任务创建函数声明:

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:我们应用程序编写的任务函数指针;
pcName:任务的名字,应用层自己设定;
usStackDepth:每一个任务堆栈的深度,我们这里是32位MCU,那么堆栈深度为usStackDepth*4字节;
pvParameters:执行的任务函数时传递的参数;
uxPriority:任务的优先级;
pxCreatedTask:任务句柄,实际就是指向任务控制块指针。
在这里我要用两篇博客进行探究上述问题。其中,第一篇会从MCU硬件架构方面是怎么能够支持上述功能的(这里分析的是STM32F407 MCU,该MCU是基于Cortex-M4架构);第二篇会实际分析FreeRTOS具体实现方法。

一、RTOS多任务运行

在这里插入图片描述实时操作系统RTOS可用于处理任务调度,它是将处理时间分为多个时间片且将时间片分配给所需的任务,实现多个任务同时执行。需要一个定时器记录RTOS中每个人物的运行时间,当时间到之后就会触发任务调度器执行上下文切换,转而执行其他任务。

二、Cortex-M4对于多任务运行的硬件架构支持特性

1、寄存器组

在这里插入图片描述Cortex-M4处理器的寄存器组中含有16个寄存器,其中13个是32位通用目的寄存器,3个特殊寄存器。
1)R0~R12
前8个被称作低寄存器,由于指令中可用的空间有限,许多16位指令只能访问低寄存器。后面4个寄存器被称为高寄存器,可以用于32位指令和几个16位指令。
2)R13,栈指针(SP)
可以通过PUSH和POP操作实现栈存储的访问,其实在物理上会有两个栈指针。MSP被称为主栈指针,复位后或者处于处理模式时会使用该针;PSP进程栈指针,只能用于线程模式。在进行PUSH和POP时候总是32位,栈操作的地址必须对齐到32位的字边界上。一般如果我们的应用程序中没有涉及到嵌入式OS是不会用到PSP寄存器的,但是如果用到嵌入式OS就必须设置PSP。
3)R14,连接寄存器(LR)
函数或者子程序调用时返回地址的保存,在函数或者子程序结束时,程序控制可以通过将LR的数值加载到PC寄存器中实现返回调用的程序。***当执行函数或者子程序调用后,LR寄存器的数值会自动更新。***因此在调用函数之前要先把LR的数值保存到栈中。
在异常处理期间,LR会被自动更新为特殊的EXC_RETURN(异常返回)的数值,之后该数值在异常处理结束之后出发异常返回。
4)程序计数器PC
可读可写,写会导致跳转。

2、EXC_RETURN

在这里插入图片描述
在这里插入图片描述
处理器进入异常处理或者中断服务程序时,连接寄存器LR的数值会被更新为EXC_RETURN。利用BX指令加载到PC寄存器时,该数值就会触发异常返回机制。由于地址区域0xF0000000~0xFFFFFFFF被架构定义为不可执行,这样不会带来问题。

3、影子栈指针

在这里插入图片描述由于在物理上采用两个栈指针寄存器,因此可以将处理器处于不同模式下使用不同的栈指针,这样我们在内核和异常处理状态下使用MSP,在普通任务下使用PSP,使得应用层与内核层完全分离。当我们应用层的代码出现BUG可以减少对内核层代码的影响,保证了软件的健壮性。
5)SVC异常
由SVC指令触发,异常类型为11,并且优先级是可编程的。利用SVC可以实现应用任务访问系统资源的API,如下图所示:
在这里插入图片描述
在FreeRTOS中使用SVC异常从出初始化切换到调度第一个任务。

总结:本文主要介绍了Cortex-m4对于RTOS支持的硬件特性,下一篇文章将会介绍FreeRTOS是怎样利用这些特性开启第一个任务的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章