STM32移植UCOSIII
本文最后更新于:2023年10月3日 下午
STM32移植UCOSIII
早期嵌入式Q开发没有嵌入式操作系统的概念,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念。通常把程序分为两部分:前台系统和后台系统。传统简单的小系统通常是前后台系统,这样的程序包括一个死循环和若干个中断服务程序:应用程序是一个无限循环,循环中调用API函数完成所需的操作,这个大循环就叫做后台系统。中断服务程序用于处理系统的异步事件,也就是前台系统。前台是中断级,后台是任务级。
在前后台系统下,所有的任务的优先级是平等的,且是以FIFO的方式排列。也就是说,后面的任务必须等待前面的任务都完成之后才可以执行。在前后台系统下,实时性非常差,而且随着任务数量的增多,实时性会愈差。就好像我们上课时突然内急(优先级很高),需要立刻去WC,但是却不得不等到下课(优先级不高)。这种情况下在程序上表现出来可能就是数据丢失,或者响应慢(比如步进电机过冲)等效果了。尽管也可以利用定时器等手段去手动分配时间片来增强实时性,但这样的方法容易造成程序的高度耦合,与程序开发的“高内聚,低耦合”相悖,这样的代码肯定是很难管理和维护的。
而在RTOS实时操作系统下进行程序开发,每个任务都是独立运行的一个有限次或无限次循环,一般情况下不会互相影响(除非栈溢出等因素),因而很容易管理和维护。每个任务都可以设置优先级,RTOS的内核大多都是可抢占式的。高优先级的任务一但就绪就可以夺走低优先级任务的CPU使用权,实时性相比于前后台系统大幅度提高。而且RTOS会提供一些内核对象供用户使用,比如信号量,常用作任务同步和共享资源保护等。
uC/OS-Ⅲ(Micro C OS Three微型的 C 语言编写的操作系统第3版)是一个可升级的,可固化的,基于优先级的实时内核,属于一种RTOS实时操作系统。它对任务的个数无限制。uC/OS-Ⅲ是一个第3代的系统内核,支持现代的实时内核所期待的大部分功能。例如资源管理,同步,任务间的通信等等。然而,uC/OS-Ⅲ提供的特色功能在其它的实时内核中是找不到的,比如说完备的运行时间测量性能,直接地发送信号或者消息到任务,任务可以同时等待多个内核对象等。
参考
STM32CubeIDE 复制工程使用CubeMX配置生成后src文件夹内容被删除(移除)_sudaroot的博客-CSDN博客
[野火]uCOS-III内核实现与应用开发实战指南—基于STM32
Weston Embedded Solutions · GitHub
2023年新版手把手教你学UCOS-III — 正点原子资料下载中心 1.0.0 文档 (openedv.com)
一、ucosⅢ源码下载
uc-OS3源码:weston-embedded/uC-OS3 at v3.08.01 (github.com)
uc-LIB源码:weston-embedded/uC-LIB at v1.39.01 (github.com)
uc-CPU源码:weston-embedded/uC-CPU at v1.32.01 (github.com)
二、ucosⅢ源码结构
三、工程添加4个分组【官方源码文件】
Keil工程分组 | 添加文件 | 备注 |
---|---|---|
(19个文件) | ||
uC_OS3/OS | ./uC_OS3/uC-OS3/Cfg/Template/os_app_hooks.c | 包含了8 个空的能被uC/OS-III 调用的hook0 函数。 |
./uC_OS3/uC-OS3/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm | 包含了汇编语言定义的函数。至少需包含OSCtxSW(),OSIntCtxSW(),OSStartHighRdy()的定义 | |
./uC_OS3/uC-OS3/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c | 包含了C 代码编写的hook 函数以及初始化任务创建时堆栈框架的相关代码 | |
./uC_OS3/uC-OS3/Source/os_cfg_app.c | 申明变量和数组(基于OS_CFG_APP.H 中的变量类型) | |
./uC_OS3/uC-OS3/Source/os_core.c | 包含uC/OS-III 的核心函数如OSInit(),OSSchedule(),OSIntExit()等等 | |
./uC_OS3/uC-OS3/Source/os_dbg.c | 申明了关于内核调试器或uC/Probe 的常量 | |
./uC_OS3/uC-OS3/Source/os_flag.c | 包含了时间管理相关的代码 | |
./uC_OS3/uC-OS3/Source/os_mem.c | 包含了uC/OS-III 内存管理相关代码 | |
./uC_OS3/uC-OS3/Source/os_msg.c | 包含了消息处理相关代码 | |
./uC_OS3/uC-OS3/Source/os_mutex.c | 包含了与互斥信号量相关的代码 | |
./uC_OS3/uC-OS3/Source/os_prio.c | 包含了管理任务优先级相关的代码。这个文件可以被改为同等功能的汇编语言写的文件(如果CPU 支持位设置,位清除指令,计数清零指令)以提高性能。 | |
./uC_OS3/uC-OS3/Source/os_q.c | 包含了管理消息队列相关的代码 | |
./uC_OS3/uC-OS3/Source/os_sem.c | 包含了管理与资源、同步相关的信号量代码 | |
./uC_OS3/uC-OS3/Source/os_stat.c | 包含了与统计任务相关的代码 | |
./uC_OS3/uC-OS3/Source/os_task.c | 包含了与管理任务相关的代码如OSTaskCreate(),OSTaskDel(),OSTaskChangePrio()等函数 | |
./uC_OS3/uC-OS3/Source/os_tick.c | 包含了与任务延时,任务停止相关的代码 | |
./uC_OS3/uC-OS3/Source/os_time.c | 包含了任务定时相关的代码 | |
./uC_OS3/uC-OS3/Source/os_tmr.c | 包含了管理软件定时器相关的代码 | |
./uC_OS3/uC-OS3/Source/os_var.c | 包含了uC/OS-III 的全局变量,这些变量都是用于管理uC/OS-III 的,不应该被用户的代码访问 | |
(2个文件) | ||
uC_OS3/BSP | ./uC_OS3/uC-CPU/BSP/Template/bsp_cpu.c | |
./uC_OS3/uC-OS3/Template/bsp_os_dt.c | ||
(3个文件) | ||
uC_OS3/CPU | ./uC_OS3/uC-CPU/ARM-Cortex-M/ARMv7-M/cpu_c.c | 特定CPU 架构的C语言代码。一般来说,如果函数能用C 编写就用C 编写,除非用汇编编写能够产生更高的性 |
./uC_OS3/uC-CPU/ARM-Cortex-M/ARMv7-M/ARM/cpu_a.asm | 包含了汇编语言编写的函数用于关中断,开中断,计数清零(如果CPU 支持这条汇编指令的话),其它CPU 相关的只能用汇编编写的函数。这个文件也包含开启caches,设置MPUs 和MMU 等等。 | |
./uC_OS3/uC-CPU/cpu_core.c | 适应于所有架构 CPU 的代码。包含了测量 CPU 关中断时间相关函数的代码。 | |
(4个文件) | ||
uC_OS3/LIB | ./uC_OS3/uC-LIB/lib_ascii.c | 包含将一些标准库函数(如 tolower()、toupper()、isalpha()、isdigit() 等)分别替换为 uC/LIB 对应函数 ASCII_ToLower()、ASCII_ToUpper()、ASCII_IsAlpha() 和ASCII_IsDig() 的源代码。 |
./uC_OS3/uC-LIB/lib_math.c | 包含将一些标准库函数(如 rand()、srand()等)分别替换为 uC/LIB 对应函数 Math_Rand()、Math_SetSeed()的源代码 | |
./uC_OS3/uC-LIB/lib_mem.c | 包含将一些标准库函数,(如 memclr()、memset()、memcpy()、memcmp() 等)分别替换为 uC/LIB 对应函数Mem_Clr()、Mem_Set()、Mem_Copy ()、Mem_Cmp() 的源代码 | |
./uC_OS3/uC-LIB/lib_str.c | 包含将一些标准库函数,(如strlen()、strcpy()、strcat()、strcmp()等)分别替换为 uC/LIB 对应函数Str_Len()、Str_Copy()、Str_Cat()、Str_Cmp()的源代码 |
四、添加头文件路径
包含头文件文件夹路径 |
---|
.._OS3-CPU |
.._OS3-CPU-Cortex-M-M |
.._OS3-CPU |
.._OS3-LIB |
.._OS3-LIB |
.._OS3-OS3 |
.._OS3-OS3-Cortex-M-M |
.._OS3-OS3 |
五、修改System文件【正点原子自定义文件】
直接拷贝正点原子项目中的文件,添加进项目分组即可
头文件 | 源文件 | 备注 |
---|---|---|
uart.h | uart.c | 调试用串口函数定义(相应修改为cubemx代码结构,可删除) |
sys.h | sys.c | 系统配置定义(相应修改为cubemx代码结构,去除配置系统时钟函数) |
delay.h | delay.c | 延时函数定义(相应修改为cubemx代码结构) |
六、替换中断服务函数
startup_stm32h743xx.s文件中的PendSV_Handler替换成OS_CPU_PendSVHandler
七、修改配置文件
使用正点原子配置文件(内容替换 或 按如下配置)
文件 | 修改内容 | 说明 |
---|---|---|
./uC_OS3/uC-CPU/Cfg/Template/cpu_cfg.h | #define CPU_CFG_NAME_EN DEF_ENABLED #define CPU_CFG_TS_32_EN DEF_ENABLED 开启Configure CPU count leading zeros bits 开启Configure CPU count trailing zeros bits 开启#define CPU_CFG_ENDIAN_TYPE CPU_ENDIAN_TYPE_LITTLE 开启#define CPU_CFG_NVIC_PRIO_BITS 4u | 启用CPU 主机名 启用 32 位 CPU 时间戳功能 定义前导零位计数函数。 定义尾零位计数函数 重写 cpu.h 中定义的默认 CPU 端位类型为小端 确定可编程中断优先级[7:4] |
/uC_OS3/uC-LIB/Cfg/Template/lib_cfg.h | #define LIB_MEM_CFG_HEAP_SIZE 0u | 禁用堆分配功能 |
./uC_OS3/uC-OS3/Cfg/Template/os_cfg_app.h | ||
./uC_OS3/uC-OS3/Cfg/Template/os_cfg.h | #define OS_CFG_APP_HOOKS_EN 0u #define OS_CFG_TS_EN 1u #define OS_CFG_PRIO_MAX 32u #define OS_CFG_TASK_REG_TBL_SIZE 0u #define OS_CFG_TASK_STK_REDZONE_EN 1u | 禁用应用程序特定的钩子 启用时间标记 定义任务优先级的最大数量32 任务专用寄存器数量0 启用堆栈红区,以便在调试时检测堆栈溢出 |
八、添加自定义功能代码
(1)STM32CubeMX配置说明(更详细的配置自行上网查询)
- 复制工程前后或使用图形化配置前记得先把文件夹下的
.mxproject
文件删除即可 - 外部有源晶振BYPASS Clock Source
- 外部无源晶振Crystal/Ceramic Resonator
- 功率调节器电压级别Power Regulator Voltage Scale限制最高工作频率
- IO引脚为黄色表示未激活,需要进行相应配置
GPIO默认电平设置 | 说明(一般在检测输入信号时设置) |
---|---|
No pull--up and no pull-down | 不使用内部电阻(用于输出模式) |
pull-up | 上拉电阻,初始化为高电平 |
pull-down | 下拉电阻,初始化为低电平 |
(2)LED灯功能代码
1.文件led.h
1 |
|
2.文件led.c
1 |
|
(3)Key按键功能代码
1.文件key.h
1 |
|
2.文件key.c
1 |
|
(4)uC_OS3用户代码
1.文件uC_OS3.h
1 |
|
2.文件uC_OS3.c
1 |
|
(5)main函数内容
1 |
|
九、关于实时操作系统的两个误区:
(1)误区一:一定能提高系统响应速度?
不一定。因为实时操作系统本身引入了执行开销,所以对于小型应用来说,有RTOS的性能也许不如无操作系统的情况。实时操作系统的优势最能体现在中大型系统中,当任务间存在复杂的耦合和依赖关系,并且应用程序经常要长时间等待外部资源时。
(2)误区二:一定可以保证系统实时性?
不一定。相对来说,使用实时系统可以改善系统的实时性。但是实时操作系统只是作为工具存在的,如果需要提供实时性保障,还需要使用实时系统理论对任务的可调度性和响应时间进行分析,才可以得到科学、系统的响应性保障。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!