STM32F429移植UCOSII笔记

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:
image.png

最后,新建一个头文件“includes.h”放到uCOS-Config文件夹中,内容如下:

/************************************************
* UCOS主要包含的头文件
************************************************/
#ifndef __INCLUDES_H_
#define __INCLUDES_H_
#include 
#include 
#include 
#include 
#include 
#include "os.h"
#include "os_cpu.h"
#include "os_cfg.h"
#include 
#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 
#include 
/*
*********************************************************************************************************
* 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 
#include 
#include 
/*
*********************************************************************************************************
* 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 
#include 
#include 
#include 
#include 

#include "os.h"
#include "os_cpu.h"
#include "os_cfg.h"

#include       

#endif

4. 修改文件

  1. 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已经定义。
  2. 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 */
}
  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;
  1. 设置UCOSII的时钟:OS_TICKS_PER_SEC改为1000U。根据CubeMX生成的工程的systick频率而来。
  2. !(废弃的方法)(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
  1. !(废弃的方法)(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移植完毕,测试正常。

你可能感兴趣的:(STM32F429移植UCOSII笔记)