完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
1.UCOSII简介
UCOSII 是一个可以基于ROM 运行的、可裁减的、抢占式、实时多任务内核,具有高度可 移植性,特别适合于微处理器和控制器,是和很多商业操作系统性能相当的实时操作系统 (RTOS)。 UCOSII 是专门为计算机的嵌入式应用设计的, 绝大部分代码是用C 语言编写的。CPU 硬 件相关部分是用汇编语言编写的、总量约200 行的汇编语言部分被压缩到最低限度,为的是便 于移植到任何一种其它的CPU 上。用户只要有标准的ANSI 的C 交叉编译器,有汇编器、连 接器等软件工具,就可以将UCOSII 嵌人到开发的产品中。UCOSII 具有执行效率高、占用空间 小、实时性能优良和可扩展性强等特点, 最小内核可编译至 2KB 。UCOSII 已经移植到了几 乎所有知名的CPU 上。 UCOSII体系结构如图所示 从上图可以看出,UCOSII 的移植,我们只需要修改:os_cpu.h、os_cpu_a.asm 和os_cpu.c 等三个文件,其中:os_cpu.h,进行数据类型的定义,以及处理器相关代码和几个函数原 型;os_cpu_a.asm,是移植过程中需要汇编完成的一些函数,主要就是任务切换函数;os_cpu.c,定义一些用户HOOK函数。 2.UCOSII移植具体步骤 新建基础工程,这里以跑马灯工程为例。 UCOSII移植具体步骤 1.在基础工程下建立相应的文件夹:CONFIG,CORE,PORT 新建UCOSII文件夹 UCOSII文件夹下新建三个文件夹 2.向core文件夹添加UCOSII的源码 在这个路径下,找到UCOSII的源码,也就是正点原子所带的软件资料: 6,软件资料2,UCOS学习资料UCOSII资料UCOS II源码MicriumSoftwareuCOS-IISource 将上面所有文件复制到CORE文件夹下,复制完的CORE文件夹下内容: 3.向CONFIG文件添加内容 此处的内容需要在该路径下找到,同样为正点原子所带的资料 4,程序源码3,扩展例程4,UCOS扩展例程例1-1 UCOSII移植UCOSIICONFIG 添加好文件的CONFIG文件夹 4.向PORT文件夹下添加文件 文件路径: 4,程序源码3,扩展例程4,UCOS扩展例程例1-1 UCOSII移植UCOSIIPORT 添加完的PORT文件夹 5.将上述三个文件添加到工程中 打开工程 点击Manage Project Items,新建三个分组:UCOSII-CORE,UCOSII-CONFIG,UCOSII-PORT 向分组中添加文件 UCOSII-CORE分组添加如下,但是需要删除掉ucos_ii.c文件,否则会报错。 删除掉ucos_ii.c文件之后 UCOSII-PORT分组添加如下 只需要添加如下三个文件os_cpu.h和os_cpu_a.asm和os_cpu_c.c UCOSII-CONFIG分组添加如下 添加includes.h和os_cfg.h文件 添加完成后会发现工程目录下多了三个文件夹 但是我们发现UCOSII-CORE文件下都是加锁的 解决办法是:找到CORE文件夹,更改文件夹属性:去掉只读 回过头来查看发现文件枷锁已经去掉 下面需要将路径包含进来 点击魔法棒,选择C/C++,找到include paths 点击后面的添加按钮 添加进来CORE,PORT,CONFIG文件 下面进行编译,发现报错 ..UCOSIICOREucos_ii.h(44): error: #5: cannot open source input file "app_cfg.h": No such file or directory 双击该错误,进入到ucos_ii.h文件,找到该头文件,由于我们不需要该头文件,注释掉即可 然后再次编译 又发现另一个错误:PendSV_Handler 函数被重定义 ..OBJLED.axf: Error: L6200E: Symbol PendSV_Handler multiply defined (by os_cpu_a.o and stm32f10x_it.o). 解决办法:删除其中一个定义,由于汇编语言执行起来更快,所以删除stm32f10x_it.c文件下PendSV_Handler 函数的定义,这里采用注释掉的方法 先找到重定义的地方 os_cpu_a.asm这是一个汇编文件 在stm32f10x_it.c文件下 解决:注释掉 再次编译,发现没有错误 6.修改sys.h文件 打开该文件:位于SYSTEM文件夹下,找到sys.c文件 右击sys.h选择Open document sys.h 将SYSTEM_SUPPORT_OS 改为1,表示支持UCOS系统 修改前: 修改后: 再次编译,有报错:还是重定义的问题,同样的,这里我们还是注释掉stm32f10x_it.c文件下SysTick_Handler 函数 ..OBJLED.axf: Error: L6200E: Symbol SysTick_Handler multiply defined (by delay.o and stm32f10x_it.o). 再次编译发现没有错误 这里需要注意的是os_cpu_c.h文件夹下的OSTaskStkInit函数,当移植时发现和下面的不一致时,需要替换成下面的OSTaskStkInit函数。 /* ********************************************************************************************************* * INITIALIZE A TASK'S STACK * * Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the * stack frame of the task being created. This function is highly processor specific. * * Arguments : task is a pointer to the task code * * p_arg is a pointer to a user supplied data area that will be passed to the task * when the task first executes. * * ptos is a pointer to the top of stack. It is assumed that 'ptos' points to * a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then * 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if * OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address * of the stack. * * opt specifies options that can be used to alter the behavior of OSTaskStkInit(). * (see uCOS_II.H for OS_TASK_OPT_xxx). * * Returns : Always returns the location of the new top-of-stack once the processor registers have * been placed on the stack in the proper order. * * Note(s) : 1) Interrupts are enabled when your task starts executing. * 2) All tasks run in Thread mode, using process stack. ********************************************************************************************************* */ OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) { OS_STK *stk; (void)opt; /* 'opt' is not used, prevent warning */ stk = ptos; /* Load stack pointer */ /* Registers stacked as if auto-saved on exception */ *(stk) = (INT32U)0x01000000L; /* xPSR */ *(--stk) = (INT32U)task; /* Entry Point */ *(--stk) = (INT32U)0xFFFFFFFEL; /* R14 (LR) (init value will cause fault if ever used)*/ *(--stk) = (INT32U)0x12121212L; /* R12 */ *(--stk) = (INT32U)0x03030303L; /* R3 */ *(--stk) = (INT32U)0x02020202L; /* R2 */ *(--stk) = (INT32U)0x01010101L; /* R1 */ *(--stk) = (INT32U)p_arg; /* R0 : argument */ /* Remaining registers saved on process stack */ *(--stk) = (INT32U)0x11111111L; /* R11 */ *(--stk) = (INT32U)0x10101010L; /* R10 */ *(--stk) = (INT32U)0x09090909L; /* R9 */ *(--stk) = (INT32U)0x08080808L; /* R8 */ *(--stk) = (INT32U)0x07070707L; /* R7 */ *(--stk) = (INT32U)0x06060606L; /* R6 */ *(--stk) = (INT32U)0x05050505L; /* R5 */ *(--stk) = (INT32U)0x04040404L; /* R4 */ return (stk); } 3.移植后的测试 下面进行UCOSII操作系统的测试 将下面代码复制到main.c中,替换掉原来的代码 #include "led.h" #include "delay.h" #include "sys.h" #include "usart.h" #include "includes.h" //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 64 //任务堆栈 OS_STK LED0_TASK_STK[LED0_STK_SIZE]; //任务函数 void led0_task(void *pdata); //LED1任务 //设置任务优先级 #define LED1_TASK_PRIO 6 //设置任务堆栈大小 #define LED1_STK_SIZE 64 //任务堆栈 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(80); LED0=1; delay_ms(100); } } //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的值为: %.4frn",float_num); //串口打印结果 OS_EXIT_CRITICAL(); //退出临界区(开中断) delay_ms(500); } } 开发板出现led灯的交替闪烁, 再进行串口测试,也就是浮点测试:每个500ms进行+0.01的操作 至此,UCOSII操作系统移植成功。 4.总结 1) 移植UCOSII 要想UCOSII在STM32正常运行,首先是需要移植UCOSII,正点原子提供的SYSTEM文件夹里面的系统函数直接支持UCOSII,只需要在sys.h文件里面将:SYSTEM_SUPPORT_UCOS宏定义改为1,即可通过delay_init函数初始化UCOSII的系统时钟节拍,为UCOSII提供时钟节拍。 2) 编写任务函数并设置其堆栈大小和优先级等参数。 编写任务函数,以便UCOSII调用。 设置函数堆栈大小,需要根据函数的需求来设置,如果任务函数的局部变量多,嵌套层数多,那么相应的堆栈就得大一些,如果堆栈设置小了,很可能出现的结果就是CPU进入HardFault,遇到这种情况,就必须把堆栈设置大一点了。另外,有些地方还需要注意堆栈字节对齐的问题,如果任务运行出现莫名其妙的错误(比如用到sprintf出错),请考虑是不是字节对齐的问题。 设置任务优先级,这个需要根据任务的重要性和实时性设置,记住高优先级的任务有优先使用CPU的权利。 3) 初始化UCOSII,并在UCOSII中创建任务 调用OSInit初始化UCOSII,通过调用OSTaskCreate函数创建任务。 4) 启动UCOSII 调用OSStart启动UCOSII。 通过以上4个步骤,UCOSII就开始在STM32上面运行。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1874 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1658 浏览 1 评论
1143 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
759 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1720 浏览 2 评论
1963浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
789浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
611浏览 3评论
628浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
590浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-11 15:13 , Processed in 0.649603 second(s), Total 47, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号