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

主要是值的改动

原文地址:https://www.cnblogs.com/schips/p/12381589.html