从 0 到 1!STM32F103C8T6+HAL 库实战 uCOS-III 移植,多任务控灯 + 串口通信全实现
从 0 到 1!STM32F103C8T6+HAL 库实战 uC/OS-III 移植,多任务控灯 + 串口通信全实现
文章目录
一、uC/OS-III 简单介绍
uC/OS-III(Micro-Controller Operating System Version III)是 Micrium 公司推出的第三代实时操作系统(RTOS),核心定位是服务嵌入式系统。它主打 “轻量 + 强功能”,专门适配微控制器(MCU)、数字信号处理器(DSP)等硬件资源受限的设备,同时继承了 uC/OS-II 的稳定架构,并在多任务、实时性等关键能力上完成增强与优化。
1、核心特性解析
(1)高可移植性:跨平台适配无压力
uC/OS-III 对主流硬件架构兼容性极强,已支持 ARM、MIPS、PowerPC、AVR 等多种微控制器架构,开发者无需大幅修改代码,即可在不同硬件平台间迁移使用。
(2)多任务管理:灵活调度高并发
- 基础能力:覆盖任务创建、调度、终止全流程,满足多任务并发需求。
- 核心调度:采用 优先级抢占式调度算法,能确保高优先级任务优先执行;同时支持动态优先级调整,可根据业务需求灵活修改任务优先级。
(3)时间管理:精准控制时序
提供毫秒级精度的系统时钟管理,支持两种核心定时场景:
- 单次延时任务:实现任务的精准延时等待。
- 周期性定时任务:满足周期性执行的业务需求(如数据定时采集)。
(4)内存管理:安全且高效
- 分配方式:同时支持静态内存分配(适合确定性要求高的场景)和动态内存分配(适合灵活使用内存的场景),并通过内存池机制统一管理内存资源。
- 安全保障:自带内存保护机制,可有效防止内存泄漏、非法访问等问题,提升系统稳定性。
(5)任务同步与通信:多任务协作无阻碍
内置 4 类核心同步通信组件,覆盖多任务交互的所有常见场景:
- 信号量(Semaphore):解决任务间的同步问题(如资源占用、步骤协同)。
- 消息队列(Message Queue):实现多任务间的批量数据传递。
- 邮件箱(Mailbox):用于单个消息的快速传递,适合轻量数据交互。
- 事件标志组(Event Flags):支持多任务间的事件通知(如 “等待多个事件触发后执行”)。
(6)高效中断处理:快速响应硬件请求
- 响应速度:支持高效的中断管理机制,能快速响应硬件中断,减少中断延迟。
- 优先级关联:允许中断服务例程(ISR)与任务优先级关联,确保中断处理不影响核心任务执行。
(7)可配置性:按需裁剪轻量运行
uC/OS-III 采用模块化设计,所有功能(如内存管理、事件标志组)均可按需开启或关闭。通过裁剪不必要的模块,能将系统代码量和内存占用压缩到极小,完美适配资源受限的嵌入式设备。
(8)强实时性:满足严苛时序要求
核心设计围绕 “实时响应” 展开,任务切换时间、中断延迟均为可预测值,能满足工业控制、医疗设备等对延迟和响应时间要求极高的场景。
(9)调试支持:降低开发难度
提供完善的调试接口,可与 JTAG 等主流调试工具无缝配合,方便开发者定位代码 bug、分析系统性能(如任务执行时间、CPU 占用率),提升开发效率。
2、uC/OS-III 的架构:模块化设计解析
uC/OS-III 采用模块化架构,核心模块分工明确且相互协同,既保证了功能的完整性,也为 “按需裁剪” 提供了基础。整体可拆解为 5 个核心模块,各模块的定位与功能如下:
(1)内核(Kernel):系统的 “中枢大脑”
内核是 uC/OS-III 的核心控制模块,承担 “统筹调度” 角色,直接管理其他所有功能模块。其核心职责包括:
- 统一协调 任务管理、时间管理、内存管理 等模块的运行;
- 封装同步与通信组件(如信号量、消息队列),为多任务交互提供底层支持;
- 作为硬件与上层任务的中间层,屏蔽硬件差异,保障系统稳定运行。
(2)任务管理:多任务的 “生命周期管家”
任务管理模块负责对用户任务的全生命周期进行管控,支持复杂的任务操作需求,核心能力包括:
- 生命周期控制:支持任务的 创建、删除、挂起、恢复 等基础操作,满足任务动态调整需求;
- 任务行为控制:提供 任务延时、任务通知 功能(如通过任务通知直接向目标任务发送消息,无需额外组件);
- 与调度器协同:将任务的优先级、状态等信息同步给调度器,为调度决策提供依据。
(3)调度器(Scheduler):任务执行的 “指挥中心”
调度器是实现 “实时性” 的关键模块,负责决定 “哪个任务何时执行”,核心逻辑如下:
- 调度算法:采用 优先级抢占式调度,系统始终优先执行当前最高优先级的就绪任务;
- 调度触发时机:任务状态变化(如高优先级任务就绪、当前任务延时)时,自动触发调度;
- 辅助调度:支持 时间片轮转调度(仅对同优先级任务生效),确保同优先级任务公平占用 CPU 资源。
(4)中断管理:硬件请求的 “快速响应通道”
中断管理模块负责处理硬件中断请求,保障系统对外部事件的快速响应,核心特性包括:
- 支持 嵌套中断(高优先级中断可打断低优先级中断的执行),提升中断响应效率;
- 低延迟设计:简化中断处理流程,缩短中断响应时间,确保实时任务不被长期阻塞;
- 中断与任务协同:允许在中断服务例程(ISR)中触发任务调度,实现 “中断处理后立即执行关联任务”。
(5)内存管理:系统内存的 “高效分配器”
内存管理模块负责统筹系统内存资源,避免内存浪费与非法访问,核心机制包括:
- 两种分配模式:支持 静态内存分配(编译时确定内存地址,适合确定性要求高的场景)和 动态内存分配(运行时灵活分配,适合内存需求动态变化的场景);
- 精细化管理:通过 内存池、内存块 机制(将大块内存划分为固定大小的内存块),减少内存碎片;
- 任务栈管理:为每个任务分配独立的栈空间,并监控栈使用情况,防止栈溢出。
总结
uC/OS-III 是一款为嵌入式场景量身打造的轻量化 RTOS,它既通过高可移植性适配多硬件架构,以优先级抢占调度、低延迟中断处理保障强实时性,又靠模块化设计实现按需裁剪,搭配内存保护、丰富同步通信组件与调试支持,兼顾了资源效率与开发便捷性;其内核统筹、任务管理、调度器、中断管理、内存管理五大模块分工协同的架构,进一步强化了 “轻量可靠、灵活适配” 的核心优势,能很好满足工业控制、汽车电子等领域对实时性与资源占用的双重需求,是嵌入式开发的优质选择。
二、cubemx配置
先建立CubeMx工程
配置RCC

配置SYS

串口配置USART1

然后配置GPIO口
这里我配置了PC13、PA3为output,用来接LED

之后设置好路径,导出工程文件
三、移植文件
获取uCOS-III源码
进入 Micrium 公司官网下载中心:http://micrium.com/downloadcenter/
选择ST系列,点击 View all STMicroelectronics,点击 STMicroelectronics STM32F107
之后按照提示注册下载即可。
1、整理文件夹
新建一个uC-BSP文件夹,将uCOS-CONFIG里的bsp.c bsp.h粘贴到uC-BSP文件夹


然后将以上文件夹粘贴到已建好的工程文件里

2、添加文件
之后打开工程,在里面添加文件
根据以下步骤添加

MDK-ARM\uC-CPU路径选择全部文件
MDK-ARM\uC-CPU\ARM-Cortex-M3\RealView路径选择全部文件


MDK-ARM\uC-LIB路径选择全部文件
MDK-ARM\uC-LIB\Ports\ARM-Cortex-M3\RealView路径选择全部文件

MDK-ARM\uCOS-III\Ports\ARM-Cortex-M3\Generic\RealView路径 选择全部路径

MDK-ARM\uCOS-III\Source路径下选中以下全部 .c .h 文件
MDK-ARM\uC-CONFIG路径下选中全部文件

MDK-ARM\uC-BSP路径下选中全部文件

3、导入文件路径
然后导入文件路径


四、更改代码
1、添加代码
另外添加两个新代码
bsp.h
#ifndef __BSP_H__
#define __BSP_H__
#include "stm32f1xx_hal.h"
void BSP_Init(void);
#endif
bsp.c
// bsp.c
#include "includes.h"
#define DWT_CR *(CPU_REG32 *)0xE0001000
#define DWT_CYCCNT *(CPU_REG32 *)0xE0001004
#define DEM_CR *(CPU_REG32 *)0xE000EDFC
#define DBGMCU_CR *(CPU_REG32 *)0xE0042004
#define DEM_CR_TRCENA (1 << 24)
#define DWT_CR_CYCCNTENA (1 << 0)
CPU_INT32U BSP_CPU_ClkFreq (void)
{
return HAL_RCC_GetHCLKFreq();
}
void BSP_Tick_Init(void)
{
CPU_INT32U cpu_clk_freq;
CPU_INT32U cnts;
cpu_clk_freq = BSP_CPU_ClkFreq();
#if(OS_VERSION>=3000u)
cnts = cpu_clk_freq/(CPU_INT32U)OSCfg_TickRate_Hz;
#else
cnts = cpu_clk_freq/(CPU_INT32U)OS_TICKS_PER_SEC;
#endif
OS_CPU_SysTickInit(cnts);
}
void BSP_Init(void)
{
BSP_Tick_Init();
MX_GPIO_Init();
}
#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void CPU_TS_TmrInit (void)
{
CPU_INT32U cpu_clk_freq_hz;
DEM_CR |= (CPU_INT32U)DEM_CR_TRCENA; /* Enable Cortex-M3's DWT CYCCNT reg. */
DWT_CYCCNT = (CPU_INT32U)0u;
DWT_CR |= (CPU_INT32U)DWT_CR_CYCCNTENA;
cpu_clk_freq_hz = BSP_CPU_ClkFreq();
CPU_TS_TmrFreqSet(cpu_clk_freq_hz);
}
#endif
#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TMR CPU_TS_TmrRd (void)
{
return ((CPU_TS_TMR)DWT_CYCCNT);
}
#endif
#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
CPU_INT64U CPU_TS32_to_uSec (CPU_TS32 ts_cnts)
{
CPU_INT64U ts_us;
CPU_INT64U fclk_freq;
fclk_freq = BSP_CPU_ClkFreq();
ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);
return (ts_us);
}
#endif
#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
CPU_INT64U CPU_TS64_to_uSec (CPU_TS64 ts_cnts)
{
CPU_INT64U ts_us;
CPU_INT64U fclk_freq;
fclk_freq = BSP_CPU_ClkFreq();
ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);
return (ts_us);
}
#endif
2、更改代码
打开startup_stm32f103xb.s文件
在以下位置处将PendSV_Handler改为OS_CPU_PendSVHandler,
SysTick_Handler改为OS_CPU_SysTickHandler


打开app_cfg.h文件
DEF_ENABLED 改为 DEF_DISABLED

#define APP_TRACE BSP_Ser_Printf 改为 #define APP_TRACE(void)

打开includes.h文件
在#include <bsp.h>下面添加 #include “gpio.h” #include “app_cfg.h”
将#include <stm32f10x_lib.h> 改为 #include “stm32f1xx_hal.h”

打开lib_cfg.h文件
修改为5(该处宏定义设置堆空间的大小,STM32F103C8T6的RAM只有20K,所以要改小一点)

打开usart.c文件,添加代码完成printf重定向
/* USER CODE BEGIN 1 */
typedef struct __FILE FILE;
int fputc(int ch,FILE *f){
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xffff);
return ch;
}
/* USER CODE END 1 */
在gpio.c文件中修改代码
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
/*Configure GPIO pin : PC13|PA3 */
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
修改main.c文件
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
#include "usart.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <includes.h>
#include "stm32f1xx_hal.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* 任务优先级 */
#define START_TASK_PRIO 3
#define LED0_TASK_PRIO 4
#define MSG_TASK_PRIO 5
#define LED1_TASK_PRIO 6
/* 任务堆栈大小 */
#define START_STK_SIZE 96
#define LED0_STK_SIZE 64
#define MSG_STK_SIZE 64
#define LED1_STK_SIZE 64
/* 任务栈 */
CPU_STK START_TASK_STK[START_STK_SIZE];
CPU_STK LED0_TASK_STK[LED0_STK_SIZE];
CPU_STK MSG_TASK_STK[MSG_STK_SIZE];
CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
/* 任务控制块 */
OS_TCB StartTaskTCB;
OS_TCB Led0TaskTCB;
OS_TCB MsgTaskTCB;
OS_TCB Led1TaskTCB;
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* 任务函数定义 */
void start_task(void *p_arg);
static void AppTaskCreate(void);
static void AppObjCreate(void);
static void led_pc13(void *p_arg);
static void send_msg(void *p_arg);
static void led_pa3(void *p_arg);
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
OS_ERR err;
OSInit(&err);
HAL_Init();
SystemClock_Config();
//MX_GPIO_Init(); 这个在BSP的初始化里也会初始化
MX_USART1_UART_Init();
/* 创建任务 */
OSTaskCreate((OS_TCB *)&StartTaskTCB, /* Create the start task */
(CPU_CHAR *)"start task",
(OS_TASK_PTR ) start_task,
(void *) 0,
(OS_PRIO ) START_TASK_PRIO,
(CPU_STK *)&START_TASK_STK[0],
(CPU_STK_SIZE) START_STK_SIZE/10,
(CPU_STK_SIZE) START_STK_SIZE,
(OS_MSG_QTY ) 0,
(OS_TICK ) 0,
(void *) 0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);
/* 启动多任务系统,控制权交给uC/OS-III */
OSStart(&err); /* Start multitasking (i.e. give control to uC/OS-III). */
}
void start_task(void *p_arg)
{
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
/* YangJie add 2021.05.20*/
BSP_Init(); /* Initialize BSP functions */
//CPU_Init();
//Mem_Init(); /* Initialize Memory Management Module */
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); //统计任务
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间
CPU_IntDisMeasMaxCurReset();
#endif
#if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候
//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif
OS_CRITICAL_ENTER(); //进入临界区
/* 创建LED0任务 */
OSTaskCreate((OS_TCB * )&Led0TaskTCB,
(CPU_CHAR * )"led_pc13",
(OS_TASK_PTR )led_pc13,
(void * )0,
(OS_PRIO )LED0_TASK_PRIO,
(CPU_STK * )&LED0_TASK_STK[0],
(CPU_STK_SIZE)LED0_STK_SIZE/10,
(CPU_STK_SIZE)LED0_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
/* 创建LED1任务 */
OSTaskCreate((OS_TCB * )&Led1TaskTCB,
(CPU_CHAR * )"led_pa3",
(OS_TASK_PTR )led_pa3,
(void * )0,
(OS_PRIO )LED1_TASK_PRIO,
(CPU_STK * )&LED1_TASK_STK[0],
(CPU_STK_SIZE)LED1_STK_SIZE/10,
(CPU_STK_SIZE)LED1_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
/* 创建MSG任务 */
OSTaskCreate((OS_TCB * )&MsgTaskTCB,
(CPU_CHAR * )"send_msg",
(OS_TASK_PTR )send_msg,
(void * )0,
(OS_PRIO )MSG_TASK_PRIO,
(CPU_STK * )&MSG_TASK_STK[0],
(CPU_STK_SIZE)MSG_STK_SIZE/10,
(CPU_STK_SIZE)MSG_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err); //挂起开始任务
OS_CRITICAL_EXIT(); //进入临界区
}
/**
* 函数功能: 启动任务函数体。
* 输入参数: p_arg 是在创建该任务时传递的形参
* 返 回 值: 无
* 说 明:无
*/
static void led_pc13 (void *p_arg)
{
OS_ERR err;
(void)p_arg;
BSP_Init(); /* Initialize BSP functions */
CPU_Init();
Mem_Init(); /* Initialize Memory Management Module */
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endif
CPU_IntDisMeasMaxCurReset();
AppTaskCreate(); /* Create Application Tasks */
AppObjCreate(); /* Create Application Objects */
while (DEF_TRUE)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
OSTimeDlyHMSM(0, 0, 1, 0,OS_OPT_TIME_HMSM_STRICT,&err);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
OSTimeDlyHMSM(0, 0, 1, 0,OS_OPT_TIME_HMSM_STRICT,&err);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
static void led_pa3 (void *p_arg)
{
OS_ERR err;
(void)p_arg;
BSP_Init(); /* Initialize BSP functions */
CPU_Init();
Mem_Init(); /* Initialize Memory Management Module */
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endif
CPU_IntDisMeasMaxCurReset();
AppTaskCreate(); /* Create Application Tasks */
AppObjCreate(); /* Create Application Objects */
while (DEF_TRUE)
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);
OSTimeDlyHMSM(0, 0, 3, 0,OS_OPT_TIME_HMSM_STRICT,&err);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);
OSTimeDlyHMSM(0, 0, 3, 0,OS_OPT_TIME_HMSM_STRICT,&err);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
static void send_msg (void *p_arg)
{
OS_ERR err;
(void)p_arg;
BSP_Init(); /* Initialize BSP functions */
CPU_Init();
Mem_Init(); /* Initialize Memory Management Module */
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endif
CPU_IntDisMeasMaxCurReset();
AppTaskCreate(); /* Create Application Tasks */
AppObjCreate(); /* Create Application Objects */
while (DEF_TRUE)
{
printf("hello uc/OS \r\n");
OSTimeDlyHMSM(0, 0, 2, 0,OS_OPT_TIME_HMSM_STRICT,&err);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/* USER CODE BEGIN 4 */
/**
* 函数功能: 创建应用任务
* 输入参数: p_arg 是在创建该任务时传递的形参
* 返 回 值: 无
* 说 明:无
*/
static void AppTaskCreate (void)
{
}
/**
* 函数功能: uCOSIII内核对象创建
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
static void AppObjCreate (void)
{
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
设置target

然后进行编译烧录
五、实验结果
两个灯,分别以1s和3s周期闪烁
效果
串口以2s周期发送“hello uc/OS!“
串口接收
六、实验心得
这次基于 HAL 库在 STM32F103C8T6 上移植 uC/OS-III,让我对 “理论到实践” 的距离有了真切体会。原本以为照着步骤复制文件、修改配置就能顺利完成,却在 CubeMX 时钟配置和源码路径导入时频频卡壳 —— 比如一开始没注意 HSE 时钟模式要选 “Crystal/Ceramic Resonator”,导致后续系统时钟初始化失败,这才意识到硬件配置与 RTOS 内核的联动远比想象中紧密。
移植过程中的 “小细节” 最磨人,也最让人成长。像是忘记将启动文件里的 SysTick_Handler 改为 OS_CPU_SysTickHandler,系统上电后直接无响应;还有没根据 STM32F103C8T6 的 20K RAM 调整 lib_cfg.h 的堆空间大小,编译时反复出现内存溢出报错。这些 “坑” 让我明白,RTOS 移植不是机械复刻,而是要结合硬件特性灵活调整,每一行代码修改都得对应底层逻辑。
当看到两个 LED 分别以 1 秒、3 秒周期稳定闪烁,串口每隔 2 秒弹出 “hello uc/OS” 时,那种成就感难以言喻。这不仅是功能的实现,更让我直观感受到了 RTOS 的优势 —— 要是用裸机开发,多个周期性任务需要靠定时器中断嵌套来协调,逻辑复杂还容易阻塞;而 uC/OS-III 的多任务调度,让每个任务独立运行又互不干扰,系统实时性和代码可读性都提升了不少。
这次实验也刷新了我对 “嵌入式开发严谨性” 的认知。比如编写 bsp.c 时,BSP_Tick_Init 函数里要根据 uC/OS-III 版本判断时钟节拍参数,少个条件编译就会导致 SysTick 初始化出错;导入文件路径时漏加 uC-LIB 的路径,就会出现一堆头文件找不到的错误。这些看似微小的疏漏,却能让整个移植功亏一篑,也让我养成了 “改代码前先想关联,改完后逐行检查” 的习惯。
这次移植不仅教会了我具体的技术方法,更打开了嵌入式开发的新思路。以前面对多任务场景总局限于裸机思维,现在知道可以借助 RTOS 高效解决问题。未来再遇到工业控制、智能硬件等复杂项目,我会更有底气用 uC/OS-III 这类 RTOS 提升开发效率,而这次 “踩坑又填坑” 的经历,也成了我嵌入式学习路上很宝贵的实践积累。
七、仓库地址
https://gitee.com/zhang-kaikaikaikai/rtos.git
八、参考博客
https://blog.csdn.net/qq_46467126/article/details/121441622
https://blog.csdn.net/junseven164/article/details/121534916
https://blog.csdn.net/weixin_43116606/article/details/105532222
https://blog.csdn.net/qq_45659777/article/details/121570886
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)