【FreeRTOS】任务状态改进播放控制

这里写目录标题

  • 1 任务状态
    • 1.1 阻塞状态(Blocked)
    • 1.2 暂停状态(Suspended)
    • 1.3 就绪状态(Ready)
    • 1.4 完整的状态转换图
  • 2 举个例子
  • 3 编写代码


在这里插入图片描述

参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》

本节课实现音乐任务的创建,音乐播放的暂停与继续播放,删除任务。

代码为:08_task_priority

重点:使用链表讲解内部原理。

  • 任务状态:09_task_suspend,添加音乐暂停/恢复功能
  • 优先级、链表管理
  • 任务切换、tick

1 任务状态

以前我们很简单地把任务的状态分为两种:运行(Runing)、非运行(Not Running)。 对于非运行的状态,还可以继续细分,比如前面的FreeRTOS_04_task_priority中:

  • Task3执行vTaskDelay后:处于非运行状态,要过3秒种才能再次运行
  • Task3运行期间,Task1、Task2也处于非运行状态,但是它们随时可以运行
  • 这两种"非运行"状态就不一样,可以细分为:
  • 阻塞状态(Blocked)
  • 暂停状态(Suspended)
  • 就绪状态(Ready)

1.1 阻塞状态(Blocked)

在日常生活的例子中,母亲在电脑前跟同事沟通时,如果同事一直没回复,那么母亲的工作就被卡住了、被堵住了、处于阻塞状态(Blocked)。重点在于:母亲在等待。

在FreeRTOS_04_task_priority实验中,如果把任务3中的vTaskDelay调用注释掉,那么任务1、任务2根本没有执行的机会,任务1、任务2被"饿死"了(starve)。

在实际产品中,我们不会让一个任务一直运行,而是使用"事件驱动"的方法让它运行:

  • 任务要等待某个事件,事件发生后它才能运行
  • 在等待事件过程中,它不消耗CPU资源
  • 在等待事件的过程中,这个任务就处于阻塞状态(Blocked)

在阻塞状态的任务,它可以等待两种类型的事件:

  • 时间相关的事件
    • 可以等待一段时间:我等2分钟
    • 也可以一直等待,直到某个绝对时间:我等到下午3点
  • 同步事件:这事件由别的任务,或者是中断程序产生
    • 例子1:任务A等待任务B给它发送数据
    • 例子2:任务A等待用户按下按键
    • 同步事件的来源有很多(这些概念在后面会细讲):
      • 队列(queue)
      • 二进制信号量(binary semaphores)
      • 计数信号量(counting semaphores)
      • 互斥量(mutexes)
      • 递归互斥量、递归锁(recursive mutexes)
      • 事件组(event groups)
      • 任务通知(task notifications)

在等待一个同步事件时,可以加上超时时间。比如等待队里数据,超时时间设为10ms:

  • 10ms之内有数据到来:成功返回
  • 10ms到了,还是没有数据:超时返回

1.2 暂停状态(Suspended)

在日常生活的例子中,母亲正在电脑前跟同事沟通,母亲可以暂停:

  • 好烦啊,我暂停一会
  • 领导说:你暂停一下

FreeRTOS中的任务也可以进入暂停状态,唯一的方法是通过vTaskSuspend函数。函数原型如下:

void vTaskSuspend( TaskHandle_t xTaskToSuspend );

参数xTaskToSuspend表示要暂停的任务,如果为NULL,表示暂停自己。

要退出暂停状态,只能由别人来操作:

  • 别的任务调用:vTaskResume
  • 中断程序调用:xTaskResumeFromISR

实际开发中,暂停状态用得不多。

1.3 就绪状态(Ready)

这个任务完全准备好了,随时可以运行:只是还轮不到它。这时,它就处于就绪态(Ready)。

1.4 完整的状态转换图

完整的状态转换图如下:

在这里插入图片描述


2 举个例子

任务的状态:Ready状态(就绪)和 Running状态(运行)

在这里插入图片描述

现在给小孩喂饭,这个就处于Running状态,回复信息就处于Ready状态,随时可以切换过去
当回复信息时候,这个就处于Running状态,给小孩喂饭就处于Ready状态

Ready状态随时有机会切换为Running状态,只要有机会运行,就称为Running状态,当Running状态被调度出去后,就成了Ready状态

还有其他状态,Blocked(被阻塞,在等待某些event事件),suspend(暂停状态,单纯的不想干活,就只想休息)

在这里插入图片描述
创建播放音乐的任务,这个任务创建好后,就处于Ready状态,这个任务的优先级最高,能运行的时候,它就处于Running状态,当调用vTaskDelay的时候,就处于Blocked状态(等待某些事件)

在这里插入图片描述
当时间到了,就会被唤醒,就变成Ready就绪状态,当能运行的时候,就变成Running状态

suspend暂停状态只能调用vTaskSuspend函数进入

  • 可以自己调用vTaskSuspend进入,也可以别人调用vTaskSuspend函数
    在这里插入图片描述

3 编写代码

编写代码实现功能:第一次按下播放按键,创建音乐播放任务,再次按下播放按键,暂停音乐播放,再次按下播放按键,恢复音乐播放,按power按键,删除音乐播放任务

工程:09_task_suspend

在默认任务里修改代码,如下:

/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
    
    uint8_t dev, data;
    int len;
    uint8_t status;     //状态变量
    uint8_t bRunning;   //是不是正在运行
    
    BaseType_t ret; // long
    TaskHandle_t xSoundTaskHandle = NULL;           // 句柄 初始值是NULL	  
    
    LCD_Init();
    LCD_Clear();

    IRReceiver_Init();
    LCD_PrintString(0, 0, "Waiting Control");

    while (1)   // 在屏幕上输出接收到的键值
    {
        
        /* 读取红外遥控器 */
        if (0 == IRReceiver_Read(&dev, &data))
        {
            if (data == 0x22)   /*play*/
            {
                /* 创建播放音乐的任务 */
                //这里需要判断是否多次按下播放按键,判断句柄是否等于NULL
                if (xSoundTaskHandle == NULL)   /* 句柄等于NULL,才来创建这个任务 */
                {
                    LCD_ClearLine(0, 0);    //清屏
                    LCD_PrintString(0, 0, "Create Task");
                    ret = xTaskCreate(PlayMusic, "SoundTask", 128, NULL, osPriorityNormal+1, &xSoundTaskHandle);
                    bRunning = 1;   //正在运行。等于1
                }
                else
                {
                    /* 要么suspend,要么resume恢复它 */
                    if (bRunning)   //如果bRunning == 1
                    {
                        LCD_ClearLine(0, 0);    //清屏
                        LCD_PrintString(0, 0, "Suspend Task");
                        vTaskSuspend(xSoundTaskHandle);     // 如果任务正在运行,就将任务切换成suspend状态
                        PassiveBuzzer_Control(0);           // Stop Buzzer 停止蜂鸣器,清除噪音
                        bRunning = 0;
                    }
                    else
                    {
                        LCD_ClearLine(0, 0);    //清屏
                        LCD_PrintString(0, 0, "Resume Task");
                        vTaskResume(xSoundTaskHandle);     // 如果任务Suspend,就将任务vTaskResume,恢复
                        bRunning = 1;
                    }
                }
            }
            else if (data == 0xA2)
            {
                /* 删除播放音乐的任务 */
                if (xSoundTaskHandle != NULL)   //如果这个句柄xSoundTaskHandle != NULL,才会删除
                {
                    LCD_ClearLine(0, 0);    //清屏
                    LCD_PrintString(0, 0, "Delete Task");
                    vTaskDelete(xSoundTaskHandle);
                    PassiveBuzzer_Control(0);   // Stop Buzzer 停止蜂鸣器
                    xSoundTaskHandle = NULL;    //删除完成,赋值NULL
                }
            }
            len = LCD_PrintString(0, 6, "Key name: ");
            LCD_PrintString(len, 6, IRReceiver_CodeToString(data));
        }
    }

  /* USER CODE END StartDefaultTask */
}

在这里插入图片描述

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

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

相关文章

java泛型学习

没有java泛型会存在的问题 假设我们有一个方法,希望通过传递不同类型的参数,输出不同类型的对象值。正常情况下我们可能会写不同的方法来实现,但是这样会导致类不断增加,并且类方法很相似,不能够复用。进而导致类爆炸…

C#实现音乐在线播放和下载——Windows程序设计作业3

1. 作业内容 编写一个C#程序,在作业二实现的本地播放功能的基础上,新增在线播放和在线下载功能,作业二博客地址:C#实现简单音乐文件解析播放——Windows程序设计作业2 2. 架构选择 考虑到需求中的界面友好和跨版本兼容性&#xf…

网站监控定时计划任务

网站监控是一种保护网站安全和稳定性的重要手段,而定时计划任务则是网站监控的一种常见方法。通过设置定时计划任务,可以定期对网站进行监测和检测,及时发现并解决潜在的问题,从而保障网站的正常运行。 首先,网站监控定…

AI播客下载:Eye on AI(AI深度洞察)

"Eye on A.I." 是一档双周播客节目,由长期担任《纽约时报》记者的 Craig S. Smith 主持。在每一集中,Craig 都会与在人工智能领域产生影响的人们交谈。该播客的目的是将渐进的进步置于更广阔的背景中,并考虑发展中的技术的全球影响…

MySQL的自增 ID 用完了,怎么办?

MySQL 自增 ID 一般用的数据类型是 INT 或 BIGINT,正常情况下这两种类型可以满足大多数应用的需求。 当然也有不正常的情况,当达到其最大值时,尝试插入新的记录会导致错误,错误信息类似于: ERROR 167 (22003): Out o…

【深度学习驱动流体力学】计算流体力学openfoam-paraview与python3交互

目的1:配置 ParaView 中的 Python Shell 和 Python 交互环境 ParaView 提供了强大的 Python 接口,允许用户通过 Python 脚本来控制和操作其可视化功能。在 ParaView 中,可以通过 View > Python Shell 菜单打开 Python Shell 窗口,用于执行 Python 代码。要确保正确配置 …

Mkdocs中文系列教程补充(1)

什么是requirements.txt 我的理解是mkdocs依赖的py库 第一次建立MKdocs文档使用 mkdocs new . 完后,比较建议执行一下: pip install -r requirements.txt 不然mkdocs serve后会出现什么 xxx not found ,比如下面这位老哥 示例 mkdocs …

【大数据】—量化交易实战案例(基础策略)

声明:股市有风险,投资需谨慎!本人没有系统学过金融知识,对股票有敬畏之心没有踏入其大门,所以只能写本文来模拟炒股。 量化交易,也被称为算法交易,是一种使用数学模型和计算机算法来分析市场数…

骑马与砍杀战团mod制作-基础-军队笔记(一)

骑马与砍杀战团mod制作-基础-军队装备笔记(一) 资料来源 学习的资料来源: b站【三啸解说】手把手教你做【骑砍】MOD,基础篇,链接为: https://www.bilibili.com/video/BV19x411Q7No?p4&vd_sourcea507…

设施布置之车间布局优化SLP分析

一 物流分析(Flow Analysis) 的基本方法 1、当物料移动是工艺过程的主要部分时,物流分析就是工厂布置设计的核心工作,也是物料搬运分析的开始。 2、零部件物流是该部件在工厂内移动时所走过的路线, 物流分析不仅要考虑…

Python18 数据结构与数据类型转换

1.python中的数据结构 在Python中,数据结构是用来存储、组织和管理数据的方式,以便有效地执行各种数据操作。Python提供了几种内置的数据结构,每种都有其特定的用途和操作方法。以下是Python中一些主要的数据结构: 1.列表&#…

Linux下Cmake安装或版本更新

下载Cmake源码 https://cmake.org/download/ 找到对应的版本和类型 放进linux环境解压 编译 安装 tar -vxvf cmake-3.13.0.tar.gz cd cmake-3.13.0 ./bootstrap make make install设置环境变量 vi ~/.bashrc在文件尾加入 export PATH/your_path/cmake-3.13.0/bin:$PAT…

css-vxe列表中ant进度条与百分比

1.vxe列表 ant进度条 <vxe-column field"actualProgress" title"进度" align"center" width"200"><template #default"{ row }"><a-progress:percent"Math.floor(row.actualProgress)"size"s…

KEIL5软件仿真观察PIN脚电平(软件仿真逻辑分析仪的使用)

仿真前的调整&#xff1a; 例&#xff1a;STM32F103C8T6 &#xff08;如果是F4的板子稍微对着修改一下&#xff09; 逻辑分析仪的使用 输入 PORTA.6( PORAT(哪一组).(哪一个引脚) )

【MySQL】

基础篇 执行一条 select 语句,期间发生了什么? 大家好,我是小林。 学习 SQL 的时候,大家肯定第一个先学到的就是 select 查询语句了,比如下面这句查询语句: // 在 product 表中,查询 id = 1 的记录 select * from product where id = 1;但是有没有想过,MySQL 执行一…

SARscape——均值滤波

目录 一、算法原理1、概述2、参考文献 二、软件操作三、结果展示1、原始图像2、滤波结果 一、算法原理 1、概述 均值滤波是选定一个合适的邻域窗口&#xff0c;然后取每个像素邻域窗口内的像素平均值&#xff0c;最后用均值取代待滤波的像素值作为最终的输出值。这种滤波比较简…

嵌入式linux系统中LCD屏驱动实现思路分析

在 Linux 下 LCD 的使用更加广泛,在搭配 QT 这样的 GUI 库下可以制作出非常精美的 UI 界面。接下来就来学习一下如何在 Linux 下驱动 LCD 屏幕。 第一:Framebuffer设备简介 先来回顾一下裸机的时候 LCD 驱动是怎么编写的,裸机 LCD 驱动编写流程如下: ①、初始化 I.MX6U 的…

【漏洞复现】Rejetto HTTP File Server 远程代码执行漏洞 (CVE-2024-23692)

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

【windows|008】DNS服务详解

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…