为了正常的体验网站,请在浏览器设置里面开启Javascript功能!
首页 > AT91SAM7S_μCOS-II 的移植

AT91SAM7S_μCOS-II 的移植

2010-08-30 6页 pdf 138KB 33阅读

用户头像

is_032109

暂无简介

举报
AT91SAM7S_μCOS-II 的移植 本页内容发表于MCUZone,但不代表MCUZone的观点。 如果你对本页的技术内容有疑问,请到 MCUZone技术论坛 [http://www.mcuzone.com/bbs] 发帖。 如 果 你 认 为 本 页 的 内 容 侵 害 了 你 的 权 益 , 请 与 hotislandn@hotmail.com [mailto:hotislandn@hotmail.com];hdapple_2000@hotmail.com [mailto:hdapple_2000@hotmail.com] 联系,我们会在确认 后移除。 A...
AT91SAM7S_μCOS-II 的移植
本页内容发于MCUZone,但不代表MCUZone的观点。 如果你对本页的技术内容有疑问,请到 MCUZone技术论坛 [http://www.mcuzone.com/bbs] 发帖。 如 果 你 认 为 本 页 的 内 容 侵 害 了 你 的 权 益 , 请 与 hotislandn@hotmail.com [mailto:hotislandn@hotmail.com];hdapple_2000@hotmail.com [mailto:hdapple_2000@hotmail.com] 联系,我们会在确认 后移除。 AT91SAM7Sxx: µC/OS-II 的移植的移植的移植的移植 本 文 的 重 点 在 移 植 µC/OS-II [http://www.micrium.com/products/rtos/kernel/rtos.html] 到 AT91SMA7S [http://www.atmel.com/dyn/products/devices.asp?family_id=605#1586]系列的中断处理。 AT91SAM7Sxx 中断系统 AT91SAM7S系列使用的是 ARM7TDMI [http://www.mcuzone.com/Datasheet/DDI0210B_7TDMI_R4.pdf]核心,处理器的中断 源有IRQ与FIQ。 为了处理系统中不同的中断源,AT91SAM7S使用AIC(Advancde Interrupt Controller)来处理系统中所有的中断请求,然后交 由处理器处理。 AIC AIC的功能如下: 能处理多个中断请求 8优先级 向量模式中断 具体可以参考 AT91SAM7S数据手册 [http://www.mcuzone.com/Datasheet/AT91SAM7S256_128_64_321_32 Preliminary.pdf] 上有关AIC的章节。 AIC 编程 如果需要使用某个外设的中断,必须对AIC及该外设进行编程: 使能该外设时钟以启用该外设(AIC本身的时钟是一直有效的,无需使能) //*---------------------------------------------------------------------------- //* \fn AT91F_PMC_EnablePeriphClock //* \brief Enable peripheral clock //*---------------------------------------------------------------------------- __inline void AT91F_PMC_EnablePeriphClock ( AT91PS_PMC pPMC, // \arg pointer to PMC controller unsigned int periphIds) // \arg IDs of peripherals { pPMC->PMC_PCER = periphIds; } 设置该外设的接口中使能该外设中断 在AIC中配置该外设的中断 中断类型(电平/边沿)1. 中断优先级2. 中断服务程序3. //*---------------------------------------------------------------------------- //* \fn AT91F_AIC_ConfigureIt //* \brief Interrupt Handler Initialization //*---------------------------------------------------------------------------- __inline unsigned int AT91F_AIC_ConfigureIt ( AT91PS_AIC pAic, // \arg pointer to the AIC registers unsigned int irq_id, // \arg interrupt number to initialize unsigned int priority, // \arg priority to give to the interrupt unsigned int src_type, // \arg activation and sense of activation void (*newHandler) () ) // \arg address of the interrupt handler { unsigned int oldHandler; unsigned int mask ; oldHandler = pAic->AIC_SVR[irq_id]; mask = 0x1 << irq_id ; //* Disable the interrupt on the interrupt controller pAic->AIC_IDCR = mask ; //* Save the interrupt handler routine pointer and the interrupt priority pAic->AIC_SVR[irq_id] = (unsigned int) newHandler ; //* Store the Source Mode Register pAic->AIC_SMR[irq_id] = src_type | priority ; //* Clear the interrupt on the interrupt controller pAic->AIC_ICCR = mask ; return oldHandler; } 在AIC中使能该外设的中断 //*---------------------------------------------------------------------------- //* \fn AT91F_AIC_EnableIt //* \brief Enable corresponding IT number //*---------------------------------------------------------------------------- __inline void AT91F_AIC_EnableIt ( AT91PS_AIC pAic, // \arg pointer to the AIC registers unsigned int irq_id ) // \arg interrupt number to initialize { //* Enable the interrupt on the interrupt controller pAic->AIC_IECR = 0x1 << irq_id ; } 中断处理 本节简单给出使用AIC 时的中断处理序列。假设程序员已了解 ARM 处理器架构 [http://www.mcuzone.com/Datasheet /DDI0210B_7TDMI_R4.pdf],特别是处理器中断模式及相关状态位。 假设如下: 高级中断控制器已编程, AIC_SVR 寄存器载入相应的中断服务程序地址且中断使能。1. ARM 中断异常向量指令地址处放置下面的指令:2. LDR PC, [PC, # -&F20] ; ← 0×18 + 0×08 - 0xF20 = 0xFFFFF100 (#define AT91C_AIC_IVR ((AT91_REG *) 0xFFFFF100) 当nIRQ 出现,若CPSR 中位 “I” 为0(内核级中断使能),序列如下: CPSR 存于SPSR_irq,程序计数器当前值载入中断链接寄存器(R14_irq) 且程序计数器(R15) 中载入0×18。 在由地址 0x1C 取指周期中,ARM内核调整R14_irq,以4递减。 1. ARM 内核进入中断(IRQ)模式 。2. 当加载地址为0×18的指令执行时,程序计数器载入由AIC_IVR读出的值。读AIC_IVR有以下效果: 将当前中断挂起并使能最高优先级中断。当前级为当前中断优先级。 将处理器上的nIRQ 线屏蔽。因此即使向量未用,也必须对AIC_IVR进行读操作以使nIRQ 失效。 若中断源的中断类型被编程为边沿触发则自动清除中断标志, 对于电平型中断无此效果。 将当前等级及当前中断序号推入AIC的硬件堆栈。 返回相应于当前中断写入AIC_SVR 的值。 3. 先前的步骤将使得程序跳转到相应的中断服务程序。4. 如果需要中断嵌套,可通过清除CPSR中的“I”位来不加以屏蔽,使得内核又可重新响应nIRQ。使得高优先级的中断可以中断 当前中断的执行。 5. 中断处理程序可按要求执行,开始时保存寄存器,结束时恢复它们的值。在此过程中,高于当前中断优先级的中断将使序列返 回步骤1。 若中断编程为电平敏感,中断源必须在此过程中清除。 6. 必须将CPSR 中“I” 位置位以使在退出前屏蔽中断,保证中断退出时严格按照必须步骤完成。7. 须写中断结束命令寄存器(AIC_EOICR),以指示AIC 当前中断已完成。这将使得当前优先级由堆栈中弹出,恢复先前优先 级。若有其它中断挂起,等于或低于原先优先级却高于当前新的优先级, nIRQ 线将有效,但由于此时CPSR“I”被置位,因 此不会立即启动中断序列。然后恢复SPSR_irq,最后存于链接寄存器中的值写入PC。这对下面情况有用:中断返回到中断 执行前的状态,将存于SPSR 中的值载入CPSR,根据保存在SPSR_irq中的状态决定是否屏蔽中断。 8. SPSR中的“I” 位非常重要。置位时,则其表示屏蔽指令中断时,ARM 内核处于中断屏蔽的边缘。因此,当SPSR 恢复 时,屏蔽指令完成(中断被屏蔽)。 移植中的中断处理 OSTimeTick OSTimeTick 用于为µC/OS提供时钟节拍,用户系统需要定时调用该函数以使得任务调度器运转。 在AT91SAM7S上可以选择使用TC或者PIT来实现这个功能。 由于TC的功能多,如果仅用于这个功能似乎浪费,因此可以考虑使用PIT。 使用PIT来实现OSTimeTick时需要注意: PIT使用SCLK,也就是片上的32768Hz的RC振荡作为时钟源,这个信号源的准确度不高 PIT中断使用SYS中断源,与其它外设复用 PIT中断类型应设置为电平类型,否则在读取IVR时的清楚标志位的动作会影响SYS中的其余中断(比如DBGU中断) OS_CPU_IRQ_ISR 该函数作为第一级的中断处理函数,以汇编编程。主要完成中断前的环境保存,跳转中断,以及中断返回的工作。 下面看下这个函数的一些移植方式: Micrium 官方代码 OS_CPU_IRQ_ISR ; Disable FIQ for a moment MSR CPSR_c, #(NO_INT | IRQ32_MODE) ; Change to IRQ mode (to use the IRQ stack to handle interrupt) STMFD SP!, {R1-R3} ; PUSH WORKING REGISTERS ONTO IRQ STACK MOV R1, SP ; Save IRQ stack pointer ADD SP, SP,#12 ; Adjust IRQ stack pointer SUB R2, LR,#4 ; Adjust PC for return address to task MRS R3, SPSR ; Copy SPSR (i.e. interrupted task's CPSR) to R3 MSR CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode ; SAVE TASK'S CONTEXT ONTO TASK'S STACK STMFD SP!, {R2} ; Push task's Return PC STMFD SP!, {LR} ; Push task's LR STMFD SP!, {R4-R12} ; Push task's R12-R4 LDMFD R1!, {R4-R6} ; Move task's R1-R3 from IRQ stack to SVC stack STMFD SP!, {R4-R6} STMFD SP!, {R0} ; Push task's R0 onto task's stack STMFD SP!, {R3} ; Push task's CPSR (i.e. IRQ's SPSR) ; HANDLE NESTING COUNTER LDR R0, ??OS_IntNesting ; OSIntNesting++; LDRB R1, [R0] ADD R1, R1,#1 STRB R1, [R0] CMP R1, #1 ; if (OSIntNesting == 1) { BNE OS_CPU_IRQ_ISR_1 LDR R4, ??OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP LDR R5, [R4] STR SP, [R5] ; } OS_CPU_IRQ_ISR_1 MSR CPSR_c, #(NO_IRQ | IRQ32_MODE) ; Re-enable FIQ, Change to IRQ mode (to use the IRQ stack to handle interrupt) LDR R0, ??OS_CPU_IRQ_ISR_Handler ; OS_CPU_IRQ_ISR_Handler(); MOV LR, PC BX R0 MSR CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode LDR R0, ??OS_IntExit ; OSIntExit(); MOV LR, PC BX R0 ; RESTORE NEW TASK'S CONTEXT LDMFD SP!, {R4} ; Pop new task's CPSR MSR SPSR_cxsf, R4 LDMFD SP!, {R0-R12,LR,PC}^ ; Pop new task's context os_cpu_a.asm Micrium官方版本 [http://www.mcuzone.com/project/sam_ucos2_porting/os_cpu_a_official.asm] Hotislandn 移植版本 ;************** enter IRQ mode, interrupt was disabled ******************** SUB LR,LR,#4 ; IRQ return address STMFD SP!,{LR} STMFD SP!,{R0-R3} ; Save registers, as ATPCS required MRS R3,SPSR ; STMFD SP!,{R3} ; Save interrupted mode CPSR LDR R0,_OS_IntNesting LDRB R1,[R0] ADD R1,R1,#1 STRB R1,[R0] ; increase OSIntNesting CMP R1, #1 ; the first interrupt BNE IRQ_Nesting ; the nesting irq ; this is the first interrupt ; save the interrupted task's stack info ADD R2,SP,#4 ; keep IRQ stack for geting R0-R3 MOV R0,LR ;************** Save task context ***************************************** MSR CPSR_cxsf,#(NO_INT | SVC32_MODE) ; switch to SVC32 mode, disable all interrupts STMFD SP!,{R0} ; PC STMFD SP!,{R4-R12,LR} ; other registers, task LR LDMIA R2!,{R4-R7} ; as R0-R3 STMFD SP!,{R4-R7} ; R0-R3 STMFD SP!,{R3} ; CPSR LDR R4, _OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP LDR R5, [R4] STR SP, [R5] ;************** Execute ISR in IRQ mode, with interrupts enable *********** IRQ_Nesting MSR CPSR_cxsf,#(NO_INT | IRQ32_MODE) ; swith back to IRQ mode LDR R0,_OS_CPU_IRQ_ISR_Handler MOV LR,PC BX R0 ; call ISR MSR CPSR_cxsf,#(NO_IRQ | IRQ32_MODE) ; swith to IRQ mode, disable interrupts MOV R14,SP ADD SP,SP,#24 ; Remove contents in IRQ stack ; Pushed 6 items(4bytes each) in IRQ stack at the begining of this routine ; if Context switch happened below, the program will not return thus the ; IRQ stack has no chance to pop them out, this cause rubbish in IRQ stack ;************** Execute OSIntExit in SVC mode ***************************** MSR CPSR_cxsf,#(NO_INT | SVC32_MODE) ; disable interrupts LDR R0,_OS_IntExit MOV LR,PC BX R0 ; OSIntExit will not return if another task is ready with higher priority ;************** IRQ end *************************************************** ; no higher priority task or OSIntNesting is not 0 ; code for exiting from IRQ ; it will return to the orignal task or the interrupted ISR (interrupt nesting) LDR R0,_OS_IntNesting ; if OSIntNesting = 0, return to the original task LDRB R0,[R0] CMP R0,#0 BNE IRQ_EXIT ;MSR CPSR_cxsf,#(NO_INT | SVC32_MODE) LDMFD SP!,{R0} ; CPSR MSR SPSR_cxsf,R0 LDMFD SP!,{R0-R12,LR,PC}^ ; end of interrupt, return to orignal task ; the task stack was saved before IRQ_EXIT ; interrupt nesting ; switch back to IRQ mode, pop out the IRQ registers MSR CPSR_cxsf,#(NO_IRQ | IRQ32_MODE) MOV SP,R14 ; restore the IRQ stack point LDMFD SP!,{R0} ; CPSR MSR SPSR_cxsf,R0 LDMFD SP!,{R0-R3,PC}^ os_cpu_a.asm Hotislandn修改版本 [http://www.mcuzone.com/project/sam_ucos2_porting/os_cpu_a_mz.asm] Leafboy 移植版本 OSIntCtxSw ;*********************************************************** ; IRQ STACK R4 R14 R0 R1 R2 R3 R12 SPSR LR(PC) ;*********************************************************** ; SAVE TASK'S CONTEXT ONTO TASK'S STACK ADD SP, SP, #(7 + 2)*4 ; Adjust IRQ stack pointer ; {R0-R3, R12, SPSR, LR}=7*4, OSIntExit=2*4 SUB R0, SP, #3*4 ; R0->R12 MSR CPSR_c, #NO_INT | SYS_MODE ; Change to SYS mode LDMIA R0, {R1-R3} ; R12,SPSR,LR(PC)=>R1,R2,R3 SUB R0, R0, #4*4 ; Moving (R3-R0) STMFD SP!, {R3} ; R3(PC)=>[SP] STMFD SP!, {R1, LR} ; R1(R12),LR=>[SP] STMFD SP!, {R4-R11} ; R4-R11=>[SP] LDMIA R0, {R4-R7} ; R0-R3=>R4-R7 STMFD SP!, {R2,R4-R7} ; R2(SPSR),R4-R11(R0-R3)=>[SP] B OSCtxSw1 ;********************************************************************************************************* ; IRQ Interrupt Service Routine ;********************************************************************************************************* RSEG CODE:CODE:NOROOT(2) CODE32 OS_CPU_IRQ_ISR SUB LR, LR, #4 ;- Adjust and save LR_irq in IRQ stack STMFD SP!, {LR} MRS R14, SPSR ;- Save SPSR need to be saved for nested interrupt STMFD SP!, {R12, R14} ; HANDLE NESTING COUNTER LDR R14, ??OS_IntNesting ; OSIntNesting++; LDRB R12, [R14] ADD R12, R12,#1 STRB R12, [R14] ;- Write in the IVR to support Protect Mode ;- No effect in Normal Mode ;- De-assert the NIRQ and clear the source in Protect Mode LDR R14, =AT91C_BASE_AIC LDR R12 , [R14, #AIC_IVR] STR R14, [R14, #AIC_IVR] ;IRQ_ISR_Handler { MSR CPSR_c, #IRQ_MODE ;- Enable Interrupt STMFD SP!, {R0-R3} ;- Save scratch/used registers and LR in IRQ Stack MOV LR, PC ;- Branch to the routine pointed by the AIC_IVR BX R12 ; IRQ_ISR_Handler() MSR CPSR_c, #I_BIT | IRQ_MODE ;- Disable Interrupt and switch back in IRQ mode ;} IRQ_ISR_Handler LDR R14, =AT91C_BASE_AIC ;- Mark the End of Interrupt on the AIC STR R14, [R14, #AIC_EOICR] LDR R12, ??OS_IntExit ; OSIntExit(); MOV LR, PC BX R12 LDMIA SP!, {R0-R3} ;- Restore scratch/used registers and LR from User Stack LDMIA SP!, {R12, R14} ;- Restore SPSR_irq and r12 from IRQ stack MSR SPSR_cxsf, R14 LDMIA SP!, {PC}^ ;- Restore adjusted LR_irq from IRQ stack directly in the PC os_cpu_a.asm leafboy修改版本 [http://www.mcuzone.com/project/sam_ucos2_porting/os_cpu_a_o1.asm] 比较以上各版本可以发现,官方版本在每次中断发生时都将寄存器保存到任务的堆栈而无视OS_IntNesting的值,会对任务堆栈造 成压力。 Hotislandn的版本仅在OS_IntNesting为1时保存寄存器到任务,结构也比较清楚,但是程序比较长,中断时间较长。 leafboy的 版 本 对 官 方 版 本 做 了 改 动,仅 保 存 必 要 的 寄 存 器(根 据 ATPCS规 范 [http://www.mcuzone.com/project /sam_ucos2_porting/ARM_Instruction_Set_wcby.pdf]),仅在中断中发生任务切换时才保存寄存器到被中断的任务,而前面两种移 植方式均在进入中断时就会保存寄存器到任务堆栈,因此时间消耗比较小(并不是每次中断都会造成任务切换)。 后两种移植方式都基于官方的移植。 以上三种移植方式都在IRQ模式下处理中断。 µC/OS-View 的移植 µC/OS-View介绍 [http://www.micrium.com/products/rtos/ucos-ii_view.html] µC/OS-View移植说明(PDF格式) [http://www.mcuzone.com/project/sam_ucos2_porting/uCOS-View.pdf] 相关链接 µC/OS 官方链接 80x86上context切换的官方动画 [http://www.micrium.com/products/rtos/kernel/rtos.html] 2.83 release notes [http://www.mcuzone.com/project/sam_ucos2_porting/ReleaseNotes.PDF] 配置参考 [http://www.mcuzone.com/project/sam_ucos2_porting/uCOS-II-CfgMan.PDF] API 参考 [http://www.mcuzone.com/project/sam_ucos2_porting/uCOS-II-RefMan.PDF] 移植参考 Micrium官方SAM7移植页面 [http://www.micrium.com/atmel/AT91SAM7.html] 官方ARM/Thumb移植的图解(PDF格式) [http://www.mcuzone.com/project/sam_ucos2_porting/AN-1014-PPT.pdf] 官方ARM/Thumb移植的代码分析(PDF格式) [http://www.mcuzone.com/project/sam_ucos2_porting/AN-1014.pdf] 移植范例 uC/OS-II 2.83在s32上的移植(论坛链接) [http://www.mcuzone.com/bbs/dispbbs.asp?BoardID=7&ID=2415] s64dek的ucos2的代码,添加了uart0的输出(论坛链接) [http://www.mcuzone.com/bbs/dispbbs.asp?BoardID=7&ID=1122] 提供 一 本 站 S64-DEK REV2.0评 估 板 移 植 uc/os-ii2.8 by IAR4.40A(论 坛 链 接 ) [http://www.mcuzone.com /bbs/dispbbs.asp?BoardID=7&ID=1643] AT91SAM7S 相关资源 Atmel 提 供 的 AT91SAM7S64 的 软 件 库 文 件 (lib_AT91SAM7S64.h) [http://www.mcuzone.com/project /sam_ucos2_porting/lib_AT91SAM7S64.h] AT91SAM7S外 设 速 查 [http://www.mcuzone.com/project/sam_ucos2_porting/BasicIAR-SAM7S64-IAR430A/BasicIAR- SAM7S/index.html] user\dracula\sam_ucos2_porting.txt — 最后更改: 2007/03/07 19:46 由 dracula
/
本文档为【AT91SAM7S_μCOS-II 的移植】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索