【STM32】uc/OS-III多任务程序

作者 : admin 本文共10205个字,预计阅读时间需要26分钟 发布时间: 2024-06-10 共2人阅读

目录

  • 一、背景介绍
  • 二、UCOS-III简单介绍
    • (一)源码
    • (二)功能
  • 三、实验
    • (一)基于STM32CubeMX建立工程
      • 1、创建项目
      • 2、配置项目
    • (二)实现
  • 四、总结
  • 五、参考

一、背景介绍

学习嵌入式实时操作系统(RTOS),以uc/OS为例,将其移植到stm32F103上,构建至少3个任务(task):
其中两个task分别以1s和3s周期对LED等进行点亮-熄灭的控制;另外一个task以2s周期通过串口发送
“hello uc/OS! 欢迎来到RTOS多任务环境!”
记录详细的移植过程

二、UCOS-III简单介绍

(一)源码

链接: http://pan.baidu.com/s/1iqYoewoQUHIJzIT-SEUJ-Q?pwd=ur6m
提取码: ur6m

(二)功能

1.实时性: μC/OS-III是一个实时操作系统,旨在满足实时嵌入式系统对任务响应时间的严格要求。它提供了多任务管理、任务优先级、中断处理等功能,以确保系统对事件的及时响应。
2.多任务管理: μC/OS-III支持多任务操作,允许在系统中同时运行多个任务。每个任务都有自己的独立堆栈和任务控制块,可以根据优先级和调度策略进行管理。
3.任务通信与同步: 提供了丰富的任务通信和同步机制,包括信号量、消息队列、邮箱、事件标志组等,以便任务之间进行数据传递和协同工作。
4.中断管理: μC/OS-III允许将中断服务程序(ISR)与任务结合起来,提供了可嵌套的中断处理机制,以便更好地处理多种中断情况。
5.内存管理: 提供内存管理功能,支持内存池、动态内存分配等机制,使得在资源有限的嵌入式系统中更加高效地管理内存。
6.时钟和定时器管理: μC/OS-III支持时钟和定时器功能,可以用于任务的定时调度、超时处理等。
7.可裁剪和可移植: μC/OS-III的内核设计具有可裁剪性,可以根据具体应用需求选择性地包含或排除功能。同时,它也是可移植的,可以在不同的硬件平台上运行。
8.学术支持和社区: μC/OS-III有一定的学术支持,包括相关的文档、培训课程等。此外,有一个活跃的社区,用户可以在社区中分享经验、提问问题。

三、实验

(一)基于STM32CubeMX建立工程

1、创建项目

配置RCC
【STM32】uc/OS-III多任务程序插图
配置SYS
【STM32】uc/OS-III多任务程序插图(1)
配置USART1
【STM32】uc/OS-III多任务程序插图(2)
生成
【STM32】uc/OS-III多任务程序插图(3)

2、配置项目

参考:
STM32F103C8移植uCOSIII(HAL库)
(1)最终结果:
【STM32】uc/OS-III多任务程序插图(4)【STM32】uc/OS-III多任务程序插图(5)
(2)为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;
#else
cnts = cpu_clk_freq/(CPU_INT32U)OS_TICKS_PER_SEC;
#endif
OS_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

(3)为bsp.h添加代码

// bsp.h
#ifndef  __BSP_H__
#define  __BSP_H__
#include "stm32f1xx_hal.h"
void BSP_Init(void);
#endif

(4)修改main.c文件代码

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
#include "usart.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include 
#include "stm32f1xx_hal.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 LED0_TASK_PRIO		4
#define MSG_TASK_PRIO		5
#define LED1_TASK_PRIO		6
/* 任务堆栈大小	*/
#define START_STK_SIZE 		96
#define LED0_STK_SIZE 		64
#define MSG_STK_SIZE 		64
#define LED1_STK_SIZE 		64
/* 任务栈 */	
CPU_STK START_TASK_STK[START_STK_SIZE];
CPU_STK LED0_TASK_STK[LED0_STK_SIZE];
CPU_STK MSG_TASK_STK[MSG_STK_SIZE];
CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
/* 任务控制块 */
OS_TCB StartTaskTCB;
OS_TCB Led0TaskTCB;
OS_TCB MsgTaskTCB;
OS_TCB Led1TaskTCB;
/* 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  led_pc13(void *p_arg);
static  void  send_msg(void *p_arg);
static  void  led_pa3(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 > 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	* )"led_pc13", 		
(OS_TASK_PTR )led_pc13, 			
(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	* )"led_pa3", 		
(OS_TASK_PTR )led_pa3, 			
(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);										 
/* 创建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  led_pc13 (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 > 0u
OSStatTaskCPUUsageInit(&err);                               /* Compute CPU capacity with no task running            */
#endif
CPU_IntDisMeasMaxCurReset();
AppTaskCreate();                                            /* Create Application Tasks                             */
AppObjCreate();                                             /* Create Application Objects                           */
while (DEF_TRUE)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
OSTimeDlyHMSM(0, 0, 1, 0,OS_OPT_TIME_HMSM_STRICT,&err);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
OSTimeDlyHMSM(0, 0, 1, 0,OS_OPT_TIME_HMSM_STRICT,&err);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
static  void  led_pa3 (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 > 0u
OSStatTaskCPUUsageInit(&err);                               /* Compute CPU capacity with no task running            */
#endif
CPU_IntDisMeasMaxCurReset();
AppTaskCreate();                                            /* Create Application Tasks                             */
AppObjCreate();                                             /* Create Application Objects                           */
while (DEF_TRUE)
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);
OSTimeDlyHMSM(0, 0, 3, 0,OS_OPT_TIME_HMSM_STRICT,&err);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);
OSTimeDlyHMSM(0, 0, 3, 0,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 > 0u
OSStatTaskCPUUsageInit(&err);                               /* Compute CPU capacity with no task running            */
#endif
CPU_IntDisMeasMaxCurReset();
AppTaskCreate();                                            /* Create Application Tasks                             */
AppObjCreate();                                             /* Create Application Objects                           */
while (DEF_TRUE)
{
printf("hello uc/OS \r
");
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
", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

(二)实现

【STM32】uc/OS-III多任务程序插图(6)

【STM32】uc/OS-III多任务程序插图(7)

四、总结

在这次实验中,我通过移植uCOS-III操作系统,完成了多个任务,对操作系统有了更多的了解。
以上为我此次学习成果,如有问题,烦请指正。

五、参考

链接:
STM32F103C8T6移植uC/OS-III基于HAL库超完整详细过程
链接:
STM32F103C8移植uCOSIII(HAL库)
链接:
【STM32】STM32F103C8T6基于HAL库移植uC/OS-III

本站无任何商业行为
个人在线分享 » 【STM32】uc/OS-III多任务程序
E-->