zoukankan      html  css  js  c++  java
  • 移植 uCos-III 3.03 到 STM32F429 上

    背景

    通过STM32 的学习,我们可以往更深层次的地方走,尝试系统上的一些开发。

    STM32: F429(StdPeriph)
    uCos-III : v3.04 + 3.03

    有关说明:

    在移植 3.04 版本 UCOSIII 的时候遇到了这样一个问题:一旦调用 OSStatTaskCPUUsageInit()函数就会进入 hardfault,(如果这时选择-O1 或者-O2 优化的话就没有问题),不知是 KEIL 问题还是 UCOSIII 3.04 版本的问题。
    另外,目前 UCOSIII 的资料基本都是基于 UCOSIII 3.03 版本的。
    如果一定要使用 UCOSIII 3.04 的话,使用 KEIL 时一定要 选择-O1 或者-O2 优化。

    其实 uCos-III 3.04 与 3.03 的移植之间就差一步,因为 uCos-III 3.04 中源码有STM32F4的BSP,而 uCos-III 3.03 中没有;
    为了达到STM32F4移植3.03的目的,可以这么做:
    1)移植uCos-III 3.04 中的有关文件
    2)再将uCos-III 3.03 中的有关的文件替换进去即可。

    如何移植不同版本的uCos系统?:只需要将源码的UCOSIIIuCOS-III下的Source文件夹,直接替换掉移植好后的Source,就可以了。

    uCos 介绍

    什么是 uC/OS-III? uC/OS-III(Micro C OS Three 微型的 C语言编写的操作系统第 3 版)是一个可升级的,可固化的,基于优先级的实时内核。它对任务的个数无限制。uC/OS-III 是一个第 3 代的系统内核,支持现代的实时内核所期待的大部分功能。例如资源管理,同步,任务间的通信等等。然而,uC/OS-III 提供的特色功能在其它的实时内核中是找不到的,比如说完备的运行时间测量性能,直接地发送信号或者消息到任务,任务可以同时等待多个内核对象等。

    为什么命名一个新的版本? uC/OS 系列,第一代产生于 1992。经过了多年的使用和上千人的反馈,已经产生了很多的进化版本。 uC/OS-III 是这些反馈和经验的总结。在 uC/OS-II 中很少使用的功能已经被删除或者被更新,添加了更高效的功能和服务。其中最有用的功能应该是时间片轮转法(round robin),这个是 uC/OS-II 中不支持的,但是现在已经是 uC/OS-III 的一个功能了。 uC/OS-III 会提供新的功能以更好地适应新出现的处理器。特别的,uC/OS-III 被设计用于 32 位处理器,但是它也能在 16 位或 8 位处理器中很好地工作。

    uC/OS-III 的目标 uC/OS-III 最主要的目标是提供一流的实时内核以适应更新很快的嵌入式产品。使用像 uC/OS-III 那样具有雄厚的基础和稳定的框架的商业实时内核,能够帮助设计师们处理日益复杂的嵌入式设计。

    各目录以及关键文件说明

    通过官网下载源码,或者使用本人整理的代码
    解压以后

    # Schips @ SCHIPS-L in UCOSIII 3.04 [9:55:00]
    $ tree -d
    .
    └── Micrium
        └── Software
            ├── EvalBoards
            ├── uC-CPU
            ├── uC-LIB
            └── uCOS-III
    

    下面我们分别对 Software 下的不同目录进行说明

    EvalBoards

    在默认情况下,uCos已经在EvalBoards目录为我们准备好了STM32F429II-SK移植。

    uC-CPU

    这个文件里面是与 CPU 相关的代码

    # Schips @ SCHIPS-L in UCOSIII 3.04/Micrium/Software/uC-CPU [10:09:39]
    .
    ├── ARM-Cortex-M4
    │   ├── GNU
    │   │   ├── cpu.h
    │   │   ├── cpu_a.s
    │   │   └── cpu_c.c
    │   ├── IAR
    │   │   ├── cpu.h
    │   │   ├── cpu_a.asm
    │   │   └── cpu_c.c
    │   └── RealView
    │       ├── cpu.h
    │       ├── cpu_a.asm
    │       └── cpu_c.c
    ├── cpu_core.c
    ├── cpu_core.h
    └── cpu_def.h
    

    cpu_core.c

    该文件包含了适用于所有 CPU 架构的 C 代码。该文件包含了用来测量中断关闭事件 的函数(中断关闭和打开分别由 CPU_CRITICAL_ENTER()和 CPU_CRITICAL_EXIT()两个宏实现),还包含一个可模仿前导码零计算的函数(以防止 CPU 不提供这样的指令),以及一些其他的 函数。

    cpu_core.h

    包含 cpu_core.c 中函数的原型声明,以及用来测量中断关闭时间变量的定义。

    cpu_def.h

    包含 uC/CPU 模块使用的各种#define 常量。

    详细大家也注意到目录(GNU、IAR、RealView)中都有 cpu.hcpu_a.asmcpu_c.c 这三个文件。GNU、IAR、RealView对应了不同的编译器,这是为了根据不同的编译平台有不同的处理。我们使用的是 KEIL,所以我们在移植时选择 RealView 中的文件。

    cpu.h

    包含了一些类型的定义,使 UCOSIII 和其他模块可与 CPU 架构和编译器字宽度无关。 在该文件中用户能够找到 CPU_INT16U、CPU_INT32U、CPU_FP32 等数据类型的定义。该文 件还指定了 CPU 使用的是大端模式还是小端模式,定义了 UCOSIII 使用的 CPU_STK 数据 类型,定义了 CPU_CRITICAL_ENTER()和 CPU_CRITICAL_EXTI(),还包括一些与 CPU 架构相关 的函数的声明。

    cpu_a.asm

    该文件包含了一些用汇编语言编写的函数,可用来开中断和关中断,计算前导零(如果 CPU 支持这条指令),以及其他一些只能用汇编语言编写的与 CPU 相关的函数,这个文件中 的函数可以从 C 代码中调用。

    cpu_c.c

    包含了一些基于特定 CPU 架构但为了可移植而用 C 语言编写的函数 C 代码。作为一个普通原则,除非汇编语言能显著提高性能,否则尽量用 C 语言编写函数。

    uC-LIB

    uC-LIB 是由一些可移植并且与编译器无关的函数组成,UCOS III 不使用 uC-LIB 中的函 数,但是 UCOS-III 和 uC-CPU 假定 lib_def.h 是存在的。

    # Schips @ SCHIPS-L in UCOSIII 3.04/Micrium/Software/uC-LIB [10:16:04]
    $ tree
    .
    ├── lib_ascii.c
    ├── lib_ascii.h
    ├── lib_def.h
    ├── lib_math.c
    ├── lib_math.h
    ├── lib_mem.c
    ├── lib_mem.h
    ├── lib_str.c
    ├── lib_str.h
    └── Ports
        └── ARM-Cortex-M4
            ├── GNU
            │   └── lib_mem_a.s
            ├── IAR
            │   └── lib_mem_a.asm
            └── RealView
                └── lib_mem_a.asm
    
    

    lib_ascii.h 和 lib_ascii.c

    提供 ASCII_ToLower()、ASCII_ToUpper()、ASCII_IsAlpha()和 ASCII_IsDig()等函数,它们可 以分别替代标准库函数 tolower()、toupper()、isalpha()和 isdigit()等。

    lib_def.h

    定义了许多常量,如 RTUE/FALSE、YES/NO、ENABLE/DISABLE,以及各种进制的常量。 但是,该文件中所有#define 常量都以 DEF_打头,所以上述常量的名字实际上为 DEF_TRUE/DEF_FALSE、DEF_YES/DEF_NO、DEF_ENABLE/DEF_DISABLE 等。该文件还为常用数 学计算定义了宏。

    lib_math.h 和 lib_math.c

    包含了 Math_Rand()、Math_SetRand()等函数的源代码,可用来替代标准库函数 rand()、
    srand()。

    lib_mem.c 和 lib_mem.h

    包含了 Mem_Clr()、Mem_Set()、Mem_Copy()和 Mem_Cmp()等函数的源代码,可用来 替代标准库函数 memclr()、memset()、memcpy()和 memcmp()等。

    lib_str.c 和 lib_str.h

    包含了 Str_Lenr()、Str_Copy()和 Str_Cmp()等函数的源代码,可用于替代标准库函数 srtlen()、strcpy()和 strcmp()等。

    lib_mem_a.asm (Ports下面)

    包含了 lib_mem.c 函数的汇编优化版。

    uCOS-III

    这个文件夹中有两个文件 Ports 和 Sourec,Ports 文件为与 CPU 平台有关的文件, Source 文件夹里面为 UCOSIII 3.04 的源码

    UCOSIII 3.04 和 UCOSIII 3.03 源码的文件都是一样的,不同的是各个文件里面的有些函 数做了修改

    # Schips @ SCHIPS-L in UCOSIII 3.04/Micrium/Software/uCOS-III [10:24:31]
    $ tree
    .
    ├── Ports
    │   └── ARM-Cortex-M4
    │       └── Generic
    │           ├── GNU
    │           │   ├── os_cpu.h
    │           │   ├── os_cpu_a.S
    │           │   └── os_cpu_c.c
    │           ├── IAR
    │           │   ├── os_cpu.h
    │           │   ├── os_cpu_a.asm
    │           │   └── os_cpu_c.c
    │           └── RealView
    │               ├── os_cpu.h
    │               ├── os_cpu_a.asm
    │               └── os_cpu_c.c
    └── Source
        ├── os.h
        ├── os_cfg_app.c
        ├── os_core.c
        ├── os_dbg.c
        ├── os_flag.c
        ├── os_int.c
        ├── os_mem.c
        ├── os_msg.c
        ├── os_mutex.c
        ├── os_pend_multi.c
        ├── os_prio.c
        ├── os_q.c
        ├── os_sem.c
        ├── os_stat.c
        ├── os_task.c
        ├── os_tick.c
        ├── os_time.c
        ├── os_tmr.c
        ├── os_type.h
        └── os_var.c
    

    UCOSIII 源码各个文件内容:

    • os.h : uCos-III 主要头文件,声明了常量、宏、全局变量、函数原型等
    • os_Cfs_app.c : 根据 os_cfg_app.h 中的宏定义声明变量和数组
    • os_core.c : uCos-III 内核功能模块
    • os_dbg.c : 内核调试或uC/Probe 使用的常量的声明
    • os_flag.c : 事件标志的管理代码
    • os_int.c : 中断处理任务的代码
    • os_mem.c : uCos-III固定大小的储存分区管理代码
    • os_msg.c : 消息处理代码
    • os_mutex.c : 互斥信号量的管理代码
    • os_pend_multi.c : 允许任务同时等待多个信号量或多个消息队列的代码
    • os_prio.c : 位映射表的管理代码(用来追踪已经就绪的任务)
    • os_q.c : 包含消息队列的管理代码
    • os_sem.c : 信号量的管理代码
    • os_stat.c : 统计任务的代码
    • os_task.c : 任务的管理代码
    • os_tick.c : 可管理正在延迟和超时等待的任务的代码
    • os_time.c : 时间调度任务的延迟管理代码
    • os_tmr.c : 软件定时器的管理代码
    • os_type.h : uCos-III的数据类型的声明
    • os_var.c : 包含uCos-III全局变量

    uCosIII 文件移植

    假设项目名称为:Project_StdPeriph_F429_uCosIII,且 目录树如下:

    关于构建 STM32 标准库工程可以参考:STM32学习笔记:创建工程模板

    # Schips @ SCHIPS-L in Project_StdPeriph_F429_uCosIII 
    $ tree -d
    .
    ├── CMSIS
    ├── Driver
    ├── Library
    │   ├── inc
    │   └── src
    ├── Project
    │   ├── Listings
    │   └── Objects
    └── User
    

    在项目中新建目录:uCosIII,并将uC-CPU、uC-LIB 和 uCOS-III 目录复制到uCosIII

    拷贝 EvalBoards 下的文件

    1)在uCosIII文件中新建两个目录:uCOS_BSP 和 uCOS_CONFIG

    2)拷贝文件到 uCOS_CONFIG
    路径:UCOSIII 3.04/Micrium/Software/EvalBoards/ST/STM32F429II-SK/uCOS-III
    对应文件: app_cfg.h, cpu_cfg.h, lib_cfg.h, os_app_hooks.c, os_app_hooks.h, os_cfg.h, os_cfg_app.h

    3)拷贝文件到 uCOS_BSP
    路径:UCOSIII 3.04/Micrium/Software/EvalBoards/ST/STM32F429II-SK/BSP
    对应文件:bsp.c, bsp.h

    最终效果

    # Schips @ SCHIPS-L in Project_StdPeriph_F429_uCosIII 
    $ tree # 由于篇幅限制,这里省略了 STM32 标准库的文件
    .
    ├── CMSIS
    ├── Driver
    ├── Library
    │   ├── inc
    │   └── src
    ├── Project
    │   ├── Listings
    │   └── Objects
    ├── uCosIII
    │   ├── uC-CPU
    │   │   ├── ARM-Cortex-M4
    │   │   │   └── RealView
    │   │   │       ├── cpu.h
    │   │   │       ├── cpu_a.asm
    │   │   │       └── cpu_c.c
    │   │   ├── cpu_core.c
    │   │   ├── cpu_core.h
    │   │   └── cpu_def.h
    │   ├── uC-LIB
    │   │   ├── lib_ascii.c
    │   │   ├── lib_ascii.h
    │   │   ├── lib_def.h
    │   │   ├── lib_math.c
    │   │   ├── lib_math.h
    │   │   ├── lib_mem.c
    │   │   ├── lib_mem.h
    │   │   ├── lib_str.c
    │   │   ├── lib_str.h
    │   │   └── Ports
    │   │       └── ARM-Cortex-M4
    │   │           ├── GNU
    │   │           │   └── lib_mem_a.s
    │   │           ├── IAR
    │   │           │   └── lib_mem_a.asm
    │   │           └── RealView
    │   │               └── lib_mem_a.asm
    │   ├── uCOS_BSP
    │   │   ├── bsp.c
    │   │   └── bsp.h
    │   ├── uCOS_CONFIG
    │   │   ├── app_cfg.h
    │   │   ├── cpu_cfg.h
    │   │   ├── includes.h
    │   │   ├── lib_cfg.h
    │   │   ├── os_app_hooks.c
    │   │   ├── os_app_hooks.h
    │   │   ├── os_cfg.h
    │   │   └── os_cfg_app.h
    │   └── uCOS-III
    │       ├── Ports
    │       │   └── ARM-Cortex-M4
    │       │       └── Generic
    │       │           └── RealView
    │       │               ├── os_cpu.h
    │       │               ├── os_cpu_a.asm
    │       │               └── os_cpu_c.c
    │       └── Source
    │           ├── os.h
    │           ├── os_cfg_app.c
    │           ├── os_core.c
    │           ├── os_dbg.c
    │           ├── os_flag.c
    │           ├── os_int.c
    │           ├── os_mem.c
    │           ├── os_msg.c
    │           ├── os_mutex.c
    │           ├── os_pend_multi.c
    │           ├── os_prio.c
    │           ├── os_q.c
    │           ├── os_sem.c
    │           ├── os_stat.c
    │           ├── os_task.c
    │           ├── os_tick.c
    │           ├── os_time.c
    │           ├── os_tmr.c
    │           ├── os_type.h
    │           └── os_var.c
    └── User
        ├── main.c
        └── main.h
    

    在Keil 中 新建 分组

    1)添加 工程目录下 uCosIII 目录中的 uC_CPU, uC_LIB, uCOS_BSP, uCOS_CONFIG, uCOS_III 到 分组 中。

    2)添加对应的.asm,.c文件到 组中
    uC_CPU: 添加 下面的 .c 与 .asm

    # Schips @ SCHIPS-L in Project_StdPeriph_F429_uCosIII/uCosIII/uC-CPU 
    
    $ tree
    .
    ├── ARM-Cortex-M4
    │   └── RealView
    │       ├── cpu_a.asm
    │       └── cpu_c.c
    └── cpu_core.c
    

    uC_LIB: 添加 下面的 .c 与 .asm

    # Schips @ SCHIPS-L in Project_StdPeriph_F429_uCosIII/uCosIII/uC-LIB 
    $ tree
    .
    ├── lib_ascii.c
    ├── lib_math.c
    ├── lib_mem.c
    ├── lib_str.c
    └── Ports
        └── ARM-Cortex-M4
            └── RealView
                └── lib_mem_a.asm
    

    uCOS_BSP:添加下面的 .c

    # Schips @ SCHIPS-L in Project_StdPeriph_F429_uCosIII/uCosIII/uCOS_BSP 
    $ tree
    .
    └── bsp.c
    
    

    uCOS_CONFIG:添加下面的 .c

    # Schips @ SCHIPS-L in Project_StdPeriph_F429_uCosIII/uCosIII/uCOS_CONFIG
    $ tree
    .
    └── os_app_hooks.c
    
    

    uCOS_III:添加下面的 .c

    # Schips @ SCHIPS-L in Project_StdPeriph_F429_uCosIII/uCosIII/uCOS-III
    $ tree | grep -v ".h"
    .
    ├── Ports
    │   └── ARM-Cortex-M4
    │       └── Generic
    │           └── RealView
    │               ├── os_cpu_a.asm
    │               └── os_cpu_c.c
    └── Source
        ├── os_cfg_app.c
        ├── os_core.c
        ├── os_dbg.c
        ├── os_flag.c
        ├── os_int.c
        ├── os_mem.c
        ├── os_msg.c
        ├── os_mutex.c
        ├── os_pend_multi.c
        ├── os_prio.c
        ├── os_q.c
        ├── os_sem.c
        ├── os_stat.c
        ├── os_task.c
        ├── os_tick.c
        ├── os_time.c
        ├── os_tmr.c
        └── os_var.c
    

    3)最终效果

    Keil 添加头文件

    将 ucos有关组 中的 .h 的所在路径添加到 头文件路径 中

    # Schips @ SCHIPS-L in Project_StdPeriph_F429_uCosIII/uCosIII 
    $ find .. | grep ".h" | grep -v "GNU" | grep -v "IAR" | xargs -i  dirname {} | uniq
    
    ..uCosIIIuC-CPUARM-Cortex-M4RealView
    ..uCosIIIuC-CPU
    ..uCosIIIuC-LIB
    ..uCosIIIuCOS-IIIPortsARM-Cortex-M4GenericRealView
    ..uCosIIIuCOS-IIISource
    ..uCosIIIuCOS_BSP
    ..uCosIIIuCOS_CONFIG
    
    

    uCos-III 代码修改

    编译后,一般会出现这样的错误:提示我们在 bsp.c 文 件中 BSP_IntInit()和 BSP_PeriphEn()这两个函数未定义,这里我们先不管这两个错误。

    compiling os_time.c...
    compiling os_tmr.c...
    compiling os_var.c...
    assembling os_cpu_a.asm...
    compiling os_cpu_c.c...
    linking...
    .ObjectsProject_StdPeriph_F429.axf: Error: L6218E: Undefined symbol BSP_IntInit (referred from bsp.o).
    .ObjectsProject_StdPeriph_F429.axf: Error: L6218E: Undefined symbol BSP_PeriphEn (referred from bsp.o).
    Not enough information to list image symbols.
    Finished: 1 information, 0 warning and 2 error messages.
    ".ObjectsProject_StdPeriph_F429.axf" - 2 Error(s), 0 Warning(s).
    Target not created.
    Build Time Elapsed:  00:00:38
    

    下载修改以后的代码:uCos-III需要修改的文件.zip,里面包括了一个基础的uCosIII项目以外还有为了方便调试而调好的串口打印程序。

    为了确保排除所有的问题,代码包中除了 uCos-III 以外的其他文件也加进项目中。

    # Schips @ SCHIPS-L in uCos-III需要修改的文件
    $ tree
    .
    ├── bsp.c
    ├── bsp.h
    ├── main.c
    ├── os_cfg_app.h
    ├── os_cpu_a.asm
    ├── os_cpu_c.c
    └── SYSTEM
        ├── delay
        │   ├── delay.c
        │   └── delay.h
        ├── sys
        │   ├── sys.c
        │   └── sys.h
        └── usart
            ├── usart.c
            └── usart.h
    

    uCOS_BSP

    替换 bsp.c和bsp.h文件,这里直接下载已经修改好的文件

    修改 bsp.c 在修改之前,我们稍微讲解一下 Cortex-M3/M4 的跟踪组件。

    在 bsp.c 文件里面有很多的代码,我们只需要其中的很少一部分关于 DWT 的代码,因此我们要做相应的修改。

    在 CM3/CM4 中有 3 种跟踪源:ETM、ITM 和 DWT,要想使用 ETM、ITM 和 DWT 的 话,要将 DEMCR(* 0XE000EDFC) 寄存器的 TRCENA 位(bit24)置 1。

    感兴趣的朋友可以自行查阅:《Cortex-M3 与 M4 权威指南》(英文名为《The DefinitiveGuide to ARM Cortex-M3 and Cortex-M4 Processors, 3rd Edition》)的 501 页有详细的讲解。

    在 DWT 组件中有一个 CYCCNT 寄存器,这个寄存器用来对时钟周期计数,我们可以使用这个寄存器来测量执行某个任务所花费的时间。

    DWT 组件有多个寄存器,我们这里只使用 DWT 的控制寄存器 CTRL( 0XE0001000)、CYCCNT 寄存器(0XE0001004)。如果我们要使用时 钟计数功能需要将 CTRL 寄存器的 bit0 置 1。

    uCOS_CONFIG

    修改os_cfg_app.h文件,系统裁剪和内核有关的,这里直接下载已经修改好的文件

    uCOS-III

    进入 uCosIIIuCOS-IIIPortsARM-Cortex-M4GenericRealView

    替换 os_cpu_a.asm汇编文件,这里直接下载已经修改好的文件

    替换os_cpu_c.c文件,这个主要是修改堆栈函数,这里直接下载已经修改好的文件

    编译

    编译以后,发项提示 PendSV_Handler(负责上下文切换) 在 os_cpu_a.o 与 stm32f4xx_it.o 重复定义。

    assembling os_cpu_a.asm...
    compiling os_cpu_c.c...
    linking...
    .ObjectsProject_StdPeriph_F429.axf: Error: L6200E: Symbol PendSV_Handler multiply defined (by os_cpu_a.o and stm32f4xx_it.o).
    Not enough information to list image symbols.
    Not enough information to list the image map.
    Finished: 2 information, 0 warning and 1 error messages.
    ".ObjectsProject_StdPeriph_F429.axf" - 1 Error(s), 0 Warning(s).
    Target not created.
    Build Time Elapsed:  00:00:02
    

    找到 STM32F4xx_it.c中的PendSV_Handler,屏蔽掉即可;或者添加 __weak 关键字

    同理,由于delay.c中实现了SysTick_Handler ,所以要把 stm32f4xx_it.c 中的 SysTick_Handler 屏蔽掉。

    Build target 'f429'
    compiling usart.c...
    compiling sys.c...
    compiling delay.c...
    linking...
    .ObjectsProject_StdPeriph_F429.axf: Error: L6200E: Symbol SysTick_Handler multiply defined (by stm32f4xx_it.o and delay.o).
    Not enough information to list image symbols.
    Not enough information to list the image map.
    Finished: 2 information, 0 warning and 1 error messages.
    ".ObjectsProject_StdPeriph_F429.axf" - 1 Error(s), 0 Warning(s).
    Target not created.
    Build Time Elapsed:  00:00:03
    

    附录:参考的修改过程

    本文档基于 uCOS-III 3.04 与 最终结果之间的差异。

    os_cpu_a.asm 修改的地方:

    1)函数 OS_CPU_PendSVHandler ,改名为 PendSV_Handler。
    2)函数 OS_CPU_PendSVHandler_nosave 改名为 PendSVHandler_nosave
    2)NVIC_PENDSV_PRI EQU 0xFF 改为 NVIC_PENDSV_PRI EQU 0xFFFF
    3)PendSV_Handler中

    PendSV_Handler
        CPSID   I                                                   ; Prevent interruption during context switch
        MRS     R0, PSP                                             ; PSP is process stack pointer
        CBZ     R0, PendSVHandler_nosave                     ; Skip register save the first time
    
    	;Is the task using the FPU context? If so, push high vfp registers.
    	TST		R14, #0X10
    	IT		EQ
    	VSTMDBEQ R0!,{S16-S31}
    	
        SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
        STM     R0, {R4-R11}
    
        LDR     R1, =OSTCBCurPtr                                    ; OSTCBCurPtr->OSTCBStkPtr = SP;
        LDR     R1, [R1]
        STR     R0, [R1]                                            ; R0 is SP of process being switched out
    
                                                                    ; At this point, entire context of process has been saved
    
    

    4)PendSVHandler_nosave 中

    PendSVHandler_nosave
        PUSH    {R14}                                               ; Save LR exc_return value
        LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
        BLX     R0
        POP     {R14}
    
        LDR     R0, =OSPrioCur                                      ; OSPrioCur   = OSPrioHighRdy;
        LDR     R1, =OSPrioHighRdy
        LDRB    R2, [R1]
        STRB    R2, [R0]
    
        LDR     R0, =OSTCBCurPtr                                    ; OSTCBCurPtr = OSTCBHighRdyPtr;
        LDR     R1, =OSTCBHighRdyPtr
        LDR     R2, [R1]
        STR     R2, [R0]
    
        LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
        LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
        ADDS    R0, R0, #0x20
       
       ;Is the task using the FPU context? If so, push high vfp registers.
    	TST 	R14, #0x10
    	IT 		EQ
    	VLDMIAEQ R0!, {S16-S31} 
    	
    	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
    

    os_cpu_.c 改动的地方

    1)引入了一个新的头文件:#include "includes.h"
    2)OSTaskSwHook 函数中,屏蔽了 此段

    #if (OS_CPU_ARM_FP_EN == DEF_ENABLED)
    //    if ((OSTCBCurPtr->Opt & OS_OPT_TASK_SAVE_FP) != (OS_OPT)0) {
    //        OS_CPU_FP_Reg_Push(OSTCBCurPtr->StkPtr);
    //    }
    //    if ((OSTCBHighRdyPtr->Opt & OS_OPT_TASK_SAVE_FP) != (OS_OPT)0) {
    //        OS_CPU_FP_Reg_Pop(OSTCBHighRdyPtr->StkPtr);
    //    }
    #endif
    

    3)OSTaskStkInit,新的内容如下:

    CPU_STK  *OSTaskStkInit (OS_TASK_PTR    p_task,
                             void          *p_arg,
                             CPU_STK       *p_stk_base,
                             CPU_STK       *p_stk_limit,
                             CPU_STK_SIZE   stk_size,
                             OS_OPT         opt)
    {
        CPU_STK    *p_stk;
    
    
        (void)opt;                                                  /* Prevent compiler warning                               */
    
        p_stk = &p_stk_base[stk_size];                              /* Load stack pointer                                     */
                                                                    /* Align the stack to 8-bytes.                            */
        p_stk = (CPU_STK *)((CPU_STK)(p_stk) & 0xFFFFFFF8);
    
    #if (__FPU_PRESENT==1)&&(__FPU_USED==1)     	/* Registers stacked as if auto-saved on exception        */
    	*(--p_stk) = (CPU_STK)0x00000000u; //No Name Register  
    	*(--p_stk) = (CPU_STK)0x00001000u; //FPSCR
    	*(--p_stk) = (CPU_STK)0x00000015u; //s15
    	*(--p_stk) = (CPU_STK)0x00000014u; //s14
    	*(--p_stk) = (CPU_STK)0x00000013u; //s13
    	*(--p_stk) = (CPU_STK)0x00000012u; //s12
    	*(--p_stk) = (CPU_STK)0x00000011u; //s11
    	*(--p_stk) = (CPU_STK)0x00000010u; //s10
    	*(--p_stk) = (CPU_STK)0x00000009u; //s9
    	*(--p_stk) = (CPU_STK)0x00000008u; //s8
    	*(--p_stk) = (CPU_STK)0x00000007u; //s7
    	*(--p_stk) = (CPU_STK)0x00000006u; //s6
    	*(--p_stk) = (CPU_STK)0x00000005u; //s5
    	*(--p_stk) = (CPU_STK)0x00000004u; //s4
    	*(--p_stk) = (CPU_STK)0x00000003u; //s3
    	*(--p_stk) = (CPU_STK)0x00000002u; //s2
    	*(--p_stk) = (CPU_STK)0x00000001u; //s1
    	*(--p_stk) = (CPU_STK)0x00000000u; //s0
    #endif
    	
    	*(--p_stk) = (CPU_STK)0x01000000u;                            /* xPSR                                                   */
            *(--p_stk) = (CPU_STK)p_task;                                 /* Entry Point                                            */
            *(--p_stk) = (CPU_STK)OS_TaskReturn;                          /* R14 (LR)                                               */
            *(--p_stk) = (CPU_STK)0x12121212u;                            /* R12                                                    */
            *(--p_stk) = (CPU_STK)0x03030303u;                            /* R3                                                     */
            *(--p_stk) = (CPU_STK)0x02020202u;                            /* R2                                                     */
            *(--p_stk) = (CPU_STK)p_stk_limit;                            /* R1                                                     */
            *(--p_stk) = (CPU_STK)p_arg;                                  /* R0 : argument                                          */
    
    #if (__FPU_PRESENT==1)&&(__FPU_USED==1)
    	*(--p_stk) = (CPU_STK)0x00000031u; //s31
    	*(--p_stk) = (CPU_STK)0x00000030u; //s30
    	*(--p_stk) = (CPU_STK)0x00000029u; //s29
    	*(--p_stk) = (CPU_STK)0x00000028u; //s28
    	*(--p_stk) = (CPU_STK)0x00000027u; //s27
    	*(--p_stk) = (CPU_STK)0x00000026u; //s26	
    	*(--p_stk) = (CPU_STK)0x00000025u; //s25
    	*(--p_stk) = (CPU_STK)0x00000024u; //s24
    	*(--p_stk) = (CPU_STK)0x00000023u; //s23
    	*(--p_stk) = (CPU_STK)0x00000022u; //s22
    	*(--p_stk) = (CPU_STK)0x00000021u; //s21
    	*(--p_stk) = (CPU_STK)0x00000020u; //s20
    	*(--p_stk) = (CPU_STK)0x00000019u; //s19
    	*(--p_stk) = (CPU_STK)0x00000018u; //s18
    	*(--p_stk) = (CPU_STK)0x00000017u; //s17
    	*(--p_stk) = (CPU_STK)0x00000016u; //s16
    #endif
                                                                    /* Remaining registers saved on process stack             */
        *(--p_stk) = (CPU_STK)0x11111111u;                            /* R11                                                    */
        *(--p_stk) = (CPU_STK)0x10101010u;                            /* R10                                                    */
        *(--p_stk) = (CPU_STK)0x09090909u;                            /* R9                                                     */
        *(--p_stk) = (CPU_STK)0x08080808u;                            /* R8                                                     */
        *(--p_stk) = (CPU_STK)0x07070707u;                            /* R7                                                     */
        *(--p_stk) = (CPU_STK)0x06060606u;                            /* R6                                                     */
        *(--p_stk) = (CPU_STK)0x05050505u;                            /* R5                                                     */
        *(--p_stk) = (CPU_STK)0x04040404u;                            /* R4                                                     */
    
        return (p_stk);
    }
    

    bsp.h 修改的地方

    删除了所有的函数声明。

    bsp.c 修改的地方

    主要是在于头部的改动。

    1)删除了关于LED有关字段的宏。

    2)宏BSP_REG_DBGMCU_CR 与 宏BSP_BIT_DEM_CR_TRCENA 之间的内容全部删除

    3)从 宏BSP_BIT_DWT_CR_CYCCNTENA 开始的下面 与 BSP_Init 的声明与实现函数之间的所有内容全部删除

    os_cfg_app.h 的改动

    主要是值的改动

  • 相关阅读:
    Hibernate5.2之一对一主键关联(四)
    Hibernate5.2关联关系之双向一对多(三)
    Hibernate5.2关联关系之单向多对一(二)
    Hibernate5.2关联关系之单向一对多(一)
    Hibernate5.2之原生SQL查询
    Hibernate5.2之HQL查询
    Winform 按键组合键
    当Bitmap的宽度大于ImageView的最大显示宽度时对ImageView的宽高重新计算来适应Bitmap的宽高(转)
    sqlserver 函數執行動態sql語句,取值
    时间格式化 字符串转时间(转)
  • 原文地址:https://www.cnblogs.com/schips/p/12381589.html
Copyright © 2011-2022 走看看