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的情况。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

neuq-acm预备队训练week 10 P1525 [NOIP2010 提高组] 关押罪犯

解题思路 本题用并查集的方法 AC代码 #include <bits/stdc.h> using namespace std; int f[55555]; struct S {int a,b,c;friend inline bool operator<(S a, S b){return a.c>b.c;} } d[100000];int find(int x) {return f[x]x? x:(f[x]find(f[x])); }int mai…

关于“Python”的核心知识点整理大全24

目录 ​编辑 10.1.6 包含一百万位的大型文件 pi_string.py 10.1.7 圆周率值中包含你的生日吗 10.2 写入文件 10.2.1 写入空文件 write_message.py programming.txt 10.2.2 写入多行 10.2.3 附加到文件 write_message.py programming.txt 10.3 异常 10.3.1 处理 Ze…

轻量封装WebGPU渲染系统示例<51>- 视差贴图(Parallax Map)(源码)

视差纹理是一种片段着色阶段增强材质表面凹凸细节的技术。 当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sample/ParallaxTexTest.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如…

自动驾驶学习笔记(二十)——Planning算法

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo 社区开发者圆桌会》免费报名—>传送门 文章目录 前言 参考线平滑 双层状态机 EM Planner …

2023年OceanBase开发者大会-核心PPT资料下载

一、峰会简介 2023年OceanBase开发者大会主要涵盖了OceanBase的最新技术进展、产品更新以及开发者工具的发布。大会发布了OceanBase 4.1版本&#xff0c;公布了两大友好工具&#xff0c;升级了文档的易用性&#xff0c;并统一了企业版和社区版的代码分支。这些举措全面呈现了O…

数据结构-猴子吃桃问题

一、需求分析 有一群猴子摘了一堆桃子&#xff0c;他们每天都吃当前桃子的一半且再多吃一个&#xff0c;到了第10天就只余下一个桃子。用多种方法实现求出原来这群猴子共摘了多少个桃子。要求&#xff1a; 1)采用数组数据结构实现上述求解&#xff1b; 2)采用链数据结构实现上述…

java --- 异常

目录 一、异常体系介绍 二、异常的作用 三、异常处理方式 3.1 捕获异常 2.1 灵魂一问&#xff1a; 如果try中没有遇到问题&#xff0c;如何执行&#xff1f; 2.2 灵魂二问&#xff1a;如果try中可能会遇到多个问题&#xff0c;怎么执行&#xff1f; 2.3 灵魂三问&#x…

08 v-text指令

概述 v-text指令主要是用来渲染文本内容&#xff0c;和双大括号的效果基本一致&#xff0c;所以使用场景非常少。 一般情况下&#xff0c;我们都会使用双大括号语法去渲染文本内容&#xff0c;而不是使用v-text指令。 基本用法 我们创建src/components/Demo08.vue&#xff…

RocketMQ源码 Broker-PullRequestHoldService 长轮询消息拉取组件源码分析

前言 PullRequestHoldService 继承了ServiceThread类&#xff0c;它本身是一个线程&#xff0c;以后台方式无线循环运行&#xff0c;支持长轮询&#xff08;默认5秒&#xff09;和短轮询&#xff08;默认1秒&#xff09;两种方式&#xff08;CountDownlatch 方式控制&#xff…

安卓端出现https请求失败(转)

背景# 某天早上&#xff0c;正在一个会议时&#xff0c;突然好几个同事被叫出去了&#xff1b;后面才知道&#xff0c;是有业务同事反馈到领导那里&#xff0c;我们app里面某个功能异常。 具体是这样&#xff0c;我们安卓版本的app是禁止截屏的&#xff08;应该是app里做了拦…

Oracle-应用会话集中在RAC集群一个节点问题

问题&#xff1a; 用户一套Oracle19c RAC集群&#xff0c;出现一个奇怪的现象&#xff0c;通过SCAN IP访问的连接会话都集中在节点一实例&#xff0c;而且用户并没有做任何的节点服务访问去控制会话的连接节点&#xff0c;比如常见的通过集群的高可用服务去控制应用访问连接集中…

【BIG_FG_CSDN】*VMware17pro*Linux*Redhit6网络管理(个人向——学习笔记)

物理机中的网络 查看物理网络的方法 “网络连接”—>单点选中网络的选项-->菜单栏中“查看此连接状态”-->“详细信息” “网络连接”中的VM网卡 在主机上对应的有VMware Network Adapter VMnet1和VMware Network Adapter VMnet8两块虚拟网卡&#xff0c;它们分别…