嵌入式RTOS多任务程序设计

目录

一、uc/OS-III介绍 

特点

源代码

应用程序接口(API)

抢占式多任务处理

时间片轮转调度

快速响应中断

确定性的

可扩展的

易移植的

可固化的

可实时配置的

任务数无限制

优先级数无限制

内核对象数无限制

服务

互斥信号量

嵌套的任务停止

软件定时器

挂起多个对象

任务信号量

任务消息

任务寄存器

错误检测

内置的性能测量

可优化

死锁预防

任务级的时基处理

用户可定义的钩子函数

时间戳

嵌入的内核调试器

对象名称

二、stm32cubemx建立项目

1、项目单片机选择

2、RCC配置

3、SYS配置 

4、USART1串口配置

5、输出端口配置

6、输出项目文件

三、移植uc/OS-III准备

1、获取uc/OS-III源码

2、整理源码文件

1)准备源码

 2)项目添加文件

2.1、“CPU”添加

2.2、“LIB”添加

2.3、“PORT”添加

2.4、“SOURCE”添加

2.5、“CONFIG”添加

2.6、“BSP”添加

3)项目添加文件路径

四、代码修改

1、为bsp.h和bsp.c添加代码

2、修改部分文件相关代码

2.1、startup_stm32f103xb.s

2.2、app_cfg.h

2.3、includes.h

2.4、lib_cfg.h

2.5、usart.c

3、初始化管脚

4、主函数修改

五、运行结果

总结

参考


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

一、uc/OS-III介绍 

uC/OS-III(Micro C OS Three 微型的C 语言编写的操作系统第3版)是一个可升级的,可固化的,基于优先级的实时内核。它对任务的个数无限制。uC/OS-III 是一个第3 代的系统内核,支持现代的实时内核所期待的大部分功能。例如资源管理,同步,任务间的通信等等。然而,uC/OS-III 提供的特色功能在其它的实时内核中是找不到的,比如说完备的运行时间测量性能,直接地发送信号或者消息到任务,任务可以同时等待多个内核对象等。

uC/OS-III 是一个可扩展的,可固化的,抢占式的实时内核,它管理的任务个数不受限制。它是第三代内核,提供了现代实时内核所期望的所有功能包括资源管理、同步、内部任务交流等。uC/OS-III 也提供了很多特性是在其他实时内核中所没有的。比如能在运行时测量运行性能,直接得发送信号或消息给任务,任务能同时等待多个信号量和消息队列。

特点

源代码

uC/OS-III 完全根据ANSI-C 标准写的。代码的规范是Micrium 团队的一种文化。虽然很多商业内核供应商提供他们产品的源代码,但是这些产品很有可能是笨重且难以利用的。除非代码严格地遵循标准并且产品有完整的带例子的说明书以展示代码是怎样工作的。

应用程序接口(API)

uC/OS-III 是很直观的。如果你熟悉类似的编码规范,你能轻松地知道函数名所对应的服务,以及需要怎样的参数。例如:指向对象的指针通常是第一个参数,指向错误代码的指针通常是最后一个参数。

抢占式多任务处理

uC/OS-III 是一个抢占式多任务处理内核,因此,uC/OS-III 正在运行的经常是最重要的就绪任务。

时间片轮转调度

uC/OS-III 允许多个任务拥有相同的优先级。当多个相同优先级的任务就绪时,并且这个优先级是目前最高的。uC/OS-III 会分配用户定义的时间片给每个任务去运行。每个任务可以定义不同的时间片。当任务用不完时间片时可以让出CPU 给另一个任务。

快速响应中断

uC/OS-III 有一些内部的数据结构和变量。uC/OS-III 保护临界段可以通过锁定调度器代替关中断。因此关中断的时间会非常少。这样就使uC/OS-III 可以响应一些非常快的中断源了。

确定性的

uC/OS-III 的中断响应时间是可确定的,uC/OS-III 提供的大部分服务的执行时间也是可确定的。

可扩展的

根据应用的需求,代码大小可以被调整。编译时通过调整uC/OS-III 源代码中的大约40 个#define(见OS_CFG.H)可以在添加或移除一些功能。uC/OS-III 的服务还提供一些实时检查功能。特别的,uC/OS-III 能检传递的参数是否为NULL 指针,ISR 是否就绪了任务级服务。参数有允许范围,指定选项都是有用的。检测功能可以被关闭(在编译时)以提供更好的性能和缩减代码大小。实际上,可扩展的uC/OS-III 支持更广泛的应用和项目。

易移植的

uC/OS-III 可以被移植到大部分的CPU 架构中。大部分的支持uC/OS-II 的器件通过改动就能支持uC/OS-III。而uC/OS-II已经移植到45 种CPU 架构中了。

可固化的

uC/OS-III 专为嵌入式系统设计,它可以跟应用程序代码一起被固化。

可实时配置的

uC/OS-III 允许用户在运行时配置内核。特别的,所有的内核对象如任务、堆栈、信号量、事件标志组、消息队列、消息、互斥信号量、内存分区、软件定时器等都是在运行时分配的,以免在编译时的过度分配。

任务数无限制

uC/OS-III 对任务数量无限制。实际上,任务的数量限制于处理器能提供的内存大小。每一个任务需要有自己的堆栈空间,uC/OS-III 在运行时监控任务堆栈的生长。uC/OS-III 对任务的大小无限制,

优先级数无限制

uC/OS-III 对优先级的数量无限制。然而,配置uC/OS-III 的优先级在32 到256 之间已经满足大多数的应用了。

内核对象数无限制

uC/OS-III 支持任何数量的任务、信号量、互斥信号量、事件标志组、消息队列、软件定时器、内存分区。用户在运行时分配所有的内核对象。

服务

uC/OS-III 提供了高档实时内核所需要的所有功能,例如任务管理、时间管理、信号量、事件标志组、互斥信号量、消息队列、软件定时器、内存分区等。

互斥信号量

互斥信号量用于资源管理。它是一个内置优先级的特殊类型信号量,用于消除优先级反转。互斥信号量可以被嵌套,因此,任务可申请同一个互斥信号量多达250 次。当然,互斥信号量的占有者需要释放同等次数。

嵌套的任务停止

uC/OS-III 允许任务停止自身或者停止另外的任务。停止一个任务意味着这个任务将不再执行直到被其他的任务恢复。停止可以被嵌套到250 级。换句话说,一个任务可以停止另外的任务多达250 次。当然,这个任务必须被恢复同等次数才有资格再次获得CPU。

软件定时器

可以定义任意数量的一次性的、周期性的、或者两者兼有的定时器。定时器是倒计时的,执行用户定义的行为一直到计数减为0。每一个定时器可以有自己的行为,如果一个定时器是周期性的,计数减为0 时会自动重装计数值并执行用户定义的行为。

挂起多个对象

uC/OS-III 允许任务等待多个事件的发生。特别的,任务可以同时等待多个信号量和消息队列被提交。等待中的任务在事件发生的时候被唤醒。

任务信号量

uC/OS-III 允许ISR 或者任务直接地发送信号量给其它任务。这样就避免了必须产生一个中间级内核对象如一个信号量或者事件标志组只为了标记一个任务。提高了内核性能。

任务消息

uC/OS-III 允许ISR 或者任务直接发送消息到另一个任务。这样就避免产生一个消息队列,提高了内核性能。

任务寄存器

每一个任务可以拥有用户可定义的任务寄存器,不同于CPU 寄存器。

错误检测

uC/OS-III 能检测指针是否为NULL、在ISR 中调用的任务级服务是否允许、参数在允许范围内、配置选项的有效性、函数的执行结果等。每一个uC/OS-III 的API 函数返回一个对应于函数调用结果的错误代号。

内置的性能测量

uC/OS-III 有内置性能测量功能。能测量每一个任务的执行时间,每个任务的堆栈使用情况,任务的执行次数,CPU的使用情况,ISR 到任务的切换时间,任务到任务的切换时间,列表中的峰值数,关中断、锁调度器平均时间等。

可优化

uC/OS-III 被设计于能够根据CPU 的架构被优化。uC/OS-III 所用的大部分数据类型能够被改变,以更好地适应CPU 固有的字大小。优先级调度法则可以通过编写一些汇编语言而获益于一些特殊的指令如位设置、位清除、计数清零指令(CLZ),find-first-one(FF1)指令。

死锁预防

uC/OS-III 中所有的挂起服务都可以有时间限制,预防死锁。

任务级的时基处理

uC/OS-III 有时基任务,时基ISR 触发时基任务。uC/OS-III 使用了哈希列表结构,可以大大减少处理延时和任务超时所产生的开支。

用户可定义的钩子函数

uC/OS-III 允许程序员定义hook 函数,hook 函数被uC/OS-III 调用。hook 函数允许用户扩展uC/OS-III 的功能。有的hook 函数在任务切换的时候被调用,有的在任务创建的时候被调用,有的在任务删除的时候被调用。

时间戳

为了测量时间,uC/OS-III 需要一个16 位或者32 位的时时间戳计数器。这个计数器值可以在运行时被读取以测量时间。例如:当ISR 提交消息到任务时,时间戳计数器自动读取并保存作为消息。当接收者接收到这条消息,时间戳被提供在消息内。通过读取现在的时间戳,消息的响应时间可以被确定。

嵌入的内核调试器

这个功能允许内核调试器查看uC/OS-III 的变量和数据结构通过一个用户定义的通道。(但是只能在调试器遇到断点的时候查看)。uC/OS-III 内核也支持uC/Probe(探针)在运行时显示信息。

对象名称

每个uC/OS-III 的内核对象有一个相关联的名字。这样就能很容易的识别出对象所指定的作用。分配一个ASCII 码的名字给任务、信号量、互斥信号量、事件标志组、消息队列、内存块、软件定时器。对象的名字长度没有限制,但是必须以空字符结束。

二、stm32cubemx建立项目

1、项目单片机选择

选择单片机stm32f103c8t6建立

2、RCC配置

3、SYS配置 

4、USART1串口配置

5、输出端口配置

将与LED相连的两个端口PA3 PC13配置为GPIO_Output,可根据LED现象作为是否移植成功的依据。

6、输出项目文件

勾选下列,否则项目缺少.c/.h文件,然后创建项目

三、移植uc/OS-III准备

1、获取uc/OS-III源码

可直接下载此网盘链接内容
链接:https://pan.baidu.com/s/10RqsDRecbmVteWmDv2oUNQ
提取码:1234

2、整理源码文件

1)准备源码

打开下载好的文件,将下列文件复制到cubeMX工程的MDK-ARM文件夹下

复制转移 ,如下

 2)项目添加文件

2.1、“CPU”添加

点击ARM-Cortex-M3后点击RealView,全部添加

2.2、“LIB”添加

点击Ports\ARM-Cortex-M3\RealView,添加

2.3、“PORT”添加

MDK-ARM\uCOS-III\Ports\ARM-Cortex-M3\Generic\RealView路径下选中以下文件,Add添加

2.4、“SOURCE”添加

MDK-ARM\uCOS-III\Source路径下选中以下全部 .c .h 文件,Add添加

2.5、“CONFIG”添加

MDK-ARM\uC-CONFIG路径下选中以下全部文件,Add添加

2.6、“BSP”添加

MDK-ARM\uC-BSP路径下选中以下全部文件,Add添加

3)项目添加文件路径

按照下图操作即可

四、代码修改

1、为bsp.h和bsp.c添加代码

bsp.h

#ifndef  __BSP_H__
#define  __BSP_H__

#include "stm32f1xx_hal.h"

void BSP_Init(void);

#endif

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

2、修改部分文件相关代码

2.1、startup_stm32f103xb.s

在以下位置处将PendSV_Handler改为OS_CPU_PendSVHandler
SysTick_Handler改为OS_CPU_SysTickHandler

记得定义一下,否则会报错

 

2.2、app_cfg.h

DEF_ENABLED 改为 DEF_DISABLED

#define APP_TRACE BSP_Ser_Printf 改为 #define APP_TRACE(void)

2.3、includes.h

在#include <bsp.h>下面添加

#include "gpio.h"
#include "app_cfg.h"

将#include <stm32f10x_lib.h> 改为 #include "stm32f1xx_hal.h"

2.4、lib_cfg.h

修改为5(该处宏定义设置堆空间的大小,STM32F103C8T6的RAM只有20K,所以要改小一点)

2.5、usart.c

添加代码完成printf重定向

/* USER CODE BEGIN 1 */

typedef struct __FILE FILE;
int fputc(int ch,FILE *f){
	HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xffff);
	return ch;
}

/* USER CODE END 1 */

3、初始化管脚

gpio.c文件中修改代码

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);


  /*Configure GPIO pin : PC13|PA3 */
  GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

4、主函数修改

修改main.c

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
#include "usart.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <includes.h>
#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\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****/

调节设置,随后进行编译 

五、运行结果

总结

整个实验过程并不复杂,只不过需要特别细心才行,只要正确的跟着步骤做是一定能成功的,如果有哪里出现了错误,那么就有可能是你路径没添加、头文件没添加、少了头文件、漏了哪部分没做等等,一定要细心

参考

uC/OS-III_百度百科 (baidu.com)

【嵌入式17】STM32F103C8T6基于HAL库移植uC/OS-III及逻辑分析仪波形观测_基于stm32hal库波形识别与检测-CSDN博客

STM32F103C8T6基于HAL库移植uC/OS-III-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值