uCOS 移植

Pursue

下载uCOS源码

uCOS官网:https://www.silabs.com/developer-tools/micrium

Github仓库:https://github.com/weston-embedded/uC-OS3

实验所需uCOS源码:https://wwrx.lanzoum.com/iFtsE2vhvezg

正点原子开发指南:https://wwrx.lanzoum.com/i6IgV2vh99kj

本次实验源码:https://wwrx.lanzoum.com/i3cyK2vquoze

HAL基本工程

stm32cubemx建立cmake工程,打开串口1,板载LED。

stm-1u1.png

stm-1u2.png

生成MDK工程

程序测试

重写printf函数

[printf]

测试

在main.c中引用<stdio.h>,并在while函数中添加以下代码:

1
2
3
HAL_Delay(500);
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
printf("hello %.2f\n",3.1415926);

编译并下载

打开串口助手,led每500ms闪烁

stm-1u3.png

移植uCOS

引用.c文件

在工程目录下新建文件夹uCOS

stm-1u4.png

打开基础工程,新建四个分组,分别为 uCOS/BSPuCOS/CPUuCOS/LIBuCOS/OS,如下图所示:

stm-1u5.png

uCOS/BSP

uC-CPU/BSP/Template/bsp_cpu.c

uC-OS3/Template/bsp_os_dt.c

stm-1u6.png

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

stm-1u7.png

uCOS/LIB

uC-LIB/lib_ascii.c

uC-LIB/lib_math.c

uC-LIB/lib_mem.c

uC-LIB/lib_str.c

stm-1u8.png

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 源文件

stm-1u9.png

添加.h文件

stm-1u10.png

替换中断服务函数

在 µC/OS-III 的移植过程中会遇到两个重要的中断,分别为 SysTick 中断和 PendSV 中断, 这两个中断分别用于为 µC/OS-III 内核提供时基和任务切换。HAL 库会默认定义 SysTick 和 PendSV 的中断服 务函数,因此在移植 µC/OS-III 的时候,需要将 HAL 库默认定义的 SysTick 和 PendSV 中断服 务函数,替换为 µC/OS-III 提供了中断服务函数。

将启动文件中的PendSV_HandlerSysTick_Handler 修改为OS_CPU_PendSVHandlerOS_CPU_SysTickHandler。分别在第7475行和215210行左右。

stm-1u11.png

stm-1u12.png

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

stm-1u13.png

编译,0错误0警告

测试uCOS

新建用户文件夹

stm-1u14.png

在keil中引用

stm-1u15.png

头文件路径

stm-1u16.png

添加测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#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++;
}
}


1
2
3
4
5
6
7
8
9
10
11
#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函数。

stm-1u17.png

实验结果

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

stm-1u18.png

评论