STM32 hal库使用笔记之FreeRTOS—任务创建、删除,任务挂起、恢复,任务中断管理

这篇具有很好参考价值的文章主要介绍了STM32 hal库使用笔记之FreeRTOS—任务创建、删除,任务挂起、恢复,任务中断管理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、简介

1.FreeRTOS简介

    RTOS全称为:Real Time OS,就是实时操作系统,强调的是:实时性。而Free显而易见体现的是其免费性。总的来说这是一个免费的嵌入式实时操作系统。

    其特点是:免费开源、可剪裁(独立性强,适应范围广)、简单、优先级/任务不限(但是受到不同开发环境和硬件的限制,一般受限)、支持三种方式的任务调度。

    与裸机的区别:裸机的应用程序整体来看放在整个大循环里,很多时候资源浪费即“空等待”;而RTOS是多个优先级相同的任务每个任务执行一个时间片(时间长度可以调节),来回切换,最终效果是所有优先级相同的任务同时进行,而且有任务被“阻塞”时,会释放cpu资源。

2.任务调度简介

一共支持三种方式:

    1)抢占式调度:主要是针对优先级不同的任务,每个任务都有一个优先级,优先级高的任务可以抢占优先级低的任务。

    2)时间片调度:主要针对优先级相同的任务,当多个任务的优先级相同时, 任务调度器会在每一次系统时钟节拍到的时候切换任务。

    3)协程式调度:当前执行任务将会一直运行,同时高优先级的任务不会抢占低优先级任务 FreeRTOS现在虽然还支持,但是官方已经表示不再更新协程式调度。仅作了解。

3.任务状态简介

FreeRTOS总共存在4种任务状态:

    运行态:正在占据CPU资源,正在运行的任务。每一时刻只存在一个任务处于运行态。

    就绪态:简单概括,此任务若准备工作都已经做完,即可进入就绪态。

    阻塞态:如果一个任务因延时或等待外部事件发生,那么这个任务就处于阻塞态。

    挂起态:类似暂停,调用函数 vTaskSuspend() 进入挂起态,需要调用解挂函数vTaskResume() 才可以进入就绪态。

    注意挂起和删除的区别,删除是将此任务从任务堆栈中完全移除,挂起只是暂时停止运行。

    所有的任务想进入运行态必须要先进入就绪态,而从运行态可以进入任何状态。如下图表示:

stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

在FreeRTOS中有许多Include可以配置,主要是使能一些功能。包括任务挂起、恢复、中断恢复等等,在需要时使能即可。

stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

二、HAL库配置

1.时钟树的配置

参考:STM32 hal库使用笔记(一)GPIO的使用—流水灯_乱码小伙的博客-CSDN博客

stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

     由于FreeRTOS的系统定时器要用滴答定时器,而CubeMX不推荐共用,所以需要修改Timebase Source的来源于其他的定时器。stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

 2.FreeRTOS的配置
2.1 动态任务的配置(代码对应3.1)

    实验目标:添加两个任务,分别是task1、task2,task1中实现LED0的定时翻转,task2中实现LED1的定时翻转。当按键1按下时,删除任务2。

    使用CubeMX配置后,会自动剪裁FreeRTOS,只保留必要文件,由于只是实验动态任务,所有大部分默认即可。

stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

    添加任务1和任务2,注意,这两个任务的级别可以相同也可以不同,因为LED翻转会有阻塞态,会释放CPU资源给另一个LED。

stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

 配置完成后生成代码即可。

2.2 静态任务的配置

    静态任务的创建与静态任务的创建的最大区别就是,静态任务需要用户自己分配任务堆栈,步骤麻烦一些,不过利用CubeMX,只需修改任务创建方式即可。

    任务控制块的作用:用来保存任务信息,在任务切换时保存任务状态,方便恢复现场。

stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

其实验效果和原理与动态基本一致,就不再演示实验效果和代码部分。

    关于任务删除有几点补充:在一个任务中删除的任务要不是这个任务本身,要不就是其他的任务,如果是其他任务,则会在本任务中将被删除的任务释放;若是任务本身,则需要在空闲任务中删除本任务,所以FreeRTOS会自动创建空闲任务。(这是针对的动态任务,静态任务需要用户进行删除。)

2.3 任务挂起和恢复的配置(包括中断恢复,对应代码3.2)

    实验目的:配置两个任务和一个外部中断,由于用LED灯来显示的话与上个任务的现象差不多,所以改用串口来检测,按键1在任务中挂起任务,按键2在任务中恢复任务,按键3在中断中恢复任务。

串口的配置参考:STM32 hal库使用笔记(二)中断—串口中断_乱码小伙的博客-CSDN博客

外部中断的配置参考:STM32 hal库使用笔记(二)中断—外部中断_乱码小伙的博客-CSDN博客  

    先说一些中断恢复的注意问题,为了任务调度时任务的优先级清楚、明晰、好分配所以CubeMX会自动将中断分组设为4,这样就没有响应优先级的冲突,由抢占优先级起到决定作用。而想在中断中使用API函数,中断的优先级必须在FreeRTOS的管理范围内,这个范围可以配置,默认是5-15。如果优先级分组/优先级不是如上所说的配置,在中断中调用API函数时会发生很多问题,老版本会不产生作用,但是我的实测是直接卡死,所以还是建议按照分组和优先级的规则进行配置。

stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

     在中断服务函数里边需调用FreeRTOS的API函数,必须使用带“FromISR”后缀的函数。

Config的配置同上就行,再就是确保以下的两个函数使能即可(才能打开对应的寄存器)。

stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

 2.4 任务中断管理配置(代码参考3.3)

    实验目的:检验中断管理的作用,属于FreeRTOS管理的范围内(5~15)的中断,可以利用portDISABLE_INTERRUPTS()函数进行关闭。利用串口进行检验,将定时器2、3的抢占优先级配为4和6,建立一个任务,在任务中利用按键1和按键2来开启和关闭中断,串口打印信息进行反馈。

定时器配置参考:STM32 hal库使用笔记(二)中断—定时器中断_乱码小伙的博客-CSDN博客

按键配置参考:STM32 hal库使用笔记(一)GPIO的使用—按键控制LED_乱码小伙的博客-CSDN博客

CubeMX的配置同上,打开两个函数的使能,配置一个任务即可。

三、代码编写

3.1

只需要编写任务即可。

任务1:

void StartTask02(void const * argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
  for(;;)
  {
     if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==0)
    {
      HAL_Delay(20);
      if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==0)
      {
          while(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == 0);         
          if(myTask03Handle!=NULL){
             
             vTaskDelete(myTask03Handle);
             myTask03Handle=NULL;              
          }
      }          
    }
    osDelay(500);
    HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
    k++;if(k==4)printf("task1正在运行\r\n");
    if(k>7)k=0;
    //uxTaskGetStackHighWaterMark(myTask02Handle);
  }
  /* USER CODE END StartTask02 */
}

任务2:

void StartTask03(void const * argument)
{
  /* USER CODE BEGIN StartTask03 */
  /* Infinite loop */
  for(;;)
  {
      osDelay(500);
      if(k==7)printf("task2正在运行\r\n");
      HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
  }
  /* USER CODE END StartTask03 */
}

串口部分不用配置,删除即可。

实现现象:

任务的建立和删除实验

3.2

编写任务1和任务2,以及外部中断更新回调函数即可。

任务1:

void StartTask02(void const * argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
  for(;;)
  {
    osDelay(500);
    HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
    count1++;
    if(count1==9)
    {
      printf("-----task1正在运行-----\r\n");
      count1=0;
    }
     if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==0)
    {
      HAL_Delay(20);
      if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==0)
      {
          while(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == 0);         
          vTaskSuspend(myTask03Handle);
          printf("!!!--------task2被挂起--------!!!\r\n");
      }          
    }
    else if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)==0)
    {
      HAL_Delay(20);
      if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)==0)
      {
          while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0);         
          vTaskResume(myTask03Handle);
          printf("!!!--------task2已在任务中恢复--------!!!\r\n");
      }          
    }
  
  }
  /* USER CODE END StartTask02 */
}

任务2:

void StartTask03(void const * argument)
{
  /* USER CODE BEGIN StartTask03 */
  /* Infinite loop */
  for(;;)
  {
    osDelay(500);
    HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
    count2++;
    if(count2==5)
    {
       printf("-----task2正在运行-----\r\n");
      count2=0;
    }
  }
  /* USER CODE END StartTask03 */
}

中断回调函数,注意抢占优先级必须在5~15

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    BaseType_t xYieldRequired;
    if(GPIO_Pin == KEY_UP_Pin)
    {
      xYieldRequired = xTaskResumeFromISR( myTask03Handle ); 
      if(xYieldRequired == pdTRUE )//需要任务切换
      {
       portYIELD_FROM_ISR( xYieldRequired );
      }
      printf("!!!----已经在中断中恢复task2----!!!");    
    }
}

有个问题需要说明,printf函数占时较长,在中断中不宜使用,下个实验已经更换。

实现现象:

stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

3.3

同理,只需要编写任务逻辑和中断更新回调函数即可。

任务编写:

void StartTask02(void const * argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
  for(;;)
  {
     if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==0)
    {
      HAL_Delay(20);
      if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==0)
      {
          while(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == 0);
          portDISABLE_INTERRUPTS();          
          printf("!!!--------中断关闭--------!!!\r\n");
      }          
    }
    else if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)==0)
    {
      HAL_Delay(20);
      if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)==0)
      {
          while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0);
           portENABLE_INTERRUPTS();          
          printf("!!!--------中断开启--------!!!\r\n");
      }          
    }
  
  }
  /* USER CODE END StartTask02 */
}

 中断回调函数:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM6) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */
    if (htim->Instance == TIM2)
    {
        
        uint8_t MyArray[] = {"定时器2正在运行\r\n"};
        HAL_UART_Transmit(&huart1, MyArray, sizeof(MyArray), 10000);
        HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
    }
   if (htim->Instance == TIM3)
    {   
        
        uint8_t MyArray2[] = {"定时器3正在运行\r\n"};
       HAL_UART_Transmit(&huart1, MyArray2, sizeof(MyArray2), 10000);
        HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
    }
  /* USER CODE END Callback 1 */
}

实验现象:

stm32 hal freertos,STM32的hal库使用,stm32,笔记,嵌入式硬件

    可以看到,中断关闭,在管理范围内的定时器3已经停止工作,不在管理范围内的定期器2仍在工作。

欢迎大家交流和指正!!!不胜欣喜!!!文章来源地址https://www.toymoban.com/news/detail-761354.html

到了这里,关于STM32 hal库使用笔记之FreeRTOS—任务创建、删除,任务挂起、恢复,任务中断管理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【复习笔记】FreeRTOS(三)任务挂起和恢复

    本文是FreeRTOS复习笔记的第三节,任务挂起和恢复,使用的开发板是stm32f407VET6,创建两个任务,task1负责闪烁LED,task2负责按键控制,当按键按下时控制任务挂起,按键再次按下恢复任务,并通过串口打印任务状态。 上一篇文章: 【复习笔记】FreeRTOS(二)创建和删除任务 首先

    2024年02月07日
    浏览(30)
  • STM32 HAL FreeRTOS 硬件I2C 使用

    因为某个项目想要颜色识别,去识别球的颜色,但是又不想多来个摄像头,所以想尝试一下颜色传感器的方案。但是经过尝试,HAL库生成的 FreeRTOS 硬件 I2C 读写一直在报错。 刚好手头上有九轴陀螺仪的例程代码。最后用FreeRTOS 硬件 I2C 读取数据。 这里提到了阻塞式 HAL 函数(

    2024年02月20日
    浏览(52)
  • FreeRTOS任务的挂起和恢复 | FreeRTOS四

    目录 说明: 一、任务挂起与恢复 1.1、什么是任务挂起 1.2、任务挂起函数 1.3、什么是任务恢复 1.4、任务恢复函数 1.5、什么是中断任务恢复函数 1.6、中断任务恢复函数 二、任务挂起与恢复实例代码(任务中) 2.1、主要代码 2.2、结果 三、任务挂起与恢复实例代码(中断中)

    2024年02月16日
    浏览(37)
  • 【学习FreeRTOS】第5章——FreeRTOS任务挂起与恢复

    vTaskSuspend() ——挂起任务(类似暂停,可恢复,但删除任务,无法恢复) vTaskResume() ——恢复被挂起的任务 xTaskResumeFromISR()—— 在中断中恢复被挂起的任务 形参:待挂起任务句柄 此函数用于挂起任务,使用时需将宏 INCLUDE_vTaskSuspend 配置为 1。 无论优先级如何,被挂起的任务

    2024年02月13日
    浏览(41)
  • STM32操作系统FreeRTOS学习——基于hal库

    目录 一、基础概念 1、FreeRTOS 2、单片机编程的系统概念 a、裸机系统,包括轮询系统(不包括中断)和前后台系统(中断为前台,轮询为后台) b、多任务系统 3、FreeRTOS编程风格 a、数据类型 b、变量名的定义 c、函数名 d、宏定义 二、Cubemx创建工程 1、创建任务 2、创建队列

    2024年02月10日
    浏览(43)
  • STM32基于HAL库和STM32CubeMX的实时操作系统FreeRtOS开发

    1、FreeRTOS RTOS是一类操作系统,µC/OS,FreeRTOS,RTX,RT-Thread 等这些都是RTOS 类的操作系统 FreeRTOS 是众多RTOS 类操作系统中的一种,FreeRTOS 十分的小巧,可以在资源有限的微控制器中运行,FreeRTOS 也不仅仅局限于在微控制器中使用。就单从文件数量上来看FreeRTOS 要比µC/OS 少得多

    2024年02月21日
    浏览(64)
  • 【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子

    【STM32】HAL库 新建MDK工程 【STM32】HAL库 串口轮询发送 【STM32】HAL库 LED闪烁、流水灯 【STM32】HAL库 定时器中断 【STM32】HAL库 外部中断 使用STM32F103C8T6开发板,用STM32CubeMX配置FreeRTOS,可以适配正点原子FreeRTOS所有实验的基础工程 HAL的时基不能选择系统定时器 PA0和PA1输出模式,

    2024年02月19日
    浏览(51)
  • STM32+FREERTOS任务堆栈大小

    在FREERTOS任务开发过程中,由于不知道具体需要分配多大的任务堆栈大小,就需要在开始开发阶段尽可能的多分配一些,不然在调试过程中会出现程序卡死或者数据通信异常的现象。 如何评估任务堆栈的分配大小问题,可以根据任务的规模以及所任务所需的数据空间大概进行

    2024年02月16日
    浏览(43)
  • STM32FreeRTOS任务通知(STM32cube高效开发)

    1、任务通知可模拟队列和信号量 任务通知是FreeRTOS另外一种进程间通信技术。不需要创建任何中间对象,可以直接从任务向任务或ISR向任务发送通知,传递一个通知值任务通知可以模拟二值信号量、计数信号量、或长度为1的消息队列,使用任务通知,一般效率更高,消耗内

    2024年03月13日
    浏览(49)
  • stm32 freertos多任务状态迁移,中断临界段,任务延时

    arm中SP,LR,PC寄存器以及其它所有寄存器以及处理器运行模式介绍 特权级与用户级的区别主要是某些寄存器能不能访问与修改: cortex M3/M4内核 特权级与用户级详解 Cortex-M3双堆栈MSP和PSP Cortex-M3双堆栈MSP和PSP M3内核何时使用MSP何时使用PSP? 特权级可以使用MSP 和PSP指针 用户级

    2024年02月12日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包