1.准备相关文件
直接使用官方的STM32F4移植例程,里面也包含UCOSII的源代码。
进入官网下载中心:
https://www.micrium.com/downloadcenter/
Browse by MCU Manufacturer,然后找到STM32F4:
点进去,选这个UCOSII的工程:
红框是这个工程主要用于评估的项目,这个工程是用于评估UCOSII的,比较容易移植,另外,这个工程支持右面4个IDE,比较方便。
然后准备自己的STM32工程,可以用CubeMX创建,在创建好的工程中新建一个UCOSII的文件夹用于存放UCOSII相关的代码文件。
下载好的工程打开,找到下面这三个文件夹,复制到UCOSII文件夹中。
然后在UCOSII中新建两个文件夹:uCOS-BSP和uCOS-Config,将Micrium\Examples\ST\STM3240G-EVAL\BSP下的这三个文件复制到uCOS-BSP中:
然后将Micrium\Examples\ST\STM3240G-EVAL\OS2下的这6个文件复制到uCOS-Config:
最后,新建一个头文件“includes.h”放到uCOS-Config文件夹中,内容如下:
/************************************************
* UCOS主要包含的头文件
************************************************/
#ifndef __INCLUDES_H_
#define __INCLUDES_H_
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include "os.h"
#include "os_cpu.h"
#include "os_cfg.h"
#include <stm32f4xx.h>
#endif
到现在为止UCOSII的文件都已经添加到项目中了,现在项目文件结构应该是这样的:
2. 编译测试
在移植来的BSP中写了许多example,会关联到官方项目的其他文件,现在把他们删除。也就是修改bsp.c、bsp.h两个文件。
bsp.c:
/*
*********************************************************************************************************
* EXAMPLE CODE
*
* This file is provided as an example on how to use Micrium products.
*
* Please feel free to use any application code labeled as 'EXAMPLE CODE' in
* your application products. Example code may be used as is, in whole or in
* part, or may be used as a reference only. This file can be modified as
* required to meet the end-product requirements.
*
* Please help us continue to provide the Embedded community with the finest
* software available. Your honesty is greatly appreciated.
*
* You can find our product's user manual, API reference, release notes and
* more information at https://doc.micrium.com.
* You can contact us at www.micrium.com.
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*
* MICRIUM BOARD SUPPORT PACKAGE
*
* ST Microelectronics STM32
* on the
*
* STM3240G-EVAL
* Evaluation Board
*
* Filename : bsp.c
* Version : V1.00
* Programmer(s) : FF
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#define BSP_MODULE
#include <bsp.h>
#include <stm32f4xx_hal.h>
/*
*********************************************************************************************************
* BSP_CPU_ClkFreq()
*
* Description : Read CPU registers to determine the CPU clock frequency of the chip.
*
* Argument(s) : none.
*
* Return(s) : The CPU clock frequency, in Hz.
*
* Caller(s) : Application.
*
* Note(s) : none.
*********************************************************************************************************
*/
CPU_INT32U BSP_CPU_ClkFreq (void)
{
CPU_INT32U hclk_freq;
hclk_freq = HAL_RCC_GetHCLKFreq();
return (hclk_freq);
}
bsp.h:
/*
*********************************************************************************************************
*
* MICRIUM BOARD SUPPORT PACKAGE
*
* ST Microelectronics STM32
* on the
*
* STM3240G-EVAL
* Evaluation Board
*
* Filename : bsp.h
* Version : V1.00
* Programmer(s) : FF
*********************************************************************************************************
*/
#ifndef BSP_PRESENT
#define BSP_PRESENT
/*
*********************************************************************************************************
* EXTERNS
*********************************************************************************************************
*/
#ifdef BSP_MODULE
#define BSP_EXT
#else
#define BSP_EXT extern
#endif
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#include <cpu.h>
#include <cpu_core.h>
#include <lib_def.h>
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
CPU_INT32U BSP_CPU_ClkFreq(void);
/*
*********************************************************************************************************
* MODULE END
*********************************************************************************************************
*/
#endif /* End of module include. */
现在,这个工程应该可以编译了。
由于我用的vscode,使用makefile进行编译,所以要把UCOSII的源代码文件、asm文件、头文件引用目录加入到makefile中。
vscode里有复制相对路径功能很好用:
但是复制的相对路径是win平台的路径格式,我用的makefile是要在minGW中运行的,所以要转为sh的路径格式,也就是''要改成'/',然后不是最后一个文件的话后面要加换行符 。改好的makefile如下:
##########################################################################################################################
# File automatically-generated by tool: [projectgenerator] version: [3.3.0] date: [Thu Aug 01 10:21:39 CST 2019]
##########################################################################################################################
# ------------------------------------------------
# Generic Makefile (based on gcc)
#
# ChangeLog :
# 2017-02-10 - Several enhancements + project update mode
# 2015-07-22 - first version
# ------------------------------------------------
######################################
# target
######################################
TARGET = STM32F429IGT-UCOSII
######################################
# building variables
######################################
# debug build?
DEBUG = 1
# optimization
OPT = -Og
#######################################
# paths
#######################################
# Build path
BUILD_DIR = build
######################################
# source
######################################
# C sources
#在此处定义路径
UCOSII = uCOS-II
BSP = BSP
UC_CPU = uCOS-II/uC-CPU
UC_LIB = uCOS-II/uC-LIB
UC_CONFIG = uCOS-II/uC-Config
UC_CORE = uCOS-II/uCOS-II
UC_BSP = uCOS-II/uC-BSP
C_SOURCES = \
Core/Src/main.c \
Core/Src/stm32f4xx_it.c \
Core/Src/stm32f4xx_hal_msp.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c \
Core/Src/system_stm32f4xx.c \
$(UC_CPU)/cpu_core.c \
$(UC_CPU)/ARM-Cortex-M4/GNU/cpu_c.c \
$(UC_LIB)/lib_ascii.c \
$(UC_LIB)/lib_math.c \
$(UC_LIB)/lib_mem.c \
$(UC_LIB)/lib_str.c \
$(UC_BSP)/bsp.c \
$(UC_BSP)/cpu_bsp.c \
$(UC_CONFIG)/app_hooks.c \
$(UC_CORE)/Source/os_core.c \
$(UC_CORE)/Source/os_flag.c \
$(UC_CORE)/Source/os_mbox.c \
$(UC_CORE)/Source/os_mem.c \
$(UC_CORE)/Source/os_mutex.c \
$(UC_CORE)/Source/os_q.c \
$(UC_CORE)/Source/os_sem.c \
$(UC_CORE)/Source/os_task.c \
$(UC_CORE)/Source/os_time.c \
$(UC_CORE)/Source/os_tmr.c \
$(UC_CORE)/Ports/ARM-Cortex-M4/Generic/GNU/os_cpu_c.c \
$(UC_CORE)/Ports/ARM-Cortex-M4/Generic/GNU/os_dbg.c \
$(BSP)/printf_support.c
# ASM sources
ASM_SOURCES = \
startup_stm32f429xx.s \
$(UC_CPU)/ARM-Cortex-M4/GNU/cpu_a.s \
$(UC_LIB)/Ports/ARM-Cortex-M4/GNU/lib_mem_a.s \
$(UC_CORE)/Ports/ARM-Cortex-M4/Generic/GNU/os_cpu_a.s
#######################################
# binaries
#######################################
PREFIX = arm-none-eabi-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
ifdef GCC_PATH
CC = $(GCC_PATH)/$(PREFIX)gcc
AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(GCC_PATH)/$(PREFIX)objcopy
SZ = $(GCC_PATH)/$(PREFIX)size
else
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
SZ = $(PREFIX)size
endif
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
#######################################
# CFLAGS
#######################################
# cpu
CPU = -mcpu=cortex-m4
# fpu
FPU = -mfpu=fpv4-sp-d16
# float-abi
FLOAT-ABI = -mfloat-abi=hard
# mcu
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
# macros for gcc
# AS defines
AS_DEFS =
# C defines
C_DEFS = \
-DUSE_HAL_DRIVER \
-DSTM32F429xx
# AS includes
AS_INCLUDES =
# C includes
C_INCLUDES = \
-ICore/Inc \
-IDrivers/STM32F4xx_HAL_Driver/Inc \
-IDrivers/STM32F4xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS/Device/ST/STM32F4xx/Include \
-IDrivers/CMSIS/Include \
-IDrivers/CMSIS/Include \
-I$(UCOSII) \
-I$(UC_CPU) \
-I$(UC_CPU)/ARM-Cortex-M4 \
-I$(UC_CPU)/ARM-Cortex-M4/GNU \
-I$(UC_LIB) \
-I$(UC_BSP) \
-I$(UC_CONFIG) \
-I$(UC_CORE)/Source \
-I$(UC_CORE)/Ports/ARM-Cortex-M4/Generic/GNU \
-I$(BSP)
# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif
# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT = STM32F429IGTx_FLASH.ld
# libraries
LIBS = -lc -lm -lnosys
LIBDIR =
LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
$(AS) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
$(SZ) $@
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(HEX) $< $@
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(BIN) $< $@
$(BUILD_DIR):
mkdir $@
#######################################
# clean up
#######################################
clean:
-rm -fR $(BUILD_DIR)
#######################################
# dependencies
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***
要注意的是C_SOURCES里面要添加所有用到的c文件,同理ASM_SOURCES里面要添加所有用到的s文件。C_INCLUDES里面要包含所有h文件所在的目录,并且父目录对子目录无效的。
另外,在我们移植来的文件中会出现这种情况:
这个时候如果是Keil选择RealView,IAR选择IAR,makefile用的是GNU,选择GNU下的文件。
makefile改一下,就可以编译测试了。但是在make过程中出现了这样的错误:
mingw32-make: *** No rule to make target 'build/os_cpu_a.S', needed by 'build/STM32F429IGT-UCOSII.elf'. Stop.
终端进程已终止,退出代码: 2
这是因为os_cpu_a.S文件的后缀不符合我们makefile中的规则(makefile中规则只对于.s文件),把这文件后缀改为小写,再次编译,成功。
3. 编写UCOS的include文件
创建一个includes.h,在里面包含使用UCOSII必要include的头文件,代码如下:
/*
************************************************************************************************
INCLUDES.C ucos
Jean J. Labrosse
************************************************************************************************
*/
#ifndef __INCLUDES_H__
#define __INCLUDES_H__
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include "os.h"
#include "os_cpu.h"
#include "os_cfg.h"
#include <stm32f4xx.h>
#endif
4. 修改文件
- PendSV_Handler():把os_cpu_a.s中的OS_CPU_PendSVHandler函数改为PendSV_Handler,总共两处。然后把stm32f4xx_it.c中的
void PendSV_Handler(void)
去掉,对应h文件的void PendSV_Handler(void);
也去掉,原因是在os_cpu_a.s已经定义。 - SysTick_Handler():在os_cpu_c.c中定义了OS_CPU_SysTickHandler(),但是同上面的pendsv一样,名称和启动文件.s中的vector不符,把这个函数定义和在头文件中的声明注释掉。(不注释掉应该也行)。然后把这个函数里的内容复制到stm32f4xx_it.c的SysTick_Handler()中,OSIntNesting++这个我参考其他人的教程没有复制,具体原因没有测试。并且,stm32f4xx_it.c要包含上面的"includes.h"。下面是代码:
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */
OSIntExit();
/* USER CODE END SysTick_IRQn 1 */
}
- 按照下面5或6的第一步,在IDE上打开FPU(makefile的工程在makefile中已经设置好了),第二步设置tm32f429xx.h中__FPU_PRESENT为1。下面的步骤是把废弃的5、6步的汇编变成C语言放在systeminit中,兼容性更好。然后在
system_stm32f4xx.c
中,void SystemInit(void)
里面加一行代码(FPU->FPCCR &= ~(FPU_FPCCR_ASPEN_Msk|FPU_FPCCR_LSPEN_Msk);
)就可以了:
oid SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
FPU->FPCCR &= ~(FPU_FPCCR_ASPEN_Msk|FPU_FPCCR_LSPEN_Msk);
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
- 设置UCOSII的时钟:OS_TICKS_PER_SEC改为1000U。根据CubeMX生成的工程的systick频率而来。
-
!(废弃的方法)(KEIL MDK5)开启FPU:在keil中,如果下面这个设置了not used,就不会出错,但是是就不适用硬件计算浮点了(F429有这个功能);如果选了use single precision,那么对应的程序必须打开FPU。
如何开启FPU:
- 首先keil按上面打开
- 在stm32f429xx.h中__FPU_PRESENT要为1
- 在os_cpu_a.asm中会根据keil设置自动切换对FPU的支持。
- Cortex-M4有个Lazy Stacking功能,如果使用FPU的话需要关闭这个功能,所以修改这个s文件。在starup_stm32f429xx.s中,要加上下面代码,
;to enable FPU
两个注释之间是要插入的代码。
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
;to enable FPU
IF {FPU} != "SoftVFP"
; Enable Floating Point Support at reset for FPU
LDR.W R0, =0xE000ED88 ; Load address of CPACR register
LDR R1, [R0] ; Read value at CPACR
ORR R1, R1, #(0xF <<20) ; Set bits 20-23 to enable CP10 and CP11 coprocessors
; Write back the modified CPACR value
STR R1, [R0] ; Wait for store to complete
DSB
; Disable automatic FP register content
; Disable lazy context switch
LDR.W R0, =0xE000EF34 ; Load address to FPCCR register
LDR R1, [R0]
AND R1, R1, #(0x3FFFFFFF) ; Clear the LSPEN and ASPEN bits
STR R1, [R0]
ISB ; Reset pipeline now the FPU is enabled
ENDIF
;to enable FPU
LDR R0, =__main
BX R0
ENDP
-
!(废弃的方法)(IAR EWARM8)开启FPU:在keil中,如果下面这个设置了none,就不会出错,但是是就不使用硬件计算浮点了(F429有这个功能);如果选了VFPv4 single precision,那么对应的程序必须打开FPU。
如何开启FPU:
- 首先IAR按上面打开
- 在stm32f429xx.h中__FPU_PRESENT要为1
- 在os_cpu_a.asm中已有对FPU的支持。
- Cortex-M4有个Lazy Stacking功能,如果使用FPU的话需要关闭这个功能,所以修改这个s文件。在starup_stm32f429xx.s中,要加上下面代码,
;to enable FPU
两个注释之间是要插入的代码。
THUMB
PUBWEAK Reset_Handler
SECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
LDR R0, =SystemInit
BLX R0
;to enable FPU
#ifdef __ARMVFP__
; Enable Floating Point Support at reset for FPU
LDR.W R0, =0xE000ED88 ; Load address of CPACR register
LDR R1, [R0] ; Read value at CPACR
ORR R1, R1, #(0xF <<20) ; Set bits 20-23 to enable CP10 and CP11 coprocessors
; Write back the modified CPACR value
STR R1, [R0] ; Wait for store to complete
DSB
; Disable automatic FP register content
; Disable lazy context switch
LDR.W R0, =0xE000EF34 ; Load address to FPCCR register
LDR R1, [R0]
AND R1, R1, #(0x3FFFFFFF) ; Clear the LSPEN and ASPEN bits
STR R1, [R0]
ISB ; Reset pipeline now the FPU is enabled
#endif
;to enable FPU
LDR R0, =__iar_program_start
BX R0
到此为止,UCOSII移植完毕,测试正常。