本文主要是介绍基于C8T6核心板的ucOS文件移植,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
ucOS文件移植
- 前言
- 一、获取uC/OS-III源码
- 二、建立工程文件
- 三、移植uC/OS-III文件
- 四、添加工程组件及路径
- (一)添加工程分组
- (二)将文件添加到分组
- (三)包含头文件路径
- 五、修改工程文件
- (一)启动文件
- (二)app_cfg.h文件
- (三)修改bsp.c和bsp.h文件
- (四)修改includes.h头文件
- (五)main.c
- 六、实例演示
- 总结
前言
uC/OS是一个可以基于ROM运行的、可裁减的、抢占式、实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,适合很多商业操作系统性能相当的实时操作系统(RTOS)。
前期我们编写的程序都是在一个while(1)循环中重复执行,本例我们使用uC/OS操作系统实现特定的功能,体会一下自己移植一个操作系统,听起来还挺有趣的,让我们开始吧!
一、获取uC/OS-III源码
官网下载
Micrium下载官网
官网下载步骤较为繁琐,如果想要在官网下载,可参考
STM32F103C8T6移植uC/OS-III基于HAL库超完整详细过程
网盘下载
当然,我也将下载好的文件上传到了网盘
下载完成后,打开文件有四个文件夹,分别是EvalBoards、uC-CPU、uC-LIB、uCOS-III,如下图所示
(1)EvalBoards文件夹
EvalBoards文件夹下是基于该评估版的应用层实现,在我们的移植中有部分文件可以移过来使用。
(2)uC-CPU文件夹
uC-CPU文件夹这是和 CPU 紧密相关的文件,里面的一些文件很重要,都是我们需要使用的。
(3)uC-LIB文件夹
uC-LIB文件夹,Micrium 公司提供的官方库,诸如字符串操作、内存操作等接口,可用可不用。一般能用于代替标准库中的一些函数,使得在嵌入式中应用更加方便安全。
(4)uCOS-III文件夹
uCOS-III文件夹,是操作系统内核文件夹,都是系统核心文件。这些文件是我们全部需要的,移植时将这些拷贝过去就可以。
二、建立工程文件
本例我们是基于HAL库移植移植uC/OS-III操作系统,实现的功能较为简单,共构建了3个任务(task)。
task1:
LED1以1s频率闪烁
task2:
LED2以3s频率闪烁
task3:
每隔2s,通过串口发送“hello uc/OS! 欢迎来到RTOS多任务环境!”的提示信息。
关于LED闪烁和串口发送/接收程序,小编之前已经详细介绍过了,具体可参考
点灯:STM32CubeMX环境搭建及使用
串口:
stm32之串口通信
stm32之中断模式
配置完成后,生成的工程文件如下
三、移植uC/OS-III文件
(1)在工程文件夹中新建ucOSIII,将源码中的uC-CPU、uC-LIB和UCOS-III这三个文件夹复制到该文件中
(2)再新建ucos_config
文件夹和ucos_bsp
文件夹,将例程文件中框选处理的官方文件复制到ucos_config
中
然后ucos_config
中新建app.h
,如下图所示
(3)将Micrium\Software\EvalBoards\Micrium\uC-Eval-STM32F107\BSP
下所框选的工程文件复制到ucos_bsp夹中
四、添加工程组件及路径
(一)添加工程分组
打开uc_OSIII工程, 按照如图所示添加六个新的分组: bsp
、uCOSIII_CPU
、 uCOSIII_LIB
、 uCOSIII_Ports
、 uCOSIII_Source
、 OS_cfg
(二)将文件添加到分组
1. 将ucos_bsp文件夹中的bsp.c
与bsp.h
添加到分组bsp中
2. 在uCOSIII_CPU 分组中添加以下文件
点击Add Filles…,在刚刚新建的ucOSIII文件夹下的uC-CPU文件夹内选中框选的文件,将其添加进去
然后到uC-CPU–>ARM-Cortex-M3–>RealView文件目录下添加以下文件
3. 添加 uCOSIII_LIB 组件
点击Add Filles…,仍然在刚刚新建的ucOSIII文件夹下的uC-LIB文件夹内选中框选的文件,将其添加进去
然后在uC-LIB\Ports\ARM-Cortex-M3\RealView
路径下添加lib_mem_a.asm
文件
4. 添加 uCOSIII_Ports 组件
在uCOS-III\Ports\ARM-Cortex-M3\Generic\RealView找到下图所框选文件,将其添加进去
5. 添加文件到 uCOSIII_Source组
在uCOS-III\Source文件下,将所框选的20个文件添加到uCOSIII_Source分组
5. 添加文件到 OS_cfg组
在刚刚新建的ucos_config文件夹中找到以下文件,并将其添加到OS_cfg分组
查看完成的工程文件结构
(三)包含头文件路径
选择魔术棒–>C/C++ 选项–>>Include Paths,添加所用到文件的路径
新添加的文件路径如下
五、修改工程文件
(一)启动文件
首先修改工程的启动文件“ startup_stm32f103xb.s”
其中将 PendSV_Handler
和 SysTick_Handler
分 别 改 为
OS_CPU_PendSVHandler
和 OS_CPU_SysTickHandler
,共两处,因为 uCOS 官方已经给我们处理好对应的中断函数,就无需我们自己处理与系统相关的中断了,同时我们最好将stm32f10x_it.c 文件中的 PendSV_Handler
和 SysTick_Handler
函数注释掉。
修改后如下:
修改 startup_stm32f103xb.s 文件(第 76、 77 行)
修改 startup_stm32f103xb.s 文件(第 174到179 行)
(二)app_cfg.h文件
修改前
:
#define APP_CFG_SERIAL_EN DEF_ENABLED
修改后
:
#define APP_CFG_SERIAL_EN DEF_DISABLED
(三)修改bsp.c和bsp.h文件
- bsp.c文件
// bsp.c
#include "includes.h"#define DWT_CR *(CPU_REG32 *)0xE0001000
#define DWT_CYCCNT *(CPU_REG32 *)0xE0001004
#define DEM_CR *(CPU_REG32 *)0xE000EDFC
#define DBGMCU_CR *(CPU_REG32 *)0xE0042004#define DEM_CR_TRCENA (1 << 24)
#define DWT_CR_CYCCNTENA (1 << 0)CPU_INT32U BSP_CPU_ClkFreq (void)
{return HAL_RCC_GetHCLKFreq();
}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();MX_GPIO_Init();
}#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void CPU_TS_TmrInit (void)
{CPU_INT32U cpu_clk_freq_hz;DEM_CR |= (CPU_INT32U)DEM_CR_TRCENA; /* Enable Cortex-M3's DWT CYCCNT reg. */DWT_CYCCNT = (CPU_INT32U)0u;DWT_CR |= (CPU_INT32U)DWT_CR_CYCCNTENA;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)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
- bsp.h
// bsp.h
#ifndef __BSP_H__
#define __BSP_H__#include "stm32f1xx_hal.h"void BSP_Init(void);#endif
(四)修改includes.h头文件
第一处修改:
#include "bsp.h"
#include "gpio.h"
#include "usart.h"
#include "app_cfg.h"
第二处修改:
#include "stm32f1xx_hal.h"
(五)main.c
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
#include "usart.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 */
/* 任务优先级 */
#define START_TASK_PRIO 3
#define LED1_TASK_PRIO 4
#define MSG_TASK_PRIO 5
#define LED2_TASK_PRIO 6/* 任务堆栈大小 */
#define START_STK_SIZE 96
#define LED1_STK_SIZE 64
#define MSG_STK_SIZE 64
#define LED2_STK_SIZE 64/* 任务栈 */
CPU_STK START_TASK_STK[START_STK_SIZE];
CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
CPU_STK MSG_TASK_STK[MSG_STK_SIZE];
CPU_STK LED2_TASK_STK[LED2_STK_SIZE];/* 任务控制块 */
OS_TCB StartTaskTCB;
OS_TCB Led1TaskTCB;
OS_TCB MsgTaskTCB;
OS_TCB Led2TaskTCB;
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* 任务函数定义 */
void start_task(void *p_arg);
static void AppTaskCreate(void);
static void AppObjCreate(void);
static void led1_pb0(void *p_arg);
static void send_msg(void *p_arg);
static void led2_pb1(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 */
/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/**Initializes the CPU, AHB and APB busses clocks */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;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_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
int main(void)
{OS_ERR err;OSInit(&err);HAL_Init();SystemClock_Config();//MX_GPIO_Init(); 这个在BSP的初始化里也会初始化
MX_USART1_UART_Init(); /* 创建任务 */OSTaskCreate((OS_TCB *)&StartTaskTCB, /* Create the start task */(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,(OS_TICK ) 0,(void *) 0,(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),(OS_ERR *)&err);/* 启动多任务系统,控制权交给uC/OS-III */OSStart(&err); /* Start multitasking (i.e. give control to uC/OS-III). */}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 > 0uOSStatTaskCPUUsageInit(&err); //统计任务
#endif#ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间CPU_IntDisMeasMaxCurReset();
#endif#if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5msOSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif OS_CRITICAL_ENTER(); //进入临界区/* 创建LED1任务 */OSTaskCreate((OS_TCB * )&Led1TaskTCB, (CPU_CHAR * )"led1_pb0", (OS_TASK_PTR )led1_pb0, (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); /* 创建LED2任务 */OSTaskCreate((OS_TCB * )&Led2TaskTCB, (CPU_CHAR * )"led2_pb1", (OS_TASK_PTR )led2_pb1, (void * )0, (OS_PRIO )LED2_TASK_PRIO, (CPU_STK * )&LED2_TASK_STK[0], (CPU_STK_SIZE)LED2_STK_SIZE/10, (CPU_STK_SIZE)LED2_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); /* 创建MSG任务 */OSTaskCreate((OS_TCB * )&MsgTaskTCB, (CPU_CHAR * )"send_msg", (OS_TASK_PTR )send_msg, (void * )0, (OS_PRIO )MSG_TASK_PRIO, (CPU_STK * )&MSG_TASK_STK[0], (CPU_STK_SIZE)MSG_STK_SIZE/10, (CPU_STK_SIZE)MSG_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(); //进入临界区
}
/*** 函数功能: 启动任务函数体。* 输入参数: p_arg 是在创建该任务时传递的形参* 返 回 值: 无* 说 明:无*/
static void led1_pb0 (void *p_arg)
{OS_ERR err;(void)p_arg;BSP_Init(); /* Initialize BSP functions */CPU_Init();Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endifCPU_IntDisMeasMaxCurReset();AppTaskCreate(); /* Create Application Tasks */AppObjCreate(); /* Create Application Objects */while (DEF_TRUE){HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);OSTimeDlyHMSM(0, 0, 1, 500,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);OSTimeDlyHMSM(0, 0, 1, 500,OS_OPT_TIME_HMSM_STRICT,&err);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
static void led2_pb1 (void *p_arg)
{OS_ERR err;(void)p_arg;BSP_Init(); /* Initialize BSP functions */CPU_Init();Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endifCPU_IntDisMeasMaxCurReset();AppTaskCreate(); /* Create Application Tasks */AppObjCreate(); /* Create Application Objects */while (DEF_TRUE){HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);OSTimeDlyHMSM(0, 0, 0, 500,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);OSTimeDlyHMSM(0, 0, 0, 500,OS_OPT_TIME_HMSM_STRICT,&err);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
static void send_msg (void *p_arg)
{OS_ERR err;(void)p_arg;BSP_Init(); /* Initialize BSP functions */CPU_Init();Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endifCPU_IntDisMeasMaxCurReset();AppTaskCreate(); /* Create Application Tasks */AppObjCreate(); /* Create Application Objects */while (DEF_TRUE){printf("hello uc/OS! 欢迎来到RTOS多任务环境!\r\n");OSTimeDlyHMSM(0, 0, 2, 0,OS_OPT_TIME_HMSM_STRICT,&err);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/* USER CODE BEGIN 4 */
/*** 函数功能: 创建应用任务* 输入参数: p_arg 是在创建该任务时传递的形参* 返 回 值: 无* 说 明:无*/
static void AppTaskCreate (void)
{}/*** 函数功能: uCOSIII内核对象创建* 输入参数: 无* 返 回 值: 无* 说 明:无*/
static void AppObjCreate (void)
{}
/* 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****/
这个是因为内存溢出,STM32C8T6内存只有20KB,而在lib_cfg.h
中宏定义了堆大小为27KB,导致内存空间不够
在lib_cfg.h
文件中找到该宏定义,并修改如下
修改前:
#define LIB_MEM_CFG_HEAP_SIZE 27u * 1024u
修改后:
#define LIB_MEM_CFG_HEAP_SIZE 5u * 1024u
六、实例演示
- LED1、2闪烁
- 串口发送数据
总结
本次是基于ucOS操作系统的移植,小编不了解ucOS系统,只是尝试能够正确的移植,对于代码的分析以及整个代码运行的流程就跳过了。
以上若有不当之处,敬请指教!!!
STM32F103C8T6移植uC/OS-III基于HAL库超完整详细过程
uCOSIII移植
uCOS-III在STM32的移植
stm32f103c8t6移植ucos-Ⅲ内存溢出bug
[野火]uCOS-III内核实现与应用开发实战指南
这篇关于基于C8T6核心板的ucOS文件移植的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!