手把手教你在MDK编译环境下移植基于STM32的UCOSII嵌入式系统

准备资料:

    Micrium官网上已经有官方移植版本。但这些版本具体是怎么移植出来的,现在来讲讲我的移植过程,希望对读者有帮助。 以下为链接地址: 

    http://micrium.com/downloadcenter/download-results/?searchterm=mp-uc-os-ii&supported=true

    在该页面下找到如下: 


     下载后解压,可以看到该目录下的文件:

    


开始搭建:

    说明:本工程是在上一篇文章:http://blog.csdn.net/ballack_linux/article/details/40003503的基础上继续搭建的.

    资源下载地址是http://download.csdn.net/detail/ballack_linux/8028111

    下载后解压,如下图:

      


1、在STM32_TEST下建立一个子文件夹UCOS-II,在UCOS-II下再建立两个子文件夹Ports和Source。

    将Micrium_STM32xxx_uCOS-II\Micrium\Software\uCOS-II\Ports\ARM-Cortex-M3\Generic\RealView下的文件拷贝到STM32_TEST\UCOS-II\Ports下,将Micrium_STM32xxx_uCOS-II\Micrium\Software\uCOS-II\Source下的文件拷贝到STM32_TEST\UCOS-II\Source下。如下图:

        

        

        

        

2、打开KEIL工程,将UCOS-II下面的源文件添加进工程中,如下图:

        

    并且将UCOS-II头文件的路径添加到工程中,如下图:

        

        

   

     点击OK后,编译,可以看到报错:

      

    

    可以看到,由于工程中没有app_cfg.h这个文件,所以才报此错误,此文件是用来定义用户自己的任务栈大小和任务优先级等,那么我们可以直接在STM32_TEST\USER\下建一个新文件app_cfg.h,先不添加任何内容,再次编译,可以看到又报了一个错误:

    

    

    问题是找不到文件os_cfg.h文件,该文件是用来给用户定制自己的系统功能模块的,用户可以选择是否需要消息邮箱、消息队列、信号量、互斥信号量等功能。那么此时将Micrium_STM32xxx_uCOS-II\Micrium\Software\EvalBoards\ST\STM3210B-EVAL\RVMDK\OS-Probe 路径下的os_cfg.h拷贝到STM32_TEST\USER\下。再次编译,还是报错,如下:

        

    

    在工程中查找App_TCBInitHook,可以看到如下:

        

    

    继续查找OS_APP_HOOKS_EN,可以在os_cfg.h文件中找到该宏的定义:

     

    

    可以先将该宏OS_APP_HOOKS_EN定义为0,但此时你会发现改不了,这是为什么呢,因为该文件的属性为“只读”,如图:

        

    

    将“只读”复选框的勾去掉即可修改。修改后如图:

      

    

    继续编译,还是报错,这次是什么错误呢?

     

    

    os_cpu_c.c文件中的OS_CPU_SysTickClkFreq()是在Micrium_STM32xxx_uCOS-II\Micrium\Software\EvalBoards\ST\STM3210B-EVAL\RVMDK\BSP中的bsp.c定义的,而本文移植中并未用到bsp.c,而OS_CPU_SysTickInit()函数是依赖于OS_CPU_SysTickClkFreq()的,此函数主要用来设置SysTick系统时钟的,后面我们会自己实现,所以直接将该函数注释掉即可。提醒一下,可以将STM32_TEST\UCOS-II\Ports下的所有文件的“只读”属性都去掉,以方便修改。注释后如下:

 

    

    编译,通过了!!!谢天谢地,不容易啊~~~~~ 不过还有几个地方需要注意:

    os_cpu_c.c文件中OS_CPU_SysTickHandler()是SysTick中断的处理函数,其实在STM32_TEST\USER\stm32f10x_it.c文件中已经有SysTick中断函数的定义SysTick_Handler(),在STM32_TEST\CORE\startup_stm32f10x_md.s下也是定义的SysTick_Handler,而且该函数经常会做修改,故在此把OS_CPU_SysTickHandler()函数也注释掉,后面我们在平台中自己实现SysTick_Handler()函数。注释后如下图:

   


3、在STM32中所有任务切换都被放到PendSV的中断处理函数中去做了,因此任务切换只需简单的触发PendSV中断即可。

STM32_TEST\CORE\startup_stm32f10x_md.s中定义了PendSV_Handler,而在STM32_TEST\UCOS-II\Ports\os_cpu_a.asm中却定义的是OS_CPU_PendSVHandler,其实它们是同一个函数,因此将os_cpu_a.asm中的所有OS_CPU_PendSVHandler都替换成PendSV_Handler。并且将STM32_TEST\USER\stm32f10x_it.c中的PendSV_Handler定义体注释掉,如下图:

      

    再次编译,通过!


4、接下来,就剩下两个函数没有实现了,一个是设置系统时钟SysTick的函数,一个是其中断处理函数SysTick_Handler()函数。在STM32_TEST.c中添加此函数:

static void SetSysTick()

{

   RCC_ClocksTypeDef rcc_clocks;

   RCC_GetClocksFreq(&rcc_clocks);

   SysTick_Config(rcc_clocks.HCLK_Frequency/OS_TICKS_PER_SEC);

}

STM32_TEST\USER\stm32f10x_it.c中仿照os_cpu_c.c文件中的OS_CPU_SysTickHandler()函数写:

#include "ucos_ii.h"

void SysTick_Handler(void)

{                                       

   OSIntEnter();                            //进入中断,实际上就是执行了OSIntNesting++;

   OSTimeTick();       //调用ucos的时钟服务程序,ucos的时钟滴答函数           

   OSIntExit();         //可能会触发中断级的任务切换

}


5、至此,移植完毕。可以在STM32_TEST.c和app_cfg.h中添加应用程序了。

app_cfg.h中添加如下代码:

#ifndef __APP_CFG_H__

#define __APP_CFG_H__

 

#define APP_TASK_START_PRIO                            5

#define APP_TASK_USER_PRIO                             6

 

#define APP_TASK_START_STK_SIZE                        128

#define APP_TASK_USER_STK_SIZE                         128

 

#endif

 

STM32_TEST.c中的代码如下:

#include "stm32f10x.h"

#include "ucos_ii.h"

 

static OS_STK        App_TaskStartStk[APP_TASK_START_STK_SIZE];

static OS_STK        App_TaskUserStk[APP_TASK_USER_STK_SIZE];

 

static void  App_TaskStart (void *p_arg);

static void  App_TaskUser (void *p_arg);

 

static void SetSysTick()

{

         RCC_ClocksTypeDefrcc_clocks;

   RCC_GetClocksFreq(&rcc_clocks);

   SysTick_Config(rcc_clocks.HCLK_Frequency/OS_TICKS_PER_SEC);

}

static void LedInit()

{

         GPIO_InitTypeDef  GPIO_InitStructure;

         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);       //使能PA端口时钟                    

         GPIO_InitStructure.GPIO_Pin= GPIO_Pin_1;                                    //LED端口配置

         GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;                //推挽输出

         GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;

         GPIO_Init(GPIOA,&GPIO_InitStructure);

         GPIO_SetBits(GPIOA,GPIO_Pin_1);                                                  //PA1 输出高

}

int main (void)

{

   LedInit();

   OSInit();                              /* Initialize "uC/OS-II, TheReal-Time Kernel". */

   OSTaskCreate(App_TaskStart,(void* )0,(OS_STK*)&App_TaskStartStk[APP_TASK_START_STK_SIZE - 1],(INT8U)APP_TASK_START_PRIO);

   OSStart();                             /* Start multitasking (i.e. givecontrol to uC/OS-II). */

   return (0);

}

static void  App_TaskStart (void *p_arg)

{

         SetSysTick();

   OSTaskCreate(App_TaskUser,(void* )0,(OS_STK*)&App_TaskUserStk[APP_TASK_USER_STK_SIZE - 1],(INT8U) APP_TASK_USER_PRIO);

   while (1)

    {

            GPIO_SetBits(GPIOA,GPIO_Pin_1);                                          //PA1 输出高

            OSTimeDly(200);

    }                                                                   

}

static void  App_TaskUser (void *p_arg)

{

   while(1)

    {

       GPIO_ResetBits(GPIOA,GPIO_Pin_1);                                        //PA1 输出低

       OSTimeDly(400);

    }

}


    资源下载地址:http://download.csdn.net/detail/ballack_linux/8034799

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值