工程结构组织如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LCrgvXxD-1631626429715)(图片/图片1.bmp)]

其中 uCOSII_core 是uCOS的内核文件,与平台无关,所以无需修改。

在移植uCOS-II时我们只需要关注 uCOSII_port中三个文件和stm32f10x_it.c就可以了:

+++

第一个文件:os_cpu.h

1.定义与编译器相关的数据类型,无需修改

typedef unsigned char  BOOLEAN;typedef unsigned char    INT8U;             // Unsigned 8 bit quantity
typedef signed  char        INT8S;             // Signed  8 bit quantity
typedef unsigned short   INT16U;          // Unsigned 16 bit quantity
typedef signed  short       INT16S;          // Signed  16 bit quantity
typedef unsigned int        INT32U;         // Unsigned 32 bit quantity
typedef signed  int            INT32S;          // Signed  32 bit quantity
typedef float                       FP32;             // Single precision floating point
typedef double                  FP64;              // Double precision floating point
typedef unsigned int        OS_STK;          // Each stack entry is 32-bit wide
typedef unsigned int        OS_CPU_SR;   // Define size of CPU status register (PSR=32 bits)

2.因为CM3是32位宽的,所以OS_STK(堆栈的数据类型)被类型重定义为unsigned int;
因为CM3的状态寄存器(xPSR)是32位宽的,因此OS_CPU_SR被类型重定义为unsigned int;OS_CPU_SR是在OS_CRITICAL_METHOD方法3中保存cpu状态寄存器用的。在CM3中,移植OS_ENTER_CRITICAL(),OS_EXIT_CRITICAL()选方法3是最合适的。

#define OS_CRITICAL_METHOD    3
typedef unsigned int    OS_STK
typedef unsigned int    OS_CPU_SR

3.μC/OS-II定义了三种方法关闭和打开中断 (OS_CRITICAL_METHED=1,2,3),
通常情况下,我们都是选用的方法3,这里定义了两个宏来禁止和允许中断

#if OS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}
#define OS_EXIT_CRITICAL()    {OS_CPU_SR_Restore(cpu_sr);}
#endif

具体定义宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL(),其中OS_CPU_SR_Save() //关中断和OS_CPU_SR_Restore() //开中断是用汇编代码写的,代码在os_cpu_a.asm中。

4.定义栈的增长方向
#define OS_STK_GROWTH 1
置OS_STK_GROWTH为0,表示堆栈从下往上增长;置OS_STK_GROWTH为1,表示堆栈从上往下增长。

5.定义OS_TASK_SW()宏,任务级上下文切换
#define OS_TASK_SW() OSCtxSw()
任务级上下文切换(即任务切换)调用宏定义OS_TASK_SW()。因为上下文切换跟处理器有密切关系,OS_TASK_SW()实质上是调用汇编函数OSCtxSW() ,它在os_cpu_a.asm文件中定义。

6.注释掉如下函数,并添加void PendSV_Handler(void)的函数声明

#if OS_CRITICAL_METHOD == 3
OS_CPU_SR OS_CPU_SR_Save(void);
void    OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
#endifvoid    OSCtxSw(void);void    OSIntCtxSw(void);void    OSStartHighRdy(void);void    PendSV_Handler(void); // void        OS_CPU_PendSVHandler(void);
// void        OS_CPU_SysTickHandler(void);
// void        OS_CPU_SysTickInit(void);
// INT32U   OS_CPU_SysTickClkFreq(void);

申明几个函数,这里要注意最后四个函数需要注释掉,为什么呢?

  1. **OS_CPU_SysTickHandler()**定义在os_cpu_c.c中,是SysTick中断的中断处理函数,而stm32f10x_it.c,中已经有该中断函数的定义SysTick_Handler(),这里也就不需要了;
  2. **OS_CPU_SysTickInit()**定义在os_cpu_c.c中,用于初始化SysTick定时器,它依赖于OS_CPU_SysTickClkFreq(),而此函数我们自己会实现,所以注释掉;
  3. **OS_CPU_SysTickClkFreq()**定义在BSP.C (Micrium\Software\EvalBoards)中,而本文移植中并未用到BSP.C,后面我们会自己实现,因此可以把它注释掉。
  4. OS_CPU_PendSVHandler()在启动文件上,一般我们自己开发基于stm32芯片的软件,都会使用标准外设库CMSIS中提供的启动文件,而官方移植的启动文件却是自己写的,在两个文件init.s,vectors.s中 (Micrium\Software\EvalBoards\ST\STM3210B-EVAL\RVMDK)。init.s负责进入main(),vectors.s设置中断向量。OS_CPU_SysTickHandler和OS_CPU_PendSVHandler就是在vectors.s中被设置的。 我的移植是使用标准外设库CMSIS中startup_stm32f10x_md.s作为启动文件的,那该怎么在这个文件中设置OS_CPU_SysTickHandler呢,事实上在startup_stm32f10x_md.s文件中,PendSV中断向量名为PendSV_Handler,所以只需用PendSV_Handler把所有出现OS_CPU_PendSVHandler的地方替换掉就可以了。

我们有提到在startup_stm32f10x_md.s中我们有定义PendSV_Handler,其中PendSV_Handler函数在我们CM3中也有实现,就在stm32f10x_it.c和stm32f10x_it.h中,现在我们选择使用uCOS的PendSV_Handler函数,所以应该将stm32f10x_it.c和stm32f10x_it.h中的PendSV_Handler函数注释起来

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8wmyht1i-1631626429717)(图片/图片2.bmp)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UTGJIy10-1631626429719)(图片/图片7.bmp)]

+++

第二个文件:os_cpu_c.c

ucosii移植时需要我们写10个相当简单的C函数

OSInitHookBegin()
OSInitHookEnd()
OSTaskCreateHook()
OSTaskDelHook()
OSTaskIdleHook()
OSTaskStatHook()
OSTaskStkInit()
OSTaskSwHook()
OSTCBInitHook()
OSTimeTickHook()

这些函数除了OSTaskStkInit(),都是一些hook函数。这些hook函数如果不使能的话,都不会用上,也都比较简单,看看就应该明白了,所以就不介绍

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;        /*  R1     */                           *(--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);
}

xPSR,PC,LR,R12,R3-R0被自动保存到栈中的,R11-R4如果需要保存,只能手工保存。因此OSTaskStkInit()的工作就是在任务自己的栈中保存cpu的所有寄存器。这些值里R1-R12都没什么意义,这里用相应的数字代号(如R1用0x01010101)主要是方便调试。
其他的几个函数都可以空着,例如:

#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0)
void OSTaskSwHook (void)
{
#if OS_APP_HOOKS_EN > 0App_TaskSwHook();
#endif
}
#endif

注释掉其中的一些内容
把OS_CPU_SysTickHandler(), OS_CPU_SysTickInit()注释掉
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z97UT5p5-1631626429719)(图片/图片3.bmp)]

把上面这些宏定义也注释掉,因为它们都用于OS_CPU_SysTickHandler(), OS_CPU_SysTickInit()。

++++

第三个文件:os_cpu_a.asm

​ 在os_cpu_a.asm中定义了4个与处理器相关的汇编函数,我们是从micrium网站上下载官方移植版本,所以其中的函数都已经实现了,如果需要了解的可以参照《Cortex-M3权威指南》。
我们在注释掉os_cpu.h中的OS_CPU_PendSVHandler() 提到需用PendSV_Handler把所有出现OS_CPU_PendSVHandler的地方替换掉,而这些需要替换掉的内容就在os_cpu_a.asm中,只需将下面的地方替换就好了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OfdTieiU-1631626429720)(图片/图片4.bmp)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-du3X2ZGp-1631626429722)(图片/图片5.bmp)]

第四个文件:stm32f10x_it.c

在前面修改os_cpu.h 文件时注释过一个OS_CPU_SysTickHandler(),是因为这个函数是提供系统时钟中断的,而在我们CM3中已经有了自己的系统时钟中断函数,就是stm32f10x_it.c的void SysTick_Handler(void),在这里只需要把OS_CPU_SysTickHandler()的内容复制给SysTick_Handler()即可(记得把头文件包含进来):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-44tGlxuE-1631626429722)(图片/图片6.bmp)]

++++

到这里为止我们的移植就算是完成了,接下来任务就是在app.c文件中实现我们的测试程序了

#include "includes.h"static OS_STK task_led1_stk[LED1_TASK_STK_SIZE];static void systick_init(void)
{RCC_ClocksTypeDef rcc_clock;
RCC_GetClocksFreq(&rcc_clock);
SysTick_Config(rcc_clock.HCLK_Frequency/OS_TICKS_PER_SEC);
}void LED1_Tast(void *p_arg)
{p_arg=p_arg;while(1)
{GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET);OSTimeDlyHMSM(0, 0,1,0);GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);OSTimeDlyHMSM(0, 0,1,0);
}
int main(void)
{BSP_Init();OSInit();systick_init();OSTaskCreate(LED1_Tast,(void *)0,&task_led1_stk[LED1_TASK_STK_SIZE-1],LED1_TASK_PRIO);  OSStart();return 0;
}

如果LED灯出现闪烁的话就大功告成了!

UCOS-II移植的基本操作相关推荐

  1. UCOS II移植到STM32F103开发板

    早期嵌入式开发没有嵌入式操作系统的概念 ,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念.通常把程序分为两部分:前台系统和后台系统. 简单的小系统通常是前后台系统,这样的程序包 ...

  2. 用C语言写ucos中断服务程序,在ARM处理器上移植uCOS II的中断处理

    uCOS II是一个源码公开.可移植.可固化.可剪裁和抢占式的实时多任务操作系统,其大部分源码是用ANSI C编写,与处理器硬件相关的部分使用汇编语言编写.总量约200行的汇编语言部分被压缩到最低限度 ...

  3. 51单片机中使用ucos ii的优缺点(好文)

    摘要:近年来,在单片机系统中嵌入操作系统已经成为人们越来越关心的一个话题.本文通过对一种源码公开的嵌入式实时操作系统ucos ii的分析,以51系列单片机为例,阐述了在单片机中使用该嵌入式操作系统的优 ...

  4. lwip协议栈在linux运行,LwIP协议栈在uCOS II下的实现

    1.概述: LwIP协议栈在设计时就考虑到了将来的移植问题,因此把所有与硬件.OS.编译器相关的部份独立出来,放在ucosii&LwIPsource etlwiparch目录下.因此LwIP在 ...

  5. 基于STM32的简易示波器的UCOS II嵌入式实时操作系统实现

    基于STM32的简易示波器的UCOS II嵌入式实时操作系统实现 在基于STM32的示波器的实现的基础上,在STM32上移植UCOS II嵌入式实时操作系统. 在UCOS II操作系统中将各个功能分发 ...

  6. ucos II任务管理之一:挂起任务

    Ucos II 任务管理之一 创建好了任务之后,就已经初步跨进了ucos II 的编程了.随着进一步的编程,发现学会创建了任务还是不够的. 在我的项目里,需要实现485通信功能,我创建了任务1用于串口 ...

  7. ucos II任务管理之三:删除任务

    ucos II任务管理之三:删除任务 有了前面的经历之后,mcu21决定全面地学习了任务的管理.这样在项目编程中才能做到"信手拈来". 在ucos II 里,创建一个任务之后,可以 ...

  8. ucos II 创建第一个任务之一

    Ucos II创建第一个任务 我们已经从远处欣赏过ucos II 的身材,现在可以近距离地欣赏Ucos II性感的局部了. 任务是什么? 有一句话:CPU不同的时刻段总是在执行着优先级最高的任务.所以 ...

  9. ucos ii堆栈大小检测

    在使用ucos ii时经常会有疑问,这个堆栈该给多大,虽然ucos ii 自带了任务堆栈检测,但是我觉得太麻烦了,而且还会占用资源,我投机取巧的使用内存是否为0来判断堆栈是否使用过,进而检测出堆栈的最 ...

  10. IAR中移植UCOS II系统以及sourceInsight 使用

    ucos 学习笔记 1 sourceInsight 使用 CSDN参考链接 新建工程 第一步:project中new project 第二步:在高亮部分输入工程的地址,工程文件夹与IAR工程文件夹放在 ...

最新文章

  1. sicily 1259 Sum of Consecutive Primes
  2. python将字符转换为字典
  3. php进销存 带apk,php进销存配送管理系统,支持h5/ios/android/微信小程序
  4. Python爬虫学习二
  5. 访问数据库_Lua 数据库访问
  6. Juniper Firewall多进单出配制实例
  7. C++ 常用算法之遍历
  8. linux下如何使用sftp命令【转】
  9. python和财务管理的区别与联系_会计管理与财务管理区别与联系
  10. React+Webpack+Antd+Babel 兼容低版本浏览器(下)
  11. HDU 4762 Cut the Cake
  12. 【VMware vSAN 7.0】5.4.2 创建 vSAN 集群—我们有软硬件解决方案
  13. 软件工程毕业设计题目推荐50例
  14. python中re模块的group()和groups()
  15. 外国参考文献计算机类,计算机毕业设计外文参考文献.docx
  16. LCD LVDS的一些术语定义
  17. 【EMC电磁兼容】01.12——差模与共模
  18. JAVA基础_ Scanner扫描仪
  19. 先试试这一招,再决定是否要撬开拉杆箱的密码锁——巧开密码锁
  20. java,png,jpg,如何合并图片进行盖章,并且对印章的位置进行定位。

热门文章

  1. 2022-2028年全球与中国氮化镓半导体器件行业市场深度调研及投资预测分析
  2. 数据库实例名查询linux,数据库名,数据库实例名,数据库域名,操作系统环境变量...
  3. 详细教程:如何用H5制作邀请函
  4. Linux内核同步机制之--RCU基础
  5. 我为什么选择产品经理
  6. 【Ubuntu20.04】【验证可行】修改切换输入法的快捷键
  7. c语言编写金字塔——数学思路总结
  8. Devoxx:学习者之旅
  9. 应聘时漂亮的回答(转自CSDN)
  10. 利用免费SEO优化工具提升网站整体收录