• 5.2.鸿蒙LiteOS-M los_dispatch


    请添加图片描述

    一、cortex-m4 los_dispatch.S代码分析

    .syntax unified     #.syntax [unified | divided], 指定arm 汇编语法规则
    .arch armv7e-m      #指定平台, 与命令行参数-march同样的作用
    .fpu fpv4-sp-d16    #指定浮点运算单元,与命令行参数-mfpu同样的作用
    .thumb              # .thumb伪操作等同于.code 16, 表明使用Thumb指令
    
    # .equ 定义静态符号,把常量值设置为可以在文本段中使用的符号
    .equ    OS_FPU_CPACR,                0xE000ED88
    .equ    OS_FPU_CPACR_ENABLE,         0x00F00000
    .equ    OS_NVIC_INT_CTRL,            0xE000ED04
    .equ    OS_NVIC_SYSPRI2,             0xE000ED20
    .equ    OS_NVIC_PENDSV_PRI,          0xF0F00000
    .equ    OS_NVIC_PENDSVSET,           0x10000000
    .equ    OS_TASK_STATUS_RUNNING,      0x0010
    .equ    OS_CONTROL_FPCA_ENABLE,      0x4
    .equ    OS_CONTROL_KERNEL_MODE,      0x2
    #if (LOSCFG_SECURE == 1)
    .equ    OS_CONTROL_USER_MODE,        0x3
    .equ    OS_TASK_FLAG_USER_TASK,      0x0200
    #endif
    
        .section .text      # 后面那些指令都属于.text段
        .thumb
        
    
    # .macro/.endm 定义一个宏,可以把需要重复执行的一段代码,或者是一组指令缩写成一个宏,
    # 在程序调用的时候就可以直接去调用这个宏而使代码更加简洁清晰
    .macro SIGNAL_CONTEXT_RESTORE
        push    {r12, lr}
        blx     OsSignalTaskContextRestore
        pop     {r12, lr}
        cmp     r0, #0
        mov     r1, r0
        bne     SignalContextRestore
    .endm
    
        .type HalStartToRun, %function  # HalStartToRun 类型为函数
        .global HalStartToRun           # 声明全局符号。全局符号是指在本程序外可访问的符号
    HalStartToRun:                      # 
        .fnstart                        # 函数开始
        .cantunwind                     # 可以被栈回溯
    
        # ldr Rt, label     从label加载一个字到寄存器Rt中
        # str Rt, label     从地址Rt读取一个字到label中
        # [Rt]表示读取地址Rt处数据
        ldr     r4, =OS_NVIC_SYSPRI2        # 加载OS_NVIC_SYSPRI2 符号到寄存器r4中
        ldr     r5, =OS_NVIC_PENDSV_PRI     # 加载OS_NVIC_PENDSV_PRI 符号到寄存器r4中
        str     r5, [r4]                    # 读取地址r5处一个字数据,到r4地址中
        # 以上3条指令等效于:*((volatile u32 *)0xE000ED20) = 0xF0F00000
        # 设置PENDSV优先级为最低
    
        # 给寄存器传递一个立即数,此时需要用“#”来修饰立即数,并且立即数为8位的,其值不能超过255.
        # 特殊寄存器必须用MRS(),MSR 指令访问
        # MRS ,  ;读特殊功能寄存器的值到通用寄存器
        # MSR ,  ;写通用寄存器的值到特殊功能寄存器
        mov     r0, #OS_CONTROL_KERNEL_MODE 
        msr     CONTROL, r0     # 将r0数据写入CONTROL特殊寄存器中
        # 以上2条指令完成,sp使用进程堆栈指针
    
    
        ldr     r1, =g_losTask      # 将g_losTask结构体变量地址加载到r1中
        ldr     r0, [r1, #4]        # 将g_losTask.newTask地址加载到r1中,r1此时为newTask的TaskCB的内存地址
        ldr     r12, [r0]           # g_losTask->newTask->stackPointer加载到寄存器r12
        # g以上3条指令完成,任务上下文加载
    
        ldr.w   r1, =OS_FPU_CPACR
        ldr     r1, [r1]
        and     r1, r1, #OS_FPU_CPACR_ENABLE
        cmp     r1, #OS_FPU_CPACR_ENABLE
        bne     __DisabledFPU           # if(r1 != 0) 执行__DisabledFPU符号位指令
        add     r12, r12, #100
    
        ldmfd   r12!, {R0-R7}
        add     r12, r12, #72
        msr     psp, r12
        vpush   {s0}
        vpop    {s0}
        mov     lr, r5
        cpsie   i
        bx      r6
    
    __DisabledFPU:
        add     r12, r12, #36       # 加载数据变为context->uwR0 = taskID;
    
        ldmfd   r12!, {r0-r7}       # 加载context->uwR0~context->uwxPSR 到 r0-r7中
        msr     psp, r12            # 加载r12地址中一个字到psp中
        mov     lr, r5              # 加载r5 context->uwLR到lr寄存器中
        cpsie   I                   # 开中断
        bx      r6                  # pc跳转到context->uwPC
    
        .fnend                  # HalStartToRun end
    
        .type ArchIntLock, %function
        .global ArchIntLock
    ArchIntLock:                    # 关闭中断
        .fnstart
        .cantunwind
    
        MRS R0, PRIMASK             # 读取寄存器PRIMASK到R0中
        CPSID I                     # 关中断
        BX LR                       # 返回
        .fnend
    
        .type ArchIntUnLock, %function
        .global ArchIntUnLock
    ArchIntUnLock:                  # 开中断
        .fnstart
        .cantunwind
    
        MRS R0, PRIMASK             # 读取寄存器PRIMASK到R0中
        CPSIE I                     # 开中断
        BX LR                       # 返回
        .fnend
    
        .type ArchIntRestore, %function
        .global ArchIntRestore
    ArchIntRestore:
        .fnstart
        .cantunwind
    
        MSR PRIMASK, R0             # 读取R0数据到PRIMAK
        BX LR                       # 返回
        .fnend
    
        .type ArchTaskSchedule, %function
        .global ArchTaskSchedule
    ArchTaskSchedule:
        .fnstart
        .cantunwind
    
        ldr     r0, =OS_NVIC_INT_CTRL
        ldr     r1, =OS_NVIC_PENDSVSET
        str     r1, [r0]            # 悬起pendSV
        bx      lr                  # 返回
        dsb                         # 数据同步屏障,确保在下一条指令开始执行前,所有的存储器访问已经完成。
        isb                         # 指令同步屏障,清除流水线并且确保在新指令执行时,之前的指令都已经执行完毕。
        .fnend
    
        .type HalPendSV, %function
        .global HalPendSV
    HalPendSV:                      # pendSV实现函数
        .fnstart
        .cantunwind
    
        mrs     r12, PRIMASK        # 加载PRIMASK寄存器到r12
        cpsid   I                   # 关中断
    
    HalTaskSwitch:
        SIGNAL_CONTEXT_RESTORE
    
        push    {r12, lr}
        blx     OsSchedTaskSwitch   # 跳转执行任务切换
        pop     {r12, lr}
        cmp     r0, #0
        mov     r0, lr
        bne     TaskContextSwitch   # 如果cmp r0, #0 执行不等于0时,跳转执行任务上下文切换
        msr     PRIMASK, r12        # 开中断
        bx      lr                  # 若不切换任务上下文,则直接返回
    
    TaskContextSwitch:
        mov     lr, r0
        mrs     r0, psp             # 任务栈指针保存到r0
    
        stmfd   r0!, {r4-r12}       # r4-r12数据存入任务栈
        ldr.w   r3, =OS_FPU_CPACR
        ldr     r3, [r3]
        and     r3, r3, #OS_FPU_CPACR_ENABLE
        cmp     r3, #OS_FPU_CPACR_ENABLE
        bne     __DisabledFPU1
        vstmdb  r0!, {d8-d15}       # 如果支持浮点寄存器时,把d8-d15压入栈中。
    
    __DisabledFPU1:
        ldr     r5, =g_losTask      # 把g_losTask地址加载到r5
        ldr     r6, [r5]            # 获取当前运行任务栈指针,然后更新当前运行的任务栈指针。
        str     r0, [r6]
    
        ldr     r0, [r5, #4]        # 获取新任务newTask的地址,
        str     r0, [r5]            # 把newTask地址赋值到runTask
        ldr     r1, [r0]            # newTask地址赋值到r1
    
    SignalContextRestore:
        ldr.w   r3, =OS_FPU_CPACR
        ldr     r3, [r3]
        and     r3, r3, #OS_FPU_CPACR_ENABLE
        cmp     r3, #OS_FPU_CPACR_ENABLE
        bne     __DisabledFPU2
        vldmia  r1!, {d8-d15}
    
    __DisabledFPU2:
    #if (LOSCFG_SECURE == 1)
        ldrh    r7, [r0, #4]
        tst     r7, #OS_TASK_FLAG_USER_TASK
        ite     eq
        moveq   r3, #OS_CONTROL_KERNEL_MODE
        movne   r3, #OS_CONTROL_USER_MODE
        msr     CONTROL, r3
    #endif
        ldmfd   r1!, {r4-r12}       # 加载newTask任务栈数据到r4-r12中
        msr     psp,  r1            # 更新任务栈指针为newTask任务栈地址
    
        msr     PRIMASK, r12        # 开中断
    
        bx      lr                  # 返回
        .fnend
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205

    坚持就有收获

    请添加图片描述

  • 相关阅读:
    vector的模拟实现
    群狼调研(长沙产品概念测试)|如何做新品上市满意度调研
    0. linux-riscv内存管理120问大纲
    node将对象按照ASCII码进行升序排列生成签名字符串,然后加载 pfx证书进行SHA256withRSA加密
    Java代码读取properties配置文件
    SQL注入之宽字节注入、堆叠注入、二次注入
    【MLT】MLT多媒体框架生产消费架构解析(一)
    迭代器 Iterator
    WEB安全之HTML基础
    20、wpf之MVVM命令绑定
  • 原文地址:https://blog.csdn.net/nawei87/article/details/136265826