首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ARM7上移植uc/os-II(2)

ARM7上移植uc/os-II(2)

关键词IMPORT声明此函数/参量在其他文件中定义,下同 IMPORTOSTCBHighRdy IMPORT OSRunning OSStartHighRdy ;使就绪表中任务最高的优先级的任务开始运行 BL OSTaskSwHook ;调用用户的Hook函数,空函数 LDR r4,=OSRunning ;将OSRunning置1,声明多任务OS开始运行 MOV r5, #1 STRB r5, [r4] LDRr4, =OSTCBHighRdy ; 伪指令,取得存储OSTCBHighRdy的地址 LDR r4, [r4]; 得到最高优先级任务的任务堆栈地址 LDR sp, [r4] ;切换到新任务的堆栈 LDMFD sp!, {r4};从新任务堆栈中读取第一个参数(CPSR)到(r4) MSR cpsr_cxsf, r4;再传给cpsr,堆栈中的CPSR弹出到CPU的cpsr寄存器 LDMFD sp!,{r0-r12,lr,pc} ;依次恢复该任务r0~r12,lr,pc,切换到该任务 ;*****下面开始OSCtxSw函数,完成任务级的任务切换***** EXPORT OSCtxSwIMPORT OSPrioCur IMPORT OSPrioHighRdy IMPORT OSTCBCur IMPORTOSTaskSwHook IMPORTOSTCBHighRdy;该变量指向任务切换后即将运行的任务的OS_TCB OSCtxSwSTMFD sp!, {lr} ; OSCtxSw是被调用的,lr的值就是调用前的PC值,入栈STMFD sp!, {r0-r12,lr} ; 将lr和其他寄存器入栈 MRS r4, cpsr;通过MRS指令将cpsr入栈 STMFD sp!, {r4} ;被挂起的当前任务的寄存器保存完毕,下面接着保存该;任务的堆栈指针,以便下次恢复时,可以找到其堆栈指针,便可恢复其寄存器LDR r4, =OSTCBCur ; 得到当前TCB块的地址,传给r4 LDR r5, [r4] ;将OSTCBCur中的值传给r5,注意OSTCBCur存的是指针 STR sp, [r5] ;将当前任务的sp传到OSTCBCur存的指针中去 ;*****下面OSCtxSw准备恢复优先级更高的就绪任务,这部分可共用OSIntCtxSw的代码*****; *****OSIntCtxSw函数开始***** EXPORT OSIntCtxSw IMPORTOSTaskSwHook OSIntCtxSw ;准备任务切换 BL OSTaskSwHook;调用Hook函数,此为空函数 LDR r4, =OSTCBHighRdy LDR r4, [r4];将高优先级的任务栈顶指针存到r4中 LDR r5, =OSTCBCur STR r4, [r5] ;OSTCBCur = OSTCBHighRdy LDR r6, =OSPrioHighRdy;取出高优先级 LDRBr6, [r6] ;优先级,字节传送 LDR r5, =OSPrioCur STRB r6, [r5] ;OSPrioCur = OSPrioHighRdy LDR sp, [r4];从r4中取得要恢复的任务的栈顶指针 LDMFD sp!, {r4};弹出任务栈中的第一个参数,即cpsr MSR cpsr_cxsf, r4;首先开始恢复cpsr LDMFD sp!, {r0-r12,lr,pc};依次恢复r0~r12,lr,pc,任务切换 ; *****OSTickISR开始***** EXPORTOSTickISR IMPORT OSIntEnter IMPORT OSTimeTick IMPORT OSIntExitLINK_SAVE DCD 0 ;用来保存时钟节拍中断前的lr,以便计算出pc而使之入栈PSR_SAVE DCD 0;用来保存中断前的spsr,中断产生时,svc模式下的cpsr存到spsrOSTickISR ;时钟节拍中断服务程序入口,需要用户在主函数中安装 STMFDsp!, {r4} ;因为r4下面要使用,故先保存r4到irq模式的堆栈中 LDR r4,=LINK_SAVE ; 准备保存LR,SPSR,以便得到中断前的pc和cpsr_svc STR lr,[r4] ; LINK_SAVE = lr_irq,此时lr=PC(中断发生前)+4 MRS lr, spsr;lr已保存,用lr取得spsr(保存的是中断前的cpsr) STR lr, [r4, #4] SR_SAVE = spsr_irq LDMFD sp!, {r4} ;恢复r4 ORR lr, lr, #0x80;在上下文切换前,屏蔽irq中断。注意lr存的是中断前的cpsr MSRcpsr_cxsf, lr ;中断产生前是svc模式,故必须要切换到此模式下保存现场SUB sp, sp, #4 ;按任务栈结构,空一个空间预留给PC STMFD sp!,{r0-r12,lr} ; 依次保存lr、r12~r0 LDR r4, =LINK_SAVE;准备保存pc,取得存svc模式下发生中断前lr的地址 LDR lr, [r4, #0] SUBlr, lr, #4 ;中断前的pc = LINK_SAVE - 4,此前lr为异常前pc+4的值 STRlr, [sp, #(14*4)];保存pc到任务栈中预留的空间 LDR r4, [r4, #4];开始保存cpsr,r4 = PSR_SAVE,即中断前的cpsr_svc STMFD sp!, {r4};保存svc模式下任务的cpsr,寄存器保护完毕 LDR r4, =OSTCBCur;下面开始将该堆栈指针传给OSTCBCur所指向的指针 LDR r4, [r4];便于OSIntExit函数判断是否当前任务优先级最高 STR sp, [r4];在OSTCBCur->OSTCBstkptr保存被中断的任务的栈顶指针 BL OSIntEnter;异常前的上下文保存好之后,开始准备中断服务,将OSIntNesting++ BLOSTimeTick ;将所有延时节拍不为1的任务的节拍数都减1,并清中断标志 BLOSIntExit;将OSIntNesting--,并判断是否有高优先级任务就绪,若有,则调;用OSIntCtxSw()调度该任务并不再返回; 若没有则返回到这里 LDMFD sp!,{r4} ;这里sp存的仍是调用OSIntEnter前的sp,即被中断的任务栈顶指针MSR cpsr_cxsf, r4;从堆栈中恢复中断前任务的cpsr,注意此时irq才被重新允许 LDMFD sp!,{r0-r12,lr,pc} ;恢复中断前任务的 r0-r12,lr和pc,返回被中断的任务;******OSTickISR函数代码完成,下面是临界段代码前后开关中断的函数******EXPORT ARMDisableInt ARMDisableInt MRS r0, cpsr;由于任务和内核都运行在svc模式下,因此可方便地操作cpsr STMFD sp!,{r0} ; 保存当前的cpsr ORR r0, r0, #0xc0 ;屏蔽FIQ,IRQ中断 MSRcpsr_c, r0 ;回写cpsr,只屏蔽IRQ中断 MOV pc, lr ;返回 EXPORTARMEnableInt ARMEnableInt ;必须和ARMDisableInt成对使用 LDMFD sp!,{r0} ;弹出在ARMDisableInt中被保存的cpsr MSR cpsr_c, r0;恢复关中断前的cpsr MOV pc, lr ;返回 END ;汇编代码结束;*****OS_CPU_A.S文件结束****** 4小结本文较详细地叙述了轻量级的实时内核礐/OS-II在ARM7处理器(S344B0X)的移植过程,并给出了简练而实用的代码,移植代码和移植思想对于礐/OS-II在其他ARM处理器上的移植具有较强的借鉴意义。一些航空电子设备比如发动机测控系统,由于功能复杂和实时性要求较高,各任务将激烈地竞争系统硬件资源,如何合理分配资源和及时调度任务则是摆在设计人员面前的重大问题。而RTOS在多任务调度和资源管理以及程序设计与系统维护升级上具有独特的优势,笔者相信RTOS在航空电子设备中应用将日趋广泛
继承事业,薪火相传
返回列表