4. PRU C语言开发环境搭建

PRU(Programmable Real-time Unit)是 TI Sitara AM335x/AM57x 等芯片内部独立于 ARM Cortex-A 核的实时协处理器,拥有自己的指令集、32 位数据通路和独立内存空间。用 C 语言开发 PRU 固件,不能直接套用 ARM 侧的工具链,必须建立一套“ARM 主程序 + PRU 固件”的双侧工程环境。本节围绕这条工具链的四个关键环节展开:CCS 安装、PRU 编译器、链接命令文件(.cmd)以及固件加载与调试配置。

一、Code Composer Studio 安装与组件选择

CCS 是 TI 官方集成开发环境,PRU 开发依赖其中的编译器、调试驱动和器件支持包。安装时建议选择较新的 CCS 版本(如 CCS 12.x 及以上),并在组件选择界面勾选以下内容:

  • 处理器支持包:勾选 Sitara AM335x 或 AM57x 系列,确保芯片 GEL 文件、Flash 编程器可用。
  • PRU 编译器:即 TI PRU C/C++ Compiler(ti-pru-cgt),这是把 C 代码编译成 PRU 汇编/目标文件的核心组件。
  • PRU 调试支持:包含 PRU 的 CCS 调试插件与仿真驱动,用于连接 PRU 内核。
  • XDS 调试探针驱动:若使用 XDS100v2/XDS110 等仿真器,需安装对应驱动。

安装完成后,可在 CCS 安装目录下的 ccs/tools/compiler/ 中看到类似 ti-cgt-pru_2.3.x 的文件夹,说明 PRU 编译器已就位。若使用命令行编译,也可单独下载 PRU CGT 并设置环境变量 PRU_CGT 指向该目录。

二、PRU 编译器与编译流程

PRU 编译器 clpru 的用法与 ARM 的 armcl 类似,但目标架构不同。一个典型的 PRU 固件编译流程如下:

# 编译单个 C 源文件为 PRU 目标文件
clpru -v3 -O2 -I./include -c pru_main.c -o pru_main.obj

# 链接生成可执行 ELF 文件
lnkpru -m pru_main.map -c pru.cmd pru_main.obj -o pru_firmware.out

# 生成可加载的二进制/文本格式
hexpru --array --ihex pru_firmware.out -o pru_firmware.h

其中 -v3 指定 PRU 指令集版本(PRU-ICSS 通常为 v3),-O2 为优化等级。链接阶段必须提供 .cmd 链接命令文件,否则链接器不知道各段应放到 PRU 的哪块内存。编译产物 .out 是 ELF 格式,可被 CCS 直接加载;.h 数组则便于 ARM 侧程序把固件嵌入到自己的镜像中。

三、链接命令文件(.cmd)的编写

PRU 的内存空间与 ARM 不同:PRU 有独立的指令 RAM(IRAM)和数据 RAM(DRAM),以及可访问的共享内存。链接命令文件的作用就是把这些段映射到正确的物理地址。以 AM335x PRU-ICSS 为例,PRU0 的 IRAM 起始地址为 0x00000000,DRAM 起始地址为 0x00000000(数据空间独立编址),共享内存通常位于 0x00010000 附近。一个简化的 pru.cmd 示例如下:

MEMORY
{
    PRU_IRAM : org = 0x00000000, len = 0x00002000
    PRU_DRAM : org = 0x00000000, len = 0x00002000
    SHARED   : org = 0x00010000, len = 0x00003000
}

SECTIONS
{
    .text    > PRU_IRAM
    .data    > PRU_DRAM
    .bss     > PRU_DRAM
    .stack   > PRU_DRAM
    .shared  > SHARED
}

这里 org 是起始地址,len 是长度。需要特别注意的是,PRU 的 IRAM 和 DRAM 在物理上是分开的,但地址都从 0 开始,因此链接器通过段名来区分。如果固件较大,IRAM 放不下,就需要把部分代码放到共享内存或外部内存,并在运行时通过跳转访问。编写 .cmd 时务必对照芯片数据手册中的 PRU 内存映射表,地址写错会导致固件加载后跑飞。

PRU C 开发工具链与固件加载路径 CCS 工程 pru_main.c pru.cmd include/ ARM 主程序 PRU 编译器 clpru 编译 lnkpru 链接 hexpru 转换 固件与加载 pru_firmware.out pru_firmware.h CCS 加载/调试 remoteproc 加载 编译产物 .out 可直接由 CCS 加载;.h 数组供 ARM 侧 remoteproc 加载

四、固件加载与调试配置

PRU 固件有两种常见加载方式。第一种是CCS 在线加载:在 CCS 中新建一个“PRU 目标配置”,选择对应的 XDS 仿真器和芯片型号,连接后右键 PRU 内核,选择 Load Program 加载 .out 文件。加载前需确保 PRU 已从复位状态释放,通常通过 GEL 脚本或 ARM 侧程序完成。加载后可在 PRU 汇编窗口看到反汇编代码,并设置断点、单步执行、查看寄存器和内存。

第二种是ARM 侧 remoteproc 加载:在 Linux 系统中,PRU 固件以 .h 数组形式嵌入 ARM 程序,或通过文件系统加载。ARM 程序调用 prussdrv 或 remoteproc 框架,把固件写入 PRU 的 IRAM,然后启动 PRU 内核。这种方式适合产品化部署,但调试时仍需借助 CCS 或 PRU 的调试寄存器。

调试配置中几个关键点:

  • 复位与启动:PRU 上电后处于复位状态,需通过 PRU 控制寄存器(如 PRU_ICSS_CTRL)的 PRU0_CTRL 位释放复位并启动。
  • 内存查看:在 CCS 的 Memory Browser 中查看 PRU IRAM/DRAM 地址,确认固件是否正确写入。
  • 断点:PRU 支持硬件断点,但数量有限,建议在关键循环或状态切换处设置。
  • 时钟与引脚:调试前确认 PRU 时钟已使能,相关引脚已配置为 PRU 功能,否则程序运行但无外部信号。
提示:若 CCS 连接 PRU 时提示“无法识别设备”,先检查仿真器驱动和 GEL 文件是否匹配芯片型号;若加载后程序不运行,优先核对 .cmd 中的内存地址是否与数据手册一致。

五、一个最小可运行示例的配置要点

假设我们要在 AM335x 的 PRU0 上运行一个翻转 GPIO 的固件,工程配置应包含:

  • 源文件 pru_gpio.c:包含 PRU 寄存器定义头文件,配置 GPIO 方向并循环翻转。
  • 链接文件 pru.cmd:将 .text 放入 IRAM,.data 和 .bss 放入 DRAM。
  • 编译选项:-v3 -O2 -I${PRU_CGT}/include。
  • 加载方式:CCS 在线加载 .out,或生成 .h 后由 ARM 程序加载。

完成上述配置后,在 CCS 中点击“Debug”即可进入 PRU 调试视图。观察 PRU 的 PC 指针是否停在 main 入口,运行后查看 GPIO 输出寄存器是否按预期翻转,即可判断固件是否正常工作。这套环境一旦搭好,后续所有 PRU 实时控制程序的开发、下载和调试都可以在此基础上进行。