完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
系统配置: IDE: HEW SuperH 9.1.1.0 for SH2A-FPU CPU: Renesas SH2A/7261 OS: uC/OS-II 2.51 Memory: 64M SDRAM Emluator: E10A-USB 本机系统时钟根据CPU定时器T0来配置,默认为每秒溢出20次,也就是每秒产生20个时钟节拍。 CPU说明: SH7261属于SH2A系列微处理器,32位RISC,采用哈佛体系结构,5级流水线,内部包含一个高速缓存,一个浮点协处理器和16个用于快速中断响应的Register Bank。 内部最高时钟频率为120MHz , 总线频率为60MHz 寄存器包括:通用寄存器,系统寄存器,控制寄存器和浮点寄存器。本机未做浮点运算,故浮点寄存器将不作考虑。 uC/OS-II说明: 该实时操作系统内核为2.51版本。可由用户运行56个任务。具体功能参见《uC/OS-II》。 移植步骤: 1.建立编译环境。 本系统将映像文件下载到SDRAM中进行调试。需要修改section段,并使用SH系列的命令行语句初始化总线控制器,以便将程序下载到SDRAM相应的map映像区。 2.修改中断向量表。 本系统使用向量号为32的陷阱指令来进行任务切换,需要在中断向量表INT_Vectors中将INT_TRAPA32替换为OSCtxSw。另外,系统时钟使用8位定时器T0溢出中断,故需要将中断向量表中的INT_TMR0_OVI0替换为OSTickISR。 3.硬件初始化 在hwsetup.c文件中初始化时钟,总线控制器,定时器,Cache等CPU及片上I/O资源,以便为uC/OS-II建立运行环境。 4.编写os_cpu_c.c文件。 根据CPU的体系结构,模拟中断发生后的栈状态。 中断发生后,SR和PC先入栈。 task()中的参数默认传递到R0 如下: // SH2A任务栈初始化 // 栈从高地址向低地址增长 OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) { OS_STK *stk; opt = opt; stk = (OS_STK *)ptos; *stk-- = 0; /* SR 任务启动后允许中断(interrupt mask bits set to 0) */ *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-- = 0x44444444; /* R4 */ *stk-- = 0x33333333; /* R3 */ *stk-- = 0x22222222; /* R2 */ *stk-- = 0x11111111; /* R1 */ *stk-- = (OS_STK)pdata; /* R0 */ *stk-- = 0x11000000; // GBR *stk-- = 0x22000000; // MACH *stk-- = 0x33000000; // MACL *stk = 0x44000000; // PR return ((OS_STK *)stk); } 5.编写os_cpu.h文件。 开中断和关中断使用set_imask()函数 陷阱指令使用trapa()函数 以上两个函数包含在系统头文件machine.h中 另,还要申明用于os_cpu_a.src的四个汇编程序。为了防止Register Bank溢出,本系统将不使用Register Bank 如下: #pragma interrupt OSCtxSw//(re***ank) // SH2A执行陷阱指令时不使用Register Bank extern void OSCtxSw(void); // 任务切换 #pragma interrupt OSTickISR//(re***ank) // 该中断不使用Register Bank extern void OSTickISR(void); // 定时器中断 extern void OSStartHighRdy(void); // 开始任务 extern void OSIntCtxSw(void); // 中断任务切换 6.编写os_cpu_a.src文件。 1) 压栈,出栈操作宏定义: ;R0 ~ Rn入栈 .MACRO PUSH Rn MOVML.L Rn,@-SPR ;将Rn~R0依入栈. R0入栈后,SP = SP-4 .ENDM ;R0 ~ Rn出栈 .MACRO POP Rn MOVML.L @SPR+,Rn ;该指令执行完时,也就是Rn出栈后,(SP = SP + 4)??? .ENDM ;保存系统和控制寄存器 .MACRO PUSH_REG STC.L GBR,@-SPR ;将控制寄存器送入stack STS.L MACH,@-SPR ;将系统寄存器送入stack STS.L MACL,@-SPR STS.L PR,@-SPR ;SP始终指向栈顶元素 .ENDM ;恢复系统和控制寄存器 .MACRO POP_REG LDS.L @SPR+,PR ;恢复系统寄存器 LDS.L @SPR+,MACL LDS.L @SPR+,MACH LDC.L @SPR+,GBR ;恢复控制寄存器 .ENDM 2) OSStartHighRdy函数: 注意:子函数跳转指令JSR和中断返回指令RTE为delay branch指令,需要在后面插入一条单周期指令,以便在delay slot中填充CPU流水线。 ;获得任务栈指针 MOV.L #_OSTCBHighRdy,R2 MOV.L @R2,R2 MOV.L @R2,SPR POP_REG POP R14 RTE NOP 3) 任务切换OSCtxSw函数: OSTaskSwHook函数可以不执行,以加快任务切换时间 PUSH R14 PUSH_REG ;保存当前任务SP MOV.L #_OSTCBCur,R3 MOV.L @R3,R2 MOV.L SPR,@R2 ;保存当前任务栈指针SP到OSTCBCur首地址 ;执行用户程序 MOV.L #_OSTaskSwHook,R4 JSR @R4 NOP ;OSPrioCur = OSPrioHighRdy MOV.L #_OSPrioHighRdy,R0 MOV.B @R0,R0 MOV.L #_OSPrioCur,R1 MOV.B R0,@R1 ;OSTCBCur = OSTCBHighRdy MOV.L #_OSTCBHighRdy,R0 MOV.L @R0,R0 MOV.L #_OSTCBCur,R3 MOV.L R0,@R3 ;恢复新任务的SP MOV.L #_OSTCBHighRdy,R5 MOV.L @R5,R5 MOV.L @R5,SPR POP_REG POP R14 RTE NOP 4) 中断级别的任务切换OSIntCtxSw: OSTaskSwHook函数可不执行,以加快任务切换 注意栈顶的多余部分只有OSIntExit的返回地址,代码如下 ;去掉栈顶多余单元 ADD #OFFSET,SPR ;NOTE!!! ;在HEW环境下,只有OSIntExit()的返回地址入栈 ;OSIntCtxSw()的返回地址保存到PR ;系统函数set_imask(15)将SR的值送入Rn,而不是入栈 ;保存当前SP MOV.L #_OSTCBCur,R7 MOV.L @R7,R7 MOV.L SPR,@R7 ;执行用户自定义程序 MOV.L #_OSTaskSwHook,R0 JSR @R0 NOP ;OSTCBCur = OSTCBHighRdy MOV.L #_OSTCBHighRdy,R0 MOV.L @R0,R0 MOV.L #_OSTCBCur,R3 MOV.L R0,@R3 ;OSPrioCur = OSPrioHighRdy MOV.L #_OSPrioHighRdy,R2 MOV.B @R2,R2 MOV.L #_OSPrioCur,R3 MOV.B R2,@R3 ;恢复新任务SP MOV.L #_OSTCBHighRdy,R6 MOV.L @R6,R6 MOV.L @R6,SPR POP_REG POP R14 RTE NOP 5) 系统时钟处理 定时器溢出标志位可清除也可不清除,反正T0就是一直计数-溢出-中断,不停循环 OSTickISR: PUSH R14 PUSH_REG ;清除定时器溢出标志位 MOV.L #TCSR_0,R1 MOV.B @R1,R2 BCLR #5,R2 MOV.B R2,@R1 ;进入中断,将嵌套数加1 MOV.L #_OSIntEnter,R5 JSR @R5 NOP ;时间节拍处理 MOV.L #_OSTimeTick,R5 JSR @R5 NOP ;中断退出处理 MOV.L #_OSIntExit,R5 JSR @R5 NOP POP_REG POP R14 RTE NOP 7.main()函数测试任务切换 本系统运行三个简单的任务,分别点亮3个LED。 分别将各个任务调度上锁和开锁,并将任务延迟一定的时间。 三个任务之间都能精确的切换,并且优先级最高的任务一直在运行。 |
|
相关推荐 |
|
只有小组成员才能发言,加入小组>>
【RA-Eco-RA2E1-48PIN-V1.0开发板试用】(第三篇)PWM输出+ADC采集
765 浏览 0 评论
【RA-Eco-RA2E1-48PIN-V1.0开发板试用】尝试嵌入式操作系统Free-RTOS
1588 浏览 0 评论
【RA-Eco-RA2E1-48PIN-V1.0开发板试用】触摸按钮尝试
697 浏览 0 评论
【RA-Eco-RA2E1-48PIN-V1.0开发板试用】IIC 通信的 OLED 显示
664 浏览 0 评论
【RA-Eco-RA2E1-48PIN-V1.0开发板试用】原创测量代码运行时间
552 浏览 0 评论
【试用答疑】RA-Eco-RA4M2-100PIN开发板试用活动答疑帖
5079浏览 4评论
1738浏览 4评论
4207浏览 3评论
【RA-Eco-RA0E1-32PIN-V1.0开发板试用】RA0E1-32PIN-V1.0开发板测试一下点灯
2295浏览 3评论
【RA4M2设计挑战赛】智慧农业监测RA4M2采集数据上传阿里云
1550浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-23 18:24 , Processed in 0.707447 second(s), Total 52, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号