Chinaunix首页 | 论坛 | 博客
  • 博客访问: 322251
  • 博文数量: 85
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 800
  • 用 户 组: 普通用户
  • 注册时间: 2014-10-18 15:21
文章分类

全部博文(85)

文章存档

2017年(1)

2016年(19)

2015年(55)

2014年(10)

我的朋友

分类: 嵌入式

2014-12-24 19:01:39

STM32汇编关键字含义:
IMPORT OSxx ;//IMPORT声明了OSxx在外文件定义
EXPORT OSxx ;//EXPORT声明OSxx可以被外文件使用,相当于全局性声明
LDR R0,=label ;//这是ARM的RISC指令下一个用于内存和CPU寄存器交换数据的指令,用法比较复杂。具体百度。
      ;//这里的含义就是把label的地址值赋值给R0,和 LDR R0,label 不同,没有'='的是取其地址的值传递给R0
      ;//
LDR R0,label   ;//取label其地址的值传递给R0
LDR?R0,0x12345678 ;//就是把0x12345678这个地址中的值存放到r0中

THUMB ;//THUMB指的是ARM中为提高代码密度而保有16位指令,也有THUMB指令的叫法。THUMB就是为了声明下面的是THUMB指令
;//具体要学习下ARM指令或者CM3的指令含义

关闭中断的进入关键区的定义
首先要知道ucos提供了3中关闭总中断的方法,第三中最为严密,第一种最为简单。要想知道为啥用第三种,
//OS_CRITICAL_METHOD = 1 
//OS_CRITICAL_METHOD = 2 
//OS_CRITICAL_METHOD = 3 

#define  OS_CRITICAL_METHOD   3  

#if OS_CRITICAL_METHOD == 3
#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}
#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}
#endif

OS_CPU_SR_Save和OS_CPU_SR_Restore为用汇编写的一小段代码,不多

OS_CPU_SR_Save
    MRS     R0, PRIMASK   ;读取PRIMASK的值到R0,R0就是返回的值,将赋值给cpu_sr
    CPSID   I                     ;PRIMASK=1 
    BX      LR       

OS_CPU_SR_Restore
    MSR     PRIMASK, R0   ;读取R0的值赋值给PRIMASK,R0为入口参数值
    BX      LR

触发软件中断
     PUSH    {R4, R5}
     LDR     R4, =NVIC_INT_CTRL

那么中断后栈中是个什么情形呢,<>中9.1.1有介绍,xPSR,PC,LR,R12,R3-R0被自动保存到栈中的,R11-R4如果需要保存,只能手工保存。
中断是由系统调度 OS_Sched ()触发,其调用了 OS_TASK_SW();  
void  OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3u                           /* Allocate storage for CPU status register     */
    OS_CPU_SR  cpu_sr = 0u;
#endif
//.................有省略
             OS_TASK_SW();                          /* Perform a context switch                     */
            }
        }
    }
    OS_EXIT_CRITICAL();
}
//在os_cpu.h中有以下宏
//任务切换宏,由汇编实现.
#define  OS_TASK_SW()         OSCtxSw()


OSCtxSw()是由汇编写的代码,主要是触发软件中断,在STM32中是PendSV异常中
OSCtxSw
PUSH    {R4, R5}
        LDR     R4, =NVIC_INT_CTRL           ;触发PendSV异常 (causes context switch)
        LDR     R5, =NVIC_PENDSVSET         ;NVIC_PENDSVSET和NVIC_INT_CTRL是ASM文件下的宏定义,
        STR     R5, [R4]
        POP     {R4, R5}
        BX 

由于在执行OS_Sched()中是中断关闭的,执行完函数最后OS_EXIT_CRITICAL()后就会触发中断,当然根据设置的中断优先级,如果有更高优先级的未处理完,则等处理完就会
响应执行PendSV中断。
PendSV中断的处理代码如下
PendSV_Handler
    CPSID   I                 ; Prevent interruption during context switch
    MRS     R0, PSP      ; PSP is process stack pointer 如果在用PSP堆栈,则可以忽略保存寄存器,参考CM3权威中的双堆栈-白菜注 OSIntExit()同样调用OSIntCtxSw()触发软件中断,硬件保存了R4-R11是不是【不用保存R4-R11】了呢
    CBZ     R0, PendSV_Handler_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

   SUBS    R0, R0, #0x20     ;为啥减的是32 ,堆栈向下生长(高地址向低地址),4*8=32
   STM     R0, {R4-R11}        ;就是保存任务堆栈的了语句了。
                                            ;所以可见堆栈保存工作不是在任务切换中做的,而是在PendSV中断函数中处理的。

                                        ;PendSV_Handler_Nosave也是一个汇编函数。
 
; At this point, entire context of process has been saved

PendSV_Handler_Nosave     ;实现找到当前最高优先级的任务的任务堆栈,并将其值取出来,分别赋值给R4-R11寄存器
    PUSH    {R14}                 ; Save LR exc_return value
    LDR     R0, =OSTaskSwHook     ; OSTaskSwHook();
    BLX     R0                                   ;转向执行OSTaskSwHook();
    POP     {R14}

    LDR     R0, =OSPrioCur             ; OSPrioCur = OSPrioHighRdy;
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]                         ;*R0 = R2 (OSTCBCur = OSTCBHighRdy)
    LDR     R0, =OSTCBCur             ; OSTCBCur  = OSTCBHighRdy;
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]

    LDR     R0, [R2] ; R0=*R2,R0 is new process SP        ; SP = OSTCBHighRdy->OSTCBStkPtr,注意OSTCBStkPtr是OSTCB的第一个变量;
    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  


参考资料《ucosii在STM32上的移植详解》
阅读(2246) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~