tricore architecture - Tasks and Functions
大多数嵌入式和实时控制系统采用一种模型,在该模型中,中断处理程序和软件管理的任务都被视为在各自的“虚拟”微控制器上运行。该模型通常由实时执行系统或实时操作系统 (RTOS) 提供支持,并层叠在底层机器架构的功能和能力之上。
在 TriCore™ 体系结构中,RTOS 层可以非常“薄”,硬件能够高效处理任务之间的切换。同时,该架构允许任务模型具有相当大的灵活性。系统设计者可以根据应用的需求选择最合适的实时执行系统和软件设计方法,且架构施加的限制相对较少。
TriCore™ 体系结构中的低开销任务切换机制与函数调用机制密切相关。
1 上下文类型
任务是一个独立的控制线程。任务的状态由其上下文定义。当任务被中断后,处理器可以使用该任务的上下文,让任务恢复并继续执行。
上下文类型包括:
- 上层上下文:包括上层地址寄存器 A[10] 到 A[15] 以及上层数据寄存器 D[8] 到 D[15]。上层上下文还包括 PCXI 和 PSW。这些寄存器被指定为非易失性寄存器,在函数调用时,其内容会被保留。
- 下层上下文:包括下层地址寄存器 A[2] 到 A[7],下层数据寄存器 D[0] 到 D[7],A[11](返回地址)以及 PCXI。
当上下文被保存到内存时,它们占用 16 字的存储块,称为 上下文保存区域(CSAs)。
1.1 上下文保存区(CSA)
该架构使用固定大小的上下文保存区(Context Save Areas,CSA)链表。每个 CSA 是 16 个字的存储单元,并且在 16 字边界上对齐。每个 CSA 可存储一个完整的上层或下层上下文。CSAs 通过链接字(Link Word)PCXI 连接在一起。
链接字包含两个字段,用于将当前 CSA 与链中的下一个 CSA 连接起来。这两个字段分别是 4-bit 段号 和 16-bit 偏移量。段号和偏移量用于生成有效地址(Effective Address,EA),即链接 CSA 的地址。见图 13。
将指针偏移值增加 1 时,总是会使 EA 增加 16 个字的位置,从而指向链中的下一个 CSA。每个地址段内的 CSA 总可用范围为 4 MBytes,这意味着一个段最多可存储 2¹⁶ 个 CSAs。
如果 CSA 正在使用中(例如,它存储了某个挂起任务的上层或下层上下文数据),则链接字还会包含与该上下文相关的其他信息(PCPN、PIE)。整个链接字实际上是与该任务关联的 PCXI 寄存器 的副本。
2 任务切换操作
当系统遇到表 7中列出的事件或指令之一时,体系结构会执行任务切换。当发生这些事件或指令时,任务的上层或下层上下文会被保存或恢复。上层上下文 会在外部中断、陷阱(Trap)或函数调用时自动保存。下层上下文 需要通过指令显式保存。
注意:多任务系统 中,软件应该 完整保存任务上下文,以确保系统的正常运行(这里包括上层上下文 和 下层上下文)。
Table 7 Context Related Events and Instructions
Event / Instruction | Context Operation | Complement Instruction | Context Operation |
---|---|---|---|
Interrupt | Save Upper | RFE - Return from Exception | Restore Upper |
Trap | Save Upper | RFE - Return from Exception | Restore Upper |
CALL - Function Call | Save Upper | RET - Return from Call | Restore Upper |
BISR - Begin Interrupt Service Routine | Save Lower | RSLCX - Restore Lower Context | Restore Lower |
SVLCX - Save Lower Context | Save Lower | RSLCX - Restore Lower Context | Restore Lower |
STLCX - Store Lower Context | Store Lower | LDLCX - Load Lower Context | Load Lower |
STUCX - Store Upper Context | Store Upper | LDUCX - Load Upper Context | Load Upper |
在 表 7 中,“保存”(Save) 指的是通过空闲 CSA 列表头指针寄存器(FCX) 进行存储,存储之前会从链接字(Link Word) 读取 FCX 的下一个值。“存储”(Store) 指的是通过指令的有效地址(Effective Address, EA)进行存储,不影响 CSA 链表或 FCX 寄存器。
“恢复”(Restore) 是 “保存”(Save) 的逆过程。
“加载”(Load) 是 “存储”(Store) 的逆过程。
上层和下层上下文中的寄存器在维护内容方面存在本质区别。
下层上下文寄存器类似于全局寄存器,意味着当中断处理程序、陷阱处理程序或被调用的函数运行时,它们可以看到中断、陷阱或调用发生前寄存器中的值。在 中断处理、陷阱处理 或 函数调用 期间对这些寄存器的修改不会自动恢复,因为它们不受函数返回(RET)或异常返回(RFE)机制的影响。这些寄存器可用于向函数传递参数或返回值。中断和陷阱处理程序在使用这些寄存器时必须先保存原始值,并在退出前恢复原始值。
上层上下文寄存器不一定是静态的硬件寄存器。函数调用或中断处理程序执行时,总是使用独立的上层上下文寄存器,而不会继承被中断的任务或调用函数的上层寄存器。在调用的函数、陷阱处理程序或中断处理程序中,只有以下寄存器在执行时具有体系结构定义的初始值:A[10](SP,堆栈指针)、A[11](RA,返回地址)、PSW(程序状态字)、PCXI(上下文指针索引寄存器)、D[15](仅适用于陷阱处理)。如果函数、陷阱处理程序或中断处理程序在写入值之前读取其他上层上下文寄存器,那么该操作是未定义的行为。
3 上下文保存区域 (CSAs) 和上下文列表
上部和下部上下文存储在 上下文保存区域 (CSAs) 中。未使用的 CSAs 通过自由上下文列表 (FCX) 连接在一起,而包含已保存的上部或下部上下文的 CSAs 通过先前上下文列表 (PCX) 连接在一起。
FCX 寄存器的内容始终指向自由上下文列表中可用的 CSA,该 CSA 的链接字指向自由上下文列表中的下一个可用 CSA。 在存储上部或下部上下文到首个可用 CSA 之前,其链接字会被读取,从而为 FCX 提供新值。对于内存子系统而言,上下文存储因此成为读取 / 修改 / 写入操作。新的 FCX 值(指向下一个可用的 CSA)在后续的上部或下部上下文存储操作时立即可用。
LCX 寄存器指向自由列表中的最后几个 CSAs 之一,用于识别即将耗尽的自由 CSA 列表。 如果当执行上下文存储的操作时,FCX 值与 LCX 值相匹配,该操作完成,并在下一条指令上触发自由 CSA 列表耗尽陷阱 (FCD);即 FCD 陷阱的返回地址为陷阱 / 中断 / 调用例程的第一条指令,或紧跟在 SVLCX 或 BISR 指令后的指令。
陷阱处理的动作取决于软件的实现方式。可能采取以下措施:
- 如果确定 CSA 列表耗尽是由于不可恢复的软件错误,可能执行系统重置。- 正常情况下,它会扩展自由列表,通过分配额外内存或终止一个或多个任务并回收它们的 CSA 调用链。在这种情况下,陷阱处理程序通过 RFE 指令 退出。
在首次使用自由上下文列表中的最后一个 CSA 之前,必须将其链接字设置为 NULL。这是为了支持 FCU 陷阱。
在首次使用 CSA 之前,PCX 指针值应为NULL,以支持 CSU(调用堆栈下溢)陷阱(这里指的是创建任务时,为其分配的模拟上下文,实际不能通过这些“假”的上下文返回)。
PCXI.PCX 字段指向存储先前上下文的 CSA。 PCXI.UL 位用于标识已存储的上下文是上部 (PCXI.UL == 1) 还是下部 (PCXI.UL == 0)。 如果上下文类型与上下文恢复操作所需的类型不匹配,将发生 CYTP 异常,并触发上下文管理陷阱。
在执行上下文存储操作后,返回地址 A11 会被更新:
- 函数调用:A11 更新为函数返回地址。
- 同步陷阱:A11 更新为引发陷阱的指令 PC。
- SYSCALL 和 异步陷阱或中断:A11 更新为下一条待执行指令的 PC。
当执行下部上下文存储操作时,A11 的值被包含在已存储的上下文中,并放置在 CSA 的第二个字中。 在下部上下文恢复操作时,该 A11 被对应恢复。
调用深度控制字段 (PSW.CDC) 包括两个子字段:
- 调用深度计数器:调用时递增,返回时恢复。
- 溢出检测掩码:定义计数器的宽度,并在溢出时触发异常。
调用深度计数器在调用时递增,在返回时恢复。 当计数器发生溢出时,会发生异常,其目的是防止软件错误导致“无限递归”并耗尽CSA 自由列表。
4 Context Switching with Interrupts and Traps
当发生中断或陷阱(例如 NMI 或 SYSTRAP)时,处理器会将当前任务的上层上下文(Upper Context)保存到内存中,暂停当前任务的执行,并开始执行相应的中断或陷阱处理程序。
如果在发生中断或陷阱时,处理器未使用中断堆栈(PSW.IS 位 == 0),则堆栈指针会被加载为当前的 ISP(中断堆栈指针)值。随后,PSW.IS 位被设置为 1,以指示当前执行来自中断堆栈。
中断控制寄存器(ICR) 包含:
- 当前 CPU 优先级号(ICR.CCPN)
- 中断使能位(ICR.IE)
- 挂起中断优先级号(ICR.PIPN)
这些字段与 先前 CPU 优先级号(PCXI.PCPN) 和 先前中断使能(PCXI.PIE) 共同构成中断管理系统。
当发生中断和陷阱:
- 当前 PCXI 的 PCPN 和 PIE 值会被存入 CSA(用于存储上层上下文)。
- 现有的 ICR 中的 IE 和 CCPN 值会被复制到 PCXI.PIE 和 PCXI.PCPN 字段。
发生中断或陷阱时,处理器会自动保存当前任务的 上层上下文。如果中断或陷阱处理程序的逻辑较小,可以完全在这些被保存的寄存器集内执行,则不需要额外的上下文保存,处理程序可以立即执行并返回。更一般的情况下,如果处理程序需要调用函数或使用更多的寄存器,则会执行 BISR(Begin Interrupt Service Routine) 或 SVLCX(Save Lower Context) 指令,以额外保存 下层上下文,这些指令必须在修改相关寄存器前执行,但不一定需要是处理程序的第一条指令。
因此,对于响应时间关键的中断处理程序:可以立即使用 上层上下文寄存器 进行初始的时间关键处理。之后执行 BISR 并继续处理相对不那么时间紧迫的任务。BISR 指令会重新启用中断,因此它可以用来将时间关键处理与非时间关键处理分开。
备注:tricore进入中断/trap后默认为关闭中断状态,BISR指令执行前,中断是关闭状态,因此不会被打断,可以用来执行关键处理。 BISR执行后,中断会被再次打开,此时可能会被高优先级中断抢占。
5 函数调用的上下文切换
当执行 CALL 指令进行函数调用时,需要保存调用者的上下文,以便在函数执行完毕后恢复其状态,从而继续调用者的执行。
函数调用时,处理器会自动保存所有 上层上下文寄存器。
CALL 指令 在执行跳转的同时,会并行保存上层上下文(即上下文保存和跳转同时进行)。RET(Return)指令 在执行返回跳转的同时,会并行恢复上层上下文。被调用的函数 无需保存和恢复调用者的上层上下文,可以自由使用这些寄存器。调用方和被调用方需要 共同管理和协调 对 下层上下文寄存器 的使用。
这一机制优化了上下文切换,使函数调用更加高效,同时减少了函数执行时的上下文管理负担。
6 快速函数调用(FCALL/FRET)
在某些情况下,如果不需要保存和恢复上层上下文寄存器,则可以使用 FCALL 指令 替代 CALL 指令,以提高执行效率。
FCALL 指令执行跳转,同时仅保存当前返回地址(A11)到栈,不会保存其他状态。由于没有额外的上下文保存,被调用函数会以与调用方相同的上下文执行(除 A10 和 A11 外)。
FRET 指令,用于从 FCALL 调用的函数返回。会执行跳转到 当前返回地址(A11),同时 恢复栈中的先前 A11 值。不加载其他状态,因此调用者恢复执行时的上下文已经被被调用函数所修改。在 FCALL/FRET 机制下,调用方和被调用方必须协调对所有寄存器的使用,以确保函数调用过程中的数据完整性。这种机制适用于不需要完整上下文切换的场景,例如简短函数或高效嵌套调用,提高了执行速度。
8 上下文管理寄存器(Context Management Registers)
上下文管理寄存器用于 上下文保存(Context Save) 和 上下文恢复(Context Restore) 操作,它们是指向相关存储区域的指针:
FCX(Free CSA List Head Pointer): 空闲上下文保存区(CSA)列表的头指针。
PCX(Previous Context Pointer): 指向先前上下文区域(CSA)的指针。
LCX(Free CSA List Limit Pointer): 空闲 CSA 列表的限制指针。用于识别即将发生的 空闲 CSA 列表耗尽问题。当执行 上下文保存操作(Context Save Operation) 时,如果 FCX 的值与 LCX 相匹配,则系统会识别出 “空闲上下文耗尽” 状态。此状态会触发 FCD(Free Context Depletion)陷阱,该陷阱会在执行导致上下文保存的操作后 立即触发。因此,FCD 陷阱的返回地址(Return Address)将会是:陷阱、 中断 或 被调用例程的第一条指令,或者 SVLCX 或 BISR 指令后面的指令(这样,在FCD trap处理中,通过合适的扩容,可以正常返回,并继续正常执行)。
每个指针包含两个字段:
- 16 位偏移量(Offset)
- 4 位段说明符(Segment Specifier)
CSA 是一个 地址范围,包含 16 个字(word)存储位置(即 64 字节),足够存储 一个上层上下文 或一个 下层上下文。指针偏移量递增 1 时,有效地址(EA)会增加 16 个字,确保新的存储空间连续分配。
每个地址段中的 CSA 总可用范围为 4 MBytes,因此最多可以存储 64 KByte 的 CSA 数据。
9 访问 CSA 内存位置
为了提高性能,一些处理器实现可能会在内部缓冲上下文信息。为了保证内存一致性(Memory Coherency),在访问活动中的 CSA(Context Save Area) 之前,必须执行 DSYNC 指令。
DSYNC 指令 的作用是强制所有内部缓冲的 CSA 寄存器状态写入内存,确保数据不会因缓存或缓冲区延迟而导致不一致性。
10 上下文保存区(CSA)的存放位置
CSA 不能存放在以下内存区域:
- 具有外设空间(Peripheral Space Attribute)的内存段
- 发生地址转换的内存区域(如果 MMU 存在并已启用)。