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