首页 > 其他分享 >FreeRTOS深入教程(中断管理)

FreeRTOS深入教程(中断管理)

时间:2023-12-02 20:32:02浏览次数:40  
标签:教程 FreeRTOS 中断 PendSV 任务 切换 上下文

(文章目录)


前言

本篇文章来分析FreeRTOS中的中断,中断在FreeRTOS中也是非常重要的,那么这篇文章将带大家来学习一下FreeRTOS中的中断处理以及涉及到的API等。

一、为什么要为中断设计一套API

1.实时性要求: 中断服务程序通常用于响应实时事件,例如硬件中断、定时器中断等。为了满足实时性要求,中断服务程序必须迅速执行,不能因等待某些资源而阻塞。中断处理必须在规定的时间内完成以确保系统的及时响应。

2.代码清晰度: 将任务和中断的操作分开可以提高代码的清晰度和可读性。任务上下文的操作通常涉及到任务切换、阻塞等,而中断上下文的操作需要考虑中断的实时性和不能阻塞的要求。通过使用两套函数,可以在代码中清晰地区分任务上下文和中断上下文的操作,使代码更易于理解。

3.可维护性:分离任务和中断的操作使得系统更易于维护和修改。如果所有的操作都混合在一起,代码会变得复杂且难以理解。通过采用清晰的接口,可以更容易地理解和修改任务和中断的行为,降低引入错误的风险。

二、两套函数区别对比

这里使用xQueueSendToBack和xQueueSendToBackFromISR进行比较说明:

xQueueSendToBack:

调用上下文: 该函数用于在任务上下文中发送数据到队列。任务上下文是正常的程序执行上下文,不是中断上下文。 任务切换: 如果向队列发送数据导致接收方任务变得可运行(即有任务等待接收数据),则该函数可能会导致任务切换。这是因为向队列发送数据可能导致等待接收数据的任务变为就绪态,而当前任务可能因此让出 CPU。

xQueueSendToBackFromISR:

调用上下文: 该函数用于在中断服务程序(ISR)或软中断上下文中发送数据到队列。中断上下文是由硬件中断或软中断触发的执行上下文。 任务切换: 该函数不会导致任务切换。因为中断上下文具有实时性的要求,任务切换可能引入不确定性和延迟,所以在中断上下文中,通常不允许发生任务切换。

下面是两个函数的使用示例:

// 任务上下文中发送数据到队列
xQueueSendToBack(xQueue, &data, portMAX_DELAY);

// 中断上下文中发送数据到队列
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xQueueSendToBackFromISR(xQueue, &data, &xHigherPriorityTaskWoken);

if(xHigherPriorityTaskWoken == pdTRUE)
{
	/*任务切换*/
	portYIELD_FROM_ISR();
}	

需要注意的是,在中断上下文中使用 xQueueSendToBackFromISR 时,通常会检查 xHigherPriorityTaskWoken 的值。如果它在调用之后被设置为 pdTRUE,则意味着有一个任务等待接收数据并且其优先级高于当前运行的任务,可能需要进行任务切换。在这种情况下,通常会调用适当的任务切换函数,如 portYIELD_FROM_ISR,以确保在适当的时机进行任务切换。

三、两类中断

前面我们在分析信号量,互斥量,队列等源码时都会涉及到需要关闭中断的操作,那么这里的关闭中断是直接关闭全部的中断吗?其实是不是的,这里关闭中断只是关闭了特定的中断,并没有将全部的中断关闭。

FreeRTOS会将中断分为两类,第一类更高优先级的中断中无法使用FreeRTOS中提供的函数,而更低优先级的一类可以使用到FreeRTOS中提供的函数。 在这里插入图片描述 实际关闭中断会调用到portDISABLE_INTERRUPTS函数,这个函数只是关闭更低优先级的中断,不会关闭其他高优先级的中断,SYStick中断也属于低优先级的中断。

void vPortEnterCritical( void )
{
    portDISABLE_INTERRUPTS();
    uxCriticalNesting++;

    /* This is not the interrupt safe version of the enter critical function so
     * assert() if it is being called from an interrupt context.  Only API
     * functions that end in "FromISR" can be used in an interrupt.  Only assert if
     * the critical nesting count is 1 to protect against recursive calls if the
     * assert function also uses a critical section. */
    if( uxCriticalNesting == 1 )
    {
        configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
    }
}

四、FreeRTOS中SYSTICK和PendSV中断的作用

在FreeRTOS中,SYSTICK和PendSV中断是两个关键的系统中断,它们在任务调度和协作方面发挥着重要的作用。

SYSTICK中断:

作用: SYSTICK中断是由系统定时器触发的中断。在FreeRTOS中,它用于实现任务调度的时基。任务调度器通过SYSTICK中断定期触发,根据任务的优先级和调度策略来决定是否切换当前运行的任务。

配置: SYSTICK中断的配置在FreeRTOS中是由configTICK_RATE_HZ参数控制的,该参数定义了系统定时器的时基。SYSTICK中断的频率通常设置为1kHz,但可以根据具体的应用需求进行调整。

示例: 当SYSTICK中断发生时,FreeRTOS的任务调度器会检查任务的状态,决定是否进行任务切换。这是实现抢占式多任务的基础。

PendSV中断:

作用: PendSV(Pending Supervisor Call)中断是一种特殊的中断,用于在任务切换时执行一些必要的操作。通常,当任务调度器决定切换到另一个任务时,它会生成一个PendSV中断请求,将切换的工作推迟到稍后在PendSV中断服务函数中执行。

配置: PendSV中断的优先级设置为最低,以确保它能够在其他中断完成后执行。PendSV中断不会被任务调度器直接触发,而是通过软件触发。 示例: 当SYSTICK中断触发任务切换时,实际的任务切换操作会被延迟到PendSV中断服务函数中执行。这样的设计有助于减小任务切换的上下文开销,并提高系统的响应速度。

总体而言,SYSTICK中断提供了任务调度的时基,而PendSV中断用于执行实际的任务切换操作。这两者共同协作,实现了FreeRTOS的多任务调度机制。

总结

本篇文章主要讲解了FreeRTOS中的中断管理,这一个部分还是比较重要的,那么希望大家可以深入的理解一下这部分的知识,有任何疑问都可以留言。

标签:教程,FreeRTOS,中断,PendSV,任务,切换,上下文
From: https://blog.51cto.com/u_16153875/8658711

相关文章

  • FreeRTOS--信号量
    示例源码基于FreeRTOSV9.0.0信号量1.概述消息队列用于传输多个数据,但是有时候只需要传递状态,这个状态值需要用一个数值表示,在这种情况下我们只需要维护一个数值,使用信号量效率更高、更节省内存。信号量用来表示资源的个数,它是特殊的队列实现,队列数据项为空。对于二值信号量......
  • FreeRTOS--邮箱
    示例源码基于FreeRTOSV9.0.0邮箱1.概述一种特殊的队列,队列深度只有1,写数据的时候是覆盖写,读数据的时候,读完不会把数据从队列删除;写数据的时候永远是成功的,读数据的时候仅第一次队列无数据时会阻塞或失败,当队列有数据后,读都会是成功的;2.接口API//写队列#definexQueueOv......
  • FreeRTOS--队列集
    示例源码基于FreeRTOSV9.0.0队列集1.概述队列集的本质也是队列,只不过里面存放的是“队列句柄”。当任务需要及时读取多个队列时,可以使用队列集。它类似于posix的多路复用思想。可以将想要监听消息的队列放入队列集中,当其中有队列有数据达到时,队列集的接口会返回可读的队列句......
  • FreeRTOS--队列
    示例源码基于FreeRTOSV9.0.0队列1.概述FreeRTOS的队列,支持任务与任务间的通信,以及任务与中断间的通信。它是FreeRTOS系统中主要的任务间通信方式。队列内的消息,是通过拷贝方式传递,而非指针。队列除了基本的先进先出特性,也支持往队列首部写入数据。FreeRTOS基于队列进行扩......
  • 无涯教程-Erlang - 运算符
    Erlang具有以下类型的运算符-算术运算符关系运算符逻辑运算符按位运算符算术运算符Erlang语言支持普通的算术运算符,就像任何一种语言一样,以下是Erlang中可用的算术运算符。运算符描述示例+加1+2=3-减1-2=-1*乘2*2=4/除2/2=1rem余数3rem2=1div......
  • FreeRTOS--链表
    示例源码基于FreeRTOSV9.0.0链表1概述链表一般可分为单向链表、双向链表、环形链表。FreeRTOS采用的是环形双向链表设计;单向链表只有后继节点,双向链表有后继和前驱节点;链表的目的是把元素串联,其设计方式一般有两种:将元素放置在链表结构体中;将链表结构体放置在元素中;方......
  • FreeRTOS--内存管理
    示例源码基于FreeRTOSV9.0.0内存管理1概述FreeRTOS有自己的一套内存管理机制,而非直接使用malloc和free等C库函数。malloc和free由于实现复杂,代码量大,运行时间不确定,存在内存碎片,非线程安全等问题,不适用于资源紧缺的FreeRTOS系统;FreeRTOS实现了5种内存管理方式,实际使用时......
  • 无涯教程-Erlang - 变量声明
    在Erlang中,所有变量都必须以大写字母开头,要注意的一件事是变量是不可变的,这意味着要更改变量的值,需要将其销毁并重新创建。变量声明定义变量的一般语法如下-var-name=var-valuevar-name-这是变量的名称。var-value-这是绑定到变量的值。-module(helloLearnfk).-e......
  • 无涯教程-Erlang - 数据类型
    您可能希望存储各种数据类型的信息,例如string,character,widecharacter,integer,floatingpoint,Boolean等,系统根据变量的数据类型分配内存。内置数据类型Erlang提供了多种内置数据类型,以下是在Erlang中定义的数据类型的列表-Number  - 在Erlang中,它们是integers和floats。......
  • 我的心血之作:一套适合 SAP UI5 从业人员从入门到进阶的学习教程,以及教程背后的故事
    一转眼2023年又要结束了。我从2007年开始,以软件开发工程师的角色进入职场,马上也快满17年了。在这快17年的软件开发职业生涯里,我也见识并使用了许许多多的开发技术,编程语言,开发框架,平台。IT界这十多年来涌现出的一些新技术,我也主动或被动地去追逐过。比如2015年时,大......