这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » Renesas » SH-Stick上的uC/OS-II移植详解

共31条 1/4 1 2 3 4 跳转至

SH-Stick上的uC/OS-II移植详解

菜鸟
2009-11-11 22:56:53     打赏
友情提示:本帖属于转载,版权归作者所有。
移植工程源码在帖子最后面,大家可以下载参考。
--------------------by red


SH-Stick使用的目标芯片为SH2/Tiny系列的SH7125,内置大容量FLASH和RAM,以及丰富的外设,非常适合工业,家电等领域。
下面我们针对SH-Stick上的目标芯片SH7125来移植一个比较简单的实时操作系统uC/OS-II。通过本次移植,相信读者一定会快速的了解SH2系列处理器的内部结构。

SH2体系介绍:
SH7125内部有16个通用寄存器R0 ~ R15。 其中R0 ~ R14为通用寄存器,用于日常的一些运算处理。R15为硬件栈指针寄存器,也就是我们平时说的SP寄存器,用于处理器发生异常时的栈操作。
另外还有PC,SR,GBR,VBR,MACH,MACL,PR寄存器。PC就是程序寄存器,SR为状态寄存器,GBR为全局基址寄存器,VBR为向量基址寄存器,MACH/MACL为乘法寄存器,PR为子程序返回地址寄存器。
如图1所示。



好了,我们熟悉了SH2的硬件结构,下面该介绍软件了。
笔者选用的RTOS为uC/OS-II 2.52版本,相信大家对这个OS已经很熟悉了,那就不用再介绍了。如果有不清楚的,可以去参考这本书的原著或者翻译本。

移植前的准备工作:
SH-Stick开发板和附送的串口仿真器
HEW平台(安装了SH编译器)

一。新建一个SH7125的HEW工程。
至于怎么建工程,附送的SH-STICK光盘里已经有很详细的例子了,大家参考一下。我这里就不再啰嗦了。

二。确保工程能连上电脑。
串口波特率建议大家选高一点,因为串口仿真会比较慢。相关教材在光盘里,不再赘述。

三。将uC/OS-II的源码加入到工程中。
为了让整个工程更好的理解,笔者分了3个部分来装载源码:boot,app,kernel,分别对应bootloader文件,应用程序,内核程序。

我们将这3个文件放在HEW工程目录下,相关的源码放入其中(读者可以参考帖子附带的工程)。之后就要设置源码路径,以便HEW能找到源文件。
设置路径如下:
Build -- SuperH Toolchain 里面,点击Add,选择Workspace directory,在里面填上源文件在HEW工程中的目录,如图2所示。
我们要添加3个目录进去(读者可以参考帖子附带的工程)。


                                           图2


四。编写uC/OS-II的BSP以及与体系结构有关的源码。

1,BSP工作。

板级支持包BSP就是OS启动之前的一段代码,负责把引导OS内核,保证内核能正常启动。
uC/OS-II将使用SH7125的定时器A0作为时钟节拍。定时器A0初始化是直接参考SH-Stick附带的源码,每10ms产生一个中断,如下:
/*************************************************************
  名称:InitTimer
  描述:初始化定时器
  初始化定时器MTU2的通道0用作定时器模式
  参数:无
返回值:无
  输入:无
  输出:无
**************************************************************/
VOID InitTimer( ){
 STB.CR4.BIT._MTU2 = 0;  //向MTU2模块提供时钟
 MTU20.TIER.BYTE = 0;  //不使能中断
 MTU2.TSTR.BIT.CST0 = 0;  //停止定时器
 MTU20.TMDR.BYTE = 0x00;  //设定为定时器模式
 MTU20.TCR.BYTE = 0x21;  //TGRA作为清除源,上升沿计数,计数源为MP/4
 MTU20.TIOR.BYTE.H = 0;  //
 MTU20.TIOR.BYTE.L = 0;
 MTU20.TSR.BYTE = 0xC0;  //清除所有的中断标志
 MTU20.TIER.BIT.TGIEA = 1; //使能TGRA匹配中断
 MTU20.TCNT = 0;
 MTU20.TGRA = 60000;   //计数频率为24MHz*8(PLL)/8(Divider)/4/60000=100Hz
 INTC.IPRD.BIT._MTU20G = 8; //设定中断优先级
// MTU2.TSTR.BIT.CST0 = 1;  //启动定时器MTU2通道0
}

另外,uC/OS-II将使用SH7125的向量号为32的陷阱指令,类似于软中断,来进行任务切换。
因为,我们需要修改定时器A0和向量号为32的陷阱指令对应的中断向量表。具体过程可参考源码。


2.体系结构有关的源码

下面我们来编写uC/OS-II在SH7125上的移植代码。只有2个文件:os_cpu_c.c, os_cpu_c.src, os_cpu.h。
os_cpu_c.c里面主要实现一个函数*OSTaskStkInit,该函数用于创建任务时,对任务栈内容的初始化。
如下:
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
    OS_STK *stk;
    opt    = opt;                         
    stk    = (OS_STK *)ptos;        
    *stk-- = 0x00000000;                /* SR   */
    *stk-- = (OS_STK)task;              /* PC */
    *stk-- = 0xeeeeeeee;                         /* R14 */  
    *stk-- = 0xdddddddd;                         /* R13 */
    *stk-- = 0xcccccccc;                         /* R12 */
    *stk-- = 0xbbbbbbbb;                         /* R11 */
    *stk-- = 0xaaaaaaaa;                         /* R10 */
    *stk-- = 0x99999999;                         /* R9 */
    *stk-- = 0x88888888;                         /* R8 */
    *stk-- = 0x77777777;                         /* R7 */
    *stk-- = 0x66666666;                         /* R6 */
    *stk-- = 0x55555555;                         /* R5 */
    *stk-- = (OS_STK)pdata;                      /* R4 */
    *stk-- = 0x33333333;                         /* R3 */
    *stk-- = 0x22222222;                         /* R2 */
    *stk-- = 0x11111111;                         /* R1 */
    *stk-- = 0x00000000;                         /* R0 */
    *stk-- = 0x11000000;                     // GBR
    *stk-- = 0x22000000;                     // MACH
    *stk-- = 0x33000000;                     // MACL
    *stk = 0x44000000;                     // PR
 
    return ((OS_STK *)stk);
}

os_cpu_c.src是汇编文件,实现四个函数:
_OSStartHighRdy  任务开始
_OSCtxSw     任务切换
_OSIntCtxSw  中断级的任务切换
_OSTickISR  定时器中断处理
;--------------------------------------------------
;任务开始
;--------------------------------------------------
_OSStartHighRdy: 
 MOV.L #_OSTCBHighRdy,R2                              ;指向指针的指针(指针的地址)
 MOV.L @R2,R2                                         ;指针值
 MOV.L @R2,SPR                                        ;将指针指向的值送入SP 
 MOV.L #_OSRunning,R0                                 ;OSRunning = TRUE
 MOV.B #1,R1
 MOV.B R1,@R0
                                        
 POP_CS
 POP_Rn
 RTE                                                  ;中断返回,开始任务
 NOP

  
;--------------------------------------------------
;任务切换
;--------------------------------------------------
_OSCtxSw:                                             ;该ISR的入口地址对应指令(TRAPA   #32)
 
 PUSH_Rn
 PUSH_CS
 MOV.L #_OSTCBCur,R3                                  ;保存当前任务SP
 MOV.L @R3,R2    
 MOV.L SPR,@R2                                        ;保存当前任务栈指针SP到OSTCBCur首地址
 MOV.L #_OSTaskSwHook,R4                              ;执行用户自定义程序
 JSR @R4 
 NOP              
 MOV.L #_OSPrioHighRdy,R0                             ;OSPrioCur = OSPrioHighRdy 
 MOV.B @R0,R0
 MOV.L #_OSPrioCur,R1
 MOV.B R0,@R1
 MOV.L #_OSTCBHighRdy,R0                              ;OSTCBCur = OSTCBHighRdy
 MOV.L @R0,R0
 MOV.L #_OSTCBCur,R3
 MOV.L R0,@R3     
 MOV.L #_OSTCBHighRdy,R5                              ;载入新任务的SP
 MOV.L @R5,R5
 MOV.L @R5,SPR     
 POP_CS                                               ;寄存器出栈
 POP_Rn
 
 RTE                                                  ;中断返回,开始新任务   
 NOP
  
;--------------------------------------------------
;中断级的任务切换
;---------------------------------------------------
_OSIntCtxSw:
 
 ADD #OFFSET,SPR                             
 MOV.L #_OSTCBCur,R7                                  ;保存当前SP
 MOV.L @R7,R7
 MOV.L SPR,@R7
 MOV.L #_OSTaskSwHook,R0                              ;执行用户自定义程序
 JSR @R0                 
 NOP
 MOV.L #_OSTCBHighRdy,R0                              ;OSTCBCur = OSTCBHighRdy
 MOV.L @R0,R0
 MOV.L #_OSTCBCur,R3
 MOV.L R0,@R3     
 MOV.L #_OSPrioHighRdy,R2                             ;OSPrioCur = OSPrioHighRdy
 MOV.B @R2,R2
 MOV.L #_OSPrioCur,R3
 MOV.B R2,@R3
 MOV.L #_OSTCBHighRdy,R6                              ;载入新任务SP
 MOV.L @R6,R6
 MOV.L @R6,SPR
 POP_CS                                               ;寄存器出栈
 POP_Rn
 
 RTE                                                  ;中断返回,新任务开始
 NOP
   
 
;---------------------------------------------------
;系统时钟中断
;---------------------------------------------------
_OSTickISR:
 PUSH_Rn
 PUSH_CS
 MOV.L #_OSIntEnter,R0                                ;进入中断
 JSR @R0
 NOP
 
 MOV.L #_OSTimeTick,R0                                ;时间节拍处理
 JSR @R0
 NOP
 
 MOV.L #_OSIntExit,R5                                 ;中断退出处理
 JSR @R5
 NOP
 POP_CS
 POP_Rn

 RTE                                                  ;定时中断返回
 NOP 

os_cpu.h里面定义一些数据结构类型,开关中断,任务切换指令等。
我们使用set_imask()实现开关中断,使用trapa()实现任务切换。


五。编译,验证。
完成以上几个步骤后,笔者尝试写了一个简单的任务来验证移植是否正确。
该任务的作用是让SH-Stick上的P13对应的LED每隔1秒闪烁一次。
/*
 *  uC/OS-II启动之后的第一个任务
 *
 *  该任务的功能是:
 *  PE13对应的LED每秒闪烁一次
 */
void task1(void *pdata)

 pdata = pdata; 
 set_imask(0);             // 开总中断
 MTU2.TSTR.BIT.CST0 = 1;   // 启动定时器
 
   
 while(1){
  PE.DRL.BIT.B13 = 1;  
  OSTimeDlyHMSM(0, 0, 1, 0);
  PE.DRL.BIT.B13 = 0;
  OSTimeDlyHMSM(0, 0, 1, 0);
 }
}    

我们开始编译工程。第一次因为要编译库文件,时间比较长。排除一些错误和警告后,生成的abs调试文件通过串口下载到SH-Stick上。点击HEW上的“运行”按钮,SH-Stick上的P13对应的LED开始有节奏的闪烁。
本次移植工作宣告成功!


顺带附上本次移植的HEW工程。
sh_stick_ucosii.rar (103 K) 下载次数:0



关键词: SH-Stick     上的     OS-II     移植     详解         

助工
2009-11-11 23:09:26     打赏
2楼

楼主你很牛啊,我还在看手册。。。


菜鸟
2009-11-11 23:26:57     打赏
3楼

这篇文章写的不错,转载过来给大家看看。
还好这里可以复制粘贴,要不然我还需要慢慢编辑。

在使用SH-STICK中,遇到什么困难,有什么意见或建议,都可以提。
谢谢大家对瑞萨的支持!Thanks.


院士
2009-11-12 08:56:36     打赏
4楼
看样子这位年兄是Renesas官方人员啊

菜鸟
2009-11-12 11:46:38     打赏
5楼
太厉害了!
学习。

菜鸟
2009-11-12 17:51:10     打赏
6楼

正在学习,收入囊中。


菜鸟
2009-11-12 18:09:44     打赏
7楼
我还在看datasheet

助工
2009-11-13 11:16:41     打赏
8楼

帮我解决一个问题,我烧录光盘中提供的demo程序,有重新编译过。发现不能run了。是为什么呢?


助工
2009-11-13 12:49:11     打赏
9楼
感谢了! 还要仔细读读

菜鸟
2009-11-13 16:29:06     打赏
10楼

回:johnliiuzk


下载之后断电,再上电就可以了。

如果不行,修改ROM起始地址为0x0后,重新编译即可。

共31条 1/4 1 2 3 4 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]