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 的改动

    主要是值的改动

  • 相关阅读:
    PHP 大小写转换、首字母大写、每个单词首字母大写转换相关函数
    【论文学习4】BiSample: Bidirectional Sampling for Handling Missing Data with Local Differential Privacy
    【论文学习3】Local Differential Privacy for Deep Learning
    【论文学习2】 Differential Privacy Reinforcement Learning
    深度学习中的优化算法
    Spatial crowdsourcing
    “pip install tensorflow ”出现错误
    python或pip'不是内部或外部命令”
    pip install torch出现错误
    打不开gitHub的解决方法
  • 原文地址:https://www.cnblogs.com/schips/p/12381589.html
Copyright © 2011-2022 走看看