在许多应用中,指令执行与预期输入刺激具有已知时序关系的 CPU 可以处理如果关系未知则需要更快 CPU 的任务。例如,在我使用 PSOC 生成视频的项目中,我使用代码每 16 个 CPU 时钟输出一个字节的视频数据。由于测试 SPI 设备是否准备就绪,如果没有,则 IIRC 分支需要 13 个时钟,而加载和存储到输出数据需要 11 个时钟,因此无法测试设备在字节之间是否准备就绪;相反,我只是安排让处理器在第一个字节之后为每个字节执行精确的 16 个周期的代码(我相信我使用了真正的索引加载、虚拟索引加载和存储)。每行的第一次 SPI 写入发生在视频开始之前,对于随后的每次写入,都有一个 16 周期的窗口,在该窗口中写入可能不会发生缓冲区溢出或欠载。分支循环产生了一个 13 周期的不确定性窗口,但可预测的 16 周期执行意味着所有后续字节的不确定性将适合相同的 13 周期窗口(这反过来又适合写入可以接受的 16 周期窗口)发生)。
对于较旧的 CPU,指令时序信息清晰、可用且不含糊。对于较新的 ARM,时序信息似乎更加模糊。我知道当代码从闪存执行时,缓存行为会使事情变得更难预测,所以我希望任何循环计数的代码都应该从 RAM 执行。但是,即使从 RAM 执行代码,规范似乎也有些模糊。使用循环计数代码仍然是个好主意吗?如果是这样,使其可靠工作的最佳技术是什么?在多大程度上可以安全地假设芯片供应商不会悄悄地溜进“新改进”芯片,在某些情况下,该芯片会缩短执行某些指令的周期?
假设以下循环从字边界开始,如何根据规范准确确定它需要多长时间(假设 Cortex-M3 具有零等待状态内存;对于本示例,系统的其他任何内容都不重要)。
循环: 移动 r0,r0 ; 简短的简单指令以允许预取更多指令 移动 r0,r0 ; 简短的简单指令以允许预取更多指令 移动 r0,r0 ; 简短的简单指令以允许预取更多指令 移动 r0,r0 ; 简短的简单指令以允许预取更多指令 移动 r0,r0 ; 简短的简单指令以允许预取更多指令 移动 r0,r0 ; 简短的简单指令以允许预取更多指令 添加 r2,r1,#0x12000000 ; 2字指令 ; 重复以下操作,可能使用不同的操作数 ; 将继续添加值,直到发生进位 国际贸易委员会 添加cc r2,r2,#0x12000000; 2字指令,加上itcc的额外“字” 国际贸易委员会 添加cc r2,r2,#0x12000000; 2字指令,加上itcc的额外“字” 国际贸易委员会 添加cc r2,r2,#0x12000000; 2字指令,加上itcc的额外“字” 国际贸易委员会 添加cc r2,r2,#0x12000000; 2字指令,加上itcc的额外“字” ;...等,带有更多有条件的两字指令 子 r8,r8,#1 bpl myloop
在执行前六条指令期间,内核将有时间获取六个字,其中三个将被执行,因此最多可以预取三个。接下来的指令都是三个字,因此内核不可能像执行指令一样快地获取指令。我希望某些“it”指令需要一个周期,但我不知道如何预测哪些指令。
如果 ARM 可以指定“it”指令时序确定的某些条件(例如,如果没有等待状态或代码总线争用,并且前面的两条指令是 16 位寄存器指令等),那就太好了。但我还没有看到任何这样的规范。
示例应用程序
假设有人试图为 Atari 2600 设计一个子板,以生成 480P 的分量视频输出。2600 具有 3.579MHz 像素时钟和 1.19MHz CPU 时钟(点时钟/3)。对于 480P 分量视频,每行必须输出两次,即 7.158MHz 点时钟输出。由于 Atari 的视频芯片 (TIA) 使用 3 位亮度信号和分辨率约为 18ns 的相位信号输出 128 种颜色中的一种,因此仅通过查看输出很难准确地确定颜色。更好的方法是截取对颜色寄存器的写入,观察写入的值,并将对应于寄存器编号的 TIA 亮度值馈入每个寄存器。
所有这一切都可以用 FPGA 完成,但是一些非常快的 ARM 设备可以比具有足够 RAM 来处理必要缓冲的 FPGA 便宜得多(是的,我知道可能会产生这样的体积,成本是' t 一个真实的因素)。然而,要求 ARM 观察输入时钟信号会显着提高所需的 CPU 速度。可预测的周期计数可以使事情变得更清洁。
一种相对简单的设计方法是让 CPLD 监视 CPU 和 TIA 并生成 13 位 RGB+同步信号,然后让 ARM DMA 从一个端口获取 16 位值并以适当的时序将它们写入另一个端口。不过,看看便宜的 ARM 是否能做所有事情,这将是一个有趣的设计挑战。如果可以预测 DMA 对 CPU 周期计数的影响(特别是如果 DMA 周期可能发生在内存总线空闲的周期中),则 DMA 可能是多合一方法的一个有用方面,但在过程中的某个时刻ARM 必须执行其查表和总线监视功能。请注意,与许多在消隐间隔期间写入颜色寄存器的视频架构不同,Atari 2600 经常在帧的显示部分期间写入颜色寄存器,
也许最好的方法是使用几个离散逻辑芯片来识别颜色写入并将颜色寄存器的低位强制为正确的值,然后使用两个 DMA 通道对传入的 CPU 总线和 TIA 输出数据进行采样,并且第三个 DMA 通道生成输出数据。然后,CPU 可以自由地处理来自每个扫描线的两个源的所有数据,执行必要的转换,并将其缓冲以供输出。必须“实时”发生的适配器职责的唯一方面是覆盖写入 COLUxx 的数据,这可以使用两个通用逻辑芯片来处理。