OSEK错误处理及跟踪调试

1 前言

        如表1所示,OSEK提供了一些特殊的钩子例程(Hook routines),应用层可以在钩子函数中自定义操作,以参与到操作系统的内部处理中。

表1 钩子函数类型
钩子函数例程功能用途
ErrorHook用于错误处理
StartupHook在系统启动后,调度器运行前调用(is called after the operating system startup and before the scheduler is running.)
ShutdownHook当应用层请求系统关闭,或OS自身因为严重的错误要关闭系统时,调用该钩子函数
PreTaskHook上下文切换过程中,新任务进入运行态那一刻调用
PostTaskHook上下文切换过程中,老任务退出运行态那一刻调用

        这些钩子函数例程有如下特点:

        • 钩子函数由OS调用,其调用的上下文取决于OS的具体实现,即完全由OS决定;
        • 优先级比所有任务都高;
        • 不会被二类中断(category 2 interrupt routines)打断;
        • 是操作系统的一部分,但由应用层来定义实现其具体操作内容;
        • 在接口层统一标准,但功能层(environment and behaviour of the hook routine itself)取决于具体实现,因此通常不具有移植性;        

图1 API调用限制说明 

       由图1可见,大多的系统API服务都不可在钩子例程中使用,这一限制主要是为了降低系统的复杂度。如果应用函数在钩子例程中违规调用了不可用的API服务,其行为是未定义的,但OS应返回特定的错误码。 


2 错误处理(Error handling)

        OSEK提供了一种错误处理服务(error service),用于处理OS的临时错误或持续性错误(temporarily and permanently occurring errors)。也就是说,ErrorHook是用来处理OS内部检测到的错误,这些错误的直接体现就是各系统服务API的返回值。

2.1 错误分类

        OSEK将错误分为两类,应用错误(Application errors)和致命错误(Fatal errors),其对应的处理策略也各不相同。在错误处理的过程中,这些错误处理服务都会获得对应的错误参数,以明确错误信息。       

        对于应用错误来说,其主要表现是OS对应的系统服务的执行出现了错误,但OS的内部数据结构仍保持正确性和完整性。在这种情况下,OS会先进行集中式的错误处理(centralised error treatment),并向通过处理状态返回错误信息,由应用层根据错误类型决定后续操作,即所谓的分散化处理(decentralised error treatment)。

        对于致命错误来说,OS无法在保证其内部数据结构的正确性和完整性,诸如任务控制块、任务控制列表等。在这种情况下,OSEK会选择人死帐销,直接调用集中式系统关闭。

        OSEK将错误检查分类两类,标准状态和拓展状态(standard status and extended
status)。如果一个任务是是在标准状态下激活的,则可以返回"E_OK" 或 “Too many task
activations”两种状态;而拓展状态在此基础上,还可以返回"Task is invalid" 或 "Task still occupies resources"等状态。

        此外,对于OSEK来说,系统调用API的返回值的优先级高于其输出参数。也就是说,当返回值为错误时,其对应的输出参数是未定义的。

2.2 避免ErrorHook的递归调用

        当一个系统调用的返回值不为E_OK时,就会调用错误处理钩子例程(ErrorHook)。特殊地,为了防止ErrorHook的递归调用,OSEK规定,如果发生错误的该系统调用来自于ErrorHook内部,则错误发生时,不会触发对ErrorHook的(递归)调用。

        因此,在ErrorHook内部,如果进行系统API的调用,其错误检查的唯一方式就是判断该系统调用的返回值。

2.3 错误处理

        OSEK为ErrorHook的错误处理制定了标准规范,以方便获取错误时的上下文信息,包括发生错误时的系统调用API及其对应调用参数,具体逻辑架构如图2所示:

图2  Example of centralised error handling (extended status)

         其中,宏OSErrorGetServiceId()提供发生错误时所调用的系统服务ID(service identifier),其对应的类型为OSServiceIdType,取值通常为OSServiceId_xxxx(xxxx为系统服务的名字)。

        关于系统服务的参数获取,也有标准的命名规范,通常统一为OSError_Name1_Name2:

• Name1: is the name of the system service
• Name2: is the official name of the parameter within the OSEK OS specification

         举例来说,当触发ErrorHook的系统服务为SetRelAlarm时,SetRelAlarm对应的参数通常可以通过以下宏定义获取:

• OSError_SetRelAlarm_AlarmID()
• OSError_SetRelAlarm_increment()
• OSError_SetRelAlarm_cycle()

 2.4 系统启动(System start-up)

        通常来说,处理器复位后,系统初始化的过程取决于具体的实现,但OSEK规定了一个标准的初始化流程,包括硬件初始化、OS初始化及应用的初始化。

        OSEK并未强制应用程序在系统初始化完成后定义特定的任务,但允许指定一些自启动任务自启动定时器(autostart alarms)随着系统初始化一起启动。

图3 System start-up

          系统的启动过程如图3所示:

        ① CPU复位后,首先进行的时硬件的初始化,初始化完成后会进行应用模式的判别(application mode),处于安全考虑,该判别不可依赖于系统历史记录(system history);

        ② 随后就是可移植的部分了,标准接口StartOS会根据当前的应用模式进行OS的初始化;

        ③ OS进行一系列的初始化操作;

        ④ 调用StartupHook,该钩子函数的实现由应用层实现,主要用于进行一些和OS强相关的一些初始化操作,应用层可以通过GetActiveApplicationMode获取当前的应用模式,在此过程中,所有中断都被禁用;

        ⑤ 钩子函数运行完毕后,OS会使能所有中断,启动调度器,并先后激活当前应用模式下定义的自启动任务和自启动定时器,最后,系统开始运行,开始按调度规则启动应用层定义的任务。

2.5 系统关闭(System shutdown)

         OSEK定义了一个标准接口ShutdownOS用于系统的关闭。该接口通常由应用层调用,请求关闭系统,或者由于OS探测到致命错误时,主动调用。

        当ShutdownOS被调用时,OS会调用钩子例程ShutdownHook函数,并待其执行完毕后,才真正关闭系统。

2.6 系统调试(Debugging)

        PreTaskHook PostTaskHook用于在任务切换的上下文中调用,具体如图4所示。这两个钩子例程函数主要用于系统调试或时间测量(time measurement),包括上下文切换时间。        

        因此,PostTaskHook会在老任务离开运行态之间被调用,而PreTaskHook 则是在新任务进入运行态那一刻被调用。由于调用时新老任务都仍旧/已经(still/already)在运行态,整个过程中,系统服务GetTaskId都是可用的。

图4 PreTaskHook and PostTaskHook

         若是被ShutdownOS调用时,有任务正在运行,则ShutdownOS可以调用PostTaskHook,也可以不调用PostTaskHook,且OSEK对PostTaskHook和ShutdownHook运行的先后顺序没有做强制要求。

  • 10
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值