手把手教UCOS II移植到DSP 2803x(28035为例)

来源:互联网 发布:log4j日志存入数据库 编辑:程序博客网 时间:2024/05/21 17:38


移植前说明:
相信学过UCOS的人都看过下面这张图,这张图讲解了UCOS移植的方法。这是ARM芯片移植UCOS的体系结构图,当然对于其它芯片也是适用的,只是个别文件名不同而已。移植的时候,图示红色部分是不需要去修改的,需要修改的是蓝色部分(这部分与芯片的型号是相关的,不同芯片是不一样的),绿色部分也可以适当更改。可以通过os_cfg.h裁剪UCOS代码,因为UCOS相对来说还是比较臃肿的。


这里写图片描述

移植前准备:
一、 准备一个28035的开发例程(也可以自己写的,注:我使用的是CCS7.2版本,不同版本文件结构可能不同)
下面是一个28035的例程整体框架,例程功能是定时器time0每500ms中断一次,中断程序中翻转GPIO口的输出状态,以此来让开发板上的LED灯闪烁。文件说明:include是头文件,在这里没有展开。这是一个最基本的28035开发例程。

这里写图片描述

二、准备UCOS II移植文件
在Micrium官网下载micrium提供的关于28335的移植例程(到目前为止只有28335),整体框架如下图所示。
文件很多,这里先不用理会,后面会讲各个文件的功能。

这里写图片描述

三、 开始移植
1、 把前面两个工程文件合并起来。
官网下载的移植文件说明:一共就这几个文件,分别是APP, BSP, UC_CPU, UC_LIB, UCOS_II。
APP包含了用户应用代码,其中各种.h文件是对ucos的一些配置。.h文件保留,并新建一个CONFIG文件夹保存起来。app.c文件删除,用自己写的文件代替。
BSP称作板级支持包,这个相当于官方提供的例程中所使用的各种.c文件。这个文件也要删除,用.c文件代替。为什么要删除BSP文件,因为这个是为28335写的文件,在28035已经不适用了。还有一个问题是,官网28335这个例程只是定义了一些用到的寄存器,还有很多寄存器没有定义,如果要用到那些寄存器则要自己去定义,这就相当于本来提供的各种.c文件都要自己重新写,很烦锁。
uC_CPU是基于 micrium 官方评估板的 ucosii 移植代码,这个直接复制过来。
uC_LIB这个是micrium 官方的一个库代码,也复制过来。
uCOS_II这个文件是ucos_ii源代码,移植的时候需要修改的文件。但是官方已经帮我们修改好了。所以直接复制过来用就可以了。

可能有人会有疑问,这个28335的CPU文件适用于28035么?答案是肯定的。看到上面的C28X目录么,就是说这个移植文件是适用于所有C28X芯片的。因为28335和28035都属于C28X系列,所以此文件也适用于28035芯片。

把上面几个文件复制到第一个工程例程,修改后的框架如下图所示:

这里写图片描述

文件说明:CONFIG文件夹文件是从上面APP文件夹里复制而来的.h文件。main文件的Example_2803xLEDBlink.c是要修改的,下一步会介绍。SXD28035_common及SXD28035_headers文件,是原来工程的文件,没有修改。uC_CPU, uC_LIB, uCOS_II这三个文件是从官网例程复制过来的。F28035.cmd文件也要自己写。
2、 修改文件路径

这里写图片描述

3、 编写主程序(主程序代替APP程序)
main / Example_2803xLEDBlink.c程序如下:

#include  <app_cfg.h>#include  <ucos_ii.h>#include  <cpu_core.h>#include  <lib_def.h>#include  <os_cpu.h>#include "DSP28x_Project.h"#define LED0        GpioDataRegs.GPBTOGGLE.bit.GPIO34CPU_STK_SIZE  App_TaskStartStk[APP_CFG_TASK_STK_SIZE];CPU_STK_SIZE  App_TaskPendStk[APP_CFG_TASK_STK_SIZE];CPU_STK_SIZE  App_TaskPostStk[APP_CFG_TASK_STK_SIZE];static  OS_EVENT    *AppTaskObjSem;static  void  App_TaskStart(void  *p_arg);static  void  App_TaskPing (void  *p_arg);static  void  App_TaskPong (void  *p_arg);interrupt void cpu_timer0_isr(void);  // 中断声明void BSP_Tick_Init(void);void BSP_Tick_Init(void){    EALLOW;    PieVectTable.TINT0 = &cpu_timer0_isr; // 定时器中断地址    // PieVectTable.RTOSINT = &RTOSINT_ISR;    // test    PieVectTable.OS_CPU_RTOSINT = &OS_CPU_RTOSINT_Handler;  // RTOS    // MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);    // InitFlash();  //初始化FLASH    EDIS;    InitCpuTimers();    ConfigCpuTimer(&CpuTimer0, 60, 1000);  // test 500000    CpuTimer0Regs.TCR.all = 0x4001; // 设置 TSS bit = 0    IER |= M_INT1;   // CPU-Timer 0属于CPU INT1,使能:    PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // Enable TINT0 in the PIE: Group 1 interrupt 7    EINT;   // 使能INTM中断    ERTM;   // 使能DBGM中断}void main(void){   InitSysCtrl();   // InitGpio();  // 本例未用到  // 第二步:初始化GPIO:   DINT;   InitPieCtrl();   IER = 0x0000;   IFR = 0x0000;   InitPieVectTable();   EALLOW;   GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0;  // LED0   GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1;   EDIS;   EINT;   // 使能INTM中断   ERTM;   // 使能DBGM中断   OSInit();   OSTaskCreateExt(App_TaskStart,                   (void    *)0,                   (CPU_STK *)&App_TaskStartStk[0],                   (INT8U    )APP_CFG_TASK_START_PRIO,                   (INT16U   )APP_CFG_TASK_START_PRIO,                   (CPU_STK *)&App_TaskStartStk[APP_CFG_TASK_STK_SIZE - 1u],                   (INT32U   )APP_CFG_TASK_STK_SIZE,                   (void    *)0,                   (INT16U   )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));   OSStart();   while (DEF_TRUE) {       ;   }}static  void  App_TaskStart (void *p_arg){    volatile CPU_INT08U  os_err;  // test    (void)&p_arg;    BSP_Tick_Init();    AppTaskObjSem = OSSemCreate(0);    OSTaskCreateExt(App_TaskPing,                    (void    *)0,                    (CPU_STK *)&App_TaskPendStk[0],                    (INT8U    )APP_CFG_TASK_PEND_PRIO,                    (INT16U   )APP_CFG_TASK_PEND_PRIO,                    (CPU_STK *)&App_TaskPendStk[APP_CFG_TASK_STK_SIZE - 1u],                    (INT32U   )APP_CFG_TASK_STK_SIZE,                    (void    *)0,                    (INT16U   )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));    OSTaskCreateExt(App_TaskPong,                    (void    *)0,                    (CPU_STK *)&App_TaskPostStk[0],                    (INT8U    )APP_CFG_TASK_POST_PRIO,                    (INT16U   )APP_CFG_TASK_POST_PRIO,                    (CPU_STK *)&App_TaskPostStk[APP_CFG_TASK_STK_SIZE - 1u],                    (INT32U   )APP_CFG_TASK_STK_SIZE,                    (void    *)0,                    (INT16U   )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));    while (DEF_TRUE) {        os_err = OSSemPost(AppTaskObjSem);        OSTimeDlyHMSM(0, 0, 0, 1);    }}static  void  App_TaskPing (void *p_arg){    CPU_INT08U  os_err;   (void)&p_arg;    while (DEF_TRUE)    {        OSSemPend( AppTaskObjSem,                   0,                  &os_err);    }}static  void  App_TaskPong (void *p_arg){   (void)&p_arg;    while (DEF_TRUE)    {        OSTimeDlyHMSM(0, 0, 0, 300);   // test   before is 300        LED0=1;        CpuTimer0.InterruptCount++;    // test  仿真测试用    }}interrupt void cpu_timer0_isr(void){   PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // LED0=1;     // test   // CpuTimer0.InterruptCount++;  //test   OSIntEnter();   OSTimeTick();   OSIntExit();}


程序说明:BSP_Tick_Init(void)和interrupt void cpu_timer0_isr(void)函数为ucos系统提供时钟节拍,第一个函数是初始化timer,此处设置的是1ms定时一到就会跳入中断函数,中断函数中调用OSTimeTick()函数为ucos提供时钟节拍。注意这里设置了OS_CPU_RTOSINT_Handler,这个后面还会讲到。
后面的函数都是官网例程的代码直接复制过来的。在void App_TaskPong (void *p_arg)函数做了一些修改,改成自己开发板用的代码及测试代码。
4、 编写CMD文件。
这个很重要,如果不懂CMD文件的可以用我这个文件。千万不要乱改,否则会出现各种各样的问题,而且极难调试。

MEMORY{PAGE 0:    /* Program Memory */           /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE1 for data allocation */   RAML0       : origin = 0x008000, length = 0x000800     /* on-chip RAM block L0 */   RAML1       : origin = 0x008800, length = 0x000400     /* on-chip RAM block L1 */   OTP         : origin = 0x3D7800, length = 0x000400     /* on-chip OTP */   FLASHH      : origin = 0x3E8000, length = 0x002000     /* on-chip FLASH */   FLASHG      : origin = 0x3EA000, length = 0x002000     /* on-chip FLASH */   FLASHF      : origin = 0x3EC000, length = 0x002000     /* on-chip FLASH */   FLASHE      : origin = 0x3EE000, length = 0x002000     /* on-chip FLASH */   FLASHD      : origin = 0x3F0000, length = 0x002000     /* on-chip FLASH */   FLASHC      : origin = 0x3F2000, length = 0x002000     /* on-chip FLASH *//*   FLASHA      : origin = 0x3F6000, length = 0x001F80 */    /* on-chip FLASH */   FLASHA      : origin = 0x3F5000, length = 0x002F80   /* test */   CSM_RSVD    : origin = 0x3F7F80, length = 0x000076     /* Part of FLASHA.  Program with all 0x0000 when CSM is in use. */   BEGIN       : origin = 0x3F7FF6, length = 0x000002     /* Part of FLASHA.  Used for "boot to Flash" bootloader mode. */   CSM_PWL_P0  : origin = 0x3F7FF8, length = 0x000008     /* Part of FLASHA.  CSM password locations in FLASHA */   IQTABLES    : origin = 0x3FE000, length = 0x000B50     /* IQ Math Tables in Boot ROM */   IQTABLES2   : origin = 0x3FEB50, length = 0x00008C     /* IQ Math Tables in Boot ROM */   IQTABLES3   : origin = 0x3FEBDC, length = 0x0000AA     /* IQ Math Tables in Boot ROM */   ROM         : origin = 0x3FF27C, length = 0x000D44     /* Boot ROM */   RESET       : origin = 0x3FFFC0, length = 0x000002     /* part of boot ROM  */   VECTORS     : origin = 0x3FFFC2, length = 0x00003E     /* part of boot ROM  */PAGE 1 :   /* Data Memory */           /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE0 for program allocation */           /* Registers remain on PAGE1                                                  */   BOOT_RSVD   : origin = 0x000000, length = 0x000050     /* Part of M0, BOOT rom will use this for stack */   RAMM0       : origin = 0x000050, length = 0x0003B0     /* on-chip RAM block M0 */   RAMM1       : origin = 0x000400, length = 0x000400     /* on-chip RAM block M1 */   RAML2       : origin = 0x008C00, length = 0x000400     /* on-chip RAM block L2 */   RAML3       : origin = 0x009000, length = 0x001000     /* on-chip RAM block L3 */   FLASHB      : origin = 0x3F4000, length = 0x002000     /* on-chip FLASH */}SECTIONS{   /* Allocate program areas: */   .cinit              : > FLASHA     PAGE = 0   .pinit              : > FLASHA     PAGE = 0   .text               : > FLASHA      PAGE = 0   codestart           : > BEGIN       PAGE = 0   ramfuncs            : LOAD = FLASHD,                         RUN = RAML0,                         LOAD_START(_RamfuncsLoadStart),                         LOAD_END(_RamfuncsLoadEnd),                         RUN_START(_RamfuncsRunStart),                         PAGE = 0   csmpasswds          : > CSM_PWL_P0  PAGE = 0   csm_rsvd            : > CSM_RSVD    PAGE = 0   /* Allocate uninitalized data sections: */   .stack              : > RAMM0       PAGE = 1   .ebss               : > RAML2 | RAML3        PAGE = 1   .esysmem            : > RAML2 | RAML3        PAGE = 1   /* Initalized sections go in Flash */   /* For SDFlash to program these, they must be allocated to page 0 */   .econst             : > FLASHA      PAGE = 0   .switch             : > FLASHA      PAGE = 0   /* Allocate IQ math areas: */   IQmath              : > FLASHA      PAGE = 0            /* Math Code */   IQmathTables        : > IQTABLES,   PAGE = 0, TYPE = NOLOAD   .reset              : > RESET,      PAGE = 0, TYPE = DSECT   vectors             : > VECTORS     PAGE = 0, TYPE = DSECT}


5、 设置堆栈(stack)大小。
右键工程项目名,选择properties。出现下面框图,如图,修改为0x3b0。这个设置跟CMD文件要对应上。CMD文件上.stack设为RAMMO段,其大小正好为0x3B0。请看上面代码。

这里写图片描述

6、 取消浮点运算float支持
因为28035是定点芯片,所以要取消浮点运算。
右键工程项目名,选择properties。出现下面框图,如图,选择softlib。fpu32用于支持浮点运算的芯片。
这里写图片描述

7、 设置OS_CPU_RTOSINT_Handler 中断
UCOS任务的跳转是调用了OSINTCTXSW这个宏定义。这个宏定义就是:asm(” TRAP #16”); TRAP #16定义为RTOSINT_ISR中断,在SXD28035_common->DSP2803X_DefaultIsr.c文件中可以看到interrupt void RTOSINT_ISR(void)函数是空的。关于cpu寄存器的操作是在ucos­ii­>prots­>C28x->generic­>ccs­>os_cpu_a.asm这个文件中的_OS_CPU_RTOSINT_Handler: 函数。所以在这里要把OS_CPU_RTOSINT_Handler定义为16号中断入口地址。具体做法如下:
1) 在main程序中修改RTOSINT中断的入口地址,如下,取消第一条指令,加上第二条指令。
// PieVectTable.RTOSINT = &RTOSINT_ISR; // test
PieVectTable.OS_CPU_RTOSINT = &OS_CPU_RTOSINT_Handler; // RTOS
2) 修改中断向量表。路径为SXD28035_headers->include->DSP2803x_PieVect.h。修改后如下所示:
这里写图片描述

3) 中断向量表初始化也要修改。路径为SXD28035_headers->include->DSP2803x_PieVect.c。修改后如下所示:
注意:在DSP2803x_PieVect.c 文件中添加os_cpu.h 头文件,否则编译器会找不到OS_CPU_RTOSINT_Handler 。 #include “os_cpu.h”
这里写图片描述

4)取消interrupt void RTOSINT_ISR(void)中断。路径为SXD28035_common->DSP2803X_DefaultIsr.c。修改后如下所示:

这里写图片描述

5) 好了,来看看OS_CPU_RTOSINT_Handler的定义长什么样子。路径为ucos­ii­>prots­>C28x->generic­>ccs­>os_cpu_a.asm

这里写图片描述

8、 裁剪代码
为什么要裁剪代码呢?一方面是因为UCOS代码比较臃肿;另一方面是不想去修改CMD文件。在这里直接把暂时没用到的代码取消就可以了。
1)uC_LIB文件夹中的lib_ascii.c, lib_math.c, lib_mem.c, lib_str.c。这四个文件取消编译。

这里写图片描述

2)裁剪UCOS II内核代码。路径为CONFIG->os_cfg.h。把暂时不用的功能注消。如下图

这里写图片描述

最后编译0错误,0警告,下载,运行正常。大功告成!

原创粉丝点击