二、从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-CPU
和UCOS-III\uC-CPU\ARM-Cortex-M4\RealView
下所有文件添加到分组:UC/OS_III-CPU
3.2.4 UC/OS_III-LIB
- 将
UCOS-III\uC-LIB
和UCOS-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_Handler
和SysTick_Handler
修改为OS_CPU_PendSVHandler
和OS_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>© 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正常闪烁,串口正常打印数据
移植成功!
- 备注:我尝试过在潘多拉开发板STM32L475VET6移植UCOSIII,步骤一致;
- 移植完成后可使用STM32CubeMX再次对工程进行配置,不会影响UCOSIII工程;
- 源码下载:https://download.csdn.net/download/u014779536/12116472
来源:CSDN
作者:超级大洋葱806
链接:https://blog.csdn.net/u014779536/article/details/104047851