0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32入门学习笔记之uCOS-II系统移植3

jf_78858299 来源:滑小稽笔记 作者:电子技术园地 2023-02-16 16:13 次阅读

⑤这两个函数都用于任务切换,它们的本质都是触发PendSV中断,具体切换过程在PendSV的中断函数中进行,其中OSCtxSw是任务级切换,OSIntCtxSw是中断级切换,是从中断退出时切换到一个任务中,从中断切换到任务的过程中,CPU寄存器入栈工作已经完成。

OSCtxSw
  PUSH    {R4, R5}
  LDR     R4, =NVIC_INT_CTRL        ;触发PendSV异常
  LDR     R5, =NVIC_PENDSVSET
  STR     R5, [R4]              ;向NVIC_INT_CTRL写入NVIC_PENDSVSET触发PendSV中断
  POP     {R4, R5}
  BX      LR
OSIntCtxSw
  PUSH    {R4, R5}
  LDR     R4, =NVIC_INT_CTRL        ;触发PendSV异常
  LDR     R5, =NVIC_PENDSVSET
  STR     R5, [R4]              ;向NVIC_INT_CTRL写入NVIC_PENDSVSET触发PendSV中断
  POP     {R4, R5}
  BX      LR
  NOP

⑥这部分代码才是真正的任务切换函数,通过触发PendSV中断来进入该函数内进行任务切换

PendSV_Handler
  CPSID  I                                ;任务切换过程中必须关闭所有中断
  MRS    R0, PSP                          ;如果在用PSP堆栈,则可以忽略保存寄存器
  CBZ    R0, PendSV_Handler_Nosave    ;如果PSP为0就转移到PendSV_Handler_Nosave


  SUBS    R0, R0, #0x20                                        ;R0-=20H
  STM     R0, {R4-R11}


  LDR     R1, =OSTCBCur
  LDR     R1, [R1]
  STR     R0, [R1]


PendSV_Handler_Nosave
    PUSH    {R14}              ;保存R14的值
    LDR     R0, =OSTaskSwHook        ;调用OSTaskSwHook()
    BLX     R0
    POP     {R14}


    LDR     R0, =OSPrioCur
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]


    LDR     R0, =OSTCBCur
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]


    LDR     R0, [R2]              ;R0作为新任务的SP
    LDM     R0, {R4-R11}            ;从堆栈中恢复R4-R11
    ADDS    R0, R0, #0x20
    MSR     PSP, R0              ;用新任务的SP加载PSP
    ORR     LR, LR, #0x04          ;确保LR的bit2为1,返回后使用进程堆栈
    CPSIE   I                ;开启所有中断
    BX      LR                ;中断返回


  end

(2)os_cpu.h文件详解

①这部分主要用于定义一些数据类型,其中重点关注OS_STK这个数据类型,我们在定义任务堆栈的时候就是该类型数据,这是一个32位的数据类型,按字节算的话实际堆栈大小是我们定义的4倍。

typedef unsigned char  BOOLEAN;
typedef unsigned char  INT8U;
typedef signed   char  INT8S;
typedef unsigned short INT16U;
typedef signed   short INT16S;
typedef unsigned int   INT32U;
typedef signed   int   INT32S;
typedef float          FP32;
typedef double         FP64;


typedef unsigned int   OS_STK;
typedef unsigned int   OS_CPU_SR;

②这部分代码定义了堆栈的增长方向,任务机切换的宏定义OS_TASK_SW,如果OS_CRITICAL_METHOD被定义为3的话那么进出临界段的宏定义分别为OS_ENTER_CRITICAL和OS_EXIT_CRITICAL,这两个函数都是用汇编语言编写的

//OS_CRITICAL_METHOD = 1 :直接使用处理器的开关中断指令来实现宏 
//OS_CRITICAL_METHOD = 2 :利用堆栈保存和恢复CPU的状态 
//OS_CRITICAL_METHOD = 3 :利用编译器扩展功能获得程序状态字,保存在局部变量cpu_sr


#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


void       OSCtxSw(void);
void       OSIntCtxSw(void);
void       OSStartHighRdy(void);
void       OSPendSV(void);


#if OS_CRITICAL_METHOD == 3u
OS_CPU_SR  OS_CPU_SR_Save(void);
void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
#endif
OS_CPU_EXT INT32U OSInterrputSum;

(3)sys.h文件修改

添加关于条件编译的定义,在文件中添加以下代码即可。

#define SYSTEM_SUPPORT_OS 1

当宏定义为1的时候,编译器在编译的时候会只编译满足条件的代码,当为0时,这部分代码不会被编译。

(4)delay.c文件修改

①添加Sys_Tick中断服务函数与函数定义

#include "includes.h"
//支持UCOSII
#ifdef  OS_CRITICAL_METHOD
#define delay_osrunning    OSRunning              //OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec  OS_TICKS_PER_SEC            //OS时钟节拍,即每秒调度次数
#define delay_osintnesting  OSIntNesting                //中断嵌套级别,即中断嵌套次数
#endif
//systick中断服务函数,使用OS时用到
void SysTick_Handler()
{
  //OS开始跑了,才执行正常的调度处理
  if( delay_osrunning==1 )
  {
    OSIntEnter() ;                        //进入中断
    OSTimeTick() ;                      //调用ucos的时钟服务程序
    OSIntExit() ;                        //触发任务切换软中断
  }
}

②时钟初始化函数修改

void SysTick_Init( u8 SYSCLK )
{
#if SYSTEM_SUPPORT_OS
  u32 reload;
#endif
   SysTick->CTRL &= ~( 1<<2 ) ;                  //SYSTICK使用外部时钟源
  fac_us = SYSCLK/8 ;                      //fac_us都需要使用
#if SYSTEM_SUPPORT_OS
  reload = SYSCLK/8 ;                      //每秒钟的计数次数,单位为K     
  reload *= 1000000/delay_ostickspersec ;              //根据delay_ostickspersec设定溢出时间
  fac_ms = 1000/delay_ostickspersec ;                //代表OS可以延时的最少单位
  SysTick->CTRL |= 1<<1 ;                    //开启SYSTICK中断
  SysTick->LOAD = reload ;                    //每1/delay_ostickspersec秒中断一次
  SysTick->CTRL |= 1<<0 ;                    //开启SYSTICK
#else
  fac_ms = ( u16 )fac_us*1000 ;                  //代表每个ms需要的systick时钟数
#endif
}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6032

    文章

    44513

    浏览量

    632738
  • 操作系统
    +关注

    关注

    37

    文章

    6733

    浏览量

    123182
  • uCOS-Ⅱ
    +关注

    关注

    0

    文章

    9

    浏览量

    8585
收藏 人收藏

    评论

    相关推荐

    ucos-II入门学习(基于cortex-M3

    ucos-II入门学习(基于cortex-M3
    发表于 08-12 17:41

    快速实现STM32移植ucos-ii

    快速实现STM32移植ucos-ii,欢迎大家一起学习[groupid=618]单片机项目开发设计群[/groupid]
    发表于 08-08 16:28

    UCOS-II系统移植问题

    这几天刚刚开始学习UCOS-II系统移植,我用的是野火开发板。资料上说是对startup_stm32f10x_hd.s 文件进行修改,但是我
    发表于 09-12 12:27

    uCOS-II理解和学习路线

    最近为啦准备嵌入式比赛,重拾stm32学习。再次学习也算基本掌握查看调用STM32固件库v3.5啦,觉得这才算入门
    发表于 08-23 09:15

    ucOS-II入门经典教程

    ucOS-II入门经典教程,ucOS-II入门经典教程
    发表于 11-06 10:07 0次下载

    盘古STM32F103开发板移植uCOS-II详细说明

    盘古STM32F103开发板移植uCOS-II详细说明
    发表于 03-02 17:29 13次下载

    STM32平台移植uCOS-II详细说明-2012.11.13

    STM32平台移植uCOS-II详细说明-2012.11.13
    发表于 03-04 15:31 12次下载

    ucos-ii中文书籍

    ucos-ii中文书(邵贝贝).rar 入门经典书籍
    发表于 03-11 11:02 6次下载

    ucOS-II入门经典教程

    ucOS-II入门经典教程,感兴趣可以看看。
    发表于 07-25 18:52 46次下载

    uCOS-ii中文书

    学习uCOS-ii的最好中文教材,uCOS-ii中文书(邵贝贝)
    发表于 08-24 18:31 0次下载

    uCOS-II原理1

    原理uCOS-II
    发表于 12-20 22:58 5次下载

    uCOS-II原理2

    uCOS-II原理2
    发表于 12-20 22:53 0次下载

    uCOS-II原理3

    uCOS-II原理3
    发表于 12-20 22:52 0次下载

    uCOS-II在MSP430移植

    uCOS-II在MSP430移植
    发表于 10-12 17:24 9次下载
    <b class='flag-5'>uCOS-II</b>在MSP430<b class='flag-5'>移植</b>

    手把手盘古STM32开发板移植uCOS-II教程

    手把手盘古STM32开发板移植uCOS-II教程
    发表于 10-16 09:38 22次下载