深入解析PRU_ICSSG外设接口:寄存器级编程与实时通信实战

📅 2026/7/20 10:42:05 👁️ 阅读次数 📝 编程学习
深入解析PRU_ICSSG外设接口:寄存器级编程与实时通信实战

1. PRU_ICSSG外设接口:实时控制的硬件基石

在工业伺服驱动、高速数据采集或者多轴运动控制这类对时序要求极为苛刻的场景里,软件轮询或者基于中断的通信方式往往力不从心。几微秒的延迟就可能导致电机失步,或者错过一个关键的传感器脉冲。这时,我们需要一种更“硬”的解决方案——一种由硬件直接管理、时序确定、几乎零CPU干预的通信接口。德州仪器(TI)在其AM64x/AM243x系列处理器中集成的PRU_ICSSG(可编程实时单元与工业通信子系统)模块,其内置的外设接口(Peripheral I/F)正是为此而生。

这个外设接口本质上是一个高度可配置的串行通信引擎,但它与我们熟知的UART或SPI不同。它没有固定的协议格式,其时钟的启动、停止、数据位的采样时机,乃至每个通道的独立使能,都完全由程序员通过直接读写PRU核心的R30和R31寄存器来精确控制。这就好比给了你一套最基础的乐高积木(时钟、数据线、使能信号),而不是一个成品玩具,让你能搭建出适应EnDAT、BISS-C、SSI等各种增量式编码器或特定传感器协议的通信链路。其核心价值在于“确定性”和“低延迟”,所有操作都在PRU的单个指令周期内响应,实现了真正的硬件级实时性。

理解并驾驭这个接口的关键,就在于掌握R30和R31这两组特殊功能寄存器。它们不是普通的内存映射寄存器,而是PRU核心与外部世界交互的“硬连线”门户。R30主要用作“控制输出”,你可以通过写它的特定位来启动时钟、选择通道、加载发送数据;而R31则主要作为“状态输入”,通过读它的特定位,你能获知FIFO状态、数据是否有效、是否有溢出错误。整个通信的流程,从时钟分频配置、数据加载、传输启动,到接收使能、数据读取和错误处理,都是围绕对这两组寄存器特定比特位的置位与清零来展开的。接下来,我们将深入这个寄存器级编程的世界,从设计思路到每个比特的具体操作,为你彻底解析如何玩转PRU_ICSSG的外设接口。

2. 核心设计思路与寄存器映射解析

要高效使用外设接口,不能仅仅死记硬背寄存器位定义,必须理解其背后的设计哲学。这个接口被设计为支持最多3个独立的双向通道(Channel 0, 1, 2),每个通道都拥有独立的TX(发送)和RX(接收)逻辑。这种多通道独立设计允许单个PRU核心同时与多个外设进行通信,例如同时读取三个光电编码器的位置数据,这对于多轴协同控制至关重要。

整个模块的运作围绕几组关键的配置寄存器和状态寄存器展开。其中,一部分是位于PRU_ICSSG配置空间(CFG Registers)的存储器映射寄存器,用于进行静态的、上电初始化的配置,例如时钟源选择、分频系数、帧长度等。另一部分,也是我们编程交互最频繁的部分,则是直接映射到PRU核心寄存器文件中的R30和R31。这种设计实现了极致的效率:PRU指令可以直接对R30/R31进行读写,无需通过加载/存储指令去访问慢速的系统内存,从而将控制延迟降到最低,通常在一个指令周期内即可完成对外设接口状态的改变或读取。

2.1 R31寄存器:系统的“眼睛”与状态感知

R31寄存器在外设接口模式下,主要充当状态输入和全局控制反馈的角色。你可以把它理解为系统的“仪表盘”。它的位域被精细地划分为几个功能区,用于监控三个通道的独立状态以及一些全局标志。

接收(RX)状态区(Bit 31-0):这是接收数据时的核心状态区。每个通道占用8个数据位(例如,Channel 0使用R31[7:0])来存放接收到的数据。但更重要的是数据位旁边的状态标志位。val0val1val2(位于R31[24], [25], [26])是“数据有效”标志。当硬件按照预设的采样大小(例如8倍过采样)收集完一个完整的数据帧后,会将对应通道的val位置1,同时将数据锁存到对应的rx_data_out位域中。此时,PRU程序必须及时读取数据,并向该val位写入1来清除标志。这是一个关键操作,如果未能及时清除,而下一个数据帧又已接收完成,硬件会设置对应的溢出标志ovf0ovf1ovf2(R31[27], [28], [29]),表示数据丢失。清除溢出标志同样需要向其写入1。

发送(TX)状态与全局控制区(Bit 31-0):当通道处于发送模式(rx_en=0)时,R31的这部分位域含义发生变化,用于监控发送过程。tx_fifo_sts0tx_fifo_sts1tx_fifo_sts2(分别位于R31[4:2], [12:10], [20:18])以3比特编码指示对应通道发送FIFO的占用情况(空、1字、2字、3字、满)。在连续发送模式下,监控这些状态位是确保FIFO不“断粮”的关键。ovr(上溢)和unr(下溢)标志则用于错误处理。tx_global_reinit_active/busy位(R31[21,13,5])则指示全局重新初始化或发送结束的状态,用于同步。

注意:R31的rx_data_out位域([23:16], [15:8], [7:0])在发送和接收模式下是共享的。当发送FIFO停止传输后,硬件会自动切换这些位域的功能以显示接收数据。编程时需根据当前模式来解读这些位。

2.2 R30寄存器:程序员的“双手”与精确控制

如果说R31是眼睛,那么R30就是我们的双手,用于发出所有控制命令。它的位域划分清晰地对应了不同的控制阶段。

通道使能与模式选择(Bit 31-16)rx_en0,rx_en1,rx_en2(R30[24], [25], [26])是接收通道的使能开关。将其置1会启动对应通道的接收逻辑,包括时钟和采样电路;清零则会复位该通道的所有计数器和状态标志。clk_mode[1:0](R30[20:19])是一个极其重要的配置,它决定了时钟(PERIF_CLK)在传输结束后的行为:是停止在高电平、停止在低电平、还是自由运行。不同的编码器协议对此有不同要求。tx_ch_sel[1:0](R30[17:16])用于在需要针对单个通道操作时(如单通道发送启动或FIFO状态查询),选择目标通道。

数据加载与全局命令(Bit 15-0)tx_data[7:0](R30[7:0])是发送数据的入口。向这里写入数据,数据就会被推入当前由tx_ch_sel选中的通道的发送FIFO。这是一个32位深的FIFO,支持单次(单发)或连续加载模式。tx_channel_go(R30[18])和tx_global_go(R30[20])是“发射按钮”。前者启动tx_ch_sel所选通道的发送,后者同时启动所有三个通道的发送。tx_global_reinit(R30[19])则是“复位按钮”,用于将整个外设接口模块(包括时钟状态)复位到默认状态,通常在协议帧之间或错误恢复时使用。

理解R30和R31的这种分工与协作,是进行有效编程的基础。发送数据时,我们通过R30选择通道、加载数据、发出启动命令;同时通过R31监控FIFO状态和错误标志。接收数据时,我们通过R30使能通道,然后轮询R31的val标志,并在数据有效时读取rx_data_out。整个流程构成了一个完整的、寄存器级的硬件控制闭环。

3. 时钟配置与时序控制:精准的节拍器

外设接口通信的可靠性,根基在于精确的时钟。PRU_ICSSG的外设接口模块提供了高度灵活的时钟生成机制,允许我们为发送(TX)和接收(RX)分别配置独立的时钟链,这对于需要过采样的接收场景尤为重要。时钟配置不当,轻则通信误码率高,重则根本无法锁定数据。

3.1 时钟源与分频器详解

模块有两个主要的时钟源可选:ICSSGn_UART_CLK(通常为192MHz)和ICSSGn_ICLK。默认使用UART_CLK,因其频率稳定且易于分频得到常用波特率。时钟生成的核心是两个独立的分频器:一个用于产生发送数据速率基准的1x时钟(TX Clock),另一个用于产生接收采样用的过采样时钟(OS Clock, Oversampling Clock)。

配置通过CFG空间的几个寄存器完成:

  • ICSSG_PRU0_ED_TX_CFG_REG[4] (PRU0_ED_TX_CLK_SEL)ICSSG_PRU0_ED_RX_CFG_REG[4] (PRU0_ED_RX_CLK_SEL):选择TX和RX的时钟源。
  • ICSSG_PRU0_ED_TX_CFG_REG[31:16] (PRU0_ED_TX_DIV_FACTOR)[15] (PRU0_ED_TX_DIV_FACTOR_FRAC):配置TX时钟的整数和小数分频系数。最终TX时钟频率 = 时钟源频率 / (DIV_FACTOR + FRAC/16)。
  • ICSSG_PRU0_ED_RX_CFG_REG[31:16] (PRU0_ED_RX_DIV_FACTOR)[15] (PRU0_ED_RX_DIV_FACTOR_FRAC):同理,配置RX过采样时钟的分频。
  • ICSSG_PRU0_ED_RX_CFG_REG[2:0] (PRU0_ED_RX_SAMPLE_SIZE):设定过采样倍数(例如,设为7表示8倍过采样)。这里有一个关键约束:RX过采样时钟频率 / TX 1x时钟频率 必须等于此处设定的过采样倍数。例如,若TX时钟为4MHz,需要8倍过采样,则RX时钟必须配置为32MHz。

为了直观理解,我们来看一个实际配置案例。假设时钟源为192MHz的ICSSGn_UART_CLK,我们需要实现一个4MHz(周期250ns)的数据传输速率,并采用8倍过采样进行接收。

  1. 计算TX分频系数:目标TX时钟 = 4MHz。分频系数 = 192MHz / 4MHz = 48。因此,设置PRU0_ED_TX_DIV_FACTOR = 48PRU0_ED_TX_DIV_FACTOR_FRAC = 0
  2. 计算RX分频系数:目标RX过采样时钟 = 4MHz * 8 = 32MHz。分频系数 = 192MHz / 32MHz = 6。因此,设置PRU0_ED_RX_DIV_FACTOR = 6PRU0_ED_RX_DIV_FACTOR_FRAC = 0
  3. 设置过采样倍数PRU0_ED_RX_SAMPLE_SIZE = 7(代表8倍过采样)。

这个配置结果正好符合TI手册中给出的一个示例。通过这样的计算,我们可以为任何所需的通信速率生成精确的时钟。

3.2 启动与停止时序的精细控制

时钟的启动和停止时机直接关系到数据帧的边界对齐,是协议实现的关键。启动时序分为TX模式和RX模式。

TX模式rx_en=0)下,当时钟配置为硬件控制(默认)时,PERIF_CLK的启动不是立即的。在你设置tx_global_gotx_channel_go位之后,硬件会依次经历两个可配置的延迟:

  • Delay 1 (Wire Delay):由ICSSG_PRU0_ED_CHm_CFG0_REG[10:0] (PRU0_ED_TX_WDLYm)配置。用于补偿信号在物理线路上的传播延迟,确保数据发送时,接收端已准备好。
  • Delay 2 (TST Delay):由ICSSG_PRU0_ED_CHm_CFG1_REG[15:0] (PRU0_ED_TST_DELAY_COUNTERm)配置。用于在时钟开始跳变前提供一个稳定的建立时间。

只有在这两个延迟结束后,PERIF_CLK才会开始运行(首先输出低电平)。因此,从“GO”信号到时钟第一个上升沿的总延迟为:Wire Delay + TST Delay + (半个TX时钟周期)。在编写驱动时,必须根据接收端芯片的要求来合理设置这两个延迟值。

RX模式rx_en=1)下,PERIF_CLK会在rx_en位置1后立即开始运行。更常用的是“自动使能RX”模式,通过设置ICSSG_PRU0_ED_CHm_CFG1_REG[31:16] (PRU0_ED_RX_EN_COUNTERm)为一个非零值,可以在TX帧发送结束后,自动延迟一定时间再开启RX模式,这非常适合全双工或半双工的问-答式协议。

时钟的停止行为则由r30[20:19] (clk_mode)控制:

  • clk_mode = 0:在最后一个RX帧结束后,时钟停止在低电平。
  • clk_mode = 1:(默认)在最后一个RX帧结束后,时钟停止在高电平。
  • clk_mode = 2:时钟自由运行,永不停止。特别注意:要退出此模式,必须执行一次tx_global_reinit
  • clk_mode = 3:在最后一个TX比特发送完毕后,时钟停止在高电平。

选择哪种模式取决于外设协议。例如,某些编码器要求时钟在帧间保持高电平,而有些则要求保持低电平。clk_mode可以在每次事务前动态配置,提供了极大的灵活性。

4. 发送(TX)操作模式与编程实战

掌握了时钟配置,我们就可以深入数据发送的具体操作了。外设接口的发送逻辑围绕一个32字深的TX FIFO展开,支持两种基本模式:单次发送(Single Shot)和连续发送(Continuous)。模式的选择取决于你发送的数据帧长度和业务需求。

4.1 单次发送(Single Shot)模式编程

单次发送模式适用于数据帧长度小于等于32字节(即FIFO深度)的场景,例如发送一个EnDAT命令帧或一个简短的配置指令。其流程是“预装载-然后发射”。以下是详细的步骤和代码示例:

  1. (可选)配置FIFO位序:通过设置ICSSG_PRU0_ED_CHm_CFG0_REG[31] (PRU0_ED_TX_FIFO_SWAP_BITSm),可以选择数据是以MSB(最高位)还是LSB(最低位)优先的顺序被移出。这需要与外设的协议要求匹配。
  2. 预装载TX FIFO: a.选择目标通道:向R30[17:16] (tx_ch_sel)写入通道号(0,1,2)。 b.写入数据:向R30[7:0] (tx_data)写入1个字节。每写入一次,数据就被压入当前选中通道的FIFO一次。对于多字节数据,需要重复此步骤。例如,要发送一个32位数据0x12345678,需要按顺序写入0x12,0x34,0x56,0x78(假设MSB优先)。 c.为其他通道装载数据:重复步骤a和b,为其他需要发送的通道装载数据。
  3. 配置TX帧长度:如果装入FIFO的数据不是完整的4字节(32位),必须通过ICSSG_PRU0_ED_CHm_CFG0_REG[15:11] (PRU0_ED_TX_FRAME_SIZEm)寄存器明确告诉硬件本次发送的比特数。例如,只装入了3个字节(24位),则需设置TX_FRAME_SIZE = 24
  4. 启动发送: a.全局启动:设置R31[20] (tx_global_go) = 1。这将启动所有三个通道的发送(只要它们的FIFO非空)。 b.单通道启动:先设置R30[17:16] (tx_ch_sel)选择通道,再设置R31[18] (tx_channel_go) = 1
  5. 等待发送完成与后续处理
    • 如果使能了自动RX(通过PRU0_ED_RX_EN_COUNTERm),硬件会在TX结束后自动切换至RX模式。
    • 否则,需要轮询状态位等待发送完成。可以轮询R31[21,13,5] (tx_global_reinit_active/busy),或者查询CFG空间中的ICSSG_PRU0_ED_TX_CFG_REG[7,6,5] (PRU0_ED_BUSY_m)位,直到其变为0。

关键陷阱与复位操作:单次发送完成后,务必检查时钟状态。如果clk_mode设置为0(停止在低电平),而你的协议要求下一帧开始时时钟为高,则必须执行时钟复位操作,否则下一帧启动会失败。复位步骤如下:

  1. 设置R31[19] (tx_global_reinit) = 1。这将强制PERIF_CLK回到高电平。
  2. 轮询PRU0_ED_BUSY_m位,直到其变为0,表示复位完成。
  3. 重新配置R30[20:19] (clk_mode),因为tx_global_reinit操作会将clk_mode重置为默认的1(停止在高电平)。这是最容易遗漏的一步!

4.2 连续发送(Continuous)模式编程

当需要发送的数据流超过32字节,或者是不定长的连续数据时,就需要使用连续发送模式。此模式下,PRU需要像“水管工”一样,持续向FIFO中灌水,确保其不会干涸。其核心思想是将TX_FRAME_SIZE设置为0,这告诉硬件:“只要FIFO里有数据,就持续发送,直到我停止灌水”��

  1. 前期配置:同单次发送模式的步骤1和2,进行位序配置和FIFO的初始预装载(例如,先灌入4字节数据)。
  2. 配置为连续模式:设置ICSSG_PRU0_ED_CHm_CFG0_REG[15:11] PRU0_ED_TX_FRAME_SIZEm = 0
  3. 启动发送:同单次发送的步骤4。
  4. 监控与维持FIFO:这是连续模式的核心。程序必须持续监控R31中的tx_fifo_sts<m>(TX FIFO状态位)。一个重要的经验法则是:当状态显示FIFO中只剩2个字(即tx_fifo_sts值为2)时,就必须立即写入新的2个字节数据。绝不能等到FIFO完全为空(状态为0)再写入,因为硬件在FIFO空时会认为传输结束,导致后续数据无法发出,并可能触发下溢(Underrun)错误。
  5. 停止发送:当需要结束发送时,只需停止向FIFO写入新数据即可。硬件在发送完FIFO中剩余的数据后会自动停止。同样,之后可能需要根据clk_mode的状态决定是否执行复位操作。

在连续模式下,必须小心处理ovr(上溢)和unr(下溢)错误标志。上溢发生在你写入太快,FIFO已满时;下溢发生在你写入太慢,FIFO已空但硬件试图读取时。稳健的驱动应该包含对这些错误的检测和恢复机制,通常的恢复手段就是执行一次tx_global_reinit

5. 接收(RX)操作模式与数据采集

接收操作的核心在于配置过采样、启动采样,并在正确的时间读取数据。根据协议不同,接收的启动可以是手动的(Non-Auto Arm),也可以由发送操作自动触发(Auto Arm)。

5.1 接收配置与自动/手动使能

  1. 配置接收参数
    • 帧长度:通过ICSSG_PRU0_ED_CHm_CFG0_REG[27:16] (PRU0_ED_RX_FRAME_SIZEm)设置期望接收的比特数。例如,接收一个25位的绝对值编码器数据,则设置为25。
    • 起始位极性:通过ICSSG_PRU0_ED_RX_CFG_REG[3] (RX_SB_POL)配置。这决定了硬件将数据线上的何种电平跳变识别为一个帧的开始。
  2. 使能接收通道
    • 手动使能(Non-Auto Arm):在需要开始接收的时刻,直接设置对应的R30[26,25,24] (rx_en<m>)位为1。
    • 自动使能(Auto Arm):这是更常用、更精确的方式。在TX配置中,设置ICSSG_PRU0_ED_CHm_CFG1_REG[31:16] (PRU0_ED_RX_EN_COUNTERm)为一个非零值(N)。当TX帧发送完最后一个比特后,硬件会等待N个TX时钟周期,然后自动将对应通道的rx_en置1。这个延迟(RX_EN_COUNTER)对于实现问-答协议至关重要,它确保了发送方的驱动器关闭、线路状态稳定后,再开启接收模式。

5.2 数据轮询与读取流程

一旦接收使能,硬件就会在检测到起始位后,开始在每个过采样时钟的上升沿对PERIF<m>_IN数据线进行采样,并将采样结果移入一个8位的影子寄存器。

  1. 轮询有效标志:程序需要持续读取R31[26,25,24] (val<m>)位。当硬件收集完一帧数据(比特数由RX_FRAME_SIZE决定)后,会将对应通道的val位置1。
  2. 读取数据:一旦检测到val位为1,应立即从R31的对应rx_data_out<m>位域(例如,Channel 0对应R31[7:0])中读取数据。数据格式(MSB/LSB)需要根据发送端和可能的SWAP_BITS配置来解析。
  3. 清除标志读取数据后,必须立即向该val位写入1来清除它。这是一个关键操作,为接收下一帧数据做好准备。
  4. 处理溢出:如果在一帧数据的时间内(从val置1到被清除),程序未能及时读取并清除val标志,而下一帧数据又已接收完成,硬件会设置对应的ovf<m>(溢出)标志。驱动程序中应包含对ovf标志的检查,并在发生时进行错误计数或恢复操作(通常包括清除ovf标志和rx_en,然后重新使能接收)。
  5. 停止接收:接收完成后,清除R30中对应的rx_en<m>位。这将复位该通道的所有接收计数器和状态机。

实操心得:优化轮询与中断结合:纯轮询val位会占用大量PRU指令周期。一个更高效的做法是利用PRU的中断系统。可以将val标志连接到PRU的内部中断控制器(INTC),当数据有效时触发PRU中断。在中断服务例程中读取数据并清除标志,这样PRU在等待数据期间可以执行其他任务。不过,对于极高速度的连续数据流,中断开销可能成为瓶颈,此时精细优化的轮询循环可能是唯一选择。

6. 常见问题排查与调试技巧实录

在实际项目中使用PRU_ICSSG外设接口时,你一定会遇到各种问题。下面是我在多个项目中总结出的最常见问题及其排查思路,这能为你节省大量调试时间。

6.1 问题排查速查表

问题现象可能原因排查步骤与解决方案
发送数据,但示波器上看不到时钟或数据信号1. 时钟未正确启动。
2. 通道未使能(TX模式需rx_en=0)。
3. FIFO为空时启动了发送。
1. 检查clk_mode配置,确认时钟源和分频器设置正确。用逻辑分析仪抓取PERIF_CLK引脚。
2. 确认对应通道的rx_en位为0。
3.确保在发出tx_global_gotx_channel_go前,FIFO中已有数据tx_fifo_sts不为0)。
接收不到数据,val标志永远不置位1. 接收通道未使能(rx_en不为1)。
2. 过采样时钟配置错误。
3. 起始位极性(RX_SB_POL)设置错误。
4.RX_FRAME_SIZE设置与实际数据位数不符。
1. 确认rx_en位已置1(对于Auto Arm,检查RX_EN_COUNTER配置)。
2.重点检查RX时钟频率 / TX时钟频率 == RX_SAMPLE_SIZE + 1。用示波器测量RX时钟是否存在且频率正确。
3. 根据外设协议确认起始位是高电平还是低电平,调整RX_SB_POL
4. 核对数据手册,设置正确的帧长度。
数据错位或位序颠倒1.TX_FIFO_SWAP_BITSm或字节写入顺序错误。
2. 读取rx_data_out后解析顺序错误。
1. 确认外设协议要求的位序(MSB/LSB),并相应设置SWAP_BITS。检查PRU代码中写入tx_data的字节顺序。
2. 确认读取rx_data_out后,是按MSB还是LSB顺序重组数据。
连续发送模式下,数据流中途断裂1. FIFO下溢(Underrun)。
2. 未及时响应FIFO状态。
1. 检查R31中的unr(下溢)标志是否被置位。
2.强化FIFO填充逻辑:确保在tx_fifo_sts显示为2(还剩2字)时就必须开始写入新数据,绝不能等到0。考虑使用更激进的水线,例如在状态为3时就开始填充。
单次发送后,无法发起下一次发送1. 时钟未处于正确的起始状态(应为高电平)。
2. 未执行必要的复位操作。
1. 检查上次发送结束后的clk_mode。如果以低电平停止,则下次启动前时钟为低,不符合模块要求。
2.严格执行复位序列:置位tx_global_reinit-> 等待BUSY位清零 ->重新配置clk_mode
自动RX模式不工作1.PRU0_ED_RX_EN_COUNTERm设置为0。
2. TX帧未成功发送完毕。
1. 确认该计数器寄存器被设置为一个大于0的合理延迟值(单位是TX时钟周期)。
2. 检查TX发送是否成功完成(轮询BUSY位),只有TX完成后,自动RX计时器才会启动。

6.2 调试技巧与实战建议

  1. 善用PRU的调试功能:AM64x/AM243x的PRU核心支持通过r31向主机发起中断,并可以通过共享内存传递调试信息。在驱动开发初期,可以在关键步骤(如:FIFO状态变化、val标志置位、错误发生)通过设置一个调试代码并触发中断,让Linux主机的应用程序读取并打印出来,这比单纯用示波器抓信号高效得多。

  2. 分阶段验证:不要试图一次性实现完整协议。建议的验证顺序是:

    • 阶段一:时钟测试。先只配置时钟,不发送数据,用示波器验证PERIF_CLK的频率、占空比以及clk_mode下的起停行为是否符合预期。
    • 阶段二:Loopback测试。将PRU的PERIF_OUT引脚通过板载跳线或飞线直接连接到PERIF_IN引脚。编写一个发送固定模式(如0xAA0x55)的程序,并立即启动接收。验证发送的数据能否被正确回环接收。这是验证整个数据通路最有效的方法。
    • 阶段三:对接真实外设。在前两个阶段成功后,再连接实际的外设(如编码器),根据其协议调整时序参数(如Wire Delay,TST Delay,RX_EN_COUNTER)。
  3. 理解“字”与“字节”:在PRU和数据手册的语境中,“字”(Word)通常指32位。但外设接口的FIFO是32深,而tx_data寄存器是8位宽。这意味着FIFO可以容纳32 * 4 = 128字节的数据。但在操作tx_fifo_sts状态位时,它指示的是“字”的占用数(0-4),编程时需要注意这个单位转换。

  4. 电源与引脚复用检查:这是一个硬件层面的“坑”。确保PRU_ICSSG模块的电源域已正确上电,并且你使用的PERIF<m>_CLKPERIF<m>_OUTPERIF<m>_IN等引脚已通过PinMux工具正确配置为PRU外设接口模式,而不是普通的GPIO或其他功能。