RTOS系统的启动
在系统上电时,第一个执行的启动文件是汇编语言编写的复位函数Reset_Handler,复位函数最后会调用C库函数_ _main,__main的主要工作是初始化系统的堆和栈,最后调用C中的main()函数,从而进入C的世界。
1 系统初始化
系统初始化是根据我们配置宏定义进行的,有一些则是系统必要的初始化,如空闲任务、时钟节拍任务等。
注意:在系统初始化中,空闲任务的初始化和时钟节拍任务的初始化是必须存在的任务,否则系统无法正常运行。
1.1 空闲任务初始化
空闲任务是一个无限的死循环,其优先级是最低的,所以任何优先级比它高的任务都能抢占它,从而取得CPU的使用权。
?? 为什么系统要有空闲任务呢?
因为CPU是不会停下来的,此时系统就必须保证有一个随时处于就绪态的任务,而且这个任务不会抢占其他任务的资源。当且仅当系统的其他任务处于阻塞态时,系统才会运行空闲任务。
1.1.1 空闲任务的作用
空闲任务可以做很多事情,如任务统计;钩入用户自定义的钩子函数,实现用户自定义的功能等。
注意:在钩子函数中,用户不容许调入任何可以使空闲任务阻塞的接口函数,空闲任务是不容许被阻塞的。
1.2 时钟节拍任务
2 CPU初始化
在main()函数中,除了需要对扳级硬件进行初始化,还需要进行一些系统相关的初始化,如CPU初始化。
?? 为什么进行CPU初始化?
在uC/OS中,有一个很好的功能就是时间戳,它的精度高达纳秒级别,是CPU内核的一个资源,所以使用时要对CPU进行相关的初始化。
2.1 时间戳
在uC/OS-III中,很多代码中都加入了时间测量的功能,比如任务关中断的时间,关调度器的时间等。
2.1.1 时间戳的实现
选择:通常执行一条代码是需要多个时钟周期的,为纳秒级别。要想准确的测量代码的运行时间,时间戳的精度很重要。通常单片机中的硬件定时器的精度都是微秒级别,远达不到测量几条代码运行时间所需要的精度。
在ARM Cortex-M系列内核中,有一个DWT的外设,该外设有一个32位的寄存器,叫做CYCCNT,它是一个向上的计数器,记录的是内核时钟HCLK的运行个数。当CYCCNT溢出之后,会清零重新开始向上计数。
该计数器在uC/OS-III中恰好被用来实现时间戳的功能。
在STM32F103系列的单片机中,HCLK时钟频率最高为72MHz,单个时钟的周期为1/72us = 0.0139us = 14ns,CYCCNT总共能记录的时间为2 32 *14 = 60s。
2.1.1.1 CPU初始化函数
/* CPU初始化函数 */ void CPU_Init(void) { /* CPU初始化函数中总共做了3件事 * 1)初始化时间戳 * 2)初始化中断禁用时间测量 * 3)初始化CPU名字 */ #if ((CPU_CFG_TS_EN == DEF_ENABLED) || \ (CPU_CFG_TS_TMR_EN == DEF_ENABLED)) CPU_TS_Init(); #endif }
2.1.1.2 时间戳初始化函数
/* CPU_TS_Init() 时间戳初始化函数 */ #if ((CPU_CFG_TS_EN == DEF_ENABLED) || \ (CPU_CFG_TS_TMR_EN == DEF_ENABLED)) static void CPU_TS_Init(void) { #if ((CPU_CFG_TS_TMR_EN == DEF_ENABLED)) CPU_TS_TmrFreq_Hz = 0u; // 表示CPU的系统时钟,具体大小与硬件有关 CPU_TS_Tmrinit(); #endif } #endif
2.1.1.3 时间戳定时器初始化函数
/* 时间戳定时器初始化函数 */ #if ((CPU_CFG_TS_TMR_EN == DEF_ENABLED)) void CPU_TS_TmrInit(void) { CPU_INT32U fclk_freq; fclk_freq = BSP_CPU_ClkFreq(); //获取CPU的HCLK时钟,与硬件有关 /* 启用 DWT 外设,由另外的内核调试寄存器DEMCR的位24控制,写1启动 */ BSP_REG_DEM_CR |= (CPU_INT32U)BSP_BIT_DEM_CR_TRCENA; /* DWT CYCCNT 寄存器启用之前先清零 */ BSP_REG_DWT_CYCCNT = (CPU_INT32U)0u; /* 启用 ortex-M3 DWT CYCCNT寄存器 * DWT_CTRL的位0控制,写1启动 * 将CPU的HCLK时钟赋值给全局变量CPU_TS_TmrFreq_Hz */ BSP_REG_DWT_CR |= (CPU_INT32U)BSP_BIT_DWT_CR_CYCCNTENA; CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq; }
3 SysTick初始化
时钟节拍需要依赖于硬件定时器,在STM32的SysTick时钟内嵌在NVIC中,是MCU的内核定时器,是一个24位的递减的计数器,计数器每计数一次的时间为 1/SYSCLK 。当重装载数值寄存器(LOAD)的值递减到0时,系统定时器就产生一次中断,按此循环。通常都使用该定时器产生操作系统的时钟节拍。
时钟节拍:是系统以固定的频率产生中断,并在中断中处理与时间相关的事件,推动所有任务向前运行。
时钟节拍的频率:表示操作系统每秒产生多少个tick。
tick:即操作系统节拍的时钟周期。
/* OS_CPU_SysTickInit() 初始化SysTick */ /* 1)配置重装载计数器(LOAD)的值 * 2)配置SysTick的优先级,这里配置为15,即最低 * 3)复位当前计数器(VAL)的值 * 4)配置控制及状态寄存器(CTRL)选择时钟源,启用中断,启用计数器开始计数 */
1 int main(void) 2 { 3 OS_ERR err; 4 5 /* 关闭中断 */ 6 CPU_IntDis(); (1) 7 8 /* 配置 SysTick 10ms 中断一次 */ 9 OS_CPU_SysTickInit (10); (2) 10 11 /* 初始化相关的全局变量 */ 12 OSInit(&err); 13 14 /* 创建任务 */ 15 OSTaskCreate ((OS_TCB*) &Task1TCB, 16 (OS_TASK_PTR ) Task1, 17 (void *) 0, 18 (CPU_STK*) &Task1Stk[0], 19 (CPU_STK_SIZE) TASK1_STK_SIZE, 20 (OS_ERR *) &err); 21 22 OSTaskCreate ((OS_TCB*) &Task2TCB, 23 (OS_TASK_PTR ) Task2, 24 (void *) 0, 25 (CPU_STK*) &Task2Stk[0], 26 (CPU_STK_SIZE) TASK2_STK_SIZE, 27 (OS_ERR *) &err); 28 29 /* 将任务加入到就绪列表 */ 30 OSRdyList[0].HeadPtr = &Task1TCB; 31 OSRdyList[1].HeadPtr = &Task2TCB; 32 33 /* 启动 OS,将不再返回 */ 34 OSStart(&err); 35 } 36 37 38 39 /* 任务 1 */ 40 void Task1( void *p_arg ) 41 { 42 for ( ;; ) { 43 flag1 = 1; 44 delay( 100 ); 45 flag1 = 0; 46 delay( 100 ); 47 48 /* 任务切换,这里是手动切换 */ 49 //OSSched(); (3) 50 } 51 } 52 53 /* 任务 2 */ 54 void Task2( void *p_arg ) 55 { 56 for ( ;; ) { 57 flag2 = 1; 58 delay( 100 ); (5) 59 flag2 = 0; 60 delay( 100 ); 61 62 /* 任务切换,这里是手动切换 */ 63 //OSSched(); (4) 64 } 65 }
中断服务函数SysTick_Handler()调用任务调度函数,进行任务切换,实现每个任务都运行相同的时间片,平等的享有CPU。但时间是按时间流的顺序显示的,两个任务轮流占用CPU。
由此可见,任务中的延时使用的是软件延时,即还是让CPU空等来达到延时的效果。使用RTOS的优势就是充分发挥CPU的性能,永远不让它闲着。任务如果需要延时,也就不能再让CPU空等来实现延时的效果。
RTOS中的延时叫阻塞延时,即当任务需要延时时,会放弃CPU的使用权,CPU可以去做其他的事情,当任务延时时间到,将重新获得CPU的使用权继续运行,这样就可以充分利用CPU,而不是空等。
4 内存初始化
系统是软件,必须为其分配一块内存,所以在系统创建任务之前,必须将系统必要的内容进行初始化。uC/OS采用一块连续的大数组作为系统管理的内存,在使用前需要先将管理的内存进行初始化。
/* 初始化内存管理模块 */ Mem_Init();
5 OSStart()
在创建完任务的时候,我们需要开启调度器,因为创建仅仅是把任务添加到系统中, 还没真正调度,我们使用 OSStart()函数就能让系统开始运行。
OSStart()是uCOS 为我们提供一个系统启动的函数接口。
来源:https://www.cnblogs.com/RSheng16/p/12603456.html