多核场景中的随机中断

文章作者:Aaron Bauch

当应用程序非常复杂时,如何捕捉随机中断或控制中断处理?

对复杂应用程序的需求正在增加,多核设备越来越受欢迎是一个明显的趋势。我们都知道“如果我们开发它,调试就会到来”。但是,当应用程序非常复杂时,如何捕捉随机中断或控制中断处理呢?在本文中,我将讨论如何处理这些随机中断,并提供一些在开发基于arm的应用程序时可能有用的工具指导。

中断基本知识

在嵌入式系统中,使用中断是处理外部事件的一种方法,这些外部事件本质上不是与系统上运行的软件同步的。例如,检测到按钮被按下。通常,当中断事件发生时,核心立即停止执行它正在运行的代码,并开始执行中断服务例程,或ISR。

当中断服务代码完成对外部事件的响应时,处理器应该从ISR开始运行时正在执行的指令后面的那条指令中恢复。如果操作正确,主应用程序代码甚至不应该“意识到”任何更改。它只是在中断服务程序运行时暂停了一段时间。

重要的是,在中断被处理后,机器的状态被恢复——这包括处理器寄存器的值和处理器状态寄存器。这样就可以在处理中断的代码执行之后继续执行原始代码。

专业的编译器支持C/ c++中编写中断、软件中断和快速中断的语法。对于每种中断类型,可以编写一个中断例程,但语法和处理将取决于MCU的实现。例如,当Arm定义Cortex A, R和M的变体时,他们也定义了每个家族的中断处理硬件和机制。在之前的arm7、arm9等版本的芯片中,由于芯片厂商的不同,中断控制器的设计和操作也不尽相同,导致移植性很困难。

然而,现代商业工具链将考虑这些差异,并使在代码中实现中断支持尽可能透明,而不管底层中断硬件和中断管理机制如何。

一个很好理解并且经常讨论的实践是中断代码应该尽可能短。这确保了CPU能够及时返回到主任务。中断服务例程应该只执行关键代码,通过设置标志变量,任务的其余部分可以降级到主进程。如果从中断服务例程调用正常函数,可能会在保留未使用寄存器时出现意外的代码膨胀。

管理此过程的一个有用技术是使用软件中断的延迟处理。

在这种方法中,硬件中断,如上面提到的按钮按下,触发一个高优先级中断服务程序。在这个例程中,您将处理那些必须立即处理的事情,例如重置开关以便它能再次启动。然而,ISR可能发布一个较低优先级的软件中断,当它是系统中最高优先级的事件时,该软件中断将运行。这样,如果优先级设置得比一些重要的时间关键的应用程序函数低,那么在这些函数运行时,优先级将被延迟。但是,只要它的优先级高于可能运行的其他代码,它就会执行并完成管理中断事件所需的时间要求较低的函数。

如果您有充分的理由在ISR中执行函数调用,那么您可以做的关键事情是向编译器提供信息,以便它能够尽可能地优化代码。通常,您需要检查在特定情况下发生了什么,但您可以尝试将被调用的函数a)静态和b)定义在与ISR相同的文件(编译单元)中。通过这样做,编译器可以确切地知道在编译ISR时被调用的函数使用了哪些寄存器,并且您可以向编译器指出,这个函数只从同一个源文件(编译单元)中调用。如果有一个pragma或选项来鼓励编译器生成内联代码,您也可以尝试这样做。有了这些信息,编译器可能会内联被调用的函数,从而允许进一步优化,类似于被调用的函数实际上是内联编写的(例如,删除不需要的push/pop对)。您应该打开适当的优化,并查看生成的代码,以确保它尽可能高效地完成您想要的工作。

多核系统中的中断

通过使用多核设备,可以实现负载平衡并利用不同核的不同强度。使用一个多核设备比使用多个设备还可能降低产品成本。不同的多核系统可能以不同的方式处理中断。在更复杂的SMP系统中,代码被任意安排在几个相同的核心上运行,中断处理也可以根据某些算法随机分配给可用的核心。

然而,嵌入式系统更有趣的模型是使用非对称多处理方法,其中每个核都有它自己执行的程序,偶尔与系统中的一个或多个其他核通信和同步。这是我们将在本次讨论中重点讨论的模型。

在这种系统中,每个中断通常被指向一个(而且只有一个)CPU。芯片的可编程中断控制器(PIC)控制这是如何发生的。当您在系统启动时初始化PICs时,您可以对它们进行编程,以便为您喜欢的任何CPU提供中断。

多核Arm芯片通常使用高级可编程中断控制器(APIC)和集成中断控制器来实现通用的中断控制器(GIC)。可以将其配置为向特定的核心或核心组提供I/O中断。此外,它还提供了操作系统用来协调多核活动的处理器间中断(IPI)。

在本文中,我们将不再深入探讨特定的MCU/MPU多核配置,而是深入研究如何监控和调试中断。

多核调试的好处

在单核系统中,中断的调试是出了名的困难,因为在调试器中停止检查中断处理程序的执行,与中断处理的典型时间敏感方面不太协调。在多核场景中,它变得更加复杂,在一个中断完全被其他中断占用的情况下,可以平衡中断并设置或重定向不同的内核。由于中断通常是由外围设备或外部事件触发的,所以某些错误可能只是偶尔被触发,而且似乎是随机的,或者是通过将中断连接到错误的核心或繁忙的核心。

多核调试器可以通过显示在多核上运行的程序来突出和简化任务。特别是,它能够根据另一个核心上的中断服务例程(ISR)中的断点选择性地停止和启动核心(图1)。

点击查看完整大小的图像

图1:具有独立启动/停止选项的多核调试控件。(来源:IAR系统)

有两种方法可以运行多核调试。

  • 对称多核调试(SMP),指调试两个或多个相同的核。
  • 非对称多核调试(AMP)是指基于不同的体系结构对两个或多个核进行调试。它可以是两个不同的Arm核心,例如Cortex-A9和Cortex-M0。

对所有核心的完全控制对于获得最佳结果至关重要。

Arm Cortex系列微控制器增加了一些在以前的Arm微控制器中不可用的高级调试功能。串行线调试或SWD通过串行线输出(SWO)接口提供对CoreSight调试基础设施功能的访问,如时间戳和中断事件跟踪。

请注意,在多核场景中,大多数软件和硬件调试器一次只在一个核心中支持SWO。这可以用于监视其中一个核心,并利用断点和交叉触发接口(CTI)接口有选择地停止和启动相邻的核心。

中断日志为您提供了关于中断事件的全面信息。这可能是有用的,例如,帮助您定位哪些中断可以调整得更快。您可以记录进出中断的入口和出口。如图2所示的中断日志允许您查看中断服务例程执行的日志以及每个例程执行所需的时间。

点击查看完整大小的图像

图2:中断日志示例。(来源:IAR系统)

时间戳信息可以以实时数字或CPU时钟周期的形式提供。

我们可以看到每个中断被触发的次数,以及对执行ISR所花费时间的统计(图3)。还可以在图4中看到中断日志信息。

点击查看完整大小的图像

图3:中断日志总结的例子。(来源:IAR系统)

点击查看完整大小的图像

图4:显示图形中断的时间轴。(来源:IAR系统)

这使我们能够看到每个ISR何时处于活动状态的图表,并将其与其他ISR进行比较,以及与其他定时活动(如数据日志断点)相关联。

在处理和调试中断时,另一个有用和强大的特性是使用跟踪。实时跟踪是对执行的选定部分的每个执行指令的连续收集序列。通过使用跟踪,您可以检查程序流到特定的状态,例如应用程序崩溃,并使用跟踪数据定位问题的根源。跟踪数据对于定位具有不规则症状和像随机中断一样偶尔发生的编程错误很有用。

在多核场景中,跟踪也主要用于一次查看一个核。有一些带有追踪漏斗的设备,可以将每个源的追踪合并成一个单一的流,并使用更复杂的芯片进行控制。拥有一个核心上的跟踪信息,并利用CTI接口停止和启动所有其他核心,将为您提供关于应用程序行为的精确图像。

专业的跟踪调试器可以提供应用程序各个方面的信息,这些信息是在应用程序运行时收集的。信息可以在时间轴中表示,以图表的形式显示跟踪系统收集的函数调用和返回的序列。您还可以获得函数调用之间的时间信息。这也可以帮助您分析应用程序的行为,并允许您快速导航到下一个中断项或最近的前一个中断项旁边,有一个清晰的图片什么程序被中断。图形化调用堆栈可以显示跟踪系统收集的函数调用和返回的序列,它还包括已经触发并使用精确的时间和周期计数进行处理的中断和ISR(图5)。

点击查看完整大小的图像

图5:带有函数和ISR的图形调用堆栈的时间线。(来源:IAR系统)

此功能提供有关系统中异常和中断的全面信息。例如,定位哪些中断可以微调以更快地执行,或者分析嵌套中断的问题,都是很有用的。

结论

开发人员经常禁用所有中断,以避免并发中断或随机中断。然而,这可能会使系统作出反应或变慢,并隐藏一些可能在未来触发的关键问题,使事情变得更糟。完全控制并理解何时触发以及为什么触发中断是确保良好性能并使应用程序完全按照预期运行的最重要步骤。能够记录所有中断处理的调试器对于捕获随机中断和控制中断处理是至关重要的。

这篇文章最初发表于嵌入式

亚伦·鲍奇高级现场应用工程师是IAR系统与美国东部和加拿大的客户合作。Aaron曾为包括英特尔、模拟设备和数字设备公司在内的公司开发嵌入式系统和软件。他的设计万博投注网址涵盖了广泛的应用领域,包括医疗仪器、导航和银行系统。他还教授了一些大学水平的课程,包括南新罕布什尔州大学的嵌入式系统设计教授。他持有The Cooper Union的电气工程学士学位和哥伦比亚大学(Columbia University)的电气工程硕士学位。

留下你的评论