粤嵌教育
gzyueqian
13352868059

嵌入式开发:加速中断处理程序的 3 个技巧

更新时间: 2022-01-22 11:03:59来源: 粤嵌教育浏览量:3766

  许多微控制器都带有一个生态系统,其中包括外围驱动程序、RTOS、中间件甚至示例应用程序代码。许多嵌入式开发人员可以将大部分时间花在高级应用程序代码上,而忽略了满足硬件的软件。问题是,虽然这个预构建的生态系统可以加速开发,但这种加速通常是以时钟周期和执行效率为代价的。


  在今天的文章中,我们将探讨开发人员可以应用的几个技巧,以帮助提高其中断服务例程回调的效率,这些回调与许多微控制器软件框架紧密集成。


  先决条件 #1 – 测量 ISR 执行时间


  加速软件执行的第一步是停止并进行一些测量。你如何知道你的中断处理程序是使用过多的 CPU 时间还是运行缓慢?你量一下!开发人员可以利用几种不同的选项来测量中断执行时间。


  首先,只需切换 GPIO 线!我经常将测试 GPIO 线初始化为高电平,然后当我进入 ISR 时,我会将 GPIO 线切换为低电平,然后在退出 ISR 时再次将 GPIO 线切换为高电平。结果是一个低电平有效信号,它近似代表 ISR 执行时间。测量值是近似值的原因是它没有考虑切换 GPIO 线的时间,我们假设它可以忽略不计(但如果你使用的是框架代码,则可能不是!)。这种方法产生了一个简单且易于测量的波形,如下所示:




  第二种方法,我将简要提及的是使用跟踪软件。如果你使用的是 RTOS,RTOS 通常会记录系统中发生的事件,包括进入和退出中断服务程序。嵌入式开发人员可以使用他们的跟踪分析器来了解他们的中断服务程序执行了多长时间。


  现在乍一看,上面测得的 24.3 us 对于 ISR 来说似乎并不算太糟糕。这实际上取决于应用程序的好坏,但总的来说,我们希望 ISR 执行时间尽可能短。在这个例子中,我设置了一个输入捕捉外设来测量输入信号的频率。如果频率只有区区 20 KHz,这个 ISR 将占用大约 50% 的 CPU 周期!


  技巧 #1 – 在 ISR 中调用的内联函数


  首先,从 ISR 调用函数是个坏主意!函数调用开销会给中断增加一大堆浪费的时钟周期,这将延迟返回到定期安排的代码执行。但问题是许多现代框架都这样做!例如,如果你查看 STM32CubeIDE 生成的定时器中断,你会看到如下内容:




  现在,我添加了 GPIO HAL 调用,但你可以看到,默认情况下,中断会调用 HAL_TIM_IRQHandler,这是 STM32 上所有定时器的通用中断处理程序。 (对于可重用和可移植的代码来说,这是一个很棒的框架理念,但它可能对时间敏感的代码有害)。 如果我们检查 HAL_TIM_IRQHandler 的定义,我们会发现以下内容:




  这里没有试图告诉编译器我们处于 ISR 中,因此编译器可能会添加函数调用的代码并向 ISR 添加无用的循环。 事实上,这个函数会有条件地检查并调用几个函数,这可能会使事情变得更糟。 内联函数可能会减少执行时间,但会以稍大的代码大小为代价。 只需将 inline 关键字添加到函数定义中即可完成,如下所示:




  进行前后测量,在这种情况下,我发现我可以将中断执行时间缩短 0.2 us。不是很大,但在时间敏感的应用程序中,它是一些东西。


  提示 #2 – 自定义默认中断服务程序 (ISR)


  预构建的框架通常会将外围类型的中断处理集中在一起。例如,我们刚刚看到的定时器中断,它传递了一个定时器对象,然后有一堆条件语句来决定它应该做什么。该框架是为重用而不是执行速度而构建的。如果我重写我的中断以删除所有这些通用函数调用,中断执行时间变为 21.712,现在为我们节省了 2.5 us (10.3%)!对于我们正在查看的数字,它似乎并不多,但如果这是一个高频中断,那可能是大量的 CPU 使用率。


  提示 #3 – 优化中断服务程序 (ISR) 回调函数


  我经常注意到,编写各种功能的示例代码是为了向嵌入式开发人员展示如何完成某事。例如,许多供应商将提供输入捕获代码,以显示如何计算信号的占空比和频率。这太棒了,除了代码通常是在中断服务程序中执行的。这是次优的。事实上,我在整个博客中展示的示例都与使用输入捕获计算频率有关。当你测量信号频率时,21.712 us 是中断运行的较长时间。


  示例代码就是这样,一个例子。算法通常是正确的,但它们不是以生产意图的方式完成的。他们可能不会考虑重要的考虑因素,例如 CPU 负载和实时响应。他们只是想向你展示他们的部分可以做你需要的事情,测量频率或任何功能。




  今天的嵌入式开发人员拥有如此多的示例代码和如此多的开箱即用的框架供我们利用,这真是太棒了。需要注意的是,这段代码可能不是为我们自己的目的而设计或实现的。它通常被快速编写以展示一个特性或功能,而不是为生产而设计的。

免费预约试听课

推荐阅读