RTOS中任务的创建与删除

我们在stm32f103c8t6单片机上验证RTOS中任务的创建与删除,利用stm32cube进行RTOS的配置。在选择TIM2当做RTOS的时钟,裸机的时钟源默认是 SysTick,但是开启 FreeRTOS 后,FreeRTOS会占用 SysTick (用来生成1ms 定时,用于任务调度),所以需要为其他总线提供另外的时钟源。

验证的功能比较简单,选择V1 版本的内核完全够用。

一、验证的思路以及需要使用的函数

1.验证思路

创建 4 个任务:taskLED1,taskLED2,taskKEY1,taskKEY2。

任务要求如下:

taskLED1:间隔 500ms 闪烁 LED1;

taskLED2:间隔 1000ms 闪烁 LED2;

taskKEY1:如果 taskLED1 存在,则按下 KEY1 后删除 taskLED1 ,否则创建 taskLED1 ; taskKEY2:如果 taskLED2 正常运行,则按下 KEY2 后挂起 taskLED2 ,否则恢复 taskLED2。

2.需要用到的函数

xTaskCreate();动态方式创建任务

vTaskDelete();删除任务

osThreadSuspend(TaskLED2Handle);挂起函数, 指定任务进行挂起,挂起后这个任务将不被执行

osThreadResume(TaskLED2Handle);恢复函数, 可以将这个任务从挂起态恢复

xTaskCreate 函数原型

pvTaskCode:指向任务函数的指针,任务必须实现为永不返回(即连续循环);

pcName:任务的名字,主要是用来调试,默认情况下最大长度是16;

pvParameters:指定的任务栈的大小;

pvParameters:传递任务函数的参数;

uxPriority:任务优先级,数值越大,优先级越大;

pxCreatedTask:用于返回已创建任务的句柄可以被引用。

vTaskDelete 函数原型

void vTaskDelete(TaskHandle_t xTaskToDelete);

只需将待删除的任务句柄传入该函数,即可将该任务删除。当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)。

二、stm32cube的配置

SYS

RCC

GPIO

PA0对应按键1,PA1对应按键2;PB8对应LED1,PB9对应LED2

RTOS

在Tasks and Queues中配置我们的四个任务

其实就是相当于stm32cube帮我们调用了并封装了xTaskCreate()函数。

四个任务的名字分别是

TaskLED1.TaskLED2,TaskKEY1,TaskKEY2;

四个任务的入口函数名字分别是

StartLED1,StartLED2,StartKEY1,StartKEY2;

其余配置相同,如下图

三、代码部分

usart.c

加入

#include "stdio.h"

int fputc(int ch, FILE *f)

{     

       unsigned char temp[1]={ch};

       HAL_UART_Transmit(&huart1,temp,1,0xffff); 

       return ch;

}

同时打开“魔术棒”,勾选Use MicroLIB,点击OK。这样就可以进行串口打印了。

freertos.c

#include "FreeRTOS.h"

#include "task.h"

#include "main.h"

#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */

#include "stdio.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/

/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/

/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/

/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN Variables */

/* USER CODE END Variables */

osThreadId TaskLED1Handle;

osThreadId TaskLED2Handle;

osThreadId TaskKEY1Handle;

osThreadId TaskKEY2Handle;

/* Private function prototypes -----------------------------------------------*/

/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void StartLED1(void const * argument);

void StartLED2(void const * argument);

void StartKEY1(void const * argument);

void StartKEY2(void const * argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* GetIdleTaskMemory prototype (linked to static allocation support) */

void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );

/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */

static StaticTask_t xIdleTaskTCBBuffer;

static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )

{

  *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;

  *ppxIdleTaskStackBuffer = &xIdleStack[0];

  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;

  /* place for user code */

}

/* USER CODE END GET_IDLE_TASK_MEMORY */

/**

  * @brief  FreeRTOS initialization

  * @param  None

  * @retval None

  */

void MX_FREERTOS_Init(void) {

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */

  /* add mutexes, ... */

  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */

  /* add semaphores, ... */

  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */

  /* start timers, add new ones, ... */

  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */

  /* add queues, ... */

  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */

  /* definition and creation of TaskLED1 */

  osThreadDef(TaskLED1, StartLED1, osPriorityNormal, 0, 128);

  TaskLED1Handle = osThreadCreate(osThread(TaskLED1), NULL);

  /* definition and creation of TaskLED2 */

  osThreadDef(TaskLED2, StartLED2, osPriorityNormal, 0, 128);

  TaskLED2Handle = osThreadCreate(osThread(TaskLED2), NULL);

  /* definition and creation of TaskKEY1 */

  osThreadDef(TaskKEY1, StartKEY1, osPriorityNormal, 0, 128);

  TaskKEY1Handle = osThreadCreate(osThread(TaskKEY1), NULL);

  /* definition and creation of TaskKEY2 */

  osThreadDef(TaskKEY2, StartKEY2, osPriorityNormal, 0, 128);

  TaskKEY2Handle = osThreadCreate(osThread(TaskKEY2), NULL);

  /* USER CODE BEGIN RTOS_THREADS */

  /* add threads, ... */

  /* USER CODE END RTOS_THREADS */

}

/* USER CODE BEGIN Header_StartLED1 */

/**

  * @brief  Function implementing the TaskLED1 thread.

  * @param  argument: Not used

  * @retval None

  */

/* USER CODE END Header_StartLED1 */

void StartLED1(void const * argument)

{

  /* USER CODE BEGIN StartLED1 */

  /* Infinite loop */

  for(;;)

  {

              HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);

    osDelay(1000);

  }

  /* USER CODE END StartLED1 */

}

/* USER CODE BEGIN Header_StartLED2 */

/**

* @brief Function implementing the TaskLED2 thread.

* @param argument: Not used

* @retval None

*/

/* USER CODE END Header_StartLED2 */

void StartLED2(void const * argument)

{

  /* USER CODE BEGIN StartLED2 */

  /* Infinite loop */

  for(;;)

  {

    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);

    osDelay(500);

  }

  /* USER CODE END StartLED2 */

}

/* USER CODE BEGIN Header_StartKEY1 */

/**

* @brief Function implementing the TaskKEY1 thread.

* @param argument: Not used

* @retval None

*/

/* USER CODE END Header_StartKEY1 */

void StartKEY1(void const * argument)

{

  /* USER CODE BEGIN StartKEY1 */

  /* Infinite loop */

  for(;;)

  {

              if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)

              {

                     osDelay(20);

                     if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)

                     {

                     printf("KEY1按下\r\n");

                            if(TaskLED1Handle==NULL)

                            {

                                   printf("任务1不存在,创建任务1\r\n");

                                    osThreadDef(TaskLED1, StartLED1, osPriorityNormal, 0, 128);

           TaskLED1Handle = osThreadCreate(osThread(TaskLED1), NULL);

                                          if(TaskLED1Handle!=NULL)

                                                 printf("任务1创建完成\r\n");

                            }

                            else

                            {

                                   printf("删除任务1\r\n");

                                   osThreadTerminate(TaskLED1Handle);

                                   TaskLED1Handle=NULL;

                            }

                     }

                     while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET);

              }

    osDelay(10);

  }

  /* USER CODE END StartKEY1 */

}

/* USER CODE BEGIN Header_StartKEY2 */

/**

* @brief Function implementing the TaskKEY2 thread.

* @param argument: Not used

* @retval None

*/

/* USER CODE END Header_StartKEY2 */

void StartKEY2(void const * argument)

{

  /* USER CODE BEGIN StartKEY2 */

       static int flag=0;

  /* Infinite loop */

  for(;;)

  {

   if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)

              {

                     osDelay(20);

                     if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)

                     {

                     printf("KEY2按下\r\n");

                            if(flag==0)

                            {

                                   osThreadSuspend(TaskLED2Handle);

                                   printf("任务2挂起\r\n");

                                   flag=1;

                            }

                                   else

                                   {

                                          osThreadResume(TaskLED2Handle);

                                          printf("任务2已恢复\r\n");

                                          flag=0;

                                   }

                     }

                     while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET);

              }

    osDelay(10);

  }

  /* USER CODE END StartKEY2 */

}

要说明的是

osThreadDef(TaskLED1, StartLED1, osPriorityNormal, 0, 128);

TaskLED1Handle = osThreadCreate(osThread(TaskLED1), NULL);

这两个函数的使用是stm32cube把任务动态创建函数xTaskCreate()封装后的变形,这两个函数的出现就代表TaskLED1的函数创建完成了,这里面的参数分别对应了任务名,入口函数,优先级,参数,堆栈大小,返回已创建任务的句柄,其余的3个任务同理。

接着看

void StartLED1(void const * argument)

{

  /* USER CODE BEGIN StartLED1 */

  /* Infinite loop */

  for(;;)

  {

              HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);

    osDelay(1000);

  }

  /* USER CODE END StartLED1 */

}

我们在stm32cube配置任务时,Entry function(入口函数)的名字是StartLED1。

意思就是说,我们的任务要运行的时候,需要我们进入“入口函数”才可以执行相应的命令。这里实现的是LED1每隔1000ms电平变化一次。

再看

void StartKEY1(void const * argument)

{

  /* USER CODE BEGIN StartKEY1 */

  /* Infinite loop */

  for(;;)

  {

              if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)

              {

                     osDelay(20);//软件消除按键抖动

                     if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)

                     {

                     printf("KEY1按下\r\n");

                            if(TaskLED1Handle==NULL)

                            {

                                   printf("任务1不存在,创建任务1\r\n");

                                    osThreadDef(TaskLED1, StartLED1, osPriorityNormal, 0, 128);

           TaskLED1Handle = osThreadCreate(osThread(TaskLED1), NULL);

                                          if(TaskLED1Handle!=NULL)

                                                 printf("任务1创建完成\r\n");

                            }

                            else

                            {

                                   printf("删除任务1\r\n");

                                   osThreadTerminate(TaskLED1Handle);

                                   TaskLED1Handle=NULL;

                            }

                     }

                     while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET);

              }

    osDelay(10);

  }

TaskLED1Handle是我们生成TaskLED1任务时的最后一个参数,句柄。如果我们要删除该任务,就用删除任务的函数,它的参数就是该任务的句柄osThreadTerminate(TaskLED1Handle);

任务被删除后就句柄TaskLED1Handle就被赋值NULL;如果没有被删除,句柄TaskLED1Handle的值就不会为NULL。这也是为什么我们按下KEY1就可以不断地通过判断句柄的状态来实现任务的创建于删除,KEY2的操作同理。下面是程序烧录完毕后,连接串口助手按下KEY1,KEY2的情况。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/253974.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

camera曝光时间

曝光和传感器读数 相机上的图像采集过程由两个不同的部分组成。第一部分是曝光。曝光完成后,第二步就是从传感器的寄存器中读取数据并传输(readout)。 曝光:曝光是图像传感器进行感光的一个过程,相机曝光时间&#xf…

JWT令牌的作用和生成

JWT令牌(JSON Web Token)是一种用于身份验证和授权的安全令牌。它由三部分组成:头部、载荷和签名。 JWT令牌的作用如下: 身份验证:JWT令牌可以验证用户身份。当用户登录后,服务器会生成一个JWT令牌并返回…

Python实验项目9 :网络爬虫与自动化

实验 1:爬取网页中的数据。 要求:使用 urllib 库和 requests 库分别爬取 http://www.sohu.com 首页的前 360 个字节的数据。 # 要求:使用 urllib 库和 requests 库分别爬取 http://www.sohu.com 首页的前 360 个字节的数据。 import urllib.r…

当心字符串连接的性能

在Java中,字符串连接的性能问题同样需要注意,尤其是在循环中进行大量连接操作时。Java中的字符串是不可变的,因此每次连接字符串都会产生一个新的字符串对象,可能导致性能下降。以下是一些示例,演示了不同方法的字符串…

YOLOv5改进 | SPPF篇 | FocalModulation替换SPPF(精度更高的空间金字塔池化)

一、本文介绍 本文给大家带来的改进是用FocalModulation技术来替换了原有的SPPF(快速空间金字塔池化)模块。FocalModulation是今年新提出的特征增强方法,它利用注意力机制来聚焦于图像中的关键区域,从而提高模型对这些区域的识别…

什么是缓存击穿、缓存穿透、缓存雪崩?

🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞…

在计算机专业中,应该把学习的重点放在哪里?

在计算机专业中,应该把学习的重点放在哪里?这是许多计算机专业学生常常面临的关键问题。随着计算机科技的快速发展,学生们往往陷入了各种各样的选择和困惑中。是将时间投入到深奥的数学领域,还是专注于编程技能的磨练?…

0x17 二叉堆

0x17 二叉堆 二叉堆是一种支持插入、删除、查询最值的数据结构。它其实是一种满足“堆性质”的完全二叉树,树上的每一个节点带有一个权值。若树中的任意一个节点的权值都小于等于其父节点的权值,则称该二叉树满足“大根堆性质”,称其为“大根…

微信小程序:布局样式

效果 wxml <view class"layout"><view class"left"><view>1</view><view>1</view><view>1</view><view>1</view><view>1</view></view><view class"right"&…

2023 亚马逊云科技 re:Invent 大会探秘:Aurora 无限数据库的突破性应用

文章目录 一、前言二、Amazon Aurora 无限数据库2.1 亚马逊云科技数据库产品发展历程2.2 什么是 Amazon Aurora Limitless Database&#xff08;无限数据库&#xff09;2.3 Amazon Aurora Limitless Database 设计架构2.4 Amazon Aurora Limitless Database 分片功能2.5 使用 A…

c语言:判断是否为整数|练习题

一、题目 输入一个数字&#xff0c;判断该数字是否为整数 如图&#xff1a; 二、思路分析 1、没有小数部分的数字&#xff0c;即为整数。所以&#xff0c;只要知道该数字是否有小数部分&#xff0c;即可。 2、例子&#xff1a;1.5减去10.5&#xff0c;由于有小数部分&#xff0…

跟着官网学 Vue - 插槽

Vue 插槽是一种强大的组件通信方式。 插槽内容与出口 在 Vue 中&#xff0c;插槽是一种让父组件向子组件传递内容的方式。子组件使用 <slot> 元素作为插槽出口&#xff0c;父组件可以通过插槽内容填充这些空白区域。 示例&#xff1a; <!-- MyButton.vue --> &…

解决“bat中文路径乱码“问题

今天&#xff0c;在使用.bat脚本&#xff0c;将hello.png从"D:\mypic\备份"目录&#xff0c;拷贝到"D:\mypic\备份"时&#xff1b;发现中文乱码,弹出如下对话框: 图(1) bat中文路径乱码 原来的命令是&#xff1a; copy D:\mypic\one\hello.png D:\mypic\备…

PIG框架学习1——密码模式登录认证获取Token流程

文章目录 O、前言一、总流程概括&#xff1a;二、具体流程分析PIG提供的具体流程图&#xff1a;鉴权请求报文示例0、网关前置处理1、客户端认证处理2、正式接受登录请求3、组装认证对象4、认证管理器进行认证&#xff08;授权认证调用&#xff09;5、认证成功处理器 O、前言 对…

读取小数部分

1.题目描述 2.题目分析 //假设字符串为 char arr[] "123.4500"; 1. 找到小数点位置和末尾位置 代码如下&#xff1a; char* start strchr(arr, .);//找到小数点位置char* end start strlen(start) - 1;//找到末尾位置 如果有不知道strchr()用法的同学&#xf…

Yapi详细安装过程(亲测可用)

1. 前置条件 1、Git 2、NodeJs&#xff08;7.6&#xff09; 3、Mongodb&#xff08;2.6&#xff09; 2. NodeJs的安装 1、获取资源 curl -sL https://rpm.nodesource.com/setup_8.x | bash - 2、安装NodeJS yum install -y nodejs 3、查看NodeJs和Npm node -v npm -v…

[AI工具推荐]AiRestful智能API代码生成

智能API代码示例生成工具AiRestful 一、产品介绍二、如何使用1、第一步(必须):2、第二步(可选):3、第三步(智能生成): 三、如何集成到您的网站(应用)1、开始接入2、接入案例 四、注意点 一、产品介绍 AiRestful是一款基于智能AI的,帮助小白快速生成任意编程语言的API接口调用示…

centos7安装node-v18版本

背景# 背景就是上一篇文章提到的&#xff0c;部署gitbook这个文档中心的话&#xff0c;是需要先安装node&#xff0c;然后&#xff0c;如果你的node版本过高的话&#xff0c;一般会报错&#xff0c;此时&#xff0c;网上很多文章就是降node版本解决&#xff0c;但其实用高版本…

如何做搜索?如何做搜索优化?如何在搜索领域快速成长?

三年多的搜索研发经历&#xff0c;万亿级集群管理经历&#xff0c;集群优化搜索优化经历。将生产环境的集群&#xff0c;检索性能提升了数十倍。也遇到过大大小小的生产事故。在工作中有幸能够得到前谷歌中国首席架构陈老师的指导。在搜索方面&#xff0c;自己也积累了蛮多的经…

最具挑战的骑行路线

1&#xff0c;318川藏线 2&#xff0c;独库公路 - 561公里 3&#xff0c;珠峰尼泊尔 1000公里 4&#xff0c;沙漠公路 1800公里 5&#xff0c;219新藏线 2500公里 下面是一些别人的骑行记录、证书或奖牌。 参考&#xff1a; 1&#xff0c;抖音 - Max骑行玩家 https://v.douy…