FreeRTOS如何结束和重新启动调度程序

2023-05-16

大多数主机或桌面系统(比如Linux,Mac或Windows)都有一个正常的用例,你可以在早上启动操作系统,然后在晚上关闭它,然后你就离开机器。嵌入式系统是不同的:他们没有参加,他们应该“永远”运行。并非每个嵌入式系统都需要运行操作系统(或者在那个世界中:实时操作系统或RTOS),但这同样适用于:在RTOS启动后,并不意味着它将关闭并重新启动。在某种程度上,他们根本不支持“关闭”和“重启”功能。如果收集覆盖率信息,这将非常有用:

                                                                        来自FreeRTOS应用程序的覆盖信息

对于FreeRTOS:如果我真的需要关闭RTOS并重新启动它会怎么样,因为默认情况下不支持。这就是本文的内容......

介绍

嵌入式系统与桌面系统根本不同:虽然不时关闭和重新启动台式机或笔记本电脑系统是正常的,但这不是计划或打算用于嵌入式系统:本质上它应该“始终”运行。从嵌入式系统的“主要”进一步可以看出这一点:通常主要永远不会返回并保持运行,如下所示:

void main(void) {

  InitClocks();

  InitPins();

  InitDrivers();

  for(;;) {

    AppRun();

  }

  /* 从未离开主程序 */

}

如果使用RTOS运行,类似的东西适用于嵌入式系统,其中看起来类似于:

void main(void) {

  InitClocks();

  InitPins();

  InitDrivers();

  CreateInitialTasks();

  StartScheduler();

  /* 调度程序永远不会终止,所以不应该到达这里 */

  for(;;) { }

  /* 从未离开主程序 */

}

为什么关机并重启?

显然,对于嵌入式RTOS而言,RTOS关闭或重启的需求可能不是最需要的。我仍然发现它非常有用:

  • 在RTOS关闭后运行某些软件*是有意义的。例如,如果我收集覆盖率信息(请参阅“ 向Eclipse添加GNU覆盖工具 ”和“ 使用Eclipse Neon和ARM gcc 5在嵌入式目标上实现GNU代码覆盖率 ”),我不希望干扰最后一个进程以转储数据RTOS。另外,我需要独占访问系统资源,包括大量的堆栈空间:关闭RTOS可以让我恢复文件I / O操作所需的所有RAM和堆栈空间。

                                                                             在调度程序关闭后写入gcov覆盖信息

  • 在监听更新时运行RTOS是有意义的。在某些情况下,在执行更新时运行RTOS肯定是可能的,但在某些阶段我必须停止并重新启动它。这可以通过重置和重新启动系统来完成(例如,请参阅“ 如何使用软件重置ARM Cortex-M ”)。我发现它是关闭RTOS的更好方法,然后在RTOS之外进行更新并重启系统。

                                                                      从任务结束FreeRTOS调度程序

  • 另一个用例是低功耗应用。虽然FreeRTOS在低功耗模式下也很出色(参见“ 使用FreeRTOS实现低功耗:无空闲模式 ”),但如果可以关闭更多活动系统,应用程序甚至可以进入功耗更低的低功耗模式。因此,只有在我的应用程序的使用寿命期间才能运行RTOS才能有意义,而不是在其他部分运行RTOS,这为我提供了更大的灵活性和更低功耗的机会。

                                                              vTaskStartScheduler()后跟低功耗模式

所以我希望你明白为什么RTOS的关闭和重启是有意义的。包括FreeRTOS在内的大多数RTOS都能够“静音”调度程序(例如vTaskSuspendAll()),但仍然存在RTOS并使用系统资源。但是,如果需要,完全“删除”并重新启动它的能力将是很酷的事情。

FreeRTOS

FreeRTOS确实有一个调度程序启动函数(vTaskStartScheduler()),甚至在其API中有一个vTaskEndScheduler()函数:

                                                  FreeRTOS vTaskEndScheduler()API函数

但正如论坛和API描述中所述,它仅支持PC端口(请参阅API说明):“ 注意:这仅适用于x86实模式PC端口。“

原来的FreeRTOS端口也是如此。我扩展的端口确实支持这个,我在ARM Cortex-M和HCS08应用程序中使用它:-)。

vTaskEndScheduler()和vTaskStartScheduler()

虽然RTOS已准备好将其关闭的API调用,但FreeRTOS在调用vTaskEndScheduler()之后没有适当的基础结构来重新启动RTOS。但这正是我想要的:在结束后重启RTOS。

要能够结束调度程序,必须在FreeRTOSConfig.h中将以下宏设置为1:

#define INCLUDE_vTaskEndScheduler                 1

挑战在于:在调度程序启动之后,在vTaskStartScheduler()调用之后立即返回代码并不容易。因为具有自己的堆栈的任务,加上FreeRTOS和M3的标准端口,M4和M7甚至会重置MSP堆栈指针(参见本论坛讨论)。因此,如果我想返回调度程序已启动的位置,我需要阻止重置ARM Cortex上的MSP堆栈指针。这就是我为FreeRTOS添加一个设置来配置它的原因:

                                                                                             重置MSP设置

这将设置以下配置:

#ifndef configRESET_MSP

  #define configRESET_MSP                         (0)

   /*!< 1: reset MSP at scheduler start (Cortex M3/M4/M7 only); 0: do not reset MSP */

#endif

将此设置设置为0,我的端口在调度程序起始点执行*不*重置MSP。

                                                                            端口代码重置msp堆栈指针

这意味着并非完整的MSP堆栈可用于中断(参见“ ARM Cortex-M中断和FreeRTOS:第3部分 ”),但这通常也可以。

为了能够跳回到调度程序的起点,我使用了C库的一个很酷的功能:setjmp / longjmp(参见http://web.eecs.utk.edu/~huangj/cs360/360/notes/ Setjmp / lecture.html)。

首先,我需要一个跳转缓冲区变量:

#if INCLUDE_vTaskEndScheduler

#include <setjmp.h>

static jmp_buf xJumpBuf; /* Used to restore the original context when the scheduler is ended. */

#endif

在xPortStartScheduler()里面我设置了跳转缓冲区:

#if INCLUDE_vTaskEndScheduler

    if(setjmp(xJumpBuf) != 0 ) {

      /* here we will get in case of a call to vTaskEndScheduler() */

      __asm volatile(

        " movs r0, #0         \n" /* Reset CONTROL register and switch back to the MSP stack. */

        " msr CONTROL, r0     \n"

        " dsb                 \n"

        " isb                 \n"

      );

      return pdFALSE;

    }

#endif

  vPortStartFirstTask(); /* Start the first task. */

  /* Should not get here! */

  return pdFALSE;

如果建立跳转缓冲区,setjmp()返回0,并且在调用setjmp()的情况下返回!= 0将在vTaskEndScheduler()期间调用。

void vTaskEndScheduler( void )

{

  /* Stop the scheduler interrupts and call the portable scheduler end

     routine so the original ISRs can be restored if necessary.  The port

     layer must ensure interrupts enable bit is left in the correct state. */

  portDISABLE_INTERRUPTS();

  xSchedulerRunning = pdFALSE;

  vPortEndScheduler();

}

然后,vPortEndscheduler()执行RTOS的所有清理和重置。重置要求不会造成调试器对任何RTOS认知的混淆:

void vPortEndScheduler(void) {

  vPortStopTickTimer();

  vPortInitializeHeap();

  uxCriticalNesting = 0xaaaaaaaa;

  /* Jump back to the processor state prior to starting the

     scheduler.  This means we are not going to be using a

     task stack frame so the task can be deleted. */

#if INCLUDE_vTaskEndScheduler

  longjmp(xJumpBuf, 1);

#else

  for(;;){} /* wait here */

#endif

}

有了这个,调度程序优雅地终止,我又回到了主堆栈上:

                                                                      在调用vTaskEndScheduler()之后在msp堆栈上

摘要

默认情况下,对于嵌入式目标,FreeRTOS不支持结束调度程序或在结束后重新启动调度程序。本文描述了ARM Cortex-M的一个端口,它实现了vTaskEndScheduler(),并能够在没有上电复位的情况下再次调用vTaskStartScheduler()。结束和启动调度程序对于低功耗应用程序非常有用,在应用程序的实时循环或引导加载程序应用程序中不需要RTOS的情况。该概念用于恩智浦的不同ARM Cortex-M内核,包括8/16位S08微控制器,但可以轻松用于任何其他微控制器架构。

参考链接

  1. 本文讨论的McuOnEclipse FreeRTOS端口:https//github.com/ErichStyger/McuOnEclipseLibrary/tree/master/lib/FreeRTOS
  2. 使用NXP MCUXpresso IDE在GitHub上使用gcov的示例项目:https//github.com/ErichStyger/mcuoneclipse/tree/master/Examples/MCUXpresso/FRDM-K64F/FRDM-K64F_gcov
  3. FreeRTOS网页:https//www.freertos.org/
  4. FreeRTOS vTaskEndScheduler API:https://www.freertos.org/a00133.html
  5. 关于FreeRTOS和MSP的恩智浦社区讨论:https//community.nxp.com/thread/493367
  6. 有关setjmp / longjmp的维基百科:https//en.wikipedia.org/wiki/Setjmp.h
  7. 关于ARM Cortex-M中断的教程系列:ARM Cortex-M,中断和FreeRTOS:第1部分
  8. MCUXpresso IDE v10.3.0:新的恩智浦MCUXpresso IDE V10.3.0版本

 

声明:本文为翻译文章,原文作者是:Erich Styger,原文址为:https://mcuoneclipse.com/2019/01/20/freertos-how-to-end-and-restart-the-scheduler/

欢迎关注:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS如何结束和重新启动调度程序 的相关文章

  • SQL语言

    1 什么是SQL SQL structured query language xff1a 结构化查询语言 SQL是一种对关系型数据库中的数据进行定义和操作的语言 SQL语言简洁 xff0c 语法简单 xff0c 好学好用 什么是SQL语句
  • 实测:Ubuntu16.04 ROS中实现RVIZ控制驱动UR10E机械臂!

    踩过了太多的坑 xff0c 此博客警醒自己 xff01 能用的收藏一下 一 演示一切之前 xff0c 要清楚两个问题 xff1a 1 你的UR是什么型号 xff0c 示教器软件版本是什么 xff1f xff08 这个不会看的话 xff0c
  • STM32CubeMX安装及使用教程(一)

    背景 随着芯片行业不断发展 xff0c STM32系列芯片不断扩大市场份额 为了方便开发者的不同需求 xff0c 意法半导体 xff08 ST xff09 推出了一款图形化配置工具 STM32CubeMX STM32CubeMX可以通过图形
  • STM32CubeMX安装及使用教程(二)

    背景 第一章我们讲述了如何安装和配置STM32CubeMX软件 xff0c 这一章我们来说说如何简单的使用STM32CubeMX软件 软件使用 1 打开STM32CubeMX软件 xff0c 点击File gt New Project 2
  • xshell无法连接虚拟机中的ubuntu解决方案

    xshell无法连接虚拟机中的ubuntu解决方案 查看虚拟机中ubuntu的IP地址的方法 ifconfig a 利用xshell工具进行远程连接 ssh IP地址 发现无法连接 xff0c 这就是我一开始将VM安装好 xff0c 一次性
  • 气压计融合定高控制逻辑

  • Git简介

    什么是版本控制 学习Git之前首先要了解一个概念 版本控制 xff0c 什么是版本控制 xff0c 版本控制就是一种在开发的过程中用于管理我们对文件 目录或工程等内容的修改历史 xff0c 方便查看更改历史记录 xff0c 备份以便恢复以前
  • Git图形化管理工具Sourcetree的使用及git冲突问题

    目录 一 了解 Sourcetree1 什么是Sourcetree2 为什么要使用Sourcetree 二 Sourcetree下载与安装1 下载2 安装 三 Sourcetree的使用1 Gitee的介绍与使用什么是GiteeGitee的
  • [智能车]平衡车/直立车的入门经验(代码讲解)

    做为第十六届智能车的FW 在半年的做车经历中把能踩的坑都踩了个遍 写这篇文章是为了留个纪念 xff0c 也是为了帮新车友快速入门 xff08 可能完全0基础 xff09 我自己的经验也不足 xff0c 所以可能会存在一些漏洞 xff0c 还
  • Mac系统 dockerfile 报错 COPY failed: stat /var/lib/docker/tmp/docker-builderxxx

    报错 xff1a Step 3 4 span class token keyword span COPY nginx 1 12 2 tar gz usr local src COPY failed span class token func
  • VS code的git设置

    先建立一个空文件夹 在git窗口先点 初始化仓库 xff0c 再点侧边栏右上角的 更多 xff0c 选 远程 下的 添加远程存储仓库 输入远程仓库地址 xff0c 再输入仓库名称 打开 源代码管理存储库 视图 xff0c 点上面的git分支
  • L4Linux的版本比较

  • 利用XML文件的一个写日志的类!!!!!

    对于程序执行期间的错误跟踪 xff01 相信大家都有自己的一套办法 xff01 xff01 xff01 但都是利用文件文件 xff0c 我这次利用的是XML amp XSL xff0c 可产生报表格式的日志 轻松生成报表 xff01 xff
  • 【Kubernetes实战】(四)MiniKube方式部署

    目录 一 当前配置环境 二 准备工作 1 关闭防火墙和SeLinux 2 禁用swap交换分区 三 Docker安装 1 配置docker源 2 安装docker环境依赖 3 安装docker 4 启动docker并设置为开机自启 5 配置
  • DGPS与RTK的区别

    2013 10 11 10 49 11 分类 xff1a GNSS 举报 字号 订阅 最近一直感觉身在这个行业不能对这个行业理论知识一无所知 xff0c 这对于技术人来说应该是一种遗憾 所以决定要学一些东西 xff0c 并记录下来以便于以后
  • 基于Ubuntu19.04安装docker

    输入命令 lsb release a 显示如下 Distributor ID Ubuntu 类别是ubuntu Description Ubuntu 19 04 16年3月发布的稳定版本 xff0c LTS是Long Release 19
  • PHP获取当月开始时间和结束时间

    startTime 61 date 39 Y m 01 39 time 获取该月份的第一天 endTime 61 date 39 Y m t 39 time 获取该月份的最后一天
  • CSS3实现动态进度条

    CSS3的线性渐变使制造动态进度条成为可能 现在就来一步一步讲解如何创建动态进度条吧 以Chrome浏览器webkit内核为例 目标 xff1a 单个矩形条背景 目标进度条 xff0c 背景是淡蓝色 xff0c 上面平铺了一层倾斜的深蓝色条
  • C语言-阶乘数列

    求Sn 61 1 43 2 43 3 43 4 43 5 43 43 n 之值 xff0c 其中n是一个数字 include lt stdio h gt include lt math h gt long long factorial in
  • 深入MTK平台bootloader启动之【 Pre-loader -> Lk】分析笔记

    1 bootloader到kernel启动总逻辑流程图 ARM架构中 xff0c EL0 EL1是必须实现 xff0c EL2 EL3是选配 xff0c ELx跟层级对应关系 xff1a EL0 app EL1 Linux kernel l

随机推荐

  • STM32输出模式详解

    本文为个人见解 xff0c 如有问题欢迎指正 首先需要明确输出 输入的意思 输出是指STM32控制外设 xff08 主要指输出高电平或低电平 xff09 或STM32发送数据给外设 xff0c 输入是指外设发送数据给STM32 输出模式有三
  • [OPNET学习总结]——SITL

    软件自带的SITL例程中 xff0c 出现如下error xff1a lt lt lt Recoverable Error gt gt gt Object repository construction failed due to erro
  • 漫谈程序员系列:程序员的生活就这样吗

    我当了快十年程序员了 xff0c 终于老得可以来谈谈程序员的生活是什么样子了 或许陈奕迅的 十年 中的一段歌词 xff0c 可以表示很多程序员和软件开发之间的感情纠葛 xff1a 十年之前 我不认识你 你不属于我 我们还是一样 陪在一个陌生
  • 程序员转行为什么这么难

    尽管我在 大龄程序员的未来在何方 这篇文章里比较乐观地介绍了程序员保持竞争力的几个方向 xff0c 但现实依然是残酷的 xff1a 很多人将不得不离开软件开发工作 xff0c 转型去从事其他职业 当你要这么做时 xff0c 就会感慨 xff
  • 使用http_parser解析URL

    用C语言编写http应用 xff0c 解析URL是一个繁琐的事儿 前几天使用http parser实现httpclient xff0c 发现里面提供了一个解析URL的方法http parser parse url xff0c 用起来相当方便
  • Android app 后台被杀恢复

    android 模拟应用因内存不足被后台杀死命令 https www jianshu com p effb4546b9aa adb shell am kill all 应用通过home键已经停留在后台使用 xff0c 杀掉所有后台程序 xf
  • Ubuntu查看linux系统版本号

    查看ubuntu版本 输入命令 cat proc version 显示如下 Linux version 5 0 0 13 generic buildd 64 lcy01 amd64 020 linux内核版本号 gcc version 8
  • Linux C Socket简介和实现

    1 网络中进程之间如何通信 xff1f 本地的进程间通信 xff08 IPC xff09 有很多种方式 xff0c 但可以总结为下面4类 xff1a 消息传递 xff08 管道 FIFO 消息队列 xff09 同步 xff08 互斥量 条件
  • C++ STL视频教程,初学者必备视频资料

    STL视频教程 初学者必备视频资料 我一个朋友做的 我转发到这里和大家分享 STL语音视频教程 下载地址 xff1a url 61 http www ctdisk com file 3388918 STL语音视频教程 7z url
  • QMessageBox简单用法(QT5.12)

    span class token comment for starf study span span class token macro property span class token directive hash span span
  • TOF相机 Realsense L515 与 Ipad pro Lidar Camera 对比

    最近好奇都是TOF 相机 L5151 和 Ipad pro 上带的深度相机模块有啥不一样 网上很少有相关的中文资料来介绍 原理上的差异 简单搜索了一下 在此小小总结 Apple Lidar Camera 苹果采用的激光是 VCSEL Ver
  • Arduino 读取GPS 数据发送解析并发布ROS topic(一)

    概述 通过Arduino收集GPS数据 xff0c 连接至电脑端 xff0c 在电脑端通过python对数据进行整理 xff0c 并通过发布 TOPIC xff0c 本部分主要记录如何通过Arduino读取GPS数据 接线方式 GPS 的
  • STM32 复位电路设计

    在此之前我是个只会抄写原理图的工程师 xff0c 每当遇到一个问题时 xff0c 确需要解决很久 xff0c 最根本的原因在于不明白其中的原理 xff0c 这次补充一下单片机复位电路设计 1 为什么要设计复位电路 xff1f 在做一件事情之
  • STM32核心板设计——电源设计

    1 STM32 数据手册电源部分研读 RTC电源管脚为V BAT 电源范围为1 8 3 6V xff0c 主要用于RTC时钟的供电 xff0c RTC在大部分场合用于保存一些重要的参数 xff0c 比如在电脑主板上用于保存boss的信息 x
  • stm32的复位电路问题

    现在比较流行的复位方式是这样的 xff1a 但我们都知道对于结构紧凑型硬件来说 xff0c 多一个电阻都是没必要的 在没有手动复位需求的场合 xff0c 能不能删掉按键与R24 xff0c 仅保留104电容 xff1f 通过阅读stm32
  • 外设驱动库开发笔记21:BME680环境传感器驱动

    环境传感器是一类我们很常用的传感器 它可以方便我们获取压力 温度 湿度以及空气质量等数据 在这一篇中 xff0c 我们将分析 BME680 环境传感器的功能 xff0c 并设计和实现 BME680 环境传感器的驱动 1 功能概述 BME68
  • 外设驱动库开发笔记45:MS4515DO压力传感器驱动

    很多时候我们需要检测流量和压力这些参数 xff0c 比如我们要检测大气压 xff0c 或者通过测量差压来获得输送流体的流量等 xff0c 都需要用到压力传感器 这一篇我们就来讨论MS4515DO压力传感器的数据获取 1 功能概述 MS451
  • 一个好看的CSS样式表格

    一个好看的CSS样式表格 自动换整行颜色的CSS样式表格 xff08 需要用到JS xff09 自动换整行颜色的CSS样式表格源代码 自动换整行颜色的CSS样式表格 xff08 需要用到JS xff09 这个CSS表格会自动切换每一行的颜色
  • docker删除镜像

    docker要删除镜像 xff0c 先要删除依赖它的容器 1 删除容器 docker ps 查看正在运行的容器 docker ps a 查看所有容器 docker rm container id 删除容器 2 删除镜像 docker ima
  • FreeRTOS如何结束和重新启动调度程序

    大多数主机或桌面系统 xff08 比如Linux xff0c Mac或Windows xff09 都有一个正常的用例 xff0c 你可以在早上启动操作系统 xff0c 然后在晚上关闭它 xff0c 然后你就离开机器 嵌入式系统是不同的 xf