STM32CubeMX HAL库+STM32F407+uCOS-III移植

STM32CubeMX HAL库+STM32F407+uC/OS-III移植详细过程

前言

参考资料:

1. 获取uC/OS-III源码

获取源码可以通过官网下载:

https://weston-embedded.com/micrium-examples

同时可以在我的博客中下载(版本为3.04):

https://download.csdn.net/download/fhdghfuiahfsdifbs/18909773

源码目录如下:
STM32CubeMX HAL库+STM32F407+uCOS-III移植

2. 建立工程

使用STM32CubeMX自动生成,选择STM32F407VE芯片

STM32CubeMX HAL库+STM32F407+uCOS-III移植

配置时钟为168MHz

STM32CubeMX HAL库+STM32F407+uCOS-III移植

配置RCC、SYS

配置两个GPIO(LED)以及USART1,用于测试uC/OS-III移植效果

STM32CubeMX HAL库+STM32F407+uCOS-III移植

设置并生成工程代码
STM32CubeMX HAL库+STM32F407+uCOS-III移植

生成后的代码框架如下:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

3. 裸机代码测试

移植uC/OS-III之前先确保裸机代码能够正常运行

在main函数的循环中添加如下代码,其目的是使两个LED灯闪烁

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_SET);
HAL_Delay(500);

STM32CubeMX HAL库+STM32F407+uCOS-III移植

编译下载之后,能够看到LED闪烁,说明裸机程序运行没有问题,接下来开始移植uC/OS-III

4. 移植uC/OS-III

4.1 新建相关文件夹

源码目录如下:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

首先在工程目录下新建一个文件夹,命名为UCOSIII,然后将uC-CPU、uC-LIB、uCOS-III三个文件夹复制到UCOSIII文件夹下,复制后的工程文件如下:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

然后在UCOSIII文件夹下新建两个文件夹,分别为uCOS-CONFIG、uCOS-BSP,如下所示:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

4.2 向uCOS-CONFIG中添加文件

UCOSIII 3.04\Micrium\Software\EvalBoards\ST\STM32F429II-SK\uCOS-III下的8个文件复制到uCOS-CONFIG中,如图所示:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

4.3 向uCOS-BSP中添加文件

UCOSIII 3.04\Micrium\Software\EvalBoards\ST\STM32F429II-SK\BSP下的bsp.c和bsp.h复制到uCOS-BSP中,如图所示:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

4.4 向工程中添加分组

STM32CubeMX HAL库+STM32F407+uCOS-III移植

4.5 向各个分组添加文件

STM32CubeMX HAL库+STM32F407+uCOS-III移植

注意:uCOS_LIB组当中,还需要添加\UCOSIII\uC-LIB\Ports\ARM-Cortex-M4\RealView目录下的lib_mem_a.asm文件

向各个分组添加文件后,还需要添加相应的头文件路径,如图所示:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

4.6 修改文件

4.6.1 修改bsp.h和bsp.c

将bsp.c文件修改为如下内容:

#ifndef  __BSP_H__
#define  __BSP_H__

#include "stm32f4xx_hal.h"

void BSP_Init(void);

#endif

将bsp.c文件修改为如下内容:

#include "includes.h"

#define  BSP_REG_DEM_CR                           (*(CPU_REG32 *)0xE000EDFC)	//DEMCR寄存器
#define  BSP_REG_DWT_CR                           (*(CPU_REG32 *)0xE0001000)    //DWT控制寄存器
#define  BSP_REG_DWT_CYCCNT                       (*(CPU_REG32 *)0xE0001004)	//DWT时钟计数寄存器	
#define  BSP_REG_DBGMCU_CR                        (*(CPU_REG32 *)0xE0042004)

//DEMCR寄存器的第24位,如果要使用DWT ETM ITM和TPIU的话DEMCR寄存器的第24位置1
#define  BSP_BIT_DEM_CR_TRCENA                    DEF_BIT_24			

//DWTCR寄存器的第0位,当为1的时候使能CYCCNT计数器,使用CYCCNT之前应当先初始化
#define  BSP_BIT_DWT_CR_CYCCNTENA                 DEF_BIT_00

/*
*********************************************************************************************************
*                                            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)
{
    return HAL_RCC_GetHCLKFreq();//返回HCLK时钟频率
}

/*
*********************************************************************************************************
*                                            BSP_Tick_Init()
* Description : BSP_Tick_Init.
* Argument(s) : none.
* Return(s)   : none.
* Note(s)     : none.
*********************************************************************************************************
*/
void BSP_Tick_Init(void)
{
	CPU_INT32U cpu_clk_freq;
	CPU_INT32U cnts;
	cpu_clk_freq = BSP_CPU_ClkFreq();
	
	#if(OS_VERSION>=3000u)
		cnts = cpu_clk_freq/(CPU_INT32U)OSCfg_TickRate_Hz;
	#else
		cnts = cpu_clk_freq/(CPU_INT32U)OS_TICKS_PER_SEC;
	#endif
	OS_CPU_SysTickInit(cnts);
}

void BSP_Init(void)
{
	BSP_Tick_Init();//此函数会初始化OS系统时钟,如果移植了正点原子的delay文件,则与主函数中的delay_init(168)只需要调用一个即可
}

#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void  CPU_TS_TmrInit (void)
{
    CPU_INT32U  cpu_clk_freq_hz;

    BSP_REG_DEM_CR     |= (CPU_INT32U)BSP_BIT_DEM_CR_TRCENA; 	//使用DWT  /* Enable Cortex-M4's DWT CYCCNT reg.*/
    BSP_REG_DWT_CYCCNT  = (CPU_INT32U)0u;					 	//初始化CYCCNT寄存器
    BSP_REG_DWT_CR     |= (CPU_INT32U)BSP_BIT_DWT_CR_CYCCNTENA;	//开启CYCCNT

    cpu_clk_freq_hz = BSP_CPU_ClkFreq();
    CPU_TS_TmrFreqSet(cpu_clk_freq_hz);
}
#endif


#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TMR  CPU_TS_TmrRd (void)
{
    return ((CPU_TS_TMR)BSP_REG_DWT_CYCCNT);
}
#endif


#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
CPU_INT64U  CPU_TS32_to_uSec (CPU_TS32  ts_cnts)
{
	CPU_INT64U  ts_us;
  CPU_INT64U  fclk_freq;

 
  fclk_freq = BSP_CPU_ClkFreq();
  ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);

  return (ts_us);
}
#endif
 
 
#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
CPU_INT64U  CPU_TS64_to_uSec (CPU_TS64  ts_cnts)
{
	CPU_INT64U  ts_us;
	CPU_INT64U  fclk_freq;


  fclk_freq = BSP_CPU_ClkFreq();
  ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);
	
  return (ts_us);
}
#endif

4.6.2 修改startup_stm32f407xx.s

                DCD     PendSV_Handler             ; PendSV Handler
                DCD     SysTick_Handler            ; SysTick Handler

修改为

                DCD     OS_CPU_PendSVHandler             ; PendSV Handler
                DCD     OS_CPU_SysTickHandler            ; SysTick Handler

PendSV_Handler  PROC
                EXPORT  PendSV_Handler             [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler            [WEAK]
                B       .
                ENDP

修改为:

OS_CPU_PendSVHandler  PROC
                EXPORT  PendSV_Handler             [WEAK]
                B       .
                ENDP
OS_CPU_SysTickHandler PROC
                EXPORT  SysTick_Handler            [WEAK]
                B       .
                ENDP

修改后如图所示:
STM32CubeMX HAL库+STM32F407+uCOS-III移植
STM32CubeMX HAL库+STM32F407+uCOS-III移植

4.6.3 支持浮点运算

在startup_stm32f407xx.s的174行添加如下汇编代码:

				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

添加完成后如图所示:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

同时需要支持浮点运算,默认是支持的

STM32CubeMX HAL库+STM32F407+uCOS-III移植

4.6.4 串口重定向

修改usart.h文件

#include <stdio.h>
#include <string.h>

添加后如图所示:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

修改usart.c文件,添加如下代码:

#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
  return ch;
}

添加后如图所示:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

4.6.5 修改main.c

创建四个任务:

  • 创建一个start_task任务,该任务用来系统初始化以及创建其他任务
  • 创建一个led0_task任务,用来控制LED0的亮灭
  • 创建一个led1_task任务,用来控制LED1的亮灭
  • 创建一个float_task任务,用来测试浮点计算
任务 任务优先级 任务堆栈 备注
start_task 3 512
led0_task 4 128
led1_task 5 128
float_task 6 128 任务堆栈8字节对齐
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <includes.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* UCOSIII中以下优先级用户程序不能使用:
 * 将这些优先级分配给了UCOSIII的5个系统内部任务
 * 优先级0:中断服务服务管理任务 OS_IntQTask()
 * 优先级1:时钟节拍任务 OS_TickTask()
 * 优先级2:定时任务 OS_TmrTask()
 * 优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask()
 * 优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()
 */

/* 任务优先级 */
#define START_TASK_PRIO		3
#define LED0_TASK_PRIO		4
#define LED1_TASK_PRIO		5
#define FLOAT_TASK_PRIO		6

/* 任务堆栈大小	*/
#define START_STK_SIZE 		512
#define LED0_STK_SIZE 		128
#define LED1_STK_SIZE 		128
#define FLOAT_STK_SIZE		128
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* 任务控制块 */
OS_TCB StartTaskTCB;
OS_TCB Led0TaskTCB;
OS_TCB Led1TaskTCB;
OS_TCB FloatTaskTCB;

/* 任务栈 */	
CPU_STK START_TASK_STK[START_STK_SIZE];
CPU_STK LED0_TASK_STK[LED0_STK_SIZE];
CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
__align(8) CPU_STK	FLOAT_TASK_STK[FLOAT_STK_SIZE];
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* 任务函数定义 */
void start_task(void *p_arg);
void led0_task(void *p_arg);
void led1_task(void *p_arg);
void float_task(void *p_arg);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	OS_ERR err;
	CPU_SR_ALLOC();
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
    //delay_init(168);   //时钟初始化 如果移植了正点原子的delay文件且SYSTEM_SUPPORT_OS被定义,此函数会初始化OS系统时钟,与start_task任务中的BSP_Init()只需要调用一个即可
    OSInit(&err);				//初始化UCOSIII
    OS_CRITICAL_ENTER();//进入临界区
    //创建开始任务
    OSTaskCreate((OS_TCB 	* )&StartTaskTCB,				//任务控制块
                 (CPU_CHAR* )"start task", 				//任务名字
                 (OS_TASK_PTR)start_task, 				//任务函数
                 (void		* )0,										//传递给任务函数的参数
                 (OS_PRIO	  )START_TASK_PRIO,     //任务优先级
                 (CPU_STK * )&START_TASK_STK[0],	//任务堆栈基地址
                 (CPU_STK_SIZE)START_STK_SIZE/10,	//任务堆栈深度限位
                 (CPU_STK_SIZE)START_STK_SIZE,		//任务堆栈大小
                 (OS_MSG_QTY)0,						//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
                 (OS_TICK	  )0,						//当使能时间片轮转时的时间片长度,为0时为默认长度,
                 (void   	* )0,						//用户补充的存储区
                 (OS_OPT    )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
                 (OS_ERR 	* )&err);				//存放该函数错误时的返回值
    OS_CRITICAL_EXIT();	//退出临界区	

    OSStart(&err); //启动多任务系统,控制权交给uC/OS-III
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
//		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);
//		HAL_Delay(500);
//		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_SET);
//		HAL_Delay(500);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
//开始任务函数
void start_task(void *p_arg)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;
	
	/* YangJie add 2021.05.20*/
  BSP_Init();                                                   /* Initialize BSP functions */
  //CPU_Init();
  //Mem_Init();                                                 /* Initialize Memory Management Module */

#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);  		//统计任务                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN			//如果使能了测量中断关闭时间
    CPU_IntDisMeasMaxCurReset();	
#endif

#if	OS_CFG_SCHED_ROUND_ROBIN_EN  		//当使用时间片轮转的时候
	 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif		
	
	OS_CRITICAL_ENTER();	//进入临界区
	/* 创建LED0任务 */
	OSTaskCreate((OS_TCB 	* )&Led0TaskTCB,		
				 (CPU_CHAR	* )"led0 task", 		
                 (OS_TASK_PTR )led0_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )LED0_TASK_PRIO,     
                 (CPU_STK   * )&LED0_TASK_STK[0],	
                 (CPU_STK_SIZE)LED0_STK_SIZE/10,	
                 (CPU_STK_SIZE)LED0_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);				
				 
	/* 创建LED1任务 */
	OSTaskCreate((OS_TCB 	* )&Led1TaskTCB,		
				 (CPU_CHAR	* )"led1 task", 		
                 (OS_TASK_PTR )led1_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )LED1_TASK_PRIO,     	
                 (CPU_STK   * )&LED1_TASK_STK[0],	
                 (CPU_STK_SIZE)LED1_STK_SIZE/10,	
                 (CPU_STK_SIZE)LED1_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, 
                 (OS_ERR 	* )&err);
				 
	/* 创建浮点测试任务 */
	OSTaskCreate((OS_TCB 	* )&FloatTaskTCB,		
				 (CPU_CHAR	* )"float test task", 		
                 (OS_TASK_PTR )float_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )FLOAT_TASK_PRIO,     	
                 (CPU_STK   * )&FLOAT_TASK_STK[0],	
                 (CPU_STK_SIZE)FLOAT_STK_SIZE/10,	
                 (CPU_STK_SIZE)FLOAT_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, 
                 (OS_ERR 	* )&err);				 
	OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err);		//挂起开始任务			 
	OS_CRITICAL_EXIT();	//进入临界区
}

/* led0任务函数 */
void led0_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	
	while(1)
	{
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
		OSTimeDly(500, OS_OPT_TIME_DLY, &err);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
		OSTimeDly(500, OS_OPT_TIME_DLY, &err);
	}
}

/* led1任务函数 */
void led1_task(void *p_arg)
{
  OS_ERR err;
	p_arg = p_arg;
	
	while(1)
	{
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
		OSTimeDly(500, OS_OPT_TIME_DLY, &err);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
		OSTimeDly(500, OS_OPT_TIME_DLY, &err);	
	}
}

/* 浮点测试任务 */
void float_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	CPU_SR_ALLOC();
	static float float_num=0.01;
	
	while(1)
	{
		float_num+=0.01f;
		OS_CRITICAL_ENTER();	//进入临界区
		printf("float_num的值为: %.4f\r\n",float_num);
		OS_CRITICAL_EXIT();		//退出临界区
		OSTimeDly(500, OS_OPT_TIME_DLY, &err);
	}
}
/* USER CODE END 4 */

 /**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM6 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM6) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

5. 编译下载

快捷键F7编译,F8下载程序到开发板

6. 实验结果

编译下载后,可以看到开发板两个LED灯闪烁,串口打印浮点型数据
STM32CubeMX HAL库+STM32F407+uCOS-III移植

STM32CubeMX HAL库+STM32F407+uCOS-III移植

在浮点计算处设置断点,全速运行,此时查看汇编窗口,如图所示:

STM32CubeMX HAL库+STM32F407+uCOS-III移植

可以看到有VLDR、VADD.F32等FPU指令,这说明使用STM32F407内部的FPU进行浮点运算成功

总结:

该移植过程主要修改的文件包括如下:

  • bsp.c和bsp.h
  • startup_stm32f407xx.s
  • main.c
  • usart.c和usart.h
上一篇:[USACO17DEC]Push a Box P


下一篇:tarjan算法