⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arm_core_s.s

📁 介绍ROCK OS操作系统.一般用于汽车电子,类似OCVX.里面是个DEMO文档,内附说明.
💻 S
字号:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;   Copyright (c) 2006 by RockOS.
;;   All rights reserved.
;;
;;   This software is supported by Rock Software Workroom.
;;
;;   Any bugs please contact the author with e-mail or QQ:
;;     E-mail : baobaoba520@yahoo.com.cn
;;         QQ : 59681888
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;File name   : arm_core.s
;;Description : the BSP core code for all ARM cpu.
;;            : 
;;            : 
;;            : 
;;            :
;;Auther      : sunxinqiu
;;History     :
;;  2006-3-15   first release.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    include 44b.inc
    
    ;; vairable for task stack init.
    IMPORT taskDeleteSelf

    ;; variables for task switch
    IMPORT g_runningTask
    IMPORT g_runningTcb
    IMPORT g_newTask
    IMPORT g_newTcb

    ;; Hook for task switch
    IMPORT OSSwTaskHook

    AREA ||.text||, CODE, READONLY

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function    : unsigned int getMemStartAddr(void)
;;Params      : N/A
;;            : 
;;            : 
;;            : 
;;Return      : N/A
;;Description : get the heap memory start address which the OS can use.
;;            : 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    EXPORT getMemStartAddr
getMemStartAddr
    ldr    r0, =|Image$$ZI$$Limit|
    mov    pc, lr

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function    : unsigned int getMemEndAddr(void)
;;Params      : N/A
;;            : 
;;            : 
;;            : 
;;Return      : N/A
;;Description : get the heap memory end address which the OS can use.
;;            : 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    EXPORT getMemEndAddr
getMemEndAddr
    ldr    r0, =_ISR_STARTADDRESS
    mov    pc, lr

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function  : void * taskStackInit(void * pStack,
;;          :                      int    stackSize, 
;;          :                      TASK_ENTRY pEntryFunc,
;;          :                      void *     pData)
;;Params    : pStack     - the task's stack start address.
;;          : stackSize  - the task's stack size, by bytes.
;;          : pEntryFunc - the task's main entry point.
;;          : pData      - param for pEntryFunc.
;;          : 
;;Return    : The initializaed SP for this task.
;;Descript  : This function is called once only when task is created. RockOS
;;          : can't know whether the stack is growth from low address or from
;;          : high address to low address, so I let this work done by BSP.
;;          : Defaultly, the LR(R14) register is set to function taskDeleteSelf(),
;;          : it is used to delete the task if the task entry function terminates.
;; The init stack frame is as below:
;;    |              | 
;;    |  Free space  | 
;;    |--------------|<-- sp
;;    |     CPSR     | 
;;    |--------------| 
;;    |              | 
;;    |    r0~r12    | 
;;    |              | 
;;    |--------------|
;;    |      LR      |
;;    |--------------| 
;;    |      PC      |
;;    |--------------|<-- end of stack.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    EXPORT taskStackInit
taskStackInit
    ;; r0 - the pStack (stack start address).
    ;; r1 - size of stack (in bytes).
    ;; r2 - the task entry point.
    ;; r3 - param for the task entry point.
    stmfd sp!, {r4-r12}

    add r4, r0, r1      ;; r4 is now the task's stack top position.
    bic r4, r4, #0x03   ;; align the r4 register(task stack pointer)

    ;; clear the stack to all 0xFE
    mov   r6, r0
    ldr   r5, =0xFEFEFEFE
1   str   r5, [r6]
    cmp   r6, r4
    addcc r6, r6, #4
    bcc   %b1

    ;; the task's entry pointer
    stmfd   r4!, {r2}           ;; will be popped to PC

    ;; once the task's entry function returns, delete the task
    ldr   r2, =taskDeleteSelf   ;; will be popped to LR
    stmfd r4!, {r2}

    ;; param for the task's entry point should be stored in r0
    mov   r0, r3            ;; the param for taskEntry()
    mov   r1, r4            ;; r1 now saves the task's stack top

    ldr   r2, =0x22222222   ;; save {r5-r12} in task's stack
    ldr   r3, =0x33333333
    ldr   r4, =0x44444444
    ldr   r5, =0x55555555
    ldr   r6, =0x66666666
    ldr   r7, =0x77777777
    ldr   r8, =0x88888888
    ldr   r9, =0x99999999
    ldr   r10,=0xaaaaaaaa
    ldr   r11,=0xbbbbbbbb
    ldr   r12,=0xcccccccc
    stmfd r1!,{r2-r12}

    ldr   r2, =0x11111111
    stmfd r1!, {r0, r2}    ;; r0 and r1 in task's stack
    
    ;; the task's CPSR, all tasks are running in SVC mode.
    mov     r0, #(SVC_MODE|FIQ_DISABLED)     ;; will be popped to CPSR
    stmfd   r1!, {r0}

    ;; return the task stack's top
    mov     r0, r1
    ldmfd   sp!,{r4-r12}
    mov     pc, lr
    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function    : void OSRunTask(void)
;;Params      : N/A
;;            : 
;;            : 
;;            : 
;;Return      : N/A
;;Description : start the first ready task when system starting.
;;            : global variable g_runningTask and g_runningTcb must be set 
;;            : properly before calling this function.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    EXPORT OSRunTask
OSRunTask
    ;; load task's stack.
    ldr    r0, =g_runningTcb
    ldr    r0, [r0]
    ldr    sp, [r0]

    ldmfd  sp!, {r0}        ;; pop cpsr for the task
    msr    spsr_cxsf, r0
    ldmfd  sp!, {r0-r12, lr, pc}^    ;; run the task

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function  : void OSSwTask (void);
;;Params    : N/A
;;          : 
;;Return    : N/A
;;Descript  : This function is called by RockOS scheduler to switch task from
;;          : one to another. These global variable should be set properly
;;          : before calling this function:
;;          :   g_runningTask - the running task's handle.
;;          :   g_runningTCB  - the running task's TCB.
;;          :   g_newTask     - the new task's handle
;;          :   g_newTCB      - the new task's TCB.
;;          : 
;; To switch from one task to another, the tasks' stack frame are:
;;    |            |                           |            |
;;    | Free space |                           | Free space |
;;    |------------|<-- sp(after SW out)       |------------|<-- sp(before SW in)
;;    |    CPSR    |                           |    CPSR    |
;;    |------------|                           |------------|
;;    |            |                           |            |
;;    |   r0~r12   |                           |   r0~r12   |
;;    |            |                           |            |
;;    |------------|                           |------------|
;;    |     LR     |                           |     LR     |
;;    |------------|                           |------------|
;;    |     PC     |                           |     PC     |
;;    |------------|<-- sp(befor SW out)       |------------|<-- sp(after SW in) 
;;    |            |                           |            |
;;    |  app data  |                           |  app data  |
;;    |            |                           |            |
;;    |------------|                           |------------|
;;  old task's stack frame                  new task's stack frame
;;          : Note that the register PC appears twicely, it is used to keep
;;          : consist with the task switch procedure in interrupt.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    EXPORT OSSwTask
OSSwTask
    ;; save the old task's all registers and PSR in its stack.
    ;; the sp is still pointer to the old task's stack now.
    stmfd sp!, {lr}             ;; pc for old task
    stmfd sp!, {r0-r12, lr}     ;; r0--r12, lr for old task
    mrs   r0,  cpsr             ;; cpsr for task
    stmfd sp!, {r0}

    bl    OSSwTaskHook          ;; OSSwTaskHook();

    ldr   r4, =g_runningTcb     ;; g_runningTcb->pSP = sp
    ldr   r4, [r4]
    str   sp, [r4]

    ldr  r0, =g_newTask         ;; g_runningTask = g_newTask;
    ldr  r0, [r0]
    ldr  r5, =g_runningTask
    str  r0, [r5]
    
    ldr  r1, =g_newTcb          ;; g_runningTcb = g_newTcb;
    ldr  r1, [r1]
    ldr  r4, =g_runningTcb
    str  r1, [r4]

    ;; restore the new task's all registers and PSR from its stack
    ldr    r4, [r4]
    ldr    sp, [r4]

    ldmfd  sp!, {r0}                ;; cpsr for the new task
    msr    spsr_cxsf, r0
    ldmfd  sp!, {r0-r12, lr, pc}^   ;; all other registers

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function  : void OSIntSwTask (void);
;;Params    : N/A
;;          : 
;;Return    : N/A
;;Descript  : This function is called by OSLeaveIsr() to switch task from
;;          : one to another. These global variables should be set properly
;;          : before calling this function:
;;          :   g_runningTask - the running task's handle.
;;          :   g_runningTCB  - the running task's TCB.
;;          :   g_newTask     - the new task's handle
;;          :   g_newTCB      - the new task's TCB.
;;          : for the task stack frame, see OSSwTask() for more.
;;          : 
;;          : note that the current task's context (which to be switched out)
;;          : has been saved in its own stack when entering the ISR, so
;;          : we only need load the new task's context directly here.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    EXPORT OSIntSwTask
OSIntSwTask
    bl    OSSwTaskHook          ;; OSSwTaskHook();

    ldr  r0, =g_newTask         ;; g_runningTask = g_newTask;
    ldr  r0, [r0]
    ldr  r1, =g_runningTask
    str  r0, [r1]
    
    ldr  r0, =g_newTcb          ;; g_runningTcb = g_newTcb;
    ldr  r0, [r0]
    ldr  r1, =g_runningTcb
    str  r0, [r1]

    ;; load the new task directly.
    ldr r0, =g_runningTcb
    ldr r0, [r0]
    ldr sp, [r0]
    
    ldmfd  sp!, {r0}                ;; cpsr for the new task
    msr    spsr_cxsf, r0
    ldmfd  sp!, {r0-r12, lr, pc}^   ;; all other registers

    END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -