一、题目要求

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

二、UCOSIII简单介绍

  UCOS是Micrium公司出品的RTOS类实时操作系统, UCOS目前有两个版本:UCOSII和UCOSIII。
  UCOSIII是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制,提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。
  UCOSIII是用C和汇编来写的,其中绝大部分都是用C语言编写的,只有极少数的与处理器密切相关的部分代码才是用汇编写的, UCOSIII结构简洁,可读性很强!非常适合初次接触嵌入式实时操作系统学生、嵌入式系统开发人员和爱好者学习。

  • 什么是任务
      任务(线程)是简单的程序。单CPU 中,在任何时刻只能是一个任务被执行。任务看起来像C 函数。在大多数嵌入式系统中,任务通常是无限循环的。任务不能像C 函数那样,它是不能return 的。
      在UCOSIII中任务就是程序实体,UCOSIII能够管理和调度这些小任务(程序)。UCOSIII中的任务由三部分组成:任务堆栈、任务控制块和任务函数
    任务堆栈:上下文切换的时候用来保存任务的工作环境,就是STM32的内部寄存器值。
       任务堆栈是任务的重要部分,堆栈是在RAM中按照“先进先出(FIFO)”的原则组织的一块连续的存储空间。为了满足任务切换和响应中断时保存CPU寄存器中的内容及任务调用其它函数时的需要,每个任务都应该有自己的堆栈。
      恢复现场即可将任务切换回上一个任务并且还能接着从上次被中断的地方开始运行。现场就是CPU的内部各个寄存器。因此在创建一个新任务时,必须把系统启动这个任务时所需的CPU各个寄存器初始值事先存放在任务堆栈中。这样当任务获得CPU使用权时,就把任务堆栈的内容复制到CPU的各个寄存器,从而可以任务顺利地启动并运行。
    任务控制块:用来记录任务的各个属性。
       任务控制块是用来记录与任务相关的信息的数据结构,每个任务都要有自己的任务控制块。我们使用OSTaskCreate()函数来创建任务的时候就会给任务分配一个任务控制块。任务控制块由用户自行创建。
    OS_TCB StartTaskTCB; //创建一个任务控制块
    
       USOCIII提供了用于任务控制块初始化的函数:OS_TaskInitTCB()。 但是,用户不需要自行初始化任务控制块。因为和任务堆栈初始化函数一样,函数OSTaskCreate()在创建任务的时候会对任务的任务控制块进行初始化。
    任务函数:由用户编写的任务处理代码,是实实在在干活的,任务函数通常是一个无限循环,也可以是一个只执行一次的任务。任务的参数是一个void类型的,可以可以传递不同类型的数据甚至是函数。
       任务函数其实就是一个C语言的函数,但是在使用UCOIII的情况下这个函数不能有用户自行调用,任务函数何时执行执行,何时停止完全有操作系统来控制。

   UCOSIII支持时间片轮转调度,因此在一个优先级下会有多个任务,那么我们就要对这些任务做一个管理,这里使用OSRdyList[]数组管理这些任务。

三、实验过程

以uc/OS-III为例,将其移植到stm32F103上,构建至少3个任务(task)。

1、建立CubeMX工程

  • 打开stm32 CubeMX,选择芯片stm32f103c8,配置系统时钟为72M。
    在这里插入图片描述
  • 配置RCC
    在这里插入图片描述
  • 配置SYS
    在这里插入图片描述
  • 配置串口USART1
    在这里插入图片描述
  • 设置PA3和PC13作为两个LED灯的端口
    在这里插入图片描述
  • 设置好工程路径和名称后导出即可。

2、移植前的文件准备

  • 获取uCOS-III源码

进入 Micrium 公司官网下载中心
选择ST系列,点击View all STMicroelectronics,点击 STMicroelectronics STM32F107
之后按照提示注册下载即可。

  • 移植前的文件准备
    打开下载好的源码,将uCOS的5个相关文件复制到cubeMX工程的MDK-ARM文件夹下
    在这里插入图片描述

    3、移植过程

  • 将uCOS文件添加到项目中
    点击Manage Project Items,按下图所示操作,为项目新建文件夹,在对应文件夹下添加文件。
    在这里插入图片描述

  • 点击CPU–>Add Files…
    MDK-ARM\uC-CPU路径下选中一下文件,点击Add添加
    在这里插入图片描述
    MDK-ARM\uC-CPU\ARM-Cortex-M3\RealView路径下选中以下文件,点击Add添加
    在这里插入图片描述

  • 点击LIB–>Add Files…
    MDK-ARM\uC-LIB路径下选中下图红框文件,Add添加
    MDK-ARM\uC-LIB\Ports\ARM-Cortex-M3\RealView路径下选中下图绿框文件,点击Add添加
    在这里插入图片描述

  • 点击PORT–>Add Files…
    MDK-ARM\uCOS-III\Ports\ARM-Cortex-M3\Generic\RealView
    路径下选中以下文件,点击Add添加
    在这里插入图片描述

  • 点击SOURCE–>Add Files…
    MDK-ARM\uCOS-III\Source
    路径下选中以下全部 .c .h 文件,点击Add添加
    在这里插入图片描述

  • 点击CONFIG–>Add Files…
    MDK-ARM\uC-CONFIG
    路径下选中以下全部文件,点击Add添加在这里插入图片描述

  • 点击BSP–>Add Files…
    MDK-ARM\uC-BSP
    路径下选中以下全部文件,点击Add添加
    在这里插入图片描述

  • 全部添加完毕后,点击OK。

  • 之后导入文件路径
    在这里插入图片描述

4、构建三个任务

  • 添加代码
    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
    
  • 修改部分文件相关代码

    • 打开startup_stm32f103xb.s文件
      在以下位置处将PendSV_Handler改为OS_CPU_PendSVHandler
      SysTick_Handler改为OS_CPU_SysTickHandler
      在这里插入图片描述
      在这里插入图片描述
    • 打开app_cfg.h文件
      DEF_ENABLED 改为DEF_DISABLED
      在这里插入图片描述
      #define APP_TRACE BSP_Ser_Printf 改为 #define APP_TRACE(void)
      在这里插入图片描述
  • 打开includes.h文件
    在#include <bsp.h>下面添加 #include “gpio.h”#include “app_cfg.h”
    将#include <stm32f10x_lib.h> 改为 #include “stm32f1xx_hal.h”
    在这里插入图片描述

  • 打开lib_cfg.h文件
    修改为5 (该处宏定义设置堆空间的大小,STM32F103C8T6的RAM只有20K,所以要改小一点)在这里插入图片描述

  • 打开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 */
    
  • 初始化管脚
    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);
      }
    
  • 编写主函数
    修改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****/
    
    • 点击魔法棒修改Target如下设置
      在这里插入图片描述

5、硬件实现

在这里插入图片描述

四、参考链接

【嵌入式17】STM32F103C8T6基于HAL库移植uC/OS-III及逻辑分析仪波形观测
完整工程文件及uCOS-III源码
链接:https://pan.baidu.com/s/1dOdrJDhBTcpvtOWQWLnx4w
提取码:3w14

Logo

「智能机器人开发者大赛」官方平台,致力于为开发者和参赛选手提供赛事技术指导、行业标准解读及团队实战案例解析;聚焦智能机器人开发全栈技术闭环,助力开发者攻克技术瓶颈,促进软硬件集成、场景应用及商业化落地的深度研讨。 加入智能机器人开发者社区iRobot Developer,与全球极客并肩突破技术边界,定义机器人开发的未来范式!

更多推荐