300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > STM32CubeMX HAL库+STM32F407+uCOS-III移植

STM32CubeMX HAL库+STM32F407+uCOS-III移植

时间:2023-02-28 08:05:42

相关推荐

STM32CubeMX HAL库+STM32F407+uCOS-III移植

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

前言

参考资料:

官网资料:/wiki/spaces/osiiidoc/overview正点原子STM32F4 UCOS开发手册_v3.0.pdf[野火]uCOS-III内核实现与应用开发实战指南/rtos/ucos/zh/latest/application/porting_to_stm32.html

1. 获取uC/OS-III源码

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

https://weston-/micrium-examples

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

/download/fhdghfuiahfsdifbs/18909773

源码目录如下:

2. 建立工程

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

配置时钟为168MHz

配置RCC、SYS

配置两个GPIO(LED)以及USART1,用于测试uC/OS-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);

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

4. 移植uC/OS-III

4.1 新建相关文件夹

源码目录如下:

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

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

4.2 向uCOS-CONFIG中添加文件

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

4.3 向uCOS-BSP中添加文件

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

4.4 向工程中添加分组

4.5 向各个分组添加文件

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

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

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 *)0xE004)//DEMCR寄存器的第24位,如果要使用DWT ETM ITM和TPIU的话DEMCR寄存器的第24位置1#define BSP_BIT_DEM_CR_TRCENADEF_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;#elsecnts = cpu_clk_freq/(CPU_INT32U)OS_TICKS_PER_SEC;#endifOS_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;//开启CYCCNTcpu_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

DCDPendSV_Handler ; PendSV HandlerDCDSysTick_Handler ; SysTick Handler

修改为

DCDOS_CPU_PendSVHandler ; PendSV HandlerDCDOS_CPU_SysTickHandler ; SysTick Handler

PendSV_Handler PROCEXPORT PendSV_Handler [WEAK]B .ENDPSysTick_Handler PROCEXPORT SysTick_Handler [WEAK]B .ENDP

修改为:

OS_CPU_PendSVHandler PROCEXPORT PendSV_Handler [WEAK]B .ENDPOS_CPU_SysTickHandler PROCEXPORT SysTick_Handler [WEAK]B .ENDP

修改后如图所示:

4.6.3 支持浮点运算

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

IF {FPU} != "SoftVFP"; Enable Floating Point Support at reset for FPULDR.W R0, =0xE000ED88 ; Load address of CPACR registerLDRR1, [R0]; Read value at CPACRORRR1, R1, #(0xF <<20); Set bits 20-23 to enable CP10 and CP11 coprocessors; Write back the modified CPACR valueSTRR1, [R0]; Wait for store to completeDSB; Disable automatic FP register content; Disable lazy context switchLDR.W R0, =0xE000EF34 ; Load address to FPCCR registerLDRR1, [R0]ANDR1, R1, #(0x3FFFFFFF) ; Clear the LSPEN and ASPEN bitsSTRR1, [R0]ISB ; Reset pipeline now the FPU is enabledENDIF

添加完成后如图所示:

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

4.6.4 串口重定向

修改usart.h文件

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

添加后如图所示:

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

#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printfset 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;}

添加后如图所示:

4.6.5 修改main.c

创建四个任务:

创建一个start_task任务,该任务用来系统初始化以及创建其他任务创建一个led0_task任务,用来控制LED0的亮灭创建一个led1_task任务,用来控制LED1的亮灭创建一个float_task任务,用来测试浮点计算

/* USER CODE BEGIN Header *//********************************************************************************* @file : main.c* @brief: Main program body******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 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:* /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_PRIO3#define LED0_TASK_PRIO4#define LED1_TASK_PRIO5#define FLOAT_TASK_PRIO6/* 任务堆栈大小*/#define START_STK_SIZE 512#define LED0_STK_SIZE 128#define LED1_STK_SIZE 128#define FLOAT_STK_SIZE128/* 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_STKFLOAT_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);//初始化UCOSIIIOS_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 .05.20*/BSP_Init(); /* Initialize BSP functions *///CPU_Init();//Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); //统计任务#endif#ifdef CPU_CFG_INT_DIS_MEAS_EN//如果使能了测量中断关闭时间CPU_IntDisMeasMaxCurReset();#endif#ifOS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5msOSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endifOS_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灯闪烁,串口打印浮点型数据

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

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

总结:

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

bsp.c和bsp.hstartup_stm32f407xx.smain.cusart.c和usart.h

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。