身为一个电子信息工程的学生, 临近毕业了才开始走进嵌入式的大门, 是不是有点晚了, 这次要用rtos主要是因为想用在物联网家居项目上.废话少说, 开始我的ucosii的移植之路吧, 参照正点原子的移植教程, 其实挺简单的.
实验开发板:信盈达stm32f103zet6(其实发现市面上的开发板都一大抄, 有几家公式来我们学校实训, 原理图都和原子的差不多)
实验参看教程:STM32F1 UCOS开发手册_V2.0.pdf
实验所用例程: 正点原子的ucosii移植例程
一. 移植准备工作:
1. 首先的准备移植所需的基础工程, 我用的原子的跑马灯实验, 只是把led端口改了一下而已(后文会上传)
2. UCOS II源码:获取途径有:
first:最权威, 最靠谱的: 从官网上下载:https://www.micrium.com/(注: 里面有ucos的源码, 同时也有在各个平台上移植好的源码, 不过我建议都是学电子的人, 什么都要会自己移植, 一开始会很苦, 但是学会后就那么回事, 始终不要被别人牵着鼻子走, 建议下不要移植好的源码)
second: 用原子提供的源码(ps: 因为在学校, 不方便下载, 就用原子的了, 后面我会上传资源)
二.移植步骤:
1.开始撸起袖子开始移植啦!!!
在跑马灯的工程中新建UCOSII文件夹, 再建子文件夹CONFIG, CORE, PORT
2.向CORE文件夹中添加文件
在CORE文件夹中添加UCOSII源码, 我们打开ucosii的源码Source文件夹, 里面一共有14个文件, 除了os_cfg_r.h os_dbg_r.c 这两个文件外, 我们奖其他的文件都复制到我们的工程中UCOSII中的CORE文件夹下.
3.向CONFIG文件夹中添加文件
在CONFIG文件夹中添加 includes.h和os_cfg.h. 这两个文件我是从原子的例程中拷过来的. 因为这两个文件涉及到系统裁剪等等, 目前还没学, 只能做一次伸手党了, 资源在后面的连接中,添加后如图所示
4.向PORT文件夹中添加文件
添加的文件如下图所示, 这些文件也是从例程中来的, copy一下吧.
4.将与ucosii有关的文件添加到工程中
我们在工程分组中添加三个分组, UCOSII-CORE, UCOSII-PORT, UCOSII-CONFIG.如下图所示
分别向UCOSII-CORE, UCOSII-PORT, UCOSII-CONFIG这中添加如下图所示的文件,
注意:前外不要将ucos_ii.c文件添加到UCOSII-CORE分组中!!! 否则编译以后会提示好多重复定义的错误!
最后添加相应的头文件路径, 如图所示:(注, mdk不会添加头文件路径的请百度)
到这一步我们可以编译一下整个工程了, 结果提示好多错误, 但是错误都是不能打开"app_cfg.h"
追踪错误的源头后, 发现是ucos_ii.h头文件中添加了app_cfg.h这个头文佳, 但是这个头文佳并没有实现, 所以屏蔽即可, 添加includes.h
因为重复定义了PendSV_Handler这个函数, 这里将stm32f10x_it.c文件的该函数屏蔽掉, 我们再编译一下工程发现没错了, 但是我们的移植还没成功
5. 修改sys.h头文佳
打开sys.h文件, 里面有个SYSTEM_SUPPORT_UCOS的宏定义, 默认定义为0 , 0不支持ucos, 我们将其改为1, 再次编译工程, 发现提示重复定义了SysTick_Handler函数,
同样, 我们将stm32f10x_it.c文件中的中断函数SysTick_Handler屏蔽掉, 编译后发现没错误了,
三.测试程序
因为我现在还不会使用ucos的api 只好用原子的例程了, main函数代码如下:
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "includes.h"
/************************************************
ALIENTEK战舰STM32开发板UCOS实验
UCOSII移植
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司
作者:正点原子 @ALIENTEK
************************************************/
//START 任务
//设置任务优先级
#define START_TASK_PRIO 10 ///开始任务的优先级为最低
//设置任务堆栈大小
#define START_STK_SIZE 128
//任务任务堆栈
OS_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *pdata);
//LED0任务
//设置任务优先级
#define LED0_TASK_PRIO 7
//设置任务堆栈大小
#define LED0_STK_SIZE 128
//任务堆栈
OS_STK LED0_TASK_STK[LED0_STK_SIZE];
//任务函数
void led0_task(void *pdata);
//LED1任务
//设置任务优先级
#define LED1_TASK_PRIO 6
//设置任务堆栈大小
#define LED1_STK_SIZE 128
//任务堆栈
OS_STK LED1_TASK_STK[LED1_STK_SIZE];
//任务函数
void led1_task(void *pdata);
//浮点测试任务
#define FLOAT_TASK_PRIO 5
//设置任务堆栈大小
#define FLOAT_STK_SIZE 128
//任务堆栈
//如果任务中使用printf来打印浮点数据的话一点要8字节对齐
__align(8) OS_STK FLOAT_TASK_STK[FLOAT_STK_SIZE];
//任务函数
void float_task(void *pdata);
int main(void)
{
delay_init(); //延时初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置
uart_init(115200); //串口波特率设置
LED_Init(); //LED初始化
OSInit(); //UCOS初始化
OSTaskCreate(start_task,(void*)0,(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO); //创建开始任务
OSStart(); //开始任务
}
//开始任务
void start_task(void *pdata)
{
OS_CPU_SR cpu_sr=0;
pdata=pdata;
OSStatInit(); //开启统计任务
OS_ENTER_CRITICAL(); //进入临界区(关闭中断)
OSTaskCreate(led0_task,(void*)0,(OS_STK*)&LED0_TASK_STK[LED0_STK_SIZE-1],LED0_TASK_PRIO);//创建LED0任务
OSTaskCreate(led1_task,(void*)0,(OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],LED1_TASK_PRIO);//创建LED1任务
OSTaskCreate(float_task,(void*)0,(OS_STK*)&FLOAT_TASK_STK[FLOAT_STK_SIZE-1],FLOAT_TASK_PRIO);//创建浮点测试任务
OSTaskSuspend(START_TASK_PRIO);//挂起开始任务
OS_EXIT_CRITICAL(); //退出临界区(开中断)
}
//LED0任务
void led0_task(void *pdata)
{
while(1)
{
LED0=0;
delay_ms(300);
LED0=1;
delay_ms(300);
}
}
//LED1任务
void led1_task(void *pdata)
{
while(1)
{
LED1=0;
delay_ms(300);
LED1=1;
delay_ms(300);
}
}
//浮点测试任务
void float_task(void *pdata)
{
OS_CPU_SR cpu_sr=0;
static float float_num=0.01;
while(1)
{
float_num+=0.01f;
OS_ENTER_CRITICAL(); //进入临界区(关闭中断)
printf("float_num的值为: %.4f\r\n",float_num); //串口打印结果
OS_EXIT_CRITICAL(); //退出临界区(开中断)
delay_ms(500);
}
}
好了, 终于能看到移植成功的标志了, led0与led1同时闪速, 并且串口有打印浮点数的信息.
本实验所需例程链接: https://download.csdn.net/download/fourleafcloverllls/10716726 博主qq:1372090604 欢迎与我交流