ucosii在sharp7a400上的移植

源代码在线查看: os_cpu_a.s

软件大小: 22 K
上传用户: budyang
关键词: ucosii sharp7 sharp a400
下载地址: 免注册下载 普通下载 VIP

相关代码

				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				; $Workfile:   os_cpu_a.s  $
				; $Revision:   1.0  $
				; $Author:   WellsK  $
				; $Date:   Jun 30 2003 15:18:32  $
				; 
				; Project: Lh7A400 MicroCos-II assembly code
				;
				; Description:
				;     Assembly language files for the MicroCos-II OS and the LH7A400
				;     port.
				;
				; Revision history:
				; $Log:   //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh7a400/ports/ucosii/os_cpu_a.s-arc  $
				; 
				;    Rev 1.0   Jun 30 2003 15:18:32   WellsK
				; Initial revision.
				; 
				;  
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				; SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
				; OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
				; AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES, 
				; SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
				; 
				; SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY 
				; FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A 
				; SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
				; FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
				; 
				; COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
				;     CAMAS, WA
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				
				    EXPORT ucos_irq_handler
				    EXPORT OSStartHighRdy
				    EXPORT OS_TASK_SW
				    EXPORT OSCtxSw
				    EXPORT OSIntCtxSw
				
				    IMPORT OSRunning
				    IMPORT OSTaskSwHook
				    IMPORT OSTCBHighRdy
				    IMPORT OSTCBCur
				    IMPORT OSPrioHighRdy
				    IMPORT OSPrioCur
				    IMPORT OSIntNesting
				    IMPORT OSIntEnter
				    IMPORT OSTimeTick
				    IMPORT OSIntExit
				    IMPORT irq_func_ptrs
				
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				; Private defines and data
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				
				MODE_SVC             EQU 0x00000013
				MODE_DIS_IRQ         EQU 0x00000080
				INTC_BASE_ADDR       EQU 0x80000500
				INTC_SOURCE_OFF      EQU 0x00000000
				INTC_TIMER1_INT_MASK EQU 0x00000100
				TIMER1_INT_CLR       EQU 0x80000C0C
				INTC_FIRST_IRQ       EQU 5
				
				    AREA |C$$code|, CODE, READONLY
				
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				;
				; Function: OSStartHighRdy
				;
				; Purpose: Set highest priority uCos-II task ready to run
				;
				; Description:
				;     Call the OSTaskSwHook() function. Set OSRunning to TRUE. Get the
				;     address of the highest priority task control block. Get the
				;     stack pointer for the highest prior task (from the fetched TCB).
				;     Set the current stack pointer to the fetched stack pointer. Set
				;     the current task control block pointer to the highest priority
				;     task control block pointer. Restore the new task's SPSR and CPSR
				;     registers. Restore all ARM registers for the task and continue
				;     the task.
				;
				; Parameters: NA
				;
				; Outputs; NA
				;
				; Returns: NA
				;
				; Notes: This function should never be called from the IRQ level.
				;
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				OSStartHighRdy
				    BL OSTaskSwHook                   ; Call OSTaskSwHook
				    LDR r0, =OSRunning
				    MOV r1, #1
				    STRB r1, [r0]                     ; OSRunning = TRUE
				
				    LDR r0, =OSTCBHighRdy             ; Get highest priority TCB
				    LDR r0, [r0]                      ; Get waiting task TCB address
				    LDR sp, [r0]                      ; Switch to the new task stack
				
				    B OSCtxSw_from_start              ; Start first task
				
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				;
				; Function: OS_TASK_SW (also known as OSCtxSw)
				;
				; Purpose: Task level context switch
				;
				; Description:
				;     Save the current task registers and status on the task stack.
				;     Save the current task stack pointer in the current TCB. Call
				;     the OSTaskSwHook() function. Set OSPrioCur = OSPrioHighRdy.
				;     Branch to the switch_tcb() function to restore the context of
				;     the new task.
				;
				; Parameters: NA
				;
				; Outputs; NA
				;
				; Returns: NA
				;
				; Notes: This function should never be called from the IRQ level.
				;
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				OS_TASK_SW
				OSCtxSw
				    STMFD sp!, {lr}                   ; Save resume address
				    STMFD sp!, {r0-r12, lr}           ; Save current task registers
				    MRS r0, cpsr
				    STMFD sp!, {r0}                   ; Save current CPSR
				
				    LDR r0, =OSTCBCur
				    LDR r0, [r0]                      ; Get pointer to current TCB
				    STR sp, [r0]                      ; Save stack pointer of cur task
				
				    BL OSTaskSwHook                   ; Call OSTaskSwHook
				
				OSCtxSw_from_int
				    LDR r0, =OSTCBHighRdy             ; Get highest priority TCB
				    LDR r2, [r0]                      ; Get waiting task TCB address
				    LDR r0, =OSTCBCur                 ; Get current TCB
				    STR r2, [r0]                      ; OSTCBCur = OSTCBHighRdy
				    LDR sp, [r2]                      ; Get new task stack pointer
				
				    LDR r0, =OSPrioHighRdy            ; Get highest priority address
				    LDRB r1, [r0]                     ; Get highest priority
				    LDR r0, =OSPrioCur                ; Get current priority address
				    STRB r1, [r0]                     ; OSPrioCur = OSPrioHighRdy
				
				OSCtxSw_from_start
				    LDMFD sp!, {r0}                   ; Get CPSR value - this will be
				    MSR spsr_cf, r0                   ; restored on function resume
				    LDMFD sp!, {r0-r12, lr, pc}^      ; Load task registers and continue
				                                      ; task 
				
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				;
				; Function: OSTickISR
				;
				; Purpose: OS timer tick
				;
				; Description:
				;     See function comments.
				;
				; Parameters: NA
				;
				; Outputs; NA
				;
				; Returns: NA
				;
				; Notes:
				;     This function will always be called from ucos_irq_handler() on
				;     a timer interrupt. All other interrupts are handled directly in
				;     the ucos_irq_handler() function.
				;
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				OSTickISR
				; At this point, the real handling of the interrupt is done and the
				; context change for the task and ARM core may need to be done. The ARM
				; core is presently in the ARM IRQ mode and may have nested interrupts.
				; Call the OSIntEnter(), OSTimeTick(), and OSIntExit() functions.
				    BL OSIntEnter                     ; Call OSIntEnter()
				    BL OSTimeTick                     ; Call OSTimeTick()
				    BL OSIntExit                      ; Call OSIntExit()
				
				; A task context is not needed if the current and highest priority
				; tasks are the same. Check the TCB pointers. If they are the same,
				; just return from the interrupt and continue the task that was
				; already running.
				    LDR r8, =OSTCBCur
				    LDR r9, =OSTCBHighRdy
				    LDR r8, [r8]
				    LDR r9, [r9]
				    CMP r8, r9                        ; Are current and next TCB's
				                                      ; the same?
				    BEQ no_switch                     ; If the same, then just exit IRQ
				
				; The ARM core is still in IRQ mode. The task's r0-12 registers and the
				; task resume address (lr) are saved on the IRQ mode stack, but need to
				; be saved on the task's stack. The task's original link register (lr
				; in the task's mode) and the task's ARM core mode (CSPR) also need to
				; be saved on the task's stack).
				
				    BL OSTaskSwHook                   ; Call OSTaskSwHook()
				
				    MRS r0, spsr                      ; Get interrupted task's mode
				    STMFD sp!, {r0}                   ; Save task's CPSR on IRQ stack
				                                      ; so task mode can use it
				
				; Restore the IRQ stack pointer
				    ADD sp, sp, #4                    ; Restore stack pointer from CPSR
				    LDMFD sp!, {r0-r12, lr}           ; Restore registers to task state
				
				; Go into task mode with interrupts disabled
				    MRS r0, spsr                      ; Get interrupted task's mode
				    ORR r0, r0, #MODE_DIS_IRQ         ; Disable interrupts in task mode
				    MOV r1, sp                        ; Get IRQ stack pointer - this is
				                                      ; need for task mode
				    MSR cpsr_cf, r0                   ; Switch to task mode with
				                                      ; interrupts disabled
				
				; Get task's PC from IRQ stack
				    LDR r0, [r1, #-4]                 ; Get task's resume address
				    STMFD sp!, {r0}                   ; Save resume address
				
				    STMFD sp!, {r2-r12, lr}           ; Save task's registers
				    LDR r0, [r1, #-60]                ; Get task's CPSR
				    LDR r2, [r1, #-52]                ; Restore task's r1
				    LDR r1, [r1, #-56]                ; Restore task's r0
				    STMFD sp!, {r0-r2}                ; Save r0, r1, and CPSR
				
				; The task state is now saved on the task stack. Adjsut the stack size
				; by one more word to account for the saved resume address and save
				; the task stack pointer
				    LDR r0, =OSTCBCur
				    LDR r0, [r0]                      ; Get pointer to current TCB
				    STR sp, [r0]                      ; Save stack pointer of cur task
				
				    B OSCtxSw_from_int                ; Switch to new task
				
				no_switch
				    LDMFD sp!, {r0-r12, pc}^          ; Restore and exit
				
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				;
				; Function: OSIntCtxSw
				;
				; Purpose: OS interrupt level task context switch
				;
				; Description:
				;     This function does nothing. The real interrupt level task context
				;     switch is done after the return from the OSIntExit() function in
				;     OSTickISR() function. It's a bit easier to do it there, makes
				;     register restoration easier, and the IRQ mode stack pointer is
				;     already in the correct position. The call to OSTaskSwHook() is
				;     still performed here.
				;
				; Parameters: NA
				;
				; Outputs; NA
				;
				; Returns: NA
				;
				; Notes:
				;     This function is called from OSIntExit() to perform a task level
				;     context switch.
				;
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				OSIntCtxSw
				    MOV pc, lr
				
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				;
				; Function: ucos_irq_handler
				;
				; Purpose: Main interrupt (IRQ) handler for uCos-II
				;
				; Description:
				;     See function comments.
				;
				; Parameters: NA
				;
				; Outputs; NA
				;
				; Returns: NA
				;
				; Notes:
				;     This function works with the LH7A400 interrupt driver and uses
				;     data initialized and maintained with that driver.
				;
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				ucos_irq_handler
				; Save registers we use for the interrupt
				    SUB lr, lr, #4                    ; Adjust lr to real return address
				    STMFD sp!, {r0-r12, lr}
				
				; Read the interrupt controller pending register
				    LDR r1, =INTC_BASE_ADDR
				    LDR r0, [r1, #INTC_SOURCE_OFF]
				
				; Was it a timer 1 interrupt?
				    LDR r2, =INTC_TIMER1_INT_MASK
				    AND r3, r0, r2                    ; Mask off timer 1 interrupt bit
				    CMP r3, r2                        ; Was it a timer 1 interrupt?
				    BNE intc_not_timer                ; Not a timer interrupt
				
				; This was a timer interrupt, so clear the timer and perform ThreadX
				; context switching
				    LDR r3, =TIMER1_INT_CLR           ; Timer 1 interrupt clear address
				    STR r0, [r3]                      ; Clear the timer 1 interrupt
				    B OSTickISR                       ; Perform OS timer tick
				
				intc_not_timer
				; Loop through all the enabled interrupts and jump to the function
				; for the first pending interrupt
				    LDR r1, =INTC_FIRST_IRQ           ; Get first interrupt to check
				    MOV r2, #0x00000001               ; Interrupt bit mask
				
				; Start checking pending interrupt states
				int_check
				    MOV r3, r2, LSL r1                ; Build interrupt mask
				    AND r4, r0, r3                    ; Check just one bit at a time
				    CMP r4, r3                        ; Is interrupt pending?
				    BEQ int_found                     ; Interrupt was found, handle it
				    ADD r1, r1, #1                    ; Check next interrupt bit
				    CMP r1, #0x1F                     ; Was this the last interrupt?
				    BLE int_check                     ; Check next interrupt
				
				; If the program made it to here, then the interrupt was not found,
				; so just return to the caller, as we can do nothing
				int_not_found
				    B int_exit
				
				; A pending interrupt was found, so jump to it's handler
				int_found
				    LDR r0, =irq_func_ptrs            ; Get address of jump table
				    ADD r0, r0, r1, LSL #2            ; Add by interrupt offset
				    LDR r0, [r0]                      ; Get handler address
				    CMP r0, #0                        ; Is handler address NULL?
				    BEQ int_exit                      ; If null, the exit
				    MOV lr, pc                        ; Will return to int_exit
				                                      ; handler, it is best to save all
				                                      ; registers, so none get corrupted
				    MOV pc, r0                        ; Jump to handler
				
				; Exit the interrupt function
				int_exit
				    LDMFD sp!, {r0-r12, pc}^          ; Restore and exit
				
				    END
							

相关资源