1. uCOS移植
下载uCOS源码
uCOS官网、 Github仓库、 实验所需uCOS源码、 正点原子开发指南、 本次实验源码。
HAL基本工程
stm32cubemx建立cmake工程,打开串口1,板载LED。


生成MDK工程
程序测试
重写printf函数
测试
在main.c中引用
HAL_Delay(500);
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
printf("hello %.2f\n",3.1415926);
编译并下载
打开串口助手,led每500ms闪烁

移植uCOS
引用.c文件
在工程目录下新建文件夹uCOS。

打开基础工程,新建四个分组,分别为 uCOS/BSP、uCOS/CPU、uCOS/LIB 和 uCOS/OS,如下图所示:

uCOS/BSP
uC-CPU/BSP/Template/bsp_cpu.c
uC-OS3/Template/bsp_os_dt.c

uCOS/CPU
uC-CPU/ARM-Cortex-M/ARMv7-M/ARM/cpu_a.asm
uC-CPU/ARM-Cortex-M/ARMv7- M/cpu_c.c
uC-CPU/cpu_core.c

uCOS/LIB
uC-LIB/lib_ascii.c
uC-LIB/lib_math.c
uC-LIB/lib_mem.c
uC-LIB/lib_str.c

uCOS/OS
uC-OS3/Cfg/Template/os_app_hooks.c
uC-OS3/Ports/ARM-Cortex-M/ARMv7- M/ARM/os_cpu_a.asm
uC-OS3/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c
uC-OS3/Source目录下除__dbg_uCOS-III.c外的所有 C 源文件

添加.h文件

替换中断服务函数
在 µC/OS-III 的移植过程中会遇到两个重要的中断,分别为 SysTick 中断和 PendSV 中断, 这两个中断分别用于为 µC/OS-III 内核提供时基和任务切换。HAL 库会默认定义 SysTick 和 PendSV 的中断服 务函数,因此在移植 µC/OS-III 的时候,需要将 HAL 库默认定义的 SysTick 和 PendSV 中断服 务函数,替换为 µC/OS-III 提供了中断服务函数。
将启动文件中的PendSV_Handler和SysTick_Handler 修改为OS_CPU_PendSVHandler和OS_CPU_SysTickHandler。分别在第74~75行和215~210行左右。


µC/CPU 的配置文件的路径在 uC-CPU/Cfg/Template/cpu_cfg.h,打开该文件,并将配置文件中用于配置配置 CPU 中断优先级寄存 器使用位数的宏开关置 1 即可

编译,0错误0警告
测试uCOS
新建用户文件夹

在keil中引用

头文件路径

添加测试代码
#include <stdio.h>
#include "rtos.h"
/**
* start_task任务配置
*/
#define START_TASK_PRIO 5 /* 任务优先级 */
#define START_TSAK_STACK_SIZE 256 /* 任务栈大小 */
CPU_STK satrt_task_stack[START_TSAK_STACK_SIZE]; /* 任务栈 */
OS_TCB start_task_tcb; /* 任务控制块 */
void start_task (void *p_arg); /* 任务函数 */
/**
* led_task任务配置
*/
#define LED_TASK_PRIO 6 /* 任务优先级 */
#define LED_TSAK_STACK_SIZE 256 /* 任务栈大小 */
CPU_STK led_task_stack[LED_TSAK_STACK_SIZE]; /* 任务栈 */
OS_TCB led_task_tcb; /* 任务控制块 */
static void led_task (void *p_arg); /* 任务函数 */
/**
* uart_task任务配置
*/
#define UART_TASK_PRIO 6 /* 任务优先级 */
#define UART_TSAK_STACK_SIZE 256 /* 任务栈大小 */
CPU_STK uart_task_stack[UART_TSAK_STACK_SIZE]; /* 任务栈 */
OS_TCB uart_task_tcb; /* 任务控制块 */
static void uart_task (void *p_arg); /* 任务函数 */
/**
* @brief uCOS入口函数
* @retval 无
*/
void OS_StartScheduler(void)
{
OS_ERR err;
/* 初始化uCOS-III */
OSInit(&err);
/* 创建 start_task */
OSTaskCreate((OS_TCB *) &start_task_tcb,
(CPU_CHAR*) "start_task",
(OS_TASK_PTR) start_task,
(void*) 0,
(OS_PRIO) START_TASK_PRIO,
(CPU_STK*) &satrt_task_stack[0],
(CPU_STK_SIZE) START_TSAK_STACK_SIZE/10,
(CPU_STK_SIZE) START_TSAK_STACK_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);
/* 开启任务调度 */
OSStart(&err);
}
void start_task (void *p_arg)
{
OS_ERR err;
CPU_INT32U cnts;
CPU_Init();
/* 根据配置的节拍频率配置 SysTick */
cnts = HAL_RCC_GetSysClockFreq() / OS_CFG_TICK_RATE_HZ;
OS_CPU_SysTickInit(cnts);
/* 创建 led_task */
OSTaskCreate((OS_TCB *) &led_task_tcb,
(CPU_CHAR*) "led_task",
(OS_TASK_PTR) led_task,
(void*) 0,
(OS_PRIO) LED_TASK_PRIO,
(CPU_STK*) &led_task_stack[0],
(CPU_STK_SIZE) LED_TSAK_STACK_SIZE/10,
(CPU_STK_SIZE) LED_TSAK_STACK_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);
/* 创建 uart_task */
OSTaskCreate((OS_TCB *) &uart_task_tcb,
(CPU_CHAR*) "uart_task",
(OS_TASK_PTR) uart_task,
(void*) 0,
(OS_PRIO) UART_TASK_PRIO,
(CPU_STK*) &uart_task_stack[0],
(CPU_STK_SIZE) UART_TSAK_STACK_SIZE/10,
(CPU_STK_SIZE) UART_TSAK_STACK_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);
/* 删除start_sask */
OSTaskDel((OS_TCB *)0, &err);
}
/**
* @brief led_task
* @param p_arg: 传入参数(未用到)
* @retval 无
*/
static void led_task (void *p_arg)
{
OS_ERR err;
while (1)
{
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
OSTimeDly(1000,OS_OPT_TIME_DLY,&err);
}
}
/**
* @brief uart_task
* @param p_arg: 传入参数(未用到)
* @retval 无
*/
static void uart_task (void *p_arg)
{
OS_ERR err;
uint8_t i = 0;
while (1)
{
OSTimeDly(1000,OS_OPT_TIME_DLY,&err);
if (i < 10)
{
printf("hello world! %d\n",i);
}
else
{
printf("task deleted\n");
OSTaskDel(NULL,&err);
}
i++;
}
}
#ifndef __RTOS_H
#define __RTOS_H
#include <cpu.h>
#include <os.h>
#include "main.h"
void OS_StartScheduler(void);
#endif
在main.c中引用#include "rtos.h",在while(1)前添加OS_StartScheduler()。程序将由uCOS接管,并不会运行while函数。

实验结果
板载LED灯每秒闪烁一次,并且串口每秒发送一次,当发送10次时停止发送
