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

📄 os_cpu_a.asm

📁 IAR_STM32_uCOS-II.rar
💻 ASM
字号:
;//********************************************************************************************************
;//                                               uC/OS-II
;//                                         The Real-Time Kernel
;//
;//                                           ARM Cortex-M3 Port
;//
;// File      : OS_CPU_A.ASM
;// Version   : V2.86
;// By        : 
;// For       : ARMv7M Cortex-M3
;// Mode      : Thumb2
;// Toolchain : IAR EWARM 5.20
;//********************************************************************************************************

;//*
;//*********************************************************************************************************
;//*                                           全局常量声明
;//*********************************************************************************************************
;//*
;// 引用外部变量的声明
    EXTERN  OSRunning
    
    EXTERN  OSPrioCur
    EXTERN  OSPrioHighRdy
    
    EXTERN  OSTCBCur
    EXTERN  OSTCBHighRdy
    
    EXTERN  OSIntNesting
    
    EXTERN  OSTaskSwHook

    EXTERN  OSRdyGrp
    EXTERN  OSRdyTbl
    EXTERN  OSPrioHighRdy

;// 外部可以调用的函数
    PUBLIC  OS_CPU_SR_Save
    PUBLIC  OS_CPU_SR_Restore
    PUBLIC  OSStartHighRdy
    PUBLIC  OSCtxSw
    PUBLIC  OSIntCtxSw
    PUBLIC  OS_CPU_PendSVHandler
;// PUBLIC  OS_SchedNew

;//********************************************************************************************************
;//                                           PendV 所使用的几个寄存器
;//********************************************************************************************************

NVIC_INT_CTRL   EQU     0xE000ED04                              ;// 中断控制及状态寄存器
NVIC_SYSPRI14   EQU     0xE000ED22                              ;// 控制PendSV优先级的寄存器
NVIC_PENDSV_PRI EQU           0xFF                              ;// PendSV 异常优先级(最低)
NVIC_PENDSVSET  EQU     0x10000000                              ;// PendSV 异常触发位掩码

;//********************************************************************************************************
;//                                           以下是汇编程序接口 
;//********************************************************************************************************

        RSEG CODE:CODE:NOROOT(2)

;//*
;//********************************************************************************************************
;//* 函 数 名 : OS_SchedNew()
;//**------------------------------------------------------------------------------------------------------
;//* 描    述 : 
;//*            寻找最高级就绪的任务
;//*            此程序使用了CM3内核的新指令RBIT, CLZ 通过程序计算代替查表, 速度相当不错
;//             不过在任务优先级及任务数小于63的系统,并没有比查表具有优势
;//      
;//             如果想使用此函数,请先屏蔽os_core.c下面的OS_SchedNew()
;//**------------------------------------------------------------------------------------------------------
;//* 输入参数 : OSRdyGrp, OSRdyTbl
;//**------------------------------------------------------------------------------------------------------
;//* 输出参数 : OSPrioHighRdy
;//**------------------------------------------------------------------------------------------------------
;//* 返   回  : None.
;//********************************************************************************************************
;//*
;//OS_SchedNew
;//    PUSH   {R0-R4}
;//    LDR    R0, =OSRdyGrp
;//
;//    LDRH   R2, [R0]
;//    RBIT   R2, R2
;//    CLZ    R2, R2                   ; y = CLZ(OSRdyGrp);
;//
;//    LDR    R0, =OSRdyTbl
;//    ADD    R1, R0, R2, LSL #0x01    ; ptbl = &OSRdyTbl[y];
;//
;//    LDRH   R3, [R1]
;//    RBIT   R3, R3
;//    CLZ    R3, R3                   ; x = CLZ(*ptbl);
;//
;//    LDR    R0, =OSPrioHighRdy
;//    ADD    R4, R3, R2, LSL #0x04
;//    STRB   R4, [R0]                 ; OSPrioHighRdy = x + (y << 4);
;//
;//    POP    {R0-R4}
;//    BX      LR

;//*
;//********************************************************************************************************
;//* 函 数 名 : 
;//*             OS_CPU_SR  OS_CPU_SR_Save(void);
;//*             void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;//**------------------------------------------------------------------------------------------------------
;//* 描    述 :  第3种方法的临界代码处理, 不再啰嗦
;//**------------------------------------------------------------------------------------------------------
;//* 输入参数 : 
;//**------------------------------------------------------------------------------------------------------
;//* 输出参数 : 
;//**------------------------------------------------------------------------------------------------------
;//* 返   回  : 
;//********************************************************************************************************
;//*
OS_CPU_SR_Save
    MRS     R0, PRIMASK
    CPSID   I
    BX      LR

OS_CPU_SR_Restore
    MSR     PRIMASK, R0
    BX      LR

;//*
;//********************************************************************************************************
;//* 函 数 名 : OSStartHighRdy();
;//**------------------------------------------------------------------------------------------------------
;//* 描    述 : 多任务开始运行
;//**------------------------------------------------------------------------------------------------------
;//* 输入参数 : 
;//**------------------------------------------------------------------------------------------------------
;//* 输出参数 : 
;//**------------------------------------------------------------------------------------------------------
;//* 返   回  : 
;//********************************************************************************************************
;//*
OSStartHighRdy
    LDR     R0, =NVIC_SYSPRI14                                  ;// 设置PendSV优先级
    LDR     R1, =NVIC_PENDSV_PRI
    STRB    R1, [R0]

    MOVS    R0, #0                                              ;// 初始化线程PSP
    MSR     PSP, R0

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

    LDR     R0, =NVIC_INT_CTRL                                  ;// 触发PendSV异常, 让PendSv任务切换开始
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]

    CPSIE   I                                                   ;// 打开总中断

OSStartHang
    B       OSStartHang                                         ;// while(1);

;//*
;//********************************************************************************************************
;//* 函 数 名 : OSCtxSw();
;//**------------------------------------------------------------------------------------------------------
;//* 描    述 : 任务级内容切换
;//**------------------------------------------------------------------------------------------------------
;//* 输入参数 : 
;//**------------------------------------------------------------------------------------------------------
;//* 输出参数 : 
;//**------------------------------------------------------------------------------------------------------
;//* 返   回  : 
;//********************************************************************************************************
;//*
OSCtxSw
    LDR     R0, =NVIC_INT_CTRL                                  ;// 触发PendSV异常
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR

;//*
;//********************************************************************************************************
;//* 函 数 名 : OSIntCtxSw();
;//**------------------------------------------------------------------------------------------------------
;//* 描    述 : 中断级内容切换
;//**------------------------------------------------------------------------------------------------------
;//* 输入参数 : 
;//**------------------------------------------------------------------------------------------------------
;//* 输出参数 : 
;//**------------------------------------------------------------------------------------------------------
;//* 返   回  : 
;//********************************************************************************************************
;//*
OSIntCtxSw
    LDR     R0, =NVIC_INT_CTRL                                  ;// 触发PendSV异常
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR

;//*
;//********************************************************************************************************
;//* 函 数 名 : OS_CPU_PendSVHandler()
;//**------------------------------------------------------------------------------------------------------
;//* 描    述 : 在cm3内核下,真正的任务文本切换是靠本函数实现
;//                 |     ....        |
;//                 |-----------------|
;//                 |     ....        |
;//                 |-----------------|
;//                 |     ....        |
;//                 |-----------------|       |---- 任务切换时PSP
;//     Low Memory  |     ....        |       |
;//                 |-----------------|       |    |---------------|      |----------------|
;//        ^        |       R4        |  <----|----|--OSTCBStkPtr  |<-----|   (OS_TCB *)   |
;//        ^        |-----------------|            |---------------|      |----------------|
;//        ^        |       R5        |            |               |         OSTCBHighRdy
;//        |        |-----------------|            |---------------|
;//        |        |       R6        |            |               |
;//        |        |-----------------|            |---------------|
;//        |        |       R7        |            |               |
;//        |        |-----------------|            |---------------|
;//        |        |       R8        |                 Task's
;//        |        |-----------------|                 OS_TCB
;//        |        |       R9        |
;//        |        |-----------------|
;//        |        |      R10        |
;//      Stack      |-----------------|
;//      Growth     |      R11        |
;//       = 1       |-----------------|
;//        |        |    R0 = p_arg   |  <-------- 异常时的PSP (向下生长的满栈)
;//        |        |-----------------|
;//        |        |       R1        |
;//        |        |-----------------|
;//        |        |       R2        |
;//        |        |-----------------|
;//        |        |       R3        |
;//        |        |-----------------|
;//        |        |       R12       |
;//        |        |-----------------|
;//        |        |       LR        |
;//        |        |-----------------|
;//        |        |    PC = task    |
;//        |        |-----------------|
;//        |        |      xPSR       |
;//    High Memory  |-----------------|
;//                 |      ....       |
;//**------------------------------------------------------------------------------------------------------
;//* 输入参数 : 
;//**------------------------------------------------------------------------------------------------------
;//* 输出参数 : 
;//**------------------------------------------------------------------------------------------------------
;//* 返   回  : 
;//********************************************************************************************************
;//*
OS_CPU_PendSVHandler
    CPSID   I                                                   ;// 任务context切换是关闭中断
    MRS     R0, PSP                                             ;// 获取PSP
    CBZ     R0, OS_CPU_PendSVHandler_nosave                     ;// 在多任务初始化时,PSP被初始化为0
                                                                ;// PSP如果是0,标示任务没有运行过,那么不需要压栈
                                                                ;// 直接加载任务context
    SUBS    R0, R0, #0x20                                       ;// 调整PSP指针, R4-R11 共32字节
    STM     R0, {R4-R11}                                        ;// 压栈R4-R11, 其他8个寄存器是在异常时自动压栈的

    LDR     R1, =OSTCBCur                                       ;// 获取OSTCBCur->OSTCBStkPtr
    LDR     R1, [R1]
    STR     R0, [R1]                                            ;// 将当前任务的堆栈保存到自己的任务控制块
                                                                ;// OSTCBCur->OSTCBStkPtr = PSP
                                                                ;// 程序运行此位置,已经保存了当前任务的context了
OS_CPU_PendSVHandler_nosave
    ;// 使能OSTaskSwHook的时候去掉注释
    ;//PUSH    {R14}
    ;//LDR     R0, =OSTaskSwHook
    ;//BLX     R0
    ;//POP     {R14}
    
                                                                ;// 在调度之前,系统内核已经计算好
                                                                ;// OSPrioHighRdy 和 OSTCBHighRdy
    LDR     R0, =OSPrioCur                                      ;// 当前任务优先级 = 就绪任务优先级
    LDR     R1, =OSPrioHighRdy                                  ;// OSPrioCur = OSPrioHighRdy;
    LDRB    R2, [R1]
    STRB    R2, [R0]

    LDR     R0, =OSTCBCur                                       ;// 当前任务控制块 = 就绪任务控制块;
    LDR     R1, =OSTCBHighRdy                                   ;// OSTCBCur  = OSTCBHighRdy;
    LDR     R2, [R1]                                            ;// 
    STR     R2, [R0]                                            ;// 此时 [R2] = 新任务的PSP

    LDR     R0, [R2]                                            ;// R0 = 新任务的PSP
    LDM     R0, {R4-R11}                                        ;// 出栈 R4 - R11
    ADDS    R0, R0, #0x20                                       ;// 调整PSP
    MSR     PSP, R0                                             ;//
    
                                                                ;// 当前异常使用的堆栈是MPS
    ORR     LR, LR, #0x04                                       ;// 修改LR的BIT2=1, 确保异常退出时堆栈使用PSP
                                                                ;// 类似修改CONTROL[1] = 1

    CPSIE   I
    BX      LR                                                  ;// 异常返回

    END

⌨️ 快捷键说明

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