1. 启动方法1
第一种我称之为万事俱备,只欠东风法。这种方法是在main函数中将硬件初始化,RTOS系统初始化,所有任务的创建这些都弄好,这个我称之为万事都已经准备好。最后只欠一道东风,即启动RTOS的调度器,开始多任务的调度。
//伪代码
int main(void)
{
HardWare_Init(); //硬件初始化
RTOS_Init(); //RTOS系统初始化
RTOS_TaskCreate(Task1); //创建任务1,但任务1不会执行,因为调度器还没有开启
RTOS_TaskCreate(Task2); //创建任务2,但任务1不会执行,因为调度器还没有开启
//继续创建各种任务
RTOS_Start(); //启动RTOS,开始调度
}
void Task1(void *arg)
{
while(1);
{
//任务实体,必须有阻塞的情况出现
}
}
void Task2(void *arg)
{
while(1);
{
//任务实体,必须有阻塞的情况出现
}
}
2. 启动方法2
第二种我称之为小心翼翼,十分谨慎法。这种方法是在main函数中将硬件和RTOS系统先初始化好,然后创建一个启动任务后就启动调度器,然后在启动任务里面创建各种应用任务,当所有任务都创建成功后,启动任务把自己删除。
//伪代码
int main(void)
{
HardWare_Init(); //硬件初始化
RTOS_Init(); //RTOS系统初始化
RTOS_TaskCreate(AppTaskCreate); //创建一个任务
RTOS_Start(); //启动RTOS,开始调度
}
void AppTaskCreate(void *arg)
{
RTOS_TaskCreate(Task1); //创建任务1,但任务1不会执行,因为调度器还没有开启
RTOS_TaskCreate(Task2); //创建任务2,但任务1不会执行,因为调度器还没有开启
//继续创建各种任务
RTOS_TaskDelete(AppTaskCreate); //当任务创建完成,删除起始任务
}
void Task1(void *arg)
{
while(1)
{
//任务实体,必须有阻塞的情况出现
}
}
void Task2(void *arg)
{
while(1)
{
//任务实体,必须有阻塞的情况出现
}
}
3. FreeRTOS的启动流程
在系统上电的时候第一个执行的是启动文件里面由汇编编写的复位函数Reset_Handler,复位函数的最后会调用C库函数__main,__main函数的主要工作是初始化系统的堆和栈,最后调用C中的main函数,从而去到C的世界。
4. 内存初始化
这种简单的特点使得FreeRTOS在初学的时候变得很简单,我们自己在main()函数中直接初始化我们的板级外设——BSP_Init(),然后进行任务的创建即可——xTaskCreate(),在任务创建中,FreeRTOS会帮我们进行一系列的系统初始化,在创建任务的时候,会帮我们初始化堆内存,
xTaskCreate() -> pvPortMalloc() -> prvHeapInit()
5. vTaskStartScheduler()
在创建完任务的时候,我们需要开启调度器,因为创建仅仅是把任务添加到系统中,还没真正调度,并且空闲任务也没实现,因为它在开启调度函数vTaskStartScheduler()中实现的。
创建完成后,调用xPortStartScheduler() 函数配置相关硬件如滴答定时器、pendsv等,然后调用prvStartFirstTask()启动第一个任务。