STM32F103移植uC/OS-III实时操作系统
·
STM32F103移植uC/OS-III实时操作系统
一、实验环境准备
1.1 硬件准备
- 主控芯片: STM32F103C8T6 (Cortex-M3内核)
- 开发板: STM32F103C8T6最小系统板
- 外设:
- LED灯 x2 (PA0, PA1)
- USB转串口模块 (PA2, PA3)
1.2 软件准备
- IDE: STM32CubeIDE 1.8.0
- RTOS: uC/OS-III v3.08.00
- HAL库: STM32Cube_FW_F1_V1.8.4
二、uC/OS-III源码获取与准备
2.1 下载uC/OS-III源码
从Micrium官网或GitHub获取uC/OS-III源码,主要包含以下文件:
uC-CPU/
uC-LIB/
uC-OS3/
三、STM32CubeMX工程配置
3.1 创建新工程
- 打开STM32CubeMX,选择STM32F103C8Tx
- 配置系统时钟:
- HSE: Crystal/Ceramic Resonator
- 系统时钟: 72MHz
3.2 GPIO配置
- LED1: PA0, Output Push-Pull
- LED2: PA1, Output Push-Pull
3.3 串口配置
- USART2: Asynchronous Mode
- Baud Rate: 115200
- Word Length: 8 Bits
- Stop Bits: 1
- Parity: None
3.4 系统配置
- SYS: Debug: Serial Wire
- NVIC: 配置PendSV、SysTick优先级
四、uC/OS-III移植步骤
4.1 添加源码到工程
将uC/OS-III源码复制到工程目录,并在IDE中添加文件:
/* 在IDE中创建文件组 */
UCOSIII/CORE
├── os_cfg_app.c
├── os_core.c
├── os_dbg.c
└── ... (其他核心文件)
UCOSIII/PORT
├── os_cpu_c.c
├── os_cpu_a.asm
└── os_cpu.h
UCOSIII/CPU
├── cpu_core.c
└── cpu_def.h
UCOSIII/LIB
├── lib_ascii.c
├── lib_math.c
└── ...
4.2 修改os_cfg_app.h配置文件
/* 任务配置 */
#define OS_CFG_PRIO_MAX 64u
#define OS_CFG_TASK_STK_LIMIT_PCT_EMPTY 10u
/* 系统配置 */
#define OS_CFG_SCHED_ROUND_ROBIN_EN 1u
#define OS_CFG_TICK_EN 1u
#define OS_CFG_TASK_TICK_EN 1u
/* 时间片轮转调度配置 */
#define OS_CFG_SCHED_ROUND_ROBIN_EN 1u
4.3 修改os_cpu.h
/* 处理器相关定义 */
#define OS_CPU_CM3_FP_PRESENT 0u
#define OS_CPU_CM3_FP_USED 0u
/* 临界段保护 */
#define OS_CRITICAL_METHOD 3u
#define OS_ENTER_CRITICAL() {CPU_SR_ALLOC(); CPU_CRITICAL_ENTER();}
#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();}
4.4 修改os_cpu_c.c
/* CPU初始化 */
void OS_CPU_SysTickInit (CPU_INT32U cnts)
{
CPU_INT32U prio;
/* 配置SysTick */
HAL_SYSTICK_Config(cnts);
/* 配置SysTick中断优先级 */
prio = (1UL << __NVIC_PRIO_BITS) - 1UL;
HAL_NVIC_SetPriority(SysTick_IRQn, prio, 0U);
}
/* SysTick中断处理 */
void SysTick_Handler(void)
{
HAL_IncTick();
if (OSRunning == OS_STATE_OS_RUNNING) {
OS_TimeTick();
}
}
4.5 修改启动文件
在startup_stm32f103xb.s中添加PendSV和SysTick中断处理:
; 在启动文件的向量表中确保有以下定义
__Vectors
DCD __initial_sp
DCD Reset_Handler
DCD NMI_Handler
DCD HardFault_Handler
DCD MemManage_Handler
DCD BusFault_Handler
DCD UsageFault_Handler
DCD 0
DCD 0
DCD 0
DCD 0
DCD SVC_Handler
DCD DebugMon_Handler
DCD 0
DCD PendSV_Handler
DCD SysTick_Handler
五、创建多任务应用程序
5.1 头文件包含和全局变量定义
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "os.h"
#include "cpu.h"
/* 任务栈大小定义 */
#define TASK_START_STK_SIZE 128
#define TASK_LED1_STK_SIZE 128
#define TASK_LED2_STK_SIZE 128
#define TASK_UART_STK_SIZE 128
/* 任务控制块 */
OS_TCB TaskStartTCB;
OS_TCB TaskLed1TCB;
OS_TCB TaskLed2TCB;
OS_TCB TaskUartTCB;
/* 任务栈 */
CPU_STK TaskStartStk[TASK_START_STK_SIZE];
CPU_STK TaskLed1Stk[TASK_LED1_STK_SIZE];
CPU_STK TaskLed2Stk[TASK_LED2_STK_SIZE];
CPU_STK TaskUartStk[TASK_UART_STK_SIZE];
5.2 任务函数实现
/* LED1任务 - 1秒周期 */
void Task_LED1(void *p_arg)
{
OS_ERR err;
(void)p_arg;
while(1) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0); // 翻转LED1
OSTimeDlyHMSM(0, 0, 1, 0, OS_OPT_TIME_HMSM_STRICT, &err); // 延时1秒
}
}
/* LED2任务 - 3秒周期 */
void Task_LED2(void *p_arg)
{
OS_ERR err;
(void)p_arg;
while(1) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1); // 翻转LED2
OSTimeDlyHMSM(0, 0, 3, 0, OS_OPT_TIME_HMSM_STRICT, &err); // 延时3秒
}
}
/* 串口任务 - 2秒周期 */
void Task_UART(void *p_arg)
{
OS_ERR err;
char uart_buf[64];
(void)p_arg;
while(1) {
sprintf(uart_buf, "hello uc/OS! 欢迎来到RTOS多任务环境!\r\n");
HAL_UART_Transmit(&huart2, (uint8_t*)uart_buf, strlen(uart_buf), 1000);
OSTimeDlyHMSM(0, 0, 2, 0, OS_OPT_TIME_HMSM_STRICT, &err); // 延时2秒
}
}
/* 启动任务 */
void Task_Start(void *p_arg)
{
OS_ERR err;
(void)p_arg;
/* 创建LED1任务 */
OSTaskCreate(&TaskLed1TCB,
"LED1 Task",
Task_LED1,
(void *)0,
2, // 优先级
&TaskLed1Stk[0],
TASK_LED1_STK_SIZE / 10,
TASK_LED1_STK_SIZE,
0,
0,
(void *)0,
OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR,
&err);
/* 创建LED2任务 */
OSTaskCreate(&TaskLed2TCB,
"LED2 Task",
Task_LED2,
(void *)0,
3, // 优先级
&TaskLed2Stk[0],
TASK_LED2_STK_SIZE / 10,
TASK_LED2_STK_SIZE,
0,
0,
(void *)0,
OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR,
&err);
/* 创建串口任务 */
OSTaskCreate(&TaskUartTCB,
"UART Task",
Task_UART,
(void *)0,
4, // 优先级
&TaskUartStk[0],
TASK_UART_STK_SIZE / 10,
TASK_UART_STK_SIZE,
0,
0,
(void *)0,
OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR,
&err);
/* 删除启动任务 */
OSTaskDel((OS_TCB *)0, &err);
}
5.3 主函数实现
int main(void)
{
OS_ERR err;
/* HAL库初始化 */
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
/* 初始化LED为关闭状态 */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
/* uC/OS-III初始化 */
OSInit(&err);
if (err != OS_ERR_NONE) {
while(1); // 初始化失败
}
/* 创建启动任务 */
OSTaskCreate(&TaskStartTCB,
"Start Task",
Task_Start,
(void *)0,
1, // 最高优先级
&TaskStartStk[0],
TASK_START_STK_SIZE / 10,
TASK_START_STK_SIZE,
0,
0,
(void *)0,
OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR,
&err);
/* 启动多任务调度 */
OSStart(&err);
/* 不会执行到这里 */
while(1);
}
六、编译配置和调试
6.1 编译器配置
- Optimization: -O0 (便于调试)
- Include Paths: 添加所有uC/OS-III头文件路径
- Preprocessor Symbols: 添加
OS_CFG_APP_H、UCOSIII等宏定义
6.2 链接器配置
- Heap Size: 0x200
- Stack Size: 0x400
6.3 调试配置
使用ST-Link调试器,在os_cfg_app.c中开启调试功能:
#define OS_CFG_DBG_EN 1u
#define OS_CFG_TRACE_EN 1u
七、实验结果验证
7.1 运行现象
- LED1: 以1秒周期闪烁
- LED2: 以3秒周期闪烁
- 串口输出: 每2秒输出"hello uc/OS! 欢迎来到RTOS多任务环境!"

7.2 使用串口调试助手观察输出

八、常见问题及解决方案
8.1 编译错误
问题: 未定义符号错误
解决: 检查所有源文件是否正确添加到工程,头文件路径是否正确配置
8.2 系统无法启动
问题: 卡在OSStart()
解决: 检查PendSV和SysTick中断优先级配置,确保时钟配置正确
8.3 任务无法正常调度
解决: 检查任务栈大小是否足够,优先级配置是否合理
九、总结
通过本次移植实验,我们成功将uC/OS-III实时操作系统移植到STM32F103平台,并创建了三个具有不同周期的任务。实验证明了uC/OS-III在STM32上的稳定运行。
移植要点总结:
- 正确配置系统时钟和中断优先级
- 合理设置任务栈大小和优先级
- 确保所有必要的源文件正确包含
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)