免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1431 | 回复: 0
打印 上一主题 下一主题

ARM ucos o_cpu_a.S (gcc) 注释 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-30 17:39 |只看该作者 |倒序浏览
/*
*********************************************************************************************************
*                                               uC/OS-II
*                                         The Real-Time Kernel
*
*                          (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
*                                          All Rights Reserved
*
* File : OS_CPU_A.ASM
* By   : Jean J. Labrosse
*********************************************************************************************************
*********************************************************************************************************
*                                               ARM Port
*
*                 Target           : ARM (Includes ARM7, ARM9)
*                 Ported by        : Michael Anburaj
*                 URL              : http://geocities.com/michaelanburaj/    Email : michaelanburaj@hotmail.com
*
*********************************************************************************************************
*/
//Pre-defined constants
#define USERMODE    0x10
#define FIQMODE     0x11
#define IRQMODE     0x12
#define SVCMODE     0x13
#define ABORTMODE   0x17
#define UNDEFMODE   0x1b
#define MODEMASK    0x1f
#define NOINT       0xc0
#define TBIT        0x20
//*********************************************************************************************************
//                                          START MULTITASKING
//                                       void OSStartHighRdy(void)
//
// Note : OSStartHighRdy() MUST:
//           a) Call OSTaskSwHook() then,
//           b) Set OSRunning to TRUE,
//           c) Switch to the highest priority task.
//*********************************************************************************************************
        .global  OSStartHighRdy
OSStartHighRdy:
        bl OSTaskSwHook             // Call user defined task switch hook
        ldr r4,=OSRunning           // Indicate that multitasking has started
        mov r5,#1
        strb r5,[r4]
        ldr r4,=OSTCBHighRdy        // Get highest priority task TCB address
        ldr r4,[r4]                 // get stack pointer
        ldr sp,[r4]                 // switch to the new stack
        ldmfd sp!,{r4}              // pop new task's spsr
        ldmfd sp!,{r4}              // pop new task's psr
        msr SPSR_cxsf,r4
        ldmfd sp!,{r0-r12,lr,pc}^   // pop new task's r0-r12,lr & pc
//*********************************************************************************************************
//                                PERFORM A CONTEXT SWITCH (From task level)
//                                           void OSCtxSw(void)
//
// Note(s):    Upon entry,
//             OSTCBCur     points to the OS_TCB of the task to suspend
//             OSTCBHighRdy points to the OS_TCB of the task to resume
//
//*********************************************************************************************************
        .global  OSCtxSw
OSCtxSw:
// Special optimised code below:
        stmfd sp!,{lr}              // push pc (lr should be pushed in place of PC)
        ldr lr,=0xdead1eaf          // Just a dummy value is pushed for lr (for actual lr is safe inside callers stack)
        stmfd sp!,{r0-r12,lr}       // push lr & register file
        mrs r4,cpsr
#ifdef THUMB_TASKS
        orr r4,r4,#TBIT
#endif
        stmfd sp!,{r4}              // push current psr
        mrs r4,spsr
        stmfd sp!,{r4}              // push current spsr
        // OSPrioCur = OSPrioHighRdy
        ldr r4,=OSPrioCur
        ldr r5,=OSPrioHighRdy
        ldrb r6,[r5]
        strb r6,[r4]
        
        // Get current task TCB address
        ldr r4,=OSTCBCur
        ldr r5,[r4]
        str sp,[r5]                 // store sp in preempted tasks's TCB
        bl OSTaskSwHook             // call Task Switch Hook
        // Get highest priority task TCB address
        ldr r6,=OSTCBHighRdy
        ldr r6,[r6]
        ldr sp,[r6]                 // get new task's stack pointer
        // OSTCBCur = OSTCBHighRdy
        str r6,[r4]                 // set new current task TCB address
        ldmfd sp!,{r4}              // pop new task's spsr
        ldmfd sp!,{r4}              // pop new task's psr
        msr SPSR_cxsf,r4
        ldmfd sp!,{r0-r12,lr,pc}^   // pop new task's r0-r12,lr & pc
//*********************************************************************************************************
//                                PERFORM A CONTEXT SWITCH (From an ISR)
//                                        void OSIntCtxSw(void)
//
// Note(s): This function only flags a context switch to the ISR Handler
//
//*********************************************************************************************************
        .global  OSIntCtxSw
OSIntCtxSw:
        //OSIntCtxSwFlag = True
        ldr r0,=OSIntCtxSwFlag        //R0=&OSIntCtxSwFlag;取地址
        mov r1,#1
        str r1,[r0]                   //OSIntCtxSwFlag = 0
        bx lr
        
//*********************************************************************************************************
//                                            IRQ HANDLER
//
//        This handles all the IRQs
//        Note: FIQ Handler should be written similar to this
//
//*********************************************************************************************************
        .global  UCOS_IRQHandler
UCOS_IRQHandler:
        // Fix the return address
        sub lr,lr,#4
        stmfd sp!,{r0-r3,r12,lr}     //R4~R11 没有用到,用到了也会自动保护
        bl OSIntEnter
        bl C_IRQHandler              //OSTick()函数中会确定OSIntCtxSwFlag的值。
        bl OSIntExit
        // Is OSIntCtxSwFlag == True ?
        ldr r0,=OSIntCtxSwFlag
        ldr r1,[r0]
        cmp r1,#1                    //OSIntCtxSwFlag=1的话就进行任务切换。
        beq _IntCtxSw
        ldmfd sp!,{r0-r3,r12,pc}^    //没有切换会运行这段代码。
_IntCtxSw:
        // OSIntCtxSwFlag = False
        mov r1,#0      
        str r1,[r0]                  //OSIntCtxSwFlag = 0;清零
        // Get old task's sp & lr
        mrs r0,spsr                  //读apsr物理状态寄存器。
        orr r0,r0,#NOINT             //或;
        bic r0,r0,#TBIT              //位清除;
        msr cpsr_c,r0                //写状态寄存器,模式切换,irq-->usr
        mov r1,sp                    //R1=(old task's)sp
        mov r2,lr                    //R2=(old tasks's)lr
        bic r0,r0,#MODEMASK          //
        orr r0,r0,#IRQMODE           //
        msr cpsr_c,r0                //模式切换,usr-->irq
        // Unwind IRQ's sp without poping r0-r3
        mov r3,sp                    //保存IRQ模式下的SP
        add sp,sp,#(4*4)             //不弹R0~R3
        ldmfd sp!,{r12,lr}           //弹出R12_usr和LR_usr ,
/////////////////////////////////////////////////////////////////////////////////////////////
        stmfd r1!,{r2,lr}            //R1=old task's SP;r2=old task's lr;lr =old task's pc
                                     //保存老任务的lr 和 PC 到老任务的栈中
        stmfd r1!,{r4-r12}           //push old task's r12-r4
        // Get r0-r3 from IRQ's stack
        mov r6,r1
        ldmfd r3,{r0-r3}
        stmfd r6!,{r0-r3}           // push old task's r3-r0
        
        mrs r3,spsr
        stmfd r6!,{r3}              // push old task's psr
        stmfd r6!,{r3}              // push old task's spsr (don't care)
///////////////////////////////////以上是保存现场///////////////////////////////////////////
        // OSPrioCur = OSPrioHighRdy
        ldr r4,=OSPrioCur
        ldr r5,=OSPrioHighRdy
        ldrb r5,[r5]
        strb r5,[r4]
        
        // Get current task's TCB address
        ldr r4,=OSTCBCur            //从TCB结构体可以看出:
        ldr r5,[r4]                 //OSTCBCur的地址也是OSTCBCur->OSTCBStkPtr的地址
        str r6,[r5]                 // store sp in preempted tasks's TCB
        bl OSTaskSwHook             // call Task Switch Hook
        // Get highest priority task's TCB address
        ldr r6,=OSTCBHighRdy
        ldr r6,[r6]                 ////OSTCBCur的地址也是OSTCBCur->OSTCBStkPtr的地址
        ldr r5,[r6]                 // get new task's stack pointer
        // OSTCBCur = OSTCBHighRdy
        str r6,[r4]                 // set new current task TCB address
        ldmfd r5!,{r4}              // pop new task's spsr (don't care)
        ldmfd r5!,{r4}              // pop new task's psr   并放到R4中
        // Leave IRQ mode
        orr r0,r4,#NOINT            //利用R4转到usr模式
        bic r0,r0,#TBIT
        msr cpsr_c,r0
        msr spsr_cxsf,r4
        mov sp,r5                   //sp=new task's sp;
        ldmfd sp!,{r0-r12,lr,pc}^   // pop new task's r0-r12,lr & pc
/////////////////////////////////新任务运行///////////////////////////////////////////////////
//*********************************************************************************************************
//                                   CRITICAL SECTION METHOD 3 FUNCTIONS
//
// Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
//              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
//              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
//              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
//              into the CPU's status register.
//
//              OS_CPU_SR OSCPUSaveSR()
// Arguments  : none
//
// Returns    : OS_CPU_SR
//
//              OSCPURestoreSR(OS_CPU_SR cpu_sr)
// Arguments  : OS_CPU_SR
//
// Returns    : none
//
// Note(s)    : These functions are used in general like this,
//
//            void Task (void *data)
//            {
//                    #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
//                          OS_CPU_SR  cpu_sr;
//                    #endif
//                         :
//                         :
//                    OS_ENTER_CRITICAL(); /* cpu_sr = OSCPUSaveSR(); */
//                         :
//                         :
//                    OS_EXIT_CRITICAL();  /* OSCPURestoreSR(cpu_sr); */
//                         :
//                         :
//            }
//*********************************************************************************************************
        .global  OSCPUSaveSR
OSCPUSaveSR:
        mrs r0,CPSR
        orr r1,r0,#NOINT
        msr CPSR_c,r1
        bx lr
        .global  OSCPURestoreSR
OSCPURestoreSR:
        msr CPSR_c,r0
        bx lr


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/75045/showart_1915491.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP