UCOS-II移植的基本操作

工程结构组织如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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);
#endif

 void    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 > 0
 App_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灯出现闪烁的话就大功告成了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值