【OS】AUTOSAR架构下的Interrupt详解(上篇)
目录
前言
正文
1.中断概念分析
1.1 中断处理API
1.2 中断级别
1.3 中断向量表
1.4 二类中断的嵌套
1.4.1概述
1.4.2激活
1.5一类中断
1.5.1一类中断的实现
1.5.2一类中断的嵌套
1.5.3在StartOS之前的1类ISR
1.5.4使用1类中断时的注意事项
1.6中断源的初始化
1.7未处理的中断
1.8未处理的系统调用
1.9零类中断
1.9.1一类中断的实现
1.9.2一类中断的嵌套
1.9.3在StartOS之前的0类ISR
1.9.4零类isr被锁定的位置
1.9.5使用0类中断时的注意事项
2.中断配置
前言
通过《【TC3xx芯片】TC3xx中断路由IR模块详解》一文我们学习了TC3xx芯片中断的硬件实现,通过《【OS】AUTOSAR架构下的中断和异常向量表》一文中我们知道中断向量表的起始地址标识符在Os生成的链接文件中定义,用户需要在启动代码中初始化BIV寄存器,知道这两点我们就能集成使用Os中断功能,但是关于更多的Os中断的细节知识还需要继续学习,比如,你能回答以下的几个问题吗?
问题1:以下三组OS ISR相关的API有何区别,分别适合在什么场景下使用?
DisableAllInterrupts()
EnableAllInterrupts()
SuspendAllInterrupts()
ResumeAllInterrupts()
SuspendOSInterrupts()
ResumeOSInterrupts()
问题2:以下两个OS ISR相关的API有何区别,分别适合在什么场景下使用?
Os_InitialEnableInterruptSources()
Os_EnableInterruptSource()
问题3:二类中断完全由OS实现,那么该如何使用一类中断了?
问题4:TC3xx芯片是如何处理中断的?
问题5:详细阐述一个中断的配置及其处理过程,以CAN中断为例。
问题6:OS是如何处理中断优先级的?
缩略词
简写 | 全称 |
BTV | Base Trap Vector Table Pointer |
BIV | Base Interrupt Vector Table Pointer |
ISR | Interrupt Service Router |
SRC | Service Request Control Register |
IR | Interrupt Router |
ICU | Interrupt Control Unit |
ICR | ICU Interrupt Control |
AUTOSAR BSW Tool:Vector
AUTOSAR MCAL Tool:EB
Hardware Platform: Infineon Tricore TC387
Build Tool: Tasking
Debug Tool: UDE
注:本文章引用了一些第三方工具和文档,若有侵权,请联系作者删除!
正文
1.中断概念分析
1.1 中断处理API
AUTOSAR标准指定了几个以下API来禁用/启用中断。
DisableAllInterrupts() EnableAllInterrupts() | 该功能将禁用所有类别1和类别2的中断。 |
SuspendAllInterrupts() ResumeAllInterrupts() | |
SuspendOSInterrupts() ResumeOSInterrupts() | 该功能仅禁用类别2的中断 |
1.2 中断级别
l2类中断的优先级必须低于1类中断的优先级。
l1类中断的优先级必须低于时间保护ISR(SC2 / SC4系统)。
l时间保护ISR的优先级必须低于0类ISR(第0类ISRs详见第1.9小结)。
l用户无法设置时间保护锁(TP Lock)级别。每当OS内部在处理时间保护相关的任务时会使用到TP Lock,这个时候中断时都是被禁用的(Disabled)。
l0类 ISRs在内部禁用很短的操作系统,例如在执行堆栈开关时(0类 ISRs被锁定的位置在1.9小结中描述)。
1.3 中断向量表
MICROSAR OS会根据用户的配置、使用的MCU类型、使用的编译器类型生成中断向量表。
在一个多核系统中,可以生成多个向量表。
MICROSAR OS会为每一个可能的中断源生成一个中断向量。
1.4 二类中断的嵌套
1.4.1概述
为了保持中断延迟尽可能低,OS遵守以下中断优先级规则:
l更高优先级的二类中断可以中断正在执行的低优先级的二类中断。
l一类中断的优先级始终高于二类中断的优先级(一类中断始终可以打断二类中断)。
1.4.2激活
设置“OsIsrEnableNesting”参数为TRUE后,2类ISR本身可以被更高优先级的ISR中断。
1.5一类中断
1.5.1一类中断的实现
MICROSAR OS提供了一个宏,用于实现一类ISR。类似AUTOSAR标准定义的2类ISR的宏。MICROSAR OS抽象了所需的编译器关键字。
Implement a category 1 ISR
OS_ISR1(<MyCategory1ISR>)
{
}
1.5.2一类中断的嵌套
由于1类ISR是直接从中断向量表调用的,没有任何操作系统的支持,因此不支持第1类ISR的自动嵌套。
忽略1类ISR的“OsIsrEnableNesting”配置属性。
然而,可以在1类 ISR期间启用中断以允许中断嵌套,但OS API函数不能用于此目的。应用程序必须使用编译器固有函数或内联汇编语句。
Example
OS_ISR1(<MyCategory1ISR>)
{
__asm(EI); /* enable nesting of this ISR */
__asm(DI); /* disable nesting before leaving the function */
}
1.5.3在StartOS之前的1类ISR
在操作系统启动之前,可能需要激活1类ISR。
以下动作序列需要被执行:
1.调用Os_InitMemory()
2.调用Call Os_Init(), (在该函数中,基本的中断控制器设置被初始化,例如中断源的优先级))。
3.通过直接操作中断控制器中的控制寄存器,来启用1类ISR的中断源。
4.通过直接操作全局中断标志和/或当前中断优先级来启用中断,以允许1类ISR.
1.5.4使用1类中断时的注意事项
1.在不支持中断请求时栈切换(中断栈和用户栈切换)的芯片平台上,如果发生了1类中断则不会发生栈切换。因此,1类中断的堆栈消耗将应该被添加到所有可以被1类ISR消耗的堆栈中。
2.虽然中断优先级是由MICROSAR OS初始化的,但是没有API来启用1类ISR, 必须直接访问中断控制寄存器来Enable 1类中断。
3.AUTOSAR OS标准不允许在1类ISR中使用OS API(唯一的例外是中断处理API)。如果在1类中断处理函数中调用了不允许使用的OS API,MICROSAR OS就无法检测到这一点,并且调用的API可能不能按预期工作。
4.一类中断始终在Trusted权限或者Supervisor等级下被执行。
5.宏“OS_ISR1”抽象了用于实现中断服务程序的适当编译器关键字。因此,编译器生成保护并恢复通用寄存器子集的代码。在某些用例中,例如使用FPU或嵌套中断,它可能需要应用程序保存和恢复更多的寄存器。
1.6中断源的初始化
通过操作系统配置,MICROSAR操作系统知道中断源的分配和ISR的优先级。在多核系统中,所有isr的核心分配也是已知的。基于这些配置信息,MICROSAR OS生成用于初始化中断控制器的数据结构。它初始化中断优先级及其核心分配。
使能中断源:
操作系统只对操作系统生成的定时器ISR启用中断源。
只有当应用程序启用了相应的中断源时,才能为其他用户ISR提供服务。
这应该通过使用中断源API来完成(详见Os_EnableInterruptSource()函数)。
1.7未处理的中断
没有分配给用户定义ISR的中断源被分配给一个默认的操作系统中断处理程序,该处理程序收集这些中断源。
因此,来自未分配中断源的中断请求由操作系统处理。在OS Hooks(例如ProtectionHook())中,应用程序可以通过OS API获得未处理中断请求的源编号。
如果一个未处理的中断请求发生在操作系统代码中,MICROSAR OS调用PanicHook(),因为一个不一致的内部状态被识别出来,操作系统不知道如何正确地继续执行。
如果一个未处理的中断请求发生在关键用户段,即StartupHook, ErrorHook, PreTaskHook, PostTaskHook, Alarm回调,IOC接收器回调,Timing Hooks, ProtectionHook和ShutdownHook, MICROSAR OS调用PanicHook(),因为一个不一致的内部状态被识别,操作系统不知道如何正确地继续执行。
在所有其他未处理中断请求的情况下,MICROSAR OS调用带有参数E_OS_SYS_PROTECTION_IRQ的ProtectionHook().
1.8未处理的系统调用
未分配给操作系统或用户处理程序的系统调用源被分配给收集这些异常的默认操作系统系统调用处理程序。
因此,来自未分配的系统调用源的系统调用请求由操作系统处理。如果一个未处理的系统调用请求发生在操作系统代码中,MICROSAR操作系统调用PanicHook(),因为一个不一致的内部状态被识别,操作系统不知道如何正确地继续执行。
如果一个未处理的系统调用请求发生在关键用户部分,即StartupHook, ErrorHook, PreTaskHook, PostTaskHook, Alarm回调,IOC接收器回调,Timing Hooks, ProtectionHook和ShutdownHook, MICROSAR OS调用PanicHook(),因为一个不一致的内部状态被识别,操作系统不知道如何正确地继续执行。
在所有未处理的系统调用请求的其他情况下MICROSAR OS调用ProtectionHook()参数E_OS_SYS_PROTECTION_SYSCALL.
1.9零类中断
MICROSAR OS实现了0类ISRs,以具有最小的中断延迟时间,特别是在SC2或SC4系统中。这是对AUTOSAR操作系统标准的一个扩展。
1.9.1一类中断的实现
MICROSAR OS提供了一个宏,用于实现一类ISR。类似AUTOSAR标准定义的2类ISR的宏。MICROSAR OS抽象了所需的编译器关键字。
Implement a category 0 ISR
OS_ISR0(<MyCategory0ISR>)
{
}
1.9.2一类中断的嵌套
由于0类ISR是直接从中断向量表调用的,没有任何操作系统的支持,因此不支持第0类ISR的自动嵌套。
忽略0类ISR的“OsIsrEnableNesting”配置属性。
然而,可以在0类 ISR期间启用中断以允许中断嵌套,但OS API函数不能用于此目的。应用程序必须使用编译器固有函数或内联汇编语句。
Example
OS_ISR0(<MyCategory0ISR>)
{
__asm(EI); /* enable nesting of this ISR */
__asm(DI); /* disable nesting before leaving the function */
}
1.9.3在StartOS之前的0类ISR
在操作系统启动之前,可能需要激活0类ISR。
以下动作序列需要被执行:
1.调用Os_InitMemory()
2.调用Call Os_Init(), (在该函数中,基本的中断控制器设置被初始化,例如中断源的优先级))。
3.通过直接操作中断控制器中的控制寄存器,来启用0类ISR的中断源。
4.通过直接操作全局中断标志和/或当前中断优先级来启用中断,以允许0类ISR.
1.9.4零类isr被锁定的位置
0类中断只能在很短的时间内在操作系统内部禁用。
以下列表中的操作提到了这些锁的位置(会禁用0类中断):
l导致上下文切换的api内部,例如TerminateTask().
l由ProtectionHook处理的异常导致部分终止。
l中断,异常和陷阱进入和返回。
lOs_Init()和StartOS()中的OS初始化。
1.9.5使用0类中断时的注意事项
1.在不支持中断请求时栈切换(中断栈和用户栈切换)的芯片平台上,如果发生了0类中断则不会发生栈切换。因此,0类中断的堆栈消耗将应该被添加到所有可以被0类ISR消耗的堆栈中。
2.零类ISR正在消耗中断任务或2类ISR的时间保护预算(执行预算和锁定时间)。
3.虽然中断优先级是由MICROSAR OS初始化的,但是没有API来启用0类ISR, 必须直接访问中断控制寄存器来Enable 0类中断。
4.如果发生时间保护中断,执行(时间保护violation handling/protection hook)延迟到0类ISR运行期间,则其0类ISR已经完成。
5.AUTOSAR OS标准不允许在0类ISR中使用OS API(唯一的例外是中断处理API)。如果在0类中断处理函数中调用了不允许使用的OS API,MICROSAR OS就无法检测到这一点,并且调用的API可能不能按预期工作。
6.一类中断始终在Trusted权限或者Supervisor等级下被执行。
7.零类ISR可能永远不会降低CPU或中断的中断优先级。
8.在操作系统关闭的情况下,甚至在操作系统进入Panic Hook的情况下,仍然可能发生0类isr。
9.请注意,0类ISR能中断2类ISR,即使2类ISR被配置为不可嵌套的。
10.如果0类ISR的owner application因任何原因被终止,分配的0类ISR也不会被禁用。
11.宏“OS_ISR0”抽象了用于实现中断服务程序的适当编译器关键字。因此,编译器生成保护并恢复通用寄存器子集的代码。在某些用例中,例如使用FPU或嵌套中断,它可能需要应用程序保存和恢复更多的寄存器。
2.中断配置
Short Name : ISR的名字,如果该ISR所属的模块是Vector SIP包中的模块,则ISR的名字和类别是固定的(不可修改的,比如CanIsr_xxx)。
Isr Category : ISR的类别(0,1,2三种类别的中断),2类中断由OS接管,用户只需要调用OS接口Enable二类中断。0类和1类中断需要用户实现中断处理函数,且需要用户在StartOS之前启用中断。0类中断的时间延迟最小。
Isr Enable Nesting: 中断是否可以被嵌套,仅适用于2类中断。如果2类中断配置为TRUE,则该2类中断可以被更高优先级的中断打断。
Isr Initial Enable Interrupt Source : 配置中断是否会被Os_InitalEnableInterruptSources()函数Enable.
Isr Interrupt Mapping : 如果相关模块的数据搬运交给DMA处理,这需要配置这个参数。
Isr Interrupt Priority : 配置中断优先级,这个地方的中断优先级是个相对值,OS在生成代码的时候会根据这些相对值生成优先级绝对值排序。
Isr Interrupt Source: 配置中断号(中断地址)。
每一个中断请求都和一个SRN一一对应,比如:
对于CAN00,也就是CAN0INT0,对应SRC为SRC_CAN0INT0,对应的SRC地址为:
0x5B0 +0*0x40 + 0*4 = 0x5B0 = 1456
Isr Interrupt Type : 配置ISR是外部中断(External)还是异常(Exception)。注意:中断和异常(.e.g. NMI)其实是两个概念,但是Exception的产生和处理过程和ISR基本一样,所以Davnici中将Exception放在了ISR中配置。
Isr Memory Protection Identifier : 配置ISR所属的内存保护集(MPU Set),如果没有配置,则该ISR和ISR所属的Application的MPU Set配置一样。至于什么是MPU Set清参考《【TC3xx芯片】TC3xx芯片MPU介绍》一文。
Isr Special Function Name : 中断处理函数的名字默认由Short Name参数生成,但是用户也可以通过Isr Special Function Name特别指定。
Isr Stack Size : 指定中断栈大小。Microsar OS的Task和ISR都有独立的栈,
Isr Stack Fpu : 指定ISR是否使用FPU。
由于TriCore Aurix平台没有需要在上下文切换中保存的专用FPU寄存器,因此不需要由于使用浮点数而扩展上下文。