uCosII移植到STM32触发中断、任务切换的汇编学习

发布者:VelvetWhisper最新更新时间:2024-10-16 来源: elecfans关键字:uCosII  移植  STM32  触发中断  任务切换 手机看文章 扫描二维码
随时随地手机看文章

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中关闭总中断的方法,第三中最为严密,第一种最为简单。要想知道为啥用第三种,

请看另一篇转载的博文《【转载】ucos中的三种临界区管理机制(OS_CRITICAL_METHOD的解释) 》

//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  触发中断  任务切换 引用地址:uCosII移植到STM32触发中断、任务切换的汇编学习

上一篇:STM32的I2S接口只支持单工模式,使用时要小心
下一篇:STM32-GPIO口设为外部中断时,中断函数名称

推荐阅读最新更新时间:2026-03-19 10:48

基于stm32的简单多任务切换设计
系统数据: 1)当前的PID 2)所有的进程总数PAMOUNT //多任务系统的初始化 1. 设置MSP值 2. 设置临时的PSP值(因为这段实际上只在启动定时器之前有效) 3. 设置CONTROL =1(设置双堆栈),马上会自动切换到PSP上 4. 设置PID=0,设置PAMOUNT=0 5. 设置为进程信息表起始地址到PLIST(注意进程信息表是向上生长的) 6. 设置为进程堆栈分配的起始地址到PSTACK(堆栈是向下生长的) //调用AddTask添加任务 1. 写入配置信息到任务表中(任务起始地址,堆栈地址(首次进行分配)xPSR等等) a) 至于输入参数,就存放在任务的堆栈中 //启动任务切换 1. 设置S
[单片机]
如何将UCOSII移植到51单片机上
一、准备工作 1. 开发环境: Keil C集成开发环境 2. 源代码:UCOSII的源代码,网上可以自己下载 3. 文件分析: 1)UCOSII文件中与处理器无关的文件: OS_CORE.C OS_FLAG.C OS_MBOX.C OS_MEM.C OS_MUTEX.C OS_Q.C OS_SEM.C OS_TASK.C OS_TIME.C UCOS_II.C UCOS_II.H 以上这些文件在c51移植过程中只需给函数加上可重入性即可,即在每个函数后面添加关键字:reentrant 2)与应用相关的文件: INCLUDES.H——其中包含51单片机头文件和相关应用头文件 OS_CFG.H——这个文件对于要应用系统中的相关工
[单片机]
如何将<font color='red'>UCOSII</font><font color='red'>移植</font>到51单片机上
ucosii在AVR系列单片机移植中出现的一个BT的问题
今天想把ucosii移植到手头的一块AVR128芯片上。 只要有移植经验,其它的问题都比较好解决。但是ICC编译器对于函数指针的处理方式特别怪异,让我大吃苦头,纠结调试了半天!!! 症状:编译通过后,运行时卡死。 经在AVR Studio中JTAG硬仿真,发现任务调度不了。最终目光聚焦在移植代码里函数中的一行: tmp = *(INT16U const *)task; /* (1) ICC compiler handles function pointers indirectly! */ 这是取得函数指针指向的函数地址。 一般编译器下直接写成 tmp = task 就可以了,但是“ICC compile
[单片机]
<font color='red'>ucosii</font>在AVR系列单片机<font color='red'>移植</font>中出现的一个BT的问题
UCOSii(六)——移植
一、前言 UCOSii官方已经提供了许多移植范例,在这种情况下自己移植UCOSii是一种不经济的做法。但为了了解一个RTOS在移植时面临的兼容性问题,知道如何移植UCOSii依然是有必要的。 那么,RTOS在编译和运行时,在不同的chip上,会面临哪些问题呢? 编译类问题 不同的芯片可能会使用不同的编译器,而不同的编译在许多处理细节上会有所不同。比如有些编译器会将函数行参推入堆栈,而另外一些则会使用寄存器传递行参以加快速度。 芯片结构类问题 芯片的工作模式是16位还是32位?堆栈向下生长还是向下生长?如何产生时钟节拍? 汇编代码 有些情况下必须使用汇编来编写程序,一是这样可以使得一个经常被调用的子程序具有极高的效率。二是C语言不提
[单片机]
典型范例:uCOSii在Coldfire MCF52235上的移植
引言 C/ OS 是一种多任务实时操作系统。内核源代码公开、短小精干、可裁剪、执行时间可确定, 可移植性较强, 非常适用于一些中小型嵌入式系统开发。uC/OS 可以移植到8~ 64 位的不同类型、不同规模的嵌入式系统, 并能在大部分的8 位、16 位、32 位, 甚至64 位的微处理器和DSP 上运行 。 MCF52235 是飞思卡尔公司Co ldf ire 系列32 位单片机解决方案的嵌入式微控制器, 采用的是V2 版本的 RISC 内核。MCF52235 内部有32 KB SRAM 和256 KB FLASH, 并且集成了标准的Coldfire 外围设备, 包括三个适合中长距离通信的SCI, 一个I2 C
[单片机]
典型范例:<font color='red'>uCOSii</font>在Coldfire MCF52235上的<font color='red'>移植</font>
移植ucosII到STM32F103ZE(三)
四、 移植过程详解: 1. 初始配置 STM32 的标准外设库 stm32 标准外设库的使用在 stm32f10x_stdperiph_lib_um.chm 中的How to use the Library一节中已有说明: 1) 加载文件:加载库文件和相应启动代码到工程中,这一步在上面步骤里已经做过了。 2) 配置芯片类型:(编译下工程,使头文件加载进工程)打开 stm32f10x.h 文件,在大约的 66-73 行,根据所选芯片类型,去掉相应注释。这里我去掉 STM322F10X_HD行的注释(高密度型的stm32芯片)。对自己选用的芯片到底是属于低密度型、中密度型、高密度型还是互联型
[单片机]
移植ucosII到STM32F103ZE(四)
a) 根据stm32f103芯片对系统文件进行修改 根据AN-1018.pdf 和移植详解介绍的移植基础知识,对OS-uCOSIIport 下的代码解释下。 并进行相关特性修改。 os_cpu.h #ifdef OS_CPU_GLOBALS #define OS_CPU_EXT #else #define OS_CPU_EXT extern #endif typedef unsigned char BOOLEAN; typedef unsigned char INT8U; typedef signed char INT8S; typedef unsign
[单片机]
ucosII在51内核单片机上的移植
自嵌入式系统开发以来,很长时间都采用前后台系统软件设计模式:主程序为一个无限循环,单任务顺序执行。通过设置一个或多个中断来处理异步事件。   这种系统对于简单的应用是可以的,但对于实时性要求比较高的、处理任务较多的应用,就会暴露出实时性差、系统可靠性低、稳定性差等缺点。   μC/OS-II 是一种基于优先级的抢占式多 任务实时操作系统,包含了实时内核、任务管理、时间管理、任务间通信同步(信号量,邮箱,消息队列)和内存管理等功能。它可以使各个任务独立工作,互不干涉,很容易实现准时而且无误执行,使实时应用程序的设计和扩展变得容易,使应用程序的设计过程大为减化。而且它内核源代码公开,可移植性强,为编程人员提供了很好的一个软件平台。
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved