电子说
前言
为了提供系统的安全性能,TC3xx上一些重要的寄存器都受Endinit保护,不能直接修改。如果想要修改这些重要寄存器,就需要先按特定步骤解锁Endinit,然后才能修改这些重要的寄存器的值,最后还要上锁Endinit。那什么是Endinit功能了? -- 本文就来详细解锁TC3xx芯片的Endinit机制。
Note: 第1到5章节都是关于Endinit的概念介绍,如果感觉比较枯燥可以先从第6章节的实际应用开始阅读。
缩略词
简写 | 全称 |
Endinit | End of initialization |
WDTCPUyCON0 | CPUy WDT Control Register 0 |
WDTSSR | Safety WDT Status Register |
注:本文章引用了一些第三方工具和文档,若有侵权,请联系作者删除!
正文
1.功能概述
在系统或应用程序的初始化过程中,通常只对一些寄存器进行一次编程(programmed only once)。 在正常应用程序运行期间修改此类寄存器可能会严重影响模块或整个系统的整体运行。
虽然 Supervisor Mode 和 Access Protection 方案提供了一定级别的保护,防止意外修改,但它们可能不足以防止对系统关键注册器的所有意外访问。
为这类寄存器提供了额外的保护,称为 Endinit (“End off initialization”)。 Endinit 是一种写保护方案,它只允许在特定时间进行写入,并使受此功能保护的寄存器的意外修改几乎不可能实现。
Endinit 功能由每个 WDT 控制寄存器中包含的 ENDINIT 位组成。 通过 Endinit 保护的寄存器决定是否启用写入。 只有当相应的 ENDINIT =0 且主管模式处于活动状态时,才会启用写入。 如果这种情况不正确,则写入尝试将被放弃,在这种情况下,寄存器内容将不会被修改。
为了获得最高的稳定性,写入 ENDINIT 位将受到 WDT 中实施的高度安全的访问保护方案的保护。 这是一个复杂的过程,几乎不可能无意中修改 ENDINIT bits。 此外,每次软件通过清除相应的 ENDINIT 位来打开对关键寄存器的访问时,每个 WDT 都会启动超时序列来监视 ENDINIT 位的修改。 如果超时时间在相应的 ENDINIT 位再次设置之前结束,则假定软件出现故障,并生成看门狗故障响应。
以下各节介绍了 WDT 的访问保护方案和 Endinit 超时操作。 在每个模块 (包括 SCU 本身) 的寄存器概览表中,通过每个 Endinit 类型保护的寄存器在描述写入访问的列中标识,如下所示:
“ CEy ” - CPU 关键寄存器。 仅当 CPUy WDT ENDINIT=0 (y=CPU number) 时可写。也就是,只有把要要访问这个寄存器的CPU的ENDINIT设为0后,这个寄存器才能被这个CPU写访问(也就是解锁WDTCPUyCON0.ENDINIT)。
“ E ” - 系统关键寄存器 - 任何 (一个或多个) CPUy 看门狗计时器 ENDINIT=0 或 EICON0.ENDINIT=0 时可写。也就是,任意一个CPU的ENDINIT设为0后,所有CPU都可以对这个寄存器进行写访问。
“ SE ” - 安全关键寄存器 - 仅当安全监控计时器 ENDINIT=0 或 SEICON0.ENDINIT=0 时才可写入。也就是,Safety Watchdog的ENDINIT设为0后,Safety EndInit的保护就解除了,所有CPU都可以对这个寄存器进行写访问(也就是解锁WDTSCON0.ENDINIT)。
以上都不是 - 随时都可以访问
图 1 显示了解锁各种 ENDINIT 写保护模式的选项。
Figure 1: ENDINIT Control Registers
Note: ENDINIT 位的清除需要一些时间。 在清除 ENDINIT 位后访问受 Endinit 保护的寄存器必须仅在 ENDINIT 位真正被清除时进行。 作为一种解决方案, ENDINIT 位应在 ENDINIT位 清除后第一次访问受 Endinit 保护的寄存器之前被读回一次。
2. WDTxCON0 的密码访问(Password Access to WDTxCON0)
为了解锁WDTxCON0(x=CPUy and y=CPU number, or S)寄存器并修改WDTxCON0寄存器,必须往WDTxCON0寄存器中写入正确的密码(password)。软件必须事先知道正确的密码,或者在运行时计算密码。 每个监视程序计时器(Watch)的密码 (x=CPUy 和 y=CPU 编号,或 S) 可以不同,以便提供独立的监视程序功能程序流,以具有独立的监视程序功能。
安全监视器密码寄存器(Safety Watchdog password register) WDTSCON0 受通用 SCU 保护,该保护方案只允许配置的masters具有写入访问权限。
特定于 CPU 的监视程序密码寄存器(CPU-specific Watchdog password) WDTCPUyCON0 单独受到保护,因此它们只能由相应的 CPUy 写入。
在安全应用程序中可以使用看门狗来提供恢复时间,在此期间软件可能会尝试从安全警报警告中恢复。 为确保 CPU 故障不允许忽略故障,提供了一个选项,用于在安全管理单元 (SMU) 处于故障状态时防止看门狗解锁。 此选项可由位 WDTxCON1.UR 启用。
如果密码有效且 SMU 状态满足 WDTxSR.US 位的要求,则一旦密码访问完成, WDTxCON0 将被解锁。 解锁条件将由 WDTxCON0.LCK = 0 指示。 为了确保正确的服务顺序(servicing sequence),只有在访问之前设置了 WDTxCON0.LCK 位时才允许密码访问。
如果在密码访问期间向 WDTxCON0 写入了不正确的密码值,则存在看门狗访问错误情况。 位 WDTxSR.AE 已设置,并向安全管理单元 (SMU) 发送警报请求。 14 位用户可定义密码 WDTxCON0.PW 提供了其他选项,用于根据应用程序的需要调整密码要求。 例如,它可用于检测意外的软件循环,或监视例程的执行顺序。
下表 汇总了密码的要求。 有多种选择,下文将更详细地介绍这些选择
Table 1:Password Access Bit Pattern Requirements
2.1 Static Password
在静态密码模式 (WDTxSR.PAL=0) 中,密码只能通过有效的“修改访问”进行更改。 密码访问(Password Access)的设计使其不可能简单的读取寄存器并重写寄存器。 在重新写入之前,某些密码读取位必须反向 (切换)。 这可以防止简单的故障通过简单的读 / 写序列意外解锁 WDT。
2.2 Automatic Password Sequencing
如果启用了自动密码排序 (WDTxSR.PA=1) ,则每次检查密码后,密码会自动更改 (即 Password Access or Check Access)。 预期的下一个密码遵循基于具有特征多项式 x14+X13+x12+x2+1 的 14 位斐波那契(Fibonacci) LFSR (Linear Feedback Shift Register) 的pseudorandom sequence。 修改访问权限还可以提供初始密码 (或后续手动密码更新)。
Figure 2: Password Sequencing LFSR
2.3 Time-Independent Pasword
如果未启用时间检查 (WDTxSR.TCS=0) ,则 WDTxCON0 寄存器的 REL 字段必须在密码访问期间使用现有的重新加载值重新写入。
2.4 Time Check Password
如果启用时间检查 (WDTxSR.TCS=1) , WDTxCON0 寄存器的 REL 字段必须使用当前 WDT 计数值的反向 (位翻转) 估计值写入。 此估计的可接受误差幅度 (在 WDT 时钟周期内) 由 WDTxSR.TCT 的值指定。 如果写入的估计值超出 WDTxSR.TIM +/- WDTxSR.TCT 范围,则 SMU 回发出Alarm报警。 此机制可以检查自上次 WDT 重新启动以来已过的程序执行时间。 请注意,当 WDT 以超时模式运行 (访问受 ENDINIT 保护的寄存器后) 时,密码或检查访问仍需要时间检查比较。
3. WDTxCON0的检查访问(Check Access to WDTxCON0)
Check Access 与 Password Access 相同,只不过锁位(lock bit)未被清除,因此不允许后续的“修改访问”。 如果满足写入数据要求,“检查访问”不会触发 SMU 警报请求。 只有在设置了 LCK 位时才能执行检查访问。
此类访问用于 WDT 服务之间的中间检查点。 这可以用于任务序列或执行时间监控 (例如,与时间戳计数检查功能或序列密码结合使用)。
Table 2: Check Access Bit Pattern Requirements
如果在检查访问期间向 WDTxCON0 写入了不正确的值 (x=CPUy and y=CPU number, or S) ,则存在看门狗访问错误情况。 位 WDTxSR.AE 已设置,并向安全管理单元 (SMU) 发送警报请求。
4. WDTxCON0的修改访问(Modify Access to WDTxCON0)
如果密码访问(Password Access)成功解锁 WDTxCON0 (x=CPUy and y=CPU number, or S) ,则以接下来的WDTxCON0 的写入访问可以对其进行修改。 但是,这种访问也必须满足某些要求才能被接受并被视为有效。 表 3列出了所需的位模式(bit patterns)。 如果访问不遵循这些规则,则会检测到监视程序访问错误情况,设置位 WDTxSR.AE ,并向安全管理单元 (SMU) 发送警报请求。 修改访问完成后,将再次设置 WDTxCON0.LCK ,自动重新锁定 WDTxCON0。 在重新修改寄存器之前,必须再次执行有效的密码访问。
Table 3: Modify Access Bit Pattern Requirements
5. 访问受Endinit保护的寄存器
如果在运行期间需要对受 Endinit 保护的寄存器进行写入访问,则可以在有限的时间内临时重新启用写入访问。 提供了两种选择:
通过 WDT 刷新重新启用对受 ENDINIT 保护的寄存器的访问
无需 WDT 刷新即可重新启用对 ENDINIT 保护的寄存器的访问
为了获得调试支持, Cerberus 模块可以覆盖所有 WDT 的所有 ENDINIT 控件,以简化调试流程。 如果设置了 CBS_OSTATE.ENIDIS位 ,则所有 ENDINIT 保护都将被禁用,而不管 WDT 配置的当前状态如何。 如果清除了 CBS_OSTATE.ENIDIS ,则完整的ENDINIT控制位于 WDT 内。
5.1 通过WDT访问Endinit保护的寄存器
要重新启用访问(修改受Endinit保护的寄存器),必须先使用有效的密码访问解锁 WDTxCON0。 在随后的有效修改访问中,可以清除 ENDINIT。解锁WDTxCON0且清除ENDINT后, 就能再次打开对受 Endinit 保护的寄存器的访问。 注意,当 WDTxCON0 解锁时, WDT 会自动切换到超时模式。 因此,访问窗口有时间限制。 超时模式仅在重新设置 ENDINIT 后终止,需要另一个有效密码和有效的 WDTxCON0 修改访问权限。
5.2 不通过WDT访问Endinit保护的寄存器
在某些应用中,可能不使用 WDT ,并将被禁用 (WDTxSR.DS =1) ,尽管不建议这样做。
在其他应用程序中,可能会使用 WDT 时间戳功能,刷新之间的 WDT 访问将是不可取的。
在这种情况下,仍然可以使用 ENDINIT 全球控制寄存器 (EICONx) 来临时访问受 Endinit 保护的寄存器。
6. Endinit实际应用
6.1 Endinit需求及场景介绍
需求:在ECU上电后需要在Startup阶段关闭看门狗,也就是配置WDTxCON1(x标识CPU0-5)的DR位域。但是,WDTxCON1寄存器是受Endinit保护的。所以,在修改前我们需要解锁Endinit,修改完WDTxCON1寄存器后再上锁Endinit。
分析1:因为CBS_OSTATE.ENIDIS只有在Debug模式下通过Cerverus module来Disable(置位CBS_OSTATE.ENIDIS),所以上电的时候因为CBS_OSTATE.ENIDIS是被Cleared的。
所以,能够通过WDT模块解锁Endinit功能。参考第5章节两种解锁Endinit的方式。
分析2:WDTSSR寄存器的Reset值是0xFFFC 0010,则WDTSSR.PAS为0,WDTSSR.TCU为0。
所以,使用static password来解锁Endinit. 参考2.1和2.2章节的static password和Automatic Psassword 。
分析3:我们通过配置WDTSCON0寄存器来解锁Endinit.
6.2 Endinit解锁
解锁流程,参考Table 1.
Example: 解锁CPU0的Endinit.
#define WDT_WDTSCON0_ADDR 0xF0036024u #define STARTUP_CLR_WDTLCK_WDTHPW27 (0xFFFFFF01u) #define STARTUP_SET_WDTHPW27 (0xF0u) #define STARTUP_SET_ENDINIT (0x01u) #define STARTUP_CLR_WDTHPW27_WDTLCK_ENDINIT (0xFFFFFFF0u) #define STARTUP_SET_WDTLCK (0x02u) #define STARTUP_SET_WDTLCK_ENDINIT (0x03u) void UnlockEndinit_Core0(void) { volatile uint32 WDTCON0_Register_Value; volatile uint32 *WDTCON0_Address; WDTCON0_Address = WDT_WDTSCON0_ADDR; /* * Create password and send to WDTSCON0 */ WDTCON0_Register_Value = *WDTCON0_Address; /* Clear WDTSCON0.LCK, WDTSCON0.PW[2:7]*/ WDTCON0_Register_Value &= STARTUP_CLR_WDTLCK_WDTHPW27; /* Set WDTSCON0.PW[2:7] to 0xF */ WDTCON0_Register_Value |= STARTUP_SET_WDTHPW27; /* Written 1 to WDTSCON0.ENDINIT for password access */ WDTCON0_Register_Value |= STARTUP_SET_ENDINIT; *WDTCON0_Address = WDTCON0_Register_Value; /* * Set the bit ENDINIT to 1 or 0 to allow access to registers of WDT_CON1 e.g. */ /* Clear WDTSCON0.PW[2:7], WDTSCON0.LCK, WDTSCON0.ENDINIT */ WDTCON0_Register_Value &= STARTUP_CLR_WDTHPW27_WDTLCK_ENDINIT; /* WDTSCON0.PW[2:7]=0, WDTSCON0.LCK=1, WDTSCON0.ENDINIT=0 */ WDTCON0_Register_Value |= STARTUP_SET_WDTLCK; *WDTCON0_Address = WDTCON0_Register_Value; WDTCON0_Register_Value = *WDTCON0_Address; }
6.3 Endinit上锁
上锁流程,参考Table 3.
Example: 上锁CPU0的Endinit.
void LockEndinit_Core0(void) { volatile uint32 WDTCON0_Register_Value; volatile uint32 *WDTCON0_Address; WDTCON0_Address = WDT_WDTSCON0_ADDR; /* * Create password and send to WDTSCON0 */ WDTCON0_Register_Value = *WDTCON0_Address; /* ClearWDTSCON0.LCK, WDTSCON0.PW[2:7]*/ WDTCON0_Register_Value &= STARTUP_CLR_WDTLCK_WDTHPW27; /* set WDTSCON0.PW[2:7] to 0xF */ WDTCON0_Register_Value |= STARTUP_SET_WDTHPW27; /* Write 1 to ENDINIT for password access */ WDTCON0_Register_Value |= STARTUP_SET_ENDINIT; *WDTCON0_Address = WDTCON0_Register_Value; /* modify access to WDTSCON0 */ /* * Set the bit ENDINIT to 1 or 0 to allow access to registers of WDT_CON1 .e.g. */ /* Clear WDTSCON0.PW[2:7], WDTSCON0.LCK, WDTSCON0.ENDINIT */ WDTCON0_Register_Value &= STARTUP_CLR_WDTHPW27_WDTLCK_ENDINIT; /* WDTSCON0.PW[2:7]={0}, WDTSCON0.LCK=1, WDTSCON0.ENDINIT=1 */ WDTCON0_Register_Value |= STARTUP_SET_WDTLCK_ENDINIT; *WDTCON0_Address = WDTCON0_Register_Value; WDTCON0_Register_Value = *WDTCON0_Address; }
7. 总结
为了提供系统的安全性,TC3xx芯片提供了Endinit机制来保护一些特殊的寄存器。在修改这些特殊寄存器的时候需要先解锁Endinit, 在解锁Endinit时需要考虑使用static静态还是automatic自动密码机制以及是否使用超时机制等。确定了解锁Endinit的类型后,就可以按照特定的步骤来解锁Endinit,然后按照UnlockEndinit à modify protected register à LockEndinit的步骤来修改特殊寄存器即可。
全部0条评论
快来发表一下你的评论吧 !