1. 项目概述与核心价值
在嵌入式实时控制领域,尤其是工业自动化、电机驱动和高速传感器接口等场景,对GPIO(通用输入输出)的性能要求早已超越了简单的“高电平/低电平”读写。传统的SoC主CPU GPIO,虽然功能完备,但在处理高速、精确时序的脉冲信号或串行数据流时,往往会受限于操作系统调度延迟、中断响应时间以及软件处理开销,难以满足微秒甚至纳秒级的实时性要求。
这时,TI Sitara系列处理器中的PRU-ICSS(可编程实时单元和工业通信子系统)就成了解决问题的利器。我接触过不少项目,从伺服驱动器的编码器接口到工业以太网从站的数字量IO模块,其核心的实时性保障往往就落在PRU上。而PRU-ICSS内部的增强型GPIO模块,正是将PRU的实时处理能力与外部物理引脚连接起来的关键桥梁。它远非普通GPIO可比,更像是一个高度可配置、支持多种专业协议的数据收发前端。
这个增强型GPIO模块的精髓在于其多模式设计。输入方面,它不仅仅是直接读取引脚状态(Direct Input),还能以硬件方式完成16位数据的并行锁存捕获(Parallel Capture),甚至实现一个28位的硬件移位寄存器(28-Bit Shift In),用于处理如串行绝对值编码器(SSI)这类协议。输出方面,除了直接驱动(Direct Output),还支持带乒乓缓冲区的硬件移位输出(Shift Out),能轻松生成精确的时钟-数据对,常用于驱动DAC、LED阵列或作为自定义串行协议的发射端。
理解并熟练配置这个模块,意味着你能用PRU这块“硬件可编程的协处理器”去接管那些最苛刻的时序任务,把主CPU解放出来处理更上层的逻辑和网络通信。接下来,我将结合手册内容和实际调试经验,为你深入拆解其工作原理、配置细节以及那些手册上不会明说的“坑点”。
2. 增强型GPIO模块整体架构与模式概览
PRU-ICSS的增强型GPIO功能主要通过两个核心寄存器R30和R31来访问。这里有个非常重要的概念需要先厘清:R30和R31并不仅仅是两个普通的32位寄存器,它们是PRU内核与外部引脚以及子系统内部事件进行交互的专用“窗口”或“端口”。
R31寄存器(输入/事件寄存器):主要用于输入和事件状态读取。其低30位(bit 29:0)在GPIO输入模式下映射到外部输入引脚。同时,R31的高位也用于接收来自PRU-ICSS内部中断控制器(INTC)的事件信号。当我们从R31读取数据时,读到的可能是引脚电平,也可能是移位寄存器捕获的数据,或者是内部计数器的状态,这完全取决于当前配置的GPIO模式。R30寄存器(输出寄存器):主要用于输出控制。其全部32位(bit 31:0)在GPIO输出模式下可以映射到外部输出引脚。向R30写入数据,可以直接控制引脚电平,也可以控制移位输出的数据和节奏。
模块的核心在于其多路复用(MUX)架构。同一组物理引脚(例如pr1_pru0_gpi0到gpi29)的功能不是固定的,它们可以被重映射到不同的逻辑功能上。这是通过配置PRU-ICSS_CFG空间内的GPCFGn寄存器(特别是PR1_PRU0_GP_MUX_SEL位域)来实现的。总共有四种主要的IO模式,且互斥,一次只能选择一种:
- 通用模式(GP Mode):
GPCFGn[PR1_PRU0_GP_MUX_SEL] = 0x0。这就是本文重点讨论的增强型GPIO模式,包含下文要详述的各种输入输出子模式。 - 外设接口模式(Peripheral I/F Mode):
MUX_SEL = 0x1。用于支持如EnDat 2.2、BiSS等绝对值编码器协议。此时,引脚被重定义为ENDATx_CLK,ENDATx_OUT,ENDATx_IN等专用信号。 - Sigma-Delta模式(SD Mode):
MUX_SEL = 0x3。用于连接Σ-Δ型ADC,PRU内部的硬件累加器可以高效地完成Sinc滤波器的积分部分,极大减轻了滤波运算的负担。 - MII_RT模式:用于工业以太网(如EtherCAT)的实时MII接口。
重要提示:在开始配置任何GPIO功能前,第一件事就是通过
GPCFGn寄存器正确设置PR1_PRU0_GP_MUX_SEL位域,选择你需要的顶层IO模式。如果模式选错,无论你怎么配置R30/R31都不会有预期效果。
选定GP模式后,我们才进入增强型GPIO的细分世界。输入和输出模式需要进一步通过CFG_GPCFGn寄存器中的其他位域(如PRU<n>_GPI_MODE和PRU<n>_GPO_MODE)来分别配置。一个PRU核心的输入和输出模式可以独立配置,例如输入可以工作在28位移位模式,而输出可以工作在直接输出模式。
3. 输入模式(R31)深度解析与配置
输入模式决定了外部信号如何被采样并呈现在R31寄存器的对应位上。PRU-ICSS提供了三种输入模式,每种都针对不同的应用场景。
3.1 直接输入模式(Direct Input)
这是最简单也是最常用的模式,可以理解为“直通”模式。
- 工作原理:物理引脚
PRU<n>_GPI[29:0]的电平状态直接映射到pru<n>_r31_status[29:0]的内部寄存器位上。PRU执行一条LBBO(按字节加载)或LBCO(按常量加载)指令读取R31时,读到的就是此刻引脚上的电平值。 - 配置方法:这是默认模式。只要
GPCFGn[PR1_PRU0_GP_MUX_SEL]设置为GP模式(0x0),且没有使能其他特殊输入模式,就是直接输入模式。无需额外配置。 - 应用场景与注意事项:
- 读取开关量、按钮状态:这是最典型的应用。
- 软件模拟低速协议:如I2C、UART的位读取(需要PRU代码严格计时)。
- 注意同步问题:
R31的读取与PRU核心时钟同步。如果外部信号是异步的(频率与PRU时钟无关),可能会遇到亚稳态问题。虽然模块内部有同步触发器(如图中的Sync Flop),但对于高速或关键信号,建议在软件中采用多次读取取一致的防抖策略。 - 引脚可用性:并非所有PRU核心都能引出全部30个输入引脚,具体需要查阅芯片的《数据手册》和《引脚复用指南》。
3.2 16位并行捕获模式(16-Bit Parallel Capture)
这个模式将GPIO引脚变身为一个16位的并行数据锁存器,特别适合捕获与时钟边沿同步的并行数据。
- 工作原理:
PRU<n>_DATAIN[15:0]引脚(对应GPI[15:0])作为16位数据输入总线。PRU<n>_CLOCKIN引脚(对应GPI[16])作为外部输入时钟(或选通信号)。- 当
CLOCKIN上出现有效的边沿(上升沿或下降沿,可配置)时,DATAIN[15:0]上的16位数据会被瞬间捕获(锁存)到pru<n>_r31_status[15:0]中。pru<n>_r31_status[16]则反映CLOCKIN引脚本身的状态。 - 数据捕获是硬件自动完成的,与PRU指令执行无关。PRU可以在任何方便的时候去读取
R31的低16位,获取被锁存的数据。
- 配置步骤:
- 通过
CFG_GPCFGn寄存器使能并行捕获模式(设置PRU<n>_GPI_MODE为相应值)。 - 在
CFG_GPCFGn寄存器中配置CLOCKIN的有效捕获边沿(上升沿或下降沿)。 - 确保相关引脚的复用功能已正确配置为PRU GPI模式。
- 通过
- 应用场景与实操心得:
- 高速并行数据采集:例如,连接一个外部ADC(模数转换器),ADC在转换完成时会发出一个
CONVST(转换完成)脉冲,将这个脉冲接到CLOCKIN,ADC的并行数据总线接到DATAIN[15:0]。这样,每次ADC转换完成,数据就被自动锁存,PRU无需精确计时去读取,只需轮询或等待中断即可。 - 编码器接口:某些增量���编码器除了A/B/Z相,还有并行输出的绝对位置信号,可以用此模式捕获。
- 关键配置:一定要正确设置时钟边沿。如果外部设备在数据稳定后给出一个上升沿作为“数据有效”信号,就应配置为上升沿捕获。如果是在数据变化前给出一个下降沿作为“锁存”信号,则应配置为下降沿捕获。理解外部设备的时序图是正确配置的前提。
- 高速并行数据采集:例如,连接一个外部ADC(模数转换器),ADC在转换完成时会发出一个
3.3 28位移位输入模式(28-Bit Shift In)
这是功能最强大也最复杂的输入模式,本质上在PRU内部实现了一个28位的硬件移位寄存器,专为处理串行数据流而生。
- 工作原理:
PRU<n>_DATAIN引脚(对应GPI[0])作为串行数据输入。- 模块内部有一个以
ocp_clk(通常为200MHz或更高)为基准的分频器链(PRU<n>_GPI_DIV0和PRU<n>_GPI_DIV1),用于产生内部移位时钟。这个时钟频率决定了串行数据的采样率。 - 在每个内部移位时钟的脉冲下,
DATAIN引脚上的电平(0或1)被采样,并移入28位移位寄存器的最低位(LSB)。移位寄存器是“左移”还是“右移”取决于数据格式,但手册描述为“fills in lsb order”,通常理解为数据从bit 0开始填充,即bit 0是最先移入的位。 - 移位寄存器的内容实时映射到
pru<n>_r31_status[27:0]。当移满28位后,新数据会从另一端“溢出”到“位桶”(Bit Bucket),即丢弃。 - 该模式还提供两个重要的状态标志位,映射到
R31的高位:- 起始位检测(SB, Start Bit):
pru<n>_r31_status[29]。当在DATAIN上检测到第一个逻辑‘1’(起始位)时,此位被硬件自动置1。这是一个非常实用的功能,可以用于帧同步。软件需要通过写CFG_GPCFGn寄存器的特定位来清除此标志。 - 移位计数器(Cnt_16):
pru<n>_r31_status[28]。在检测到起始位(SB置位)后,每采样16个移位时钟周期,此位会被硬件置位一次。它是自清除的,并且连接到PRU的中断控制器(INTC)。这意味着你可以配置一个中断,每接收16位数据就触发一次PRU中断,从而高效地处理数据块。
- 起始位检测(SB, Start Bit):
- 配置要点:
- 通过
CFG_GPCFGn寄存器使能28位移位输入模式。 - 配置
PRU<n>_GPI_DIV0和PRU<n>_GPI_DIV1分频器,以产生与串行数据波特率匹配的内部移位时钟。手册中的表格给出了生成常见频率(如8MHz, 10MHz)的配置示例。计算公式为:移位时钟频率 = OCP_CLK / (DIV0 * DIV1)。例如,OCP_CLK = 200MHz,要得到10MHz移位时钟,可设置DIV0=10,DIV1=2。 - 理解并规划如何使用SB和Cnt_16标志。如果使用Cnt_16中断,还需要在PRU-ICSS的INTC模块中配置相应的中断通道和事件。
- 通过
- 应用场景与避坑指南:
- 串行绝对值编码器(SSI):这是此模式的经典应用。SSI编码器输出一个时钟信号和一组串行数据。PRU可以用另一个GPIO(或定时器)产生时钟给编码器,同时将编码器的串行数据线接入
DATAIN引脚。使能28位移位模式和起始位检测,PRU可以自动捕获一帧完整的位置数据。 - 自定义串行协议:任何单数据线的串行协议都可以用此模式接收,大大减轻PRU代码中位提取和拼接的负担。
- 时钟同步难题:最大的“坑”在于内部移位时钟与外部数据源的同步。如果外部串行数据有自己的时钟(如SPI的SCLK),你需要确保PRU的内部移位时钟频率与其匹配,并且相位关系正确,否则采样点可能落在数据变化边缘,导致误码。最佳实践是,如果外部有同步时钟,尽量使用16位并行捕获模式(如果数据宽度<=16位)或使用PRU的定时器去精确采样。28位移位模式更适用于异步串行通信或由PRU自身提供时钟的场景。
- 数据溢出:移位寄存器只有28位。如果一帧数据超过28位,你需要确保在移满28位之前,PRU代码已经读取了
R31[27:0],否则最早移入的数据会丢失。通常配合Cnt_16中断,每16位读取一次,可以很好地管理长数据帧。
- 串行绝对值编码器(SSI):这是此模式的经典应用。SSI编码器输出一个时钟信号和一组串行数据。PRU可以用另一个GPIO(或定时器)产生时钟给编码器,同时将编码器的串行数据线接入
4. 输出模式(R30)深度解析与配置
输出模式决定了如何通过R30寄存器控制外部引脚的电平。PRU-ICSS提供了两种输出模式。
4.1 直接输出模式(Direct Output)
这是最直观的输出模式。
- 工作原理:PRU核心向
pru<n>_r30[31:0]寄存器写入的值,会直接驱动到对应的物理输出引脚PRU<n>_GPO[31:0]上。写入1输出高电平,写入0输出低电平。 - 配置方法:这是默认模式。在GP模式下,如果没有使能移位输出模式,即为直接输出模式。
- 应用场景与关键警告:
- 控制LED、继电器、MOSFET:基础的数字输出控制。
- 生成简单的PWM波:通过PRU循环代码快速翻转
R30的某一位,可以产生频率和占空比可调的PWM,精度远高于Linux下的软件PWM。 - 一个至关重要的警告:手册中明确提到:“R30 may not be initialized after reset. To avoid outside effect, R30 should be initialized before PINMUX configuration.”这句话非常关键!它意味着芯片上电复位后,
R30寄存器的值是不确定的。如果你先配置了引脚的复用功能为PRU GPO,而此时R30的值是随机的(比如是0xFFFFFFFF),那么这些引脚会立即输出随机的高低电平,可能导致外围电路误动作,甚至损坏设备。 - 正确的上电初始化顺序:
- PRU固件开始运行。
- 立即将
R30寄存器写入一个已知的安全状态(例如全0)。 - 然后再通过配置芯片的
PINMUX控制器,将相关引脚的功能切换到PRU GPO模式。 - 最后,根据应用需求,更新
R30的值以控制输出。
4.2 移位输出模式(Shift Out)
这是一个强大的硬件辅助串行数据发送引擎,特别适合生成带有时钟信号的同步串行数据流,如SPI、WS2812B(NeoPixel)时序等。
- 工作原理:
pru<n>_r30[0]位被映射到PRU<n>_DATAOUT引脚(对应GPO[0]),作为串行数据输出。pru<n>_r30[1]位被映射到PRU<n>_CLOCKOUT引脚(对应GPO[1]),作为移位时钟输出。注意:当时钟输出使能后,pru<n>_r30[1]的写入值将被忽略,硬件会自动生成时钟信号。- 模块内部有两个16位的影子寄存器(Shadow Register):
gpo_sh0和gpo_sh1。它们构成了一个“乒乓缓冲区”。 - PRU将需要发送的16位数据写入
R30[15:0],然后通过置位R30[29](加载gpo_sh0)或R30[30](加载gpo_sh1)来将数据从R30[15:0]加载到对应的影子寄存器。 - 当
R30[31](ENABLE_SHIFT)被置位后,移位引擎启动。它从gpo_sh0的LSB开始,在每个CLOCKOUT的上升沿,将一位数据从DATAOUT引脚移出。同时,CLOCKOUT引脚输出连续的时钟信号。 - 移位时钟的频率由
PRU<n>_GPO_DIV0和PRU<n>_GPO_DIV1两个分频器控制,原理与输入分频器类似。 - 乒乓缓冲区机制:当一个影子寄存器(例如
gpo_sh0)的数据正在被移出时,PRU可以准备下一组16位数据,并将其加载到另一个空闲的影子寄存器(gpo_sh1)中。硬件会自动在两个缓冲区之间切���,实现数据的无缝连续输出。PRU可以通过查询GPCFGn寄存器中的PRU<n>_GPI_SH_SEL状态位,来获知当前正在输出哪个影子寄存器的数据,从而决定该加载哪个缓冲区。
- 配置与操作流程:
- 初始化: a. 配置
PRU<n>_GPO_DIV0/1,设定所需的移位时钟频率。 b. 通过CFG_GPCFGn寄存器使能移位输出模式(PRU<n>_GPO_MODE = 0x1)。 c. 将R30[31](ENABLE_SHIFT)清零,确保移位引擎未启动。 - 加载初始数据: a. 将第一个16位数据写入
R30[15:0]。 b. 置位R30[29](LOAD_GPO_SH0),将数据加载到gpo_sh0。 c. 将第二个16位数据写入R30[15:0]。 d. 置位R30[30](LOAD_GPO_SH1),将数据加载到gpo_sh1。 e. 清除R30[29]和R30[30]。 - 启动移位:置位
R30[31](ENABLE_SHIFT)。此时,DATAOUT和CLOCKOUT引脚开始输出波形。 - 循环加载(数据流): a. 轮询
GPCFGn寄存器中的PRU<n>_GPI_SH_SEL位。当该位为1时,表示gpo_sh0的数据正在被移出,gpo_sh1空闲,可以加载新数据到gpo_sh1;反之亦然。 b. 根据查询结果,将新数据写入R30[15:0],然后置位对应的加载控制位(R30[29]或R30[30]),加载完成后清除该位。 - 停止移位:当所有数据发送完毕后,清除
R30[31](ENABLE_SHIFT)。硬件会完成当前影子寄存器的移位操作后停止。
- 初始化: a. 配置
- 应用场景与高级技巧:
- 驱动串行设备:如SPI从设备、移位寄存器(74HC595)、串行DAC/ADC等。硬件生成时钟,保证了极高的时序精度和稳定性。
- 生成复杂波形:通过精心编排送入影子寄存器的数据,可以产生任意占空比的PWM、红外遥控编码、甚至简单的模拟波形(通过外部RC滤波)。
- “乒乓缓冲区”的意义:这个设计避免了在移位过程中因PRU来不及准备数据而导致的输出中断或时钟停顿。对于需要连续、高速数据流的应用(如音频流、LED灯带刷新)至关重要。
- 时钟频率计算:与输入模式类似,
CLOCKOUT频率 =OCP_CLK/ (GPO_DIV0*GPO_DIV1)。需要根据外设要求精确计算。 - 引脚复用冲突:手册中有一个重要提示:如果
pru<n>_r30[2:15]对应的物理引脚被配置为其他复用功能(非r30[2:15]的Pinmux模式),那么这些引脚将不会反映影子寄存器写入r30[2:15]的值。这意味着,在移位输出模式下,只有DATAOUT(GPO0)和CLOCKOUT(GPO1)是严格用于移位功能的。GPO[2:15]这些引脚是否受R30[2:15]控制,取决于它们的Pinmux配置。这是一个容易混淆的地方。
5. 高级应用模式:Sigma-Delta解码与外围接口
除了基本的GPIO模式,增强型模块还集成了两种面向特定应用的高级硬件加速模式,它们同样复用R30/R31寄存器接口。
5.1 Sigma-Delta解码模式
Σ-Δ调制是一种高精度ADC常用的技术,但其输出是高速的1位数据流,需要经过数字滤波(通常是Sinc滤波器)才能得到可用的高分辨率数据。PRU-ICSS的Sigma-Delta模式用硬件实现了Sinc滤波器的累加部分。
- 核心思想:将外部Σ-Δ调制器(通常是一个简单的比较器电路)产生的1位数据流(
SDx_D)和时钟(SDx_CLK)接入PRU。PRU内部的硬件积分器(24位累加器)对数据流进行累加。PRU固件则负责在适当时刻读取累加值,并执行差分运算(Sinc滤波的微分部分),从而还原出模拟量。 - 主要特性:
- 支持最多9个独立通道。
- 每个通道有3级24位级联累加器(支持Sinc3滤波)。
- 可编程的过采样率(OSR),通过
sample_size寄存器配置。 - 灵活的时钟源选择,每个通道可独立配置。
- 操作流程简述:
- 配置
GPCFGn[PR1_PRU0_GP_MUX_SEL] = 0x3,将引脚切换到SD模式。 - 通过
CFG_SD_P<n>_CLKSEL_<m>等寄存器配置每个通道的时钟源、极性、选择累加器2作为数据源等。 - 配置
CFG_SD_P<n>_SS_<m>[sample_size]设置过采样率。 - 通过
R30[29:26]选择要操作的通道,然后向R31[23]写入1来重新初始化(re_init)该通道,清除所有计数器和标志。 - 置位
R30[25](channel_en)使能所有通道。 - 轮询
R31[24](shadow_update_flag),当该位置1时,表示一次过采样完成,影子寄存器中已准备好有效的累加值。 - 读取
R31[23:0](data_out)获取24位累加值。 - 在PRU固件中对此值进行差分计算,得到最终的滤波结果。
- 配置
- 应用价值:将计算密集型的累加操作卸载到硬件,PRU只需处理轻量的差分和标定,极大提高了多路Σ-Δ信号采集的效率和实时性,常用于高精度电流、电压采样。
5.2 外围接口模式
此模式专为支持EnDat 2.2、BiSS-C等用于绝对值编码器的数字接口协议而设计。它提供了完整的硬件支持,包括可编程的波特率时钟生成、TX/RX FIFO、自动RX使能、可配置的时钟启动/停止时序等。
- 核心功能:每个通道提供4个信号:
ENDATx_CLK(时钟)、ENDATx_OUT(数据输出)、ENDATx_IN(数据输入)、ENDATx_OUT_EN(输出使能)。硬件自动处理时钟生成、数据移位、帧计数等底层时序,PRU主要负责通过R30/R31配置参数和搬运数据。 - 关键特性:
- 灵活的时钟生成:基于
uart_clk或ocp_clk,通过两级分频产生精确的TX时钟和RX过采样时钟。 - 硬件FIFO:TX和RX各有32位FIFO,支持单次发送和连续流模式。
- 自动时序控制:可配置的线延迟(
wire_delay)、测试延迟(tst_delay),以及TX结束后自动切换到RX的延迟计数(rx_en_counter)。 - 多种时钟停止模式:支持在最后一帧RX后停止在高/低电平,或在最后一帧TX后停止在高电平,或自由运行。
- 灵活的时钟生成:基于
- 操作模式:
- TX单次发送:预加载数据到TX FIFO,设置帧长度,触发
tx_global_go或tx_channel_go。硬件自动处理时钟启动、数据发送、以及根据rx_en_counter决定是否自动进入RX模式。 - TX连续发送:设置帧长度为0,并持续监控FIFO状态,确保在数据移空前及时填充新数据,用于发送长于32位的数据帧。
- RX接收:配置RX过采样率和帧长度,使能
rx_en。硬件在检测到起始位后开始采集,帧完成后置位有效标志val,PRU读取rx_data_out。
- TX单次发送:预加载数据到TX FIFO,设置帧长度,触发
- 应用场景:直接连接海德汉、发格等品牌的EnDat 2.2绝对值编码器,实现高速、可靠的位置反馈读取。PRU硬件处理了协议中最耗时的位级时序,使得响应速度极快,满足了高性能伺服驱动和数控系统的要求。
6. 实战配置指南与常见问题排查
理解了原理,最终要落到代码和配置上。以下是一个基于PRU软件支持包(PRU-SWPKG)或类似底层库的典型配置流程框架和问题排查思路。
6.1 通用配置步骤框架
- 引脚复用配置:在主机端(Linux),通过设备树(Device Tree)或
config-pin工具,将目标引脚的功能设置为对应的PRU模式(例如pru-uart,pru-gpio等,具体名称因芯片和内核版本而异)。这是信号能否连接到PRU的前提。 - PRU固件初始化: a.设置IO模式:通过写
CTRL模块或CFG空间的相关寄存器,将GPCFGn[PR1_PRU0_GP_MUX_SEL]设置为所需模式(0x0 for GP, 0x1 for Periph, 0x3 for SD)。 b.初始化R30:务必在使能引脚输出功能前,将R30寄存器写为已知值(通常为0)。 c.配置具体模式:根据选择的GP模式,配置CFG_GPCFGn中的GPI_MODE和GPO_MODE。如果需要分频(如移位模式),配置GPI_DIV0/1或GPO_DIV0/1。 d.配置中断(如需要):如果使用Cnt_16中断或SD模式的中断,需要配置PRU-ICSS的INTC模块,映射系统事件到PRU主机中断。 - 主循环��理:根据模式编写数据读写、状态轮询或中断服务例程。
6.2 常见问题与排查技巧
问题:配置了GPIO,但引脚没有反应(无输出或读不到输入)。
- 检查1:引脚复用:这是最常见的原因。确认主机端的Pinmux配置已生效,且配置到了正确的PRU核心和引脚上。使用
cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins(路径因平台而异)或config-pin -q <pin>命令查看引脚当前状态。 - 检查2:IO模式选择:确认
GPCFGn[PR1_PRU0_GP_MUX_SEL]设置正确。你想用GP模式,却设成了SD模式,自然无法工作。 - 检查3:方向与初始化:对于输出,确认已按正确顺序初始化
R30再配置Pinmux。对于输入,确认外部信号确实到达了引脚(可用万用表或示波器测量)。
- 检查1:引脚复用:这是最常见的原因。确认主机端的Pinmux配置已生效,且配置到了正确的PRU核心和引脚上。使用
问题:28位移位输入模式数据错乱。
- 检查1:时钟频率与相位:计算并确认
GPI_DIV0/1设置产生的内部移位时钟频率与外部数据波特率一致。如果外部有同步时钟,尝试调整GPI_DIV0/1使内部时钟略快于数据速率,并确保在数据稳定中心采样。最可靠的方法是使用示波器同时测量DATAIN和CLOCKIN(如果外部提供时钟)或一个由PRU产生的参考时钟,观察时序关系。 - 检查2:起始位检测:如果协议有起始位,确保使能了SB检测功能,并在固件中正确处理SB标志。有时噪声可能被误判为起始位,需要在软件中加入超时和帧校验。
- 检查3:数据读取时机:确保PRU在数据溢出前(每16位或28位)及时读取
R31。使用Cnt_16中断是最佳实践。
- 检查1:时钟频率与相位:计算并确认
问题:移位输出模式时钟不稳定或数据不对。
- 检查1:影子寄存器加载顺序:确保在启动移位(
ENABLE_SHIFT=1)前,至少加载了一个影子寄存器(gpo_sh0或gpo_sh1)。否则,移位引擎会输出不确定的数据。 - 检查2:乒乓缓冲区管理:在连续输出时,必须通过查询
GPI_SH_SEL状态位来正确判断该加载哪个影子寄存器。加载到正在移出的缓冲区会导致数据冲突。 - 检查3:时钟分频器:确认
GPO_DIV0/1配置正确,生成的时钟频率在外设允许范围内。过高的频率可能导致信号完整性问题。
- 检查1:影子寄存器加载顺序:确保在启动移位(
问题:使用高级模式(SD或Periph)时,无法进入或功能异常。
- 检查1:模式互斥性:再次确认
GPCFGn[PR1_PRU0_GP_MUX_SEL]已设置为0x1(Periph)或0x3(SD),并且没有和其他模式冲突。 - 检查2:时钟源配置:对于SD模式,检查
CFG_SD_P<n>_CLKSEL_<m>[CLKSEL]是否正确选择了外部SDx_CLK引脚。对于Periph模式,检查TX和RX的时钟源(uart_clk/ocp_clk)和分频因子配置。 - 检查3:寄存器访问延迟:手册中多次强调,在更改某些配置(如SD模式的通道选择
channel_select)后,需要等待至少1个PRU周期(插入NOP指令)再进行后续操作,否则可能访问到旧数据或状态。这是硬件同步的要求,容易被忽略。
- 检查1:模式互斥性:再次确认
调试PRU硬件外设,示波器或逻辑分析仪是必不可少的工具。直接观察引脚上的实际波形,与预期的时序图进行对比,是定位硬件配置问题最快最直接的方法。同时,充分利用PRU的调试功能(如通过R31bit 31触发主机中断来传递调试信息)也能极大提高开发效率。