移植 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系統?:只需要將源碼的UCOSIII\uCOS-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

..\uCosIII\uC-CPU\ARM-Cortex-M4\RealView
..\uCosIII\uC-CPU
..\uCosIII\uC-LIB
..\uCosIII\uCOS-III\Ports\ARM-Cortex-M4\Generic\RealView
..\uCosIII\uCOS-III\Source
..\uCosIII\uCOS_BSP
..\uCosIII\uCOS_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...
.\Objects\Project_StdPeriph_F429.axf: Error: L6218E: Undefined symbol BSP_IntInit (referred from bsp.o).
.\Objects\Project_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.
".\Objects\Project_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

進入 uCosIII\uCOS-III\Ports\ARM-Cortex-M4\Generic\RealView

替換 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...
.\Objects\Project_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.
".\Objects\Project_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...
.\Objects\Project_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.
".\Objects\Project_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 的改動

主要是值的改動


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM