UCOS-III 基础知识积累

初识 µC/OS-III

µC/OS-III 是基于 C 语言编写的第三代 小型操作系统。

µC/OS/III 是一个操作系统,准确地说应该是一个实时操 作系统,也就是 RTOS(Real Time Operating System),与之类似的 RTOS 还有 FreeRTOS、RTX、 RT-Thread 等。

操作系统最直观的特点就体现在,操作系统能够使得一个 CPU 核心“同时运行”多个任 务,这个特性就被称为“多任务”。然而,实际上,一个 CPU 核心在某一时刻只能运行一个任 务,而操作系统中任务调度器的责任就是决定在某一时刻 CPU 究竟要运行哪一个任务,任务调 度器使得 CPU 在各个任务之间来回切换并处理任务,由于切换处理任务的速度非常快,因此给 人造成了一种同一时刻有多个任务同时运行的错觉。

操作系统的分类方式可以由任务调度器的工作方式决定,比如有的操作系统给每个任务分 配同样的运行时间,时间到了就切换到下一个任务,Unix 操作系统就是这样的。RTOS 的任务 调度器被设计为可预测的,而这正是嵌入式实时操作系统所需要的。在实时环境中,要求操作 系统必须实时地对某一个事件做出响应,因此任务调度器的行为必须是可预测的。像 µC/OS-III 这种传统的 RTOS 类操作系统是由用户给每个任务分配一个任务优先级,任务调度器就可以根 据此优先级来决定下一刻应该运行哪个任务。

µC/OS-III 支持多种不同架构的不同型 号的处理器,例如 STM32 系列的 F1、F4、F7 和 H7 等型号的 MCU 都受 µC/OS-III 的支持,读 者只需要进行简单的移植操作,就能够在这些 MCU 上运行 µC/OS-III 操作系统。

µC/OS-III 的特点

µC/OS-III 是一个可裁剪、可固化到 ROM 的抢占式实时内核,并且可管理任务的数量不受 限制。µC/OS-III 是第三代的 µC/OS 内核,具有以下几个重要的特性:

1、抢占式多任务管理:µC/OS-III 是一个支持多任务抢占的内核,因此总是优先执行任务优先 级高的任务。

2、时间片调度:µC/OS-III 允许系统中有多个相同任务优先级的任务,如果系统中处于就绪状 态的任务中,优先级最高的任务有多个,那么 µC/OS-III 将以时间片的方式调度任务,即根据用 户指定的时间(时间片)轮流调度这些任务。

3、极短的中断禁用时间:µC/OS-III 通过锁定任务调度器代替禁用中断来保护一些关键区域 (临界区),这确保了 µC/OS-III 能够快速地响应中断。

4、任务数量不限:µC/OS-III 理论上支持不受限制的任务数量,但实际上,系统中任务的最大 数量受处理器内存空间的限制。

5、任务优先级数量不限:µC/OS-III 支持的任务优先级数量不受限制,但对于大多数应用场景 而言,使用 32~256 个任务优先级就绰绰有余了。

6、内核对象数量不限:µC/OS-III 提供了多种内核对象,如任务、信号量、事件标志、消息队 列、软件定时器和内存区等,并且在不考虑处理器内存限制的情况下,用户可以无限制的创建 这些内核对象。

7、时间戳:µC/OS-III 提供了时间戳功能,用户可以非常方便地测量系统在运行过程中,处理 器处理某些事件所消耗的时间,以方便用户对系统进行针对性的优化。

8、自定义钩子函数:µC/OS-III 提供了一些在内核执行操作之前、之后或过程中的钩子函数, 这样可以方便用户扩展 µC/OS-III 的功能。

9、防死锁:µC/OS-III 允许任务在等待某些内核对象前,设置一个等待的最大超时时间,这样 可以有效地防止死锁的发生。 软件定时器:在 µC/OS-III 中,用户可以创建任意数量的“单次”和“周期”软件定时器, 并且每个软件定时器都可以有独立的超时回调函数。

任务内嵌信号量:µC/OS-III 提供了任务的内嵌信号量功能,这使得任务可以直接获取来自 其他任务或中断的信号,而不需要任何的中间内核对象,大大地提高了系统的运行效率。

任务内嵌消息队列:µC/OS-III 提供了任务的内嵌消息队列,这使得任务可以直接接收来自 其他任务或中断的消息,而不需要任何的中间内核对象,大大地提高了系统的运行效率。

源码初探

µC/OS-III 文件预览

Cfg 文件夹中包含的是 µC/OS-III 配置文件的模板文件。

Ports 文件夹包含的是与硬件相关的移植文件,µC/OS-III 提供了 针对不同的芯片架构的移植文件。

Source 文件夹中包含了 与 µC/OS-III 内核、任务、软件定时器和事件标志相关的源码文件。也是 µC/OS-III 的核心文件。

Tamplate 文件夹中仅包含了一个文件,这个文件是与动态 Tick 管理相关的文件。

TLS 是 Thread Local Storage(线程本地存储)

Trace 文件夹中是用来存放一些调试工具的,调试工具主要有 SEGGER SystemView for uC/OS-III 和 Percepio Tracealyzer for uC/OS-III,

µC/CPU 文件预览

ARM-Cortex-M 文件夹:包含了与 ARM Cortex-M 内核的 CPU 相关的移植文件。

BSP(Board Support Package,板级支持包)相关的文件,主要包含了 用于配置和使用为 µC/OS-III 中时间戳功能提供支持的硬件定时器。

Cfg 文件夹:包含了 µC/CPU 这一组件的配置文件。

µC/LIB 文件预览

Cfg 文件夹 :包含了 µC/LIB 这一组件的配置文件

Ports 文件夹:包含了 µC/LIB 与硬件相关的移植文件。,µC/LIB 组件仅支持了 ARM 和 AVR 部分架构的处理器,因此 µC/LIB 组件是移植 µC/OS-III 时非必须的,µC/LIB 主要是提供了 ASCII 字符操作、数学、内存管理、字符串操作的库,方便开发。

配置项

µC/OS-III 配置项

µC/OS-III 作为一个完善的操作系统,提供了丰富的功能,但在通常实际的应用场景中,需 要考虑到各方面的因素,例如芯片上 Flash 和 RAM 的大小。为了使得 µC/OS-III 能够适用于各 种各样的场景,µC/OS-III 被设计成可配置和裁剪的。

os_cfg.h

配置文件。文件主要用于配置 µC/OS-III 内核的一些功能,例如使能或禁用钩子函数、参数检 查、信号量功能、消息队列功能等等,

1. OS_CFG_APP_HOOKS_EN

此宏用于配置使能或禁用应用程序指定的钩子函数。当此宏配置为 1 时,使能应用程序指 定的钩子函数,通过这个功能,用户可以很方便地在应用程序中扩展 µC/OS-III 的功能。

2. OS_CFG_ARG_CHK_EN

此宏用于配置使能或禁用 µC/OS-III 函数的参数检查功能。当此宏配置为 1 时,µC/OS-III 会检查函数的传入参数是否合法,例如传递给函数的指针是否非空、传递的参数是否在允许的 范围值内、参数对应的选项是否有效等。启用此功能将会增加 µC/OS-III 占用的 Flash 空间和 RAM 空间。

3. OS_CFG_CALLED_FROM_ISR_CHK_EN

此宏用于配置使能或禁用检查是否在中断中非法调用任务级函数。当此宏配置为 1 时, µC/OS-III 会在执行函数前,判断该函数是否为中断中被非法调用。

4. OS_CFG_DBG_EN

此宏用于配置使能或禁用 µC/OS-III 的代码调试功能。当此宏配置为 1 时,会编译 os_dbg.c 文件中的内容,以帮助进行代码调试。

5. OS_CFG_TICK_EN

此宏用于配置使能或禁用 µC/OS-III 的内核时钟节拍。当此宏配置为 1 时,则使能 µC/OSIII 内核的时钟节拍功能。

6. OS_CFG_DYN_TICK_EN

此宏用于配置使能或禁用 µC/OS-III 的动态时钟节拍管理功能。当此宏配置为 1 时,则使 能 µC/OS-III 的动态时钟节拍管理功能。

7. OS_CFG_INVALID_OS_CALLS_CHK_EN

此宏用于配置使能或禁用检查是否在 µC/OS-III 系统开始运行前非法调用系统函数。当此 宏配置为 1 时,则使能该检查功能。

8. OS_CFG_OBJ_TYPE_CHK_EN

此宏用于配置使能或禁用检查 µC/OS-III 对象操作函数传入的对象参数类型是否合法。当 此宏配置为 1 时,则使能该检查功能。

9. OS_CFG_OBJ_CREATED_CHK_EN

此宏用于配置使能或禁用检查 µC/OS-III 对象是否被重复创建。当此宏配置为 1 时,则使 能该检查功能。

10. OS_CFG_TS_EN

此宏用于配置使能或禁用时间戳功能。当此宏配置为 1 时,则使能时间戳功能。

11. OS_CFG_PRIO_MAX

此宏用于定义任务优先级的最大数值。系统中最高任务优先级的数值为 0,最低任务优先 级的数值为 OS_CFG_PRIO_MAX-1。

其他在文件《UCOS-III开发指南-V1.0.PDF》中,P61。

os_cfg_app.h

文件主要用于配置于应用程序相关的 µC/OS-III 内核配置,例如空闲任务、任 务统计任务、软件定时器任务的任务参数配置等等。

1. OS_CFG_ISR_STK_SIZE

此宏用于定义用于异常的 Main Stack 栈的大小,默认单位为字(由变量类型 CPU_STK 决 定)。

2. OS_CFG_MSG_POOL_SIZE

此宏用于定义消息队列的消息池大小。

3. OS_CFG_TASK_STK_LIMIT_PCT_EMPTY

此宏用于定义空闲任务、统计任务、软件定时器任务任务栈的剩余最小值,当任务栈剩余 量小于这个值,说明任务栈移植,单位:百分比。

4. OS_CFG_IDLE_TASK_STK_SIZE

此宏用于定义空闲任务任务栈的大小,默认单位为字(由变量类型 CPU_STK 决定)。

5. OS_CFG_STAT_TASK_PRIO

此宏用于定义任务统计任务的任务优先级。

6. OS_CFG_STAT_TASK_RATE_HZ

此宏用于定义任务统计任务的运行频率,单位:赫兹。

7. OS_CFG_STAT_TASK_STK_SIZE

此宏用于定义任务统计任务栈的大小,默认单位为字(由变量类型 CPU_STK 决定)。

8. OS_CFG_TICK_RATE_HZ

此宏用于定义系统时钟节拍的频率,单位:赫兹。

9. OS_CFG_TMR_TASK_PRIO

此宏用于定义软件定时器任务的任务优先级。

10. OS_CFG_TMR_TASK_STK_SIZE

此宏用于定义软件定时器任务的任务栈大小,默认单位为字(由变量类型 CPU_STK 决定)。

11. OS_CFG_TMR_TASK_RATE_HZ

此宏用于定义软件定时器任务的运行频率,单位:赫兹。

µC/CPU 配置项

cpu_cfg.h

cpu_cfg.h 文件主要用于配置 µC/CPU 组件,配置一些于 CPU 硬件相关的配置项,例如时 间戳功能时基硬件定时器位数、CPU 是否支持前导零和后导零位数计算、CPU 为大端或小端格 式等等。

1. CPU_CFG_NAME_EN

此宏用于使能或禁止 CPU 主机名功能。当此宏配置为 DEF_ENABLE 时,则使能 CPU 主 机名功能。

2. CPU_CFG_NAME_SIZE

此宏用于定义 CPU 主机名的最大长度。

3. CPU_CFG_TS_32_EN

此宏用于使能或禁用使用 32 位硬件定时器作为时间戳功能的时基定时器。此宏配置为 DEF_ENABLE 时,使能使用 32 位硬件定时器作为时间戳功能的时基定时器。

4. CPU_CFG_TS_64_EN

此宏用于使能或禁用使用 64 位硬件定时器作为时间戳功能的时基定时器。此宏配置为 DEF_ENABLE 时,使能使用 64 位硬件定时器作为时间戳功能的时基定时器。

5. CPU_CFG_TS_TMR_SIZE

此宏用于定义时间戳的实际使用位数,可定义为 CPU_WORD_SIZE_08(实际使用 8 位时 间戳)、CPU_WORD_SIZE_16(实际使用 16 位时间戳)、CPU_WORD_SIZE_32(实际使用 32 位时间戳)、CPU_WORD_SIZE_64(实际使用 64 位时间戳)。

6. CPU_CFG_INT_DIS_MEAS_EN

此宏用于使能或禁用使用时间戳测量进入临界区和退出临界区期间的耗时时间。此宏配置 为 DEF_ENABLE 时,使能使用时间戳测量进入临界区和退出临界区期间的耗时时间。

7. CPU_CFG_INT_DIS_MEAS_OVRHD_NBR

此宏用于定义执行多少次临界区进入和退出函数,以计算出平均的进入临界区和退出临界 区期间的额外耗时时间。

8. CPU_CFG_LEAD_ZEROS_ASM_PRESENT

此宏用于指示 CPU 具有硬件计算前导零的指令,如 CLZ 指令。在 µC/OS-III 中,函数 CPU_CntLeadZeros()用于计算前导零,如果定义了此宏,则函数 CPU_CntLeadZeros()定义在文 件 cpu_a.asm 中使用 CLZ 指令实现;反之,则函数 CPU_CntLeadZeros()定义在文件 cpu_core.c 文件中使用软件算法实现。

9. CPU_CFG_TRAIL_ZEROS_ASM_PRESENT

此宏用于指示 CPU 具有硬件计算后导零的指令,如 RBIT 指令和 CLZ 指令配合使用。在µC/OS-III 中 , 函数 CPU_CntTrailZeros() 用 于 计算 后 导 零 , 如 果定 义了 此 宏 , 则 函数 CPU_CntTrailZeros()定义在 cpu_a.asm 文件中使用 RBIT 指令配置 CLZ 指令实现;反之,则函 数 CPU_CntTrailZeros()定义在 cpu_core.c 文件中使用软件算法实现。

10. CPU_CFG_ENDIAN_TYPE

此宏用于指示 CPU 的端格式,当此宏配置为 CPU_ENDIAN_TYPE_BIG 时,表明 CPU 为 大端格式,当此宏配置为 CPU_ENDIAN_TYPE_LITTLE 时,表明 CPU 为小端格式。

11. CPU_CFG_CACHE_MGMT_EN

此宏用于使能或禁用 µC/OS-III 的 Cache 管理功能。当此宏配置为 DEF_ENABLE 时,则使 能 µC/OS-III 的 Cache 管理功能。

12. CPU_CFG_KA_IPL_BOUNDARY

此宏用于定义受 µC/OS-III 管理的最高中断优先等级,中断优先级低于此宏定义值(中断 优先级数值大于此宏定义值)的中断受 µC/OS-III 管理。

13. CPU_CFG_NVIC_PRIO_BITS

此宏用于定义中断优先级配置寄存器的实际使用位数。

µC/LIB 配置项

lib_cfg.h

文件主要用于配置 µC/LIB 组件

1. LIB_MEM_CFG_ARG_CHK_EXT_EN

此宏用于使能或禁用检查内存库(文件 lib_mem.c)中函数的传入参数是否合法。当此宏配 置为 DEF_ENABLE 时,则使能检查内存库中函数的传入参数是否合法。

2. LIB_MEM_CFG_OPTIMIZE_ASM_EN

此宏用于使能或禁用使用内存库中优化的内存相关操作函数。当此宏配置为 DEF_ENABLE 时,则使能使用内存库中优化的内存相关操作函数,例如使用内存库中的函数 Mem_Copy()代 替标准 C 库中的函数 memcpy()。

3. LIB_MEM_CFG_DBG_INFO_EN

此宏用于使能或禁用为申请的每一个内存块分配一个用于跟踪调试的名称。当此宏配置为 DEF_ENABLE 时,则使能位申请的每一个内存块分配一个用于跟踪调试的名称。

4. LIB_MEM_CFG_HEAP_SIZE

此宏用于定义用于内存库管理的内存堆的大小,单位:字节。

5. LIB_MEM_CFG_HEAP_PADDING_ALIGN

此宏用于定义使用函数 Mem_HeapAlloc()申请内存时,所申请的内存大小需按多少字节向 上对齐。

6. LIB_MEM_CFG_HEAP_BASE_ADDR

此宏用于定义用于内存库管理的内存堆的起始地址。当没有定义这个宏时,用于内存库管 理的内存堆将由编译器自动分配,当定义了这个宏后,用于内存库管理的内存堆将被分配到该 宏定义的地址上。

7. LIB_STR_CFG_FP_EN

此宏用于使能或禁用浮点数转字符串功能。当此宏配置为 DEF_ENABLE 时,将编译函数 Str_FmtNbr_32(),用于浮点数转字符串。

8. LIB_STR_CFG_FP_MAX_NBR_DIG_SIG

此宏用于配置浮点数转字符串函数 Str_FmtNbr_32()的转换精度。

µC/OS-III 中断管理

中断是学习 µC/OS-III 的过程中一个重要的部分,任务切换、系统时钟节拍等等,都是利用 中断来完成的,并且,既然是 RTOS,那么对中断的响应也应该是十分迅速的。µC/OS-III 有一 套中断管理的方法,并且在用户使用 µC/OS-III 的中断管理前,仅需进行少量的配置,使用起来 非常方便。

 ARM Cortex-M 中断

中断是 CPU 的一种常见特性,中断一般由硬件产生,当中断发生后,会中断 CPU 当前正 在执行的程序而跳转到中断对应的服务程序中去执行,ARM Cortex-M 内核的 MCU 具有一个 用于中断管理的嵌套向量中断控制器(NVIC,全称:Nested Vectored Interrupt Controller)。

ARM Cortex-M 的 NVIC 最大可支持 256 个中断源,其中包括 16 个系统中断和 240 个外部中断。

中断优先级配置寄存器的值与对应的优先等级成反比,即中断优先级配置寄存器的值越小, 中断的优先等级就越高。

STM32 的中断优先级可分为抢占优先级和子优先级,抢占优先级和子优先级的区别如下:

抢占优先级:抢占优先级高的中断可以打断正在执行但抢占优先级低的中断,即中断嵌套。

子优先级:当抢占优先级相同时,子优先级高的中断不能打断正在执行但子优先级低的中 断,即子优先级不支持中断嵌套。

三个中断优先级配置寄存器 除了外部中断,系统中断有独立的中断优先级配置寄存器,分别为 SHPR1、SHPR2、SHPR3,

µC/OS-III 在配置 PendSV 和 SysTick 中断优先级的时候,就使用到了 SHPR3 寄存器,因此 请读者多留意该寄存器。

µC/OS-III 中断管理详解

PendSV 和 SysTick 中断优先级配置

PendSV 中断优先级配置

PendSV 主要用于任务切换,因此在 µC/OS-III 内核开始进行多任务处理前,也就是在 µC/OS-III 内核启动之前,就需要配置好 PendSV。在文件 os_cpu_a.asm 中有标号(汇编中的标 号,类似于 C 语言中的函数名)OSStartHighRdy,OSStartHighRdy 用于开启系统中第一个任务, 在函数 OSStart()中被调用。

µC/OS-III 任务基础知识

任务和任务管理是 RTOS 的核心,µC/OS-III 也不例外,并且,绝大多数项目使用 RTOS 的 目的就是为了使用 RTOS 的多任务管理能力。对于初学者,特别是没有 RTOS 基础的读者,了 解 µC/OS-III 的任务管理机制,是非常有必要的。

单任务系统

单任务系统的编程方式,即裸机的编程方式,这种编程方式的框架一般都是在 main()函数 中使用一个大循环,在循环中顺序地调用相应地函数以处理相应的事务,这个大循环的部分可 视为应用程序的后台,而应用程序的前台,则是各种中断的中断服务函数。

因此单任务系统也 叫做前后台系统。

前后台系统的实时性很差,因为大循环中函数处理的事务没有优先级 之分,因此在大循环中函数处理的事务需要顺序地被执行,不论待处理的事务紧急程度有多高, 没轮到只能等着,虽然中断能后处理一些紧急的事务,但是在一些大型的嵌入式应用中,这样 的单任务系统就会显得力不从心。

多任务系统

从宏观上来看,多任务系统的 多个任务是可以“同时”运行的,因此紧急的事务就可以无需等待 CPU 处理完其他事务,在被 处理。

要注意的是,上面提到的所任务系统中多个任务可以“同时”运行,是从宏观的角度而言 的,对于单核的 CPU 而言,CPU 在同一时刻只能够处理一个任务,但是多任务系统的任务调 度器会根据相关的任务调度算法,将 CPU 的使用权分配给任务,在任务获取到 CPU 使用权之 后的极短时间(宏观角度)后,任务调度器又会将 CPU 的使用权分配给其他任务,如此往复, 在宏观角度看来,就像是多个任务在同时运行了一样。

相较于单任务系统而言,多任务系统的任务是具有优先级的,高优先级 的任务可以像中断的抢占机制一样,抢占低优先级任务的运行,从而获得 CPU 的使用权;优先 级相同的任务则各轮流运行一段极短的时间(宏观角度),从而产生“同时”运行的错觉。以上 就是抢占式调度和时间片调度的基本原理。

在任务有了优先级的多任务系统中,用户就可以将紧急的事务放在优先级高的任务中进行 处理,那么整个系统的实时性就会大大地提高。

µC/OS-III 任务状态

µC/OS-III 中任务存在五种状态,分别为休眠态、就绪态、运行态、挂起态和中断态,一个 任务在某一时刻一定是处于这五种状态中的一种。

µC/OS-III 中的五种任务状态之间的转换图如

1. 休眠态

处于休眠态的任务对应的是那些存在于内存中,但是尚未提供给 µC/OS-III 内核的任务。 应用程序可以通过调用函数 OSTaskCreate()对一个处于休眠态的任务进行创建,休眠态任务的 任务代码实际上已经存在于代码空间中,只是需要应用程序通知 µC/OS-III 内核。当不在需要 某个任务时,可以通过函数 OSTaskDel()删除这个任务,被删除的任务就会重新回到休眠态,这 里所说的删除,并非将任务从代码空间中删除,而仅仅是将任务切换到休眠态,让 µC/OS-III 内 核不再管理这个任务。

2. 就绪态

当任务被函数 OSTaskCreate()创建后,准备好运行但还未运行时,任务就处于就绪态。 µC/OS-III 中有一个就绪态任务链表,就绪态任务按照任务的优先级排序被链接到就绪态任务链 表中。

3. 运行态

处于运行态的任务就是当前 CPU 正在执行的任务,对于只具有单核 CPU 的 MCU 而言,在某一时刻只能执行一个任务,换言之,只具有单核 CPU 的 MCU,在某一时刻中,只存在一 个就绪态任务。

4. 挂起态

当处于运行态的任务需要等待某一事件时,例如等待信号量、消息队列或事件标志等,这 时运行态任务就会让出 CPU 的使用权,切换到挂起态等待事件发生。当等待的事件发生后,处 于挂起态的任务就会切换到就绪态,等待任务调度器调度运行。

5. 中断态

当处于运行态的任务被中断打断,CPU 跳转去执行中断的中断服务函数时,原本处于运行 态的任务就会切换到中断态,直到中断服务函数处理结束后,在切换回运行态继续运行。

µC/OS-III 任务优先级

任务优先级是决定任务调度器如何分配 CPU 使用权的因素之一。每一个任务都被分配一个 0~(OS_CFG_PRIO_MAX-1)的任务优先级,并且 µC/OS-III 支持多了任务具有相同的任务优先 级,宏 OS_CFG_PRIO_MAX 是在 µC/OS-III 的配置文 os_cfg.h 中定义配置的。

µC/OS-III 任务调度方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蛋蛋的学习记录

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值