STM32CubeMX创建F429/L475 HAL库工程并移植UCOSIII (二)(文末附源码)

依然范特西╮ 提交于 2020-01-22 16:16:05

二、从Micrium官网下载UCOSIII源码并添加文件到工程中

1. 到Micrium官网下载ucos源码程序(MDK版)

  • micrium网址:https://www.micrium.com/
    在这里插入图片描述
  • 选择STM32F4xx
    在这里插入图片描述
  • 下载示例工程
    在这里插入图片描述
  • 此处需要账号,大家自己注册一下
    在这里插入图片描述
  • 下载下来目录如下图所示:
    在这里插入图片描述

2.在STM32CubeMX生成的工程中添加UCOS-III文件夹

在这里插入图片描述

2.1 在UCOS-III目录下创建文件夹,放置UCOSIII源码
  • 在STM32CubeMX工程STM32F429_UCOSIII_DEMO\UCOS-III\目录下创建 BSP 和 CONFIG目录
    在这里插入图片描述
2.1.1 BSP目录填充

复制Micrium_STM32F429II-SK_OS3\Micrium\Examples\ST\STM32F429II-SK\BSP目录下的bsp.c 和 bsp.h到STM32CubeMX工程STM32F429_UCOSIII_DEMO\UCOS-III\BSP
在这里插入图片描述

2.1.2 CONFIG目录填充

复制Micrium_STM32F429II-SK_OS3\Micrium\Examples\ST\STM32F429II-SK\OS3目录下的8个文件到STM32CubeMX工程STM32F429_UCOSIII_DEMO\UCOS-III\CONFIG
在这里插入图片描述

2.1.3 复制源码到UCOS-III目录

复制\Micrium_STM32F429II-SK_OS3\Micrium\Software目录下的uC-CPU、uC-LIB、uCOS-III三个文件夹到STM32CubeMX工程STM32F429_UCOSIII_DEMO\UCOS-III目录下
在这里插入图片描述

2.1.4 文件添加完成

在这里插入图片描述

3.在MDK5工程中添加UCOS-III目录下的文件

3.1 在工程中添加分组文件夹

在这里插入图片描述

3.2 添加文件到分组
3.2.1 UC/OS_III-BSP
  • UCOS-III\BSP下所有文件添加到分组:UC/OS_III-BSP
    在这里插入图片描述
3.2.2 UC/OS_III-CONFIG
  • UCOS-III\CONFIG下所有文件添加到分组:UC/OS_III-CONFIG
    在这里插入图片描述
3.2.3 UC/OS_III-CPU
  • UCOS-III\uC-CPUUCOS-III\uC-CPU\ARM-Cortex-M4\RealView下所有文件添加到分组:UC/OS_III-CPU
    在这里插入图片描述
3.2.4 UC/OS_III-LIB
  • UCOS-III\uC-LIBUCOS-III\uC-LIB\Ports\ARM-Cortex-M4\RealView下所有文件添加到分组:UC/OS_III-LIB
    在这里插入图片描述
3.2.5 UC/OS_III-SOURCE
  • UCOS-III\uCOS-III\Source下所有文件添加到分组:UC/OS_III-SOURCE
    在这里插入图片描述
3.2.6 UC/OS_III-PORTS
  • UCOS-III\uCOS-III\Ports\ARM-Cortex-M4\Generic\RealView下所有文件添加到分组:UC/OS_III-PORTS
    在这里插入图片描述
3.3 添加依赖的头文件路径
  • 点击此处进行设置
    在这里插入图片描述
  • 如图依次添加以下七个路径
    在这里插入图片描述
  • 点击OK,编译,此处会报错,是正常的 我们还要修改几个文件
    在这里插入图片描述

4.STM32CubeMX工程文件修改

4.1 启动文件修改

将启动文件中的PendSV_HandlerSysTick_Handler 修改为OS_CPU_PendSVHandlerOS_CPU_SysTickHandler

  • 修改前:
    在这里插入图片描述
    在这里插入图片描述
  • 修改后:
    在这里插入图片描述
    在这里插入图片描述

增加FPU运算支持

  • 修改前:
    在这里插入图片描述
  • 修改后:
    在这里插入图片描述
4.2 bsp.c 和 bsp.h修改
  • 将bsp.c的内容替换成以下代码
#define   BSP_MODULE
#include  <bsp.h>
#include  <os.h>

#define  BSP_REG_DEM_CR                           (*(CPU_REG32 *)0xE000EDFC)
#define  BSP_REG_DWT_CR                           (*(CPU_REG32 *)0xE0001000)
#define  BSP_REG_DWT_CYCCNT                       (*(CPU_REG32 *)0xE0001004)
#define  BSP_REG_DBGMCU_CR                        (*(CPU_REG32 *)0xE0042004)

#define  BSP_BIT_DEM_CR_TRCENA                    DEF_BIT_24
#define  BSP_BIT_DWT_CR_CYCCNTENA                 DEF_BIT_00

CPU_INT32U  BSP_CPU_ClkFreq (void)
{
		return HAL_RCC_GetHCLKFreq();
}


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


    fclk_freq = BSP_CPU_ClkFreq();

    BSP_REG_DEM_CR     |= (CPU_INT32U)BSP_BIT_DEM_CR_TRCENA;    /* Enable Cortex-M4's DWT CYCCNT reg.                   */
    BSP_REG_DWT_CYCCNT  = (CPU_INT32U)0u;
    BSP_REG_DWT_CR     |= (CPU_INT32U)BSP_BIT_DWT_CR_CYCCNTENA;

    CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq);
}
#endif


#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TMR  CPU_TS_TmrRd (void)
{
    CPU_TS_TMR  ts_tmr_cnts;


    ts_tmr_cnts = (CPU_TS_TMR)BSP_REG_DWT_CYCCNT;

    return (ts_tmr_cnts);
}
#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
  • 将bsp.h的内容替换成以下代码
#ifndef  BSP_PRESENT
#define  BSP_PRESENT

#ifdef   BSP_MODULE
#define  BSP_EXT
#else
#define  BSP_EXT  extern
#endif

#include <stdio.h>
#include <stdarg.h>
#include <cpu.h>
#include <cpu_core.h>
#include <lib_def.h>
#include <lib_ascii.h>

//如果修改芯片,需要修改此包含的库文件名
#include "stm32l4xx_hal.h"

#endif
4.3 再次编译,编译通过!

在这里插入图片描述

5.在main.c中创建usart1和led任务,测试是否移植成功

5.1 引入ucos头文件
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "includes.h"
/* USER CODE END Includes */
5.2 完整main.c代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 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 */
/* USER CODE END PD */

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

/* USER CODE END PM */

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

/* USER CODE BEGIN PV */
//注意这里任务优先级从3开始,1和2分别被
//时钟节拍任务和定时器任务占用
//任务优先级
#define START_TASK_PRIO  3
//任务堆栈大小
#define START_STK_SIZE 512
//任务控制块
OS_TCB StartTaskTCB;
//任务堆栈
CPU_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *p_arg);

//任务优先级
#define LDE_TASK_PRIO  4
//任务堆栈大小
#define LDE_STK_SIZE 256
//任务控制块
OS_TCB LedTaskTCB;
//任务堆栈
CPU_STK LDE_TASK_STK[LDE_STK_SIZE];
//任务函数
void led_task(void *p_arg);

//任务优先级
#define USART1_TASK_PRIO  4
//任务堆栈大小
#define USART1_STK_SIZE 256
//任务控制块
OS_TCB USART1TaskTCB;
//任务堆栈
CPU_STK USART1_TASK_STK[USART1_STK_SIZE];
//任务函数
void usart1_task(void *p_arg);
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* 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 */
		/*注意 硬件初始化放这里 不能正常运行 要要放到开始任务里面初始化*/
	
	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); //开启UCOSIII
  /* USER CODE END 2 */
 
 

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

    /* USER CODE BEGIN 3 */
//		
//		HAL_UART_Transmit(&huart1,TxData,20,0xffff);
//		HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_10);
//		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_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 180;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Activate the Over-Drive mode 
  */
  if (HAL_PWREx_EnableOverDrive() != 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;
	
	CPU_Init();
	#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(); //临界区保护
	
	//创建LED_D2 任务
	OSTaskCreate((OS_TCB* )&LedTaskTCB,
	(CPU_CHAR* )"led_task",
	(OS_TASK_PTR )led_task,
	(void* )0,
	(OS_PRIO  )LDE_TASK_PRIO,
	(CPU_STK* )&LDE_TASK_STK[0], 
	(CPU_STK_SIZE )LDE_STK_SIZE/10,
	(CPU_STK_SIZE )LDE_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* )&USART1TaskTCB,
	(CPU_CHAR* )"USART1_task",
	(OS_TASK_PTR )usart1_task,
	(void* )0,
	(OS_PRIO  )USART1_TASK_PRIO,
	(CPU_STK* )&USART1_TASK_STK[0], 
	(CPU_STK_SIZE )USART1_STK_SIZE/10,
	(CPU_STK_SIZE )USART1_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();  //退出临界区
}

//LDE任务函数
void led_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	
	while(1)
	{
		HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_10);
		OSTimeDly(200, OS_OPT_TIME_DLY, &err);
	}
}

//USART1任务函数
void usart1_task(void *p_arg)
{
	OS_ERR err;
	uint8_t TxData[20]= "usart1 transmit!\n";
	p_arg = p_arg;
	
	while(1)
	{
		HAL_UART_Transmit(&huart1,TxData,20,0xffff);
		OSTimeDly(500, OS_OPT_TIME_DLY, &err);
	}
}
/* USER CODE END 4 */

/**
  * @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.3 编译,下载,观察现象

在这里插入图片描述

  • LED正常闪烁,串口正常打印数据
    在这里插入图片描述
移植成功!
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!