lpc1788_ucos\uCOSII_cpu\cpu_a.asm os_cpu_a.asm --ucosii移植在lpc1788--part3

;*****************************************************************************************
;                                               uC/CPU
;                                    CPU CONFIGURATION & PORT LAYER
;
;                          (c) Copyright 2004-2008; Micrium, Inc.; Weston, FL
;                                            CPU PORT FILE
;                                            ARM-Cortex-M3
;                                      RealView Development Suite
;                            RealView Microcontroller Development Kit (MDK)
;                                       ARM Developer Suite (ADS)
;                                            Keil uVision
; Filename      : cpu_a.asm
; Version       : V1.19
; Programmer(s) : BAN
;                                           PUBLIC FUNCTIONS
;*****************************************************************************************
        EXPORT  CPU_IntDis
        EXPORT  CPU_IntEn

        EXPORT  CPU_SR_Save
        EXPORT  CPU_SR_Restore

        EXPORT  CPU_CntLeadZeros
        EXPORT  CPU_RevBits

        EXPORT  CPU_WaitForInt
        EXPORT  CPU_WaitForExcept

;*****************************************************************************************
;                                      CODE GENERATION DIRECTIVES
;*****************************************************************************************
        AREA |.text|, CODE, READONLY, ALIGN=2
        THUMB
        REQUIRE8
        PRESERVE8
;******************************************************************************************
;                                    DISABLE and ENABLE INTERRUPTS
; Description : Disable/Enable interrupts.
;
; Prototypes  : void  CPU_IntDis(void);
;               void  CPU_IntEn (void);
;******************************************************************************************
CPU_IntDis
        CPSID   I
        BX      LR
CPU_IntEn
        CPSIE   I
        BX      LR
;******************************************************************************************
;                                      CRITICAL SECTION FUNCTIONS
; Description : Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking, the
;               state of the interrupt disable flag is stored in the local variable 'cpu_sr' & interrupts
;               are then disabled ('cpu_sr' is allocated in all functions that need to disable interrupts).
;               The previous interrupt state is restored by copying 'cpu_sr' into the CPU's status register.
;
; Prototypes  : CPU_SR  CPU_SR_Save   (void);
;               void    CPU_SR_Restore(CPU_SR cpu_sr);
;
; Note(s)     : (1) These functions are used in general like this:
;
;                   void  Task (void *p_arg)
;                   {
;                                                               /* Allocate storage for CPU status register */
;                   #if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
;                       CPU_SR  cpu_sr;
;                   #endif
;                       CPU_CRITICAL_ENTER();                   /* cpu_sr = CPU_SR_Save();                  */
;                            :
;                       CPU_CRITICAL_EXIT();                    /* CPU_SR_Restore(cpu_sr);                  */
;                            :
;                   }
;******************************************************************************************
CPU_SR_Save
        MRS     R0, PRIMASK     ; Set prio int mask to mask all (except faults)
        CPSID   I
        BX      LR
CPU_SR_Restore                  ; See Note #2.
        MSR     PRIMASK, R0
        BX      LR
;*****************************************************************************************
;                                         COUNT LEADING ZEROS
;
; Description : Counts the number of binary zero bits before the first binary one bit in the argument.
;               If the argument is zero, the value 32 is returned.
;
; Prototypes : CPU_INT32U  CPU_CntLeadZeros (CPU_INT32U  val)
;
; Argument(s) : val     variable to count leading zeros
;*****************************************************************************************
CPU_CntLeadZeros
        CLZ     R0, R0          ; Count leading zeros
        BX      LR
;*****************************************************************************************
;                                             REVERSE BITS
;
; Description : Reverses the bits in the argument.
;
; Prototypes : CPU_INT32U  CPU_RevBits (CPU_INT32U  val)
;
; Argument(s) : val     variable to reverse
;*****************************************************************************************
CPU_RevBits
        RBIT    R0, R0          ; Reverse bits
        BX      LR
;*****************************************************************************************
;                                         WAIT FOR INTERRUPT
;
; Description : Enters sleep state, which will be exited when an interrupt is received.
;
; Prototypes  : void  CPU_WaitForInt (void)
;
; Argument(s) : none.
;*****************************************************************************************
CPU_WaitForInt
        WFI                     ; Wait for interrupt
        BX      LR
;*****************************************************************************************
;                                         WAIT FOR EXCEPTION
;
; Description : Enters sleep state, which will be exited when an exception is received.
;
; Prototypes  : void  CPU_WaitForExcept (void)
;
; Argument(s) : none.
;*****************************************************************************************
CPU_WaitForExcept
        WFE                     ; Wait for exception
        BX      LR
;*****************************************************************************************
;                                     CPU ASSEMBLY PORT FILE END
;*****************************************************************************************
        END

;*****************************************************************************************
;                                               uC/OS-II
;                                         The Real-Time Kernel
;
;                               (c) Copyright 1992-2006, Micrium, Weston, FL
;                                          All Rights Reserved
;                                           Generic ARM Port
; File      : OS_CPU_A.ASM
; Version   : V2.86
; By        : Jean J. Labrosse
;
; For       : ARMv7M Cortex-M3
; Mode      : Thumb2
; Toolchain : RealView Development Suite
;             RealView Microcontroller Development Kit (MDK)
;             ARM Developer Suite (ADS)
;             Keil uVision
;*****************************************************************************************

;*****************************************************************************************
;                                           PUBLIC FUNCTIONS
;*****************************************************************************************
    EXTERN  OSRunning                       ; External references
    EXTERN  OSPrioCur
    EXTERN  OSPrioHighRdy
    EXTERN  OSTCBCur
    EXTERN  OSTCBHighRdy
    EXTERN  OSIntNesting
    EXTERN  OSIntExit
    EXTERN  OSTaskSwHook
    EXPORT  OS_CPU_SR_Save                  ; Functions declared in this file
    EXPORT  OS_CPU_SR_Restore
    EXPORT  OSStartHighRdy
    EXPORT  OSCtxSw
    EXPORT  OSIntCtxSw
    EXPORT  OS_CPU_PendSVHandler
;*****************************************************************************************
;                                                EQUATES
;*****************************************************************************************
NVIC_INT_CTRL   EQU     0xE000ED04          ; Interrupt control state register.
NVIC_SYSPRI14   EQU     0xE000ED22          ; System priority register (priority 14).
NVIC_PENDSV_PRI EQU           0xFF          ; PendSV priority value (lowest).
NVIC_PENDSVSET  EQU     0x10000000          ; Value to trigger PendSV exception.

;*****************************************************************************************
;                                      CODE GENERATION DIRECTIVES
;*****************************************************************************************
    AREA |.text|, CODE, READONLY, ALIGN=2
    THUMB
    REQUIRE8
    PRESERVE8

;*****************************************************************************************
;                                   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.
;
; Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void);
;                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
; Note(s)    : 1) These functions are used in general like this:
;
;                 void Task (void *p_arg)
;                 {
;                 #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
;                     OS_CPU_SR  cpu_sr;
;                 #endif
;                          :
;                          :
;                     OS_ENTER_CRITICAL();    /* cpu_sr = OS_CPU_SaveSR();                */
;                          :
;                          :
;                     OS_EXIT_CRITICAL();     /* OS_CPU_RestoreSR(cpu_sr);                */
;                          :
;                          :
;                 }
;*****************************************************************************************
OS_CPU_SR_Save
    MRS     R0, PRIMASK         ; Set prio int mask to mask all (except faults)
    CPSID   I                   ;Disable interrupts and configurable fault handlers (set PRIMASK)
    BX      LR                  ;Return from function call
OS_CPU_SR_Restore
    MSR     PRIMASK, R0
    BX      LR
;*****************************************************************************************
;                                          START MULTITASKING
;                                       void OSStartHighRdy(void)
;
; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause
;              the first task to start.
;
;           2) OSStartHighRdy() MUST:
;              a) Setup PendSV exception priority to lowest;
;              b) Set initial PSP to 0, to tell context switcher this is first run;
;              c) Set OSRunning to TRUE;
;              d) Trigger PendSV exception;
;              e) Enable interrupts (tasks will run with interrupts enabled).
;*****************************************************************************************
OSStartHighRdy
    LDR     R0, =NVIC_SYSPRI14          ; Set the PendSV exception priority
    LDR     R1, =NVIC_PENDSV_PRI
    STRB    R1, [R0]

    MOVS    R0, #0                      ; Set the PSP to 0 for initial context switch call
    MSR     PSP, R0

    LDR     R0, =OSRunning              ; OSRunning = TRUE
    MOVS    R1, #1
    STRB    R1, [R0]

    LDR     R0, =NVIC_INT_CTRL          ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    CPSIE   I                           ; Enable interrupts at processor level
OSStartHang
    B       OSStartHang                 ; Should never get here

;*****************************************************************************************
;                               PERFORM A CONTEXT SWITCH (From task level)
;                                           void OSCtxSw(void)
; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch.  This function
;              triggers the PendSV exception which is where the real work is done.
;*****************************************************************************************
OSCtxSw
    LDR     R0, =NVIC_INT_CTRL      ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR

;*****************************************************************************************
;                             PERFORM A CONTEXT SWITCH (From interrupt level)
;                                         void OSIntCtxSw(void)
;
; Notes:    1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as
;              the result of an interrupt.  This function simply triggers a PendSV exception which will
;              be handled when there are no more interrupts active and interrupts are enabled.
;*****************************************************************************************
OSIntCtxSw
    LDR     R0, =NVIC_INT_CTRL       ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR

;*****************************************************************************************
;                                         HANDLE PendSV EXCEPTION
;                                     void OS_CPU_PendSVHandler(void)
;
; Note(s) : 1) PendSV is used to cause a context switch.  This is a recommended method for performing
;              context switches with Cortex-M3.  This is because the Cortex-M3 auto-saves half of the
;              processor context on any exception, and restores same on return from exception.  So only
;              saving of R4-R11 is required and fixing up the stack pointers.  Using the PendSV exception
;              this way means that context saving and restoring is identical whether it is initiated from
;              a thread or occurs due to an interrupt or exception.
;           2) Pseudo-code is:
;              a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
;              b) Save remaining regs r4-r11 on process stack;
;              c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
;              d) Call OSTaskSwHook();
;              e) Get current high priority, OSPrioCur = OSPrioHighRdy;
;              f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
;              g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
;              h) Restore R4-R11 from new process stack;
;              i) Perform exception return which will restore remaining context.
;           3) On entry into PendSV handler:
;              a) The following have been saved on the process stack (by processor):
;                 xPSR, PC, LR, R12, R0-R3
;              b) Processor mode is switched to Handler mode (from Thread mode)
;              c) Stack is Main stack (switched from Process stack)
;              d) OSTCBCur      points to the OS_TCB of the task to suspend
;                 OSTCBHighRdy  points to the OS_TCB of the task to resume
;           4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
;              know that it will only be run when no other exception or interrupt is active, and
;              therefore safe to assume that context being switched out was using the process stack (PSP).
;*****************************************************************************************
OS_CPU_PendSVHandler
    CPSID   I                               ; Prevent interruption during context switch
    MRS     R0, PSP                         ; PSP is process stack pointer
    CBZ     R0, OS_CPU_PendSVHandler_nosave ; Skip register save the first time
    SUBS    R0, R0, #0x20                   ; Save remaining regs r4-11 on process stack
    STM     R0, {R4-R11}
    LDR     R1, =OSTCBCur                   ; OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                        ; R0 is SP of process being switched out
                                            ; At this point, entire context of process has been saved
OS_CPU_PendSVHandler_nosave
    PUSH    {R14}                           ; Save LR exc_return value
    LDR     R0, =OSTaskSwHook               ; OSTaskSwHook();
    BLX     R0
    POP     {R14}
    LDR     R0, =OSPrioCur                  ; OSPrioCur = OSPrioHighRdy;
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]
    LDR     R0, =OSTCBCur                   ; OSTCBCur  = OSTCBHighRdy;
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]
    LDR     R0, [R2]                        ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
    LDM     R0, {R4-R11}                    ; Restore r4-11 from new process stack
    ADDS    R0, R0, #0x20
    MSR     PSP, R0                         ; Load PSP with new process SP
    ORR     LR, LR, #0x04                   ; Ensure exception return uses process stack
    CPSIE   I
    BX      LR                              ; Exception return will restore remaining context
    END

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值