前言
《AUTOSAR OsTask切换原理》一文中,我们介绍基于TC3xx平台的OsTask的切换原理,TC3xx的CSA + Stack组合实现Task的上下文的切换和恢复,知道TC3xx芯片的A[10]寄存器始终指向当前运行的Task的Stack的栈顶,那么A[10]寄存器在运行过程中是否会越过Task的Stack区域了?也就是发生Stack的Overflow后Os又有什么机制可以监控的到了?本文就来介绍OsStack的监控原理。
目录
注:本文章引用了一些第三方工具和文档,若有侵权,请联系作者删除!
正文
官方文档描述:
在不提供任何内存保护硬件的处理器上,可能仍然需要为可检测的内存故障类别提供“尽最大努力利用可用资源”的方案。堆栈监控将识别任务或ISR在上下文切换时超过指定堆栈使用量的位置。这可能意味着在系统出错和检测到故障之间有相当长的时间。同样,在通知故障时,错误可能已被清除(当上下文切换发生时,堆栈可能小于指定的大小)。
仅仅监视系统的整个堆栈空间通常是不够的,因为不一定是正在执行的任务/ISR使用了比所需更多的堆栈空间——它可能是一个优先级较低的对象被抢占了。
通过让操作系统正确识别错误的Task/2类ISR,可以节省大量调试时间。
请注意,对于使用MPU和可扩展性等级3或4的系统,堆栈溢出可能会在堆栈监控能够检测到故障之前导致内存异常。
操作系统模块应提供堆栈监控,以检测Task/2类ISR的可能堆栈故障。
如果堆栈监控检测到堆栈故障,并且未配置ProtectionHook(),则操作系统模块应调用状态为E_OS_STACKFAULT的ShutdownOS()服务。
如果堆栈监控检测到堆栈故障,并且配置了ProtectionHook(),则操作系统模块应调用状态为E_OS_STACKFAULT的ProtectionHook.
MICROSAR定义了堆栈消费者(运行时上下文)可以使用的不同堆栈。然而,并非所有堆栈都可以被所有消费者使用。下表给出了MICROSAR的栈类型及其使用场景。
栈类型(Stack Type) | 多样性(Multiplicity) | 可能的堆栈消费者(Consumers) |
Init Stack | 每个核1个 | OS initialization, Os_PanicHook(), Category 0/1 ISRs |
Kernel stack | 每个核1个 | > OS memory exception handling > Os_PanicHook() > Category 0 ISRs |
Protection stack | 每个核1个或者0个 | > ProtectionHook() > OS API calls > Os_PanicHook() > Category 0 ISRs |
Error stack | 每个核1个或者0个 | > ErrorHooks (global and OS-application specific) > OS API calls > Category 0/1 ISRs > Os_PanicHook() |
Shutdown stack | 每个核1个或者0个 | > ShutdownHooks (global and OS-application specific) > OS API calls > Os_PanicHook() > Category 0 ISRs |
Startup stack | 每个核1个或者0个 | > StartupHooks (global and OS-application specific) > OS API calls > Category 0/1 ISRs > Os_PanicHook() |
Non-Trusted Functions Stack | 0…n个 | > Non-trusted functions > OS API calls > OS ISR wrapper > Trusted functions > Alarm callback functions > Pre / PostTaskHook() > Category 0/1 ISRs > Os_PanicHook() |
No nesting interrupt stack | 每个核1个或者0个 | > No nesting category 2 ISRs > OS API calls > Trusted functions > Alarm callback functions > Category 0/1 ISRs > Os_PanicHook() |
Interrupt level stacks | 0…n个 | > Nesting category 2 ISRs > OS API calls > OS ISR wrapper > Trusted functions > Alarm callback functions > Category 0/1 ISRs > Os_PanicHook() |
Task stacks | 0…n个 | > Tasks > OS API calls > OS ISR wrapper > Trusted functions > Alarm callback functions > Pre / PostTaskHook() > Category 0/1 ISRs > Os_PanicHook() |
IOC receiver pull callback stack | 每个核1个或者0个 | > IOC receiver pull callback functions > Category 0 ISRs |
Table 2-1 MICROSAR Classic OS Stack Types
为了节省RAM,不同的基本任务可能共享相同的任务堆栈。满足以下要求的任务共享一个堆栈:
·具有相同配置优先级的基本任务。
·非抢占式的基本任务,配置为共享堆栈。在这些基本任务中,不允许调用OS服务Schedule().
·共享内部资源并配置为共享堆栈的基本任务。在这些基本任务中,不允许调用OS服务Schedule().
Basic Task的OsTaskStackSharing属性需要配置为True. 然后,操作系统根据抢占设置和分配的内部资源决定是否可以共享基本任务堆栈。
共享任务堆栈的大小是共享堆栈的所有任务堆栈大小的最大值。
注意1:无论OsTaskStackSharing的值如何,操作系统都会自动为具有相同配置优先级的基本任务激活堆栈共享。
注意2:通过将“OsTaskStackSharing”设置为TRUE,可能无法在相应的基本任务中调用OS API服务Schedule()。如果在激活了堆栈共享的任务中调用Schedule(),操作系统会抛出错误。
注意3:任务的堆栈共享只能在分配给同一CPU核的任务之间实现
相互协作的任务共享同一堆栈。无需采取额外行动。
为了节省RAM,不同的2类ISR可能共享相同的ISR堆栈。
·所有不可嵌套的2类ISR可以共享一个堆栈。
·具有相同优先级的所有2类ISR可以共享一个堆栈。
对于2类 ISR,属性“OsIsrEnableNesting”必须设置为FALSE。
共享ISR堆栈的大小是所有配置的非稳定2类ISR堆栈大小的最大值。
注意:ISR的堆栈共享只能在分配给同一CPU核的ISR之间实现。
该功能由操作系统自动使用。同一核上所有不可嵌套的2类ISR共享同一堆栈。
操作系统将每个堆栈的最后一个元素初始化为特定的堆栈检查模式(check pattern)。每当执行堆栈切换(例如任务切换)时,操作系统都会检查有效堆栈的最后一个元素是否仍然保持堆栈检查模式(check pattern)。
如果操作系统检测到堆栈检查模式已被更改,则假定最后一个有效堆栈确实溢出。
MCU Types | Stack check pattern |
32-Bit Microcontrollers | 0xAAAAAAAA |
Table 2-2 Stack Check Patterns
注意1:软件堆栈检查能够检测堆栈溢出。它无法避开它们!
注意2:软件堆栈检查无法检测到所有堆栈溢出。可能存在相邻堆栈的内存已被覆盖,但当前堆栈的最后一个元素仍保存堆栈检查模式的情况。在这种情况下,软件堆栈检查无法检测到溢出。
注意3:软件堆栈检查无法检测已销毁的内存量。
注意4:如果由于堆栈错误(E_OS_STACK_FAULT)而报告错误,API GetTaskID()可能不会返回导致栈错误的任务的ID.
在SC1或SC2配置中,必须将属性“OsStackMonitoring”设置为TRUE以激活软件堆栈检查功能。
注意:在Supervisor模式禁用MPU的平台上,SC3和SC4配置的软件堆栈检查也可能被激活。在其他平台上,应在SC3或SC4配置中关闭软件堆栈检查。
一旦该功能被激活,操作系统就会在每次堆栈切换时自动检查堆栈。
如果操作系统检测到堆栈溢出,它将关闭。如果配置了ShutdownHook,则会调用它来通知应用程序操作系统已关闭。
调试提示:在调用ShutdownHook()之前,操作系统会恢复堆栈检查模式。
在操作系统的整个运行期间,当前活动堆栈由微控制器的MPU监控。因此,操作系统保留了一个MPU区域,该区域由操作系统通过每个堆栈开关重新编程(切换改MPU区域到Next Task的Stack区域)。
由于MPU避免了超出堆栈边界的写访问,因此不会发生堆栈溢出。
每当识别到内存违规(例如由于堆栈违规)时,都会引发异常。在异常处理中,操作系统调用ProtectionHook().
应用程序在ProtectionHook() 中决定如何处理内存保护违规。如果应用程序调用关闭操作系统,则还会调用ShutdownHook()(如果已配置)。
该系统必须配置为SC3或SC4系统。
在SC3/SC4系统中,操作系统自动初始化一个MPU区域以进行堆栈监控。
为了安全地检测堆栈违规,必须特别注意配置额外的MPU区域以及连接以下部分:
·配置其他MPU区域时,存储器区域不得授予对任何操作系统堆栈部分的写访问权限。这里还需要考虑区域的重叠。
·通过使用操作系统生成的链接器命令文件,可以确保操作系统堆栈连续链接到RAM中。
·需要一个与栈相邻的栈安全间隙(取决于栈的生长方向;见图2-1)。任何软件部件都不得对堆栈安全间隙具有写访问权限。
·堆栈安全间隙的大小必须至少达到MPU的粒度。这种限制通常是不够的,因为堆栈的访问偏移量可能大于MPU粒度。一种可能的解决方案是在RAM的开始或结束处链接堆栈部分(取决于增长方向)。
·安全间隙的连接是强制性的。否则,无法检测到地址最低的堆栈的堆栈违规。
Figure 2-1 Stack Safety Gap
注意1:不要配置授予任何操作系统堆栈写访问权限的MPU区域。
注意2:在联动方案(linkage scheme)中添加堆栈安全间隙。堆栈安全间隙是一个受限的内存区域。任何软件部件都不得具有对此区域的写访问权限。如果堆栈与存储区域相邻链接,则不需要安全间隙,因为写入访问受到硬件(如ROM)的限制。
在操作系统运行期间,应用程序可以获得最大的堆栈使用率。操作系统使用堆栈检查模式初始化所有操作系统堆栈(见表2-2)。
API函数能够返回每个堆栈的最大堆栈使用量(自调用StartOS() 以来)。
设置” OsStackUsageMeasurement”参数位TRUE.
堆栈使用API可以在应用程序的任何地方使用。
AUTOSAR标准:如果堆栈监控检测到堆栈故障,且未配置ProtectionHook,则操作系统模块应调用状态为E_OS_STACKFAULT的ShutdownOS()服务。
MICROSAR实现:在具有MPU堆栈监控的SC3/SC4系统中:如果堆栈监控检测到堆栈故障且未配置ProtectionHook,操作系统模块应调用状态为E_OS_PROTECT_MEMORY的ShutdownOS()服务。
偏差原因:通过硬件堆栈监督,MICROSAR Classic OS无法区分堆栈违规和其他内存违规。
AUTOSAR标准:如果堆栈监控检测到堆栈故障并且配置了ProtectionHook,则操作系统模块应调用状态为E_OS_STACKFAULT的ProtectionHook().
MICROSAR实现:在具有MPU堆栈监控的SC3/SC4系统中:如果堆栈监控检测到堆栈故障并且配置了ProtectionHook,则操作系统模块应调用状态为E_OS_PROTECT_MEMORY的ProtectionHook().
偏差原因:通过硬件堆栈监督,MICROSAR Classic OS无法区分堆栈违规和其他内存违规。
参考链接:https://blog.csdn.net/qq_36056498?spm=1011.2266.3001.5343
本文介绍了AUTOSAR OS中关于栈监控的概念以及Stack监控的具体实现。在SC3和SC4系统中因为使能了MPU保护,发生Stack Overflow后首先会由MPU识别到并产生Memory Protection Trap, 通过ProtectionHook()上报E_OS_PROTECT_MEMORY的Error. 在SC1和SC2系统中因为没有使能MPU保护,则通过软件监控Stack实现,其监控原理也就是监控stack end address处的Stack Pattern有没有被篡改过,如果被篡改则上报E_OS_STACKFAULT的Error.
End
「汽车电子嵌入式在CSDN上同步推出AUTOSAR精进之路专栏,本专栏每个模块完全按实际项目中开发及维护过程来详细介绍。模块核心概念介绍、实际需求描述、实际工程配置、特殊需求介绍及背后原理、实际工程使用经验总结。目的是让读者看完每一个章节后能理解原理后根据需求完成一个模块的配置或者解决一个问题。」
点击文章最后左下角的阅读原文可以获取更多信息
或者复制如下链接到浏览器获取更多信息
https://blog.csdn.net/qq_36056498/article/details/132125693
文末福利
2.为便于技术交流,创建了汽车电子嵌入式技术交流群,可尽情探讨AP,CP,DDS,SOME/IP等前沿热点话题,后台回复“加群”即可加入;
注:本文引用了一些第三方工具和文档,若有侵权,请联系作者删除!
推荐阅读
汽车电子嵌入式精彩文章汇总第一期:20210530-20230703
汽车电子嵌入式精彩文章汇总第2期
汽车电子嵌入式精彩文章汇总第3期
【OS】AUTOSAR OS Event实现原理
【OS】AUTOSAR OS Spinlock实现原理(下篇)
【OS】AUTOSAR OS Spinlock实现原理(上篇)
CanNm处于PBS状态下接收到一帧诊断报文DCM会响应吗
TC3xx芯片CAN模块详解
AUTOSAR OS Alarm实现原理
AUTOSAR OsTask切换原理
TC3xx 芯片SPI模块详解
AUTSOAR ComStack如何实现PDU只收不发的
End
欢迎点赞,关注,转发,在看,您的每一次鼓励,都是我最大的动力!
汽车电子嵌入式
微信扫描二维码,关注我的公众号