1. 双核通信初始化与验证

任务目标

在双核架构伺服驱动系统中,DSP与FPGA之间的数据交换是电流环、速度环高速控制的基础。本案例以TI C2000系列DSP与Xilinx FPGA为例,通过EMIF接口(16位异步模式)建立通信链路,实现DSP向FPGA写入控制字、读取状态字的双向数据通路,并通过回环校验验证通信正确性。

硬件连接与接口约定

  • EMIF总线:DSP的EMIF_CS2片选空间映射至FPGA寄存器基地址0x200000
  • 数据宽度:16位,异步读/写时序,无等待状态插入
  • FPGA侧寄存器映射:
    • 偏移0x00:控制寄存器(DSP写,FPGA读)
    • 偏移0x02:状态寄存器(FPGA写,DSP读)
    • 偏移0x04:回环数据寄存器(FPGA内部将写入值原样返回)

DSP端完整实现(C2000)

// emif_test.c - DSP与FPGA EMIF通信验证
#include "F2837xD_device.h"
#include "F2837xD_Examples.h"

// EMIF片选2空间基地址(与FPGA连接)
#define FPGA_BASE      0x200000U
// 寄存器偏移(字节地址)
#define REG_CTRL       0x00U
#define REG_STATUS     0x02U
#define REG_LOOPBACK   0x04U

// 使用volatile防止编译器优化
#define FPGA_CTRL      (*(volatile Uint16 *)(FPGA_BASE + REG_CTRL))
#define FPGA_STATUS    (*(volatile Uint16 *)(FPGA_BASE + REG_STATUS))
#define FPGA_LOOPBACK  (*(volatile Uint16 *)(FPGA_BASE + REG_LOOPBACK))

// EMIF初始化:CS2空间,16位异步接口
void EMIF_Init(void)
{
    // 使能EMIF时钟(GPIO时钟已在InitSysCtrl使能)
    CpuSysRegs.PCLKCR0.bit.EMIF1 = 1;

    // 配置CS2空间:异步模式,16位数据总线
    EMIF1CS2CR.all = 0x00000020;  // 异步接口,16位总线宽度

    // 读时序:建立2周期,选通6周期,保持2周期
    EMIF1CS2RCR.all = 0x00020062;

    // 写时序:建立2周期,选通6周期,保持2周期
    EMIF1CS2WCR.all = 0x00020062;

    // 片选空间使能
    EMIF1CS2CR.bit.CS_EN = 1;
}

// 回环测试:写入0x5A5A,读取返回值并比较
Uint16 EMIF_LoopbackTest(void)
{
    Uint16 testPattern = 0x5A5A;
    Uint16 readBack;

    // 写控制寄存器(FPGA侧仅存储)
    FPGA_CTRL = testPattern;

    // 写回环寄存器(FPGA内部将数据原样返回)
    FPGA_LOOPBACK = testPattern;

    // 读取回环值
    readBack = FPGA_LOOPBACK;

    // 读取状态寄存器(FPGA上电默认0x0001,表示链路就绪)
    Uint16 status = FPGA_STATUS;

    // 验证:回环数据一致且状态寄存器bit0=1
    if ((readBack == testPattern) && (status & 0x0001))
        return 1;   // 通信正常
    else
        return 0;   // 通信异常
}

void main(void)
{
    // 系统初始化(时钟、GPIO等)
    InitSysCtrl();
    InitGpio();

    // GPIO引脚复用为EMIF功能
    // EMIF1_D[0..15], EMIF1_A[0..7], EMIF1_CS2, EMIF1_WE, EMIF1_OE, EMIF1_RNW
    // 具体引脚号见F2837xD原理图,此处为关键配置示例:
    GPIO_SetupPinMux(0, GPIO_MUX_CPU1, 1);  // EMIF1_D0
    GPIO_SetupPinMux(1, GPIO_MUX_CPU1, 1);  // EMIF1_D1
    // ...(其余数据/地址/控制引脚按相同方式配置)

    // 初始化EMIF
    EMIF_Init();

    // 执行回环验证
    Uint16 result = EMIF_LoopbackTest();

    // 结果指示:GPIO31输出高电平表示成功(需外部LED或示波器观察)
    GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 0);
    GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSH_PULL);
    GPIO_WritePin(31, result ? 1 : 0);

    // 程序停留,观察结果
    while(1);
}

FPGA端最小逻辑(Verilog)

// fpga_emif_slave.v - EMIF从设备接口
module fpga_emif_slave (
    input wire clk,              // 50MHz系统时钟
    input wire rst_n,
    // EMIF接口
    input wire cs,               // 片选(低有效)
    input wire we,               // 写使能(低有效)
    input wire oe,               // 读使能(低有效)
    input wire [7:0] addr,       // 地址总线
    inout wire [15:0] data,      // 数据总线
    // 内部寄存器
    output reg [15:0] ctrl_reg,  // 控制寄存器
    input wire [15:0] status_reg // 状态寄存器(外部输入)
);

    reg [15:0] loopback_reg;
    reg [15:0] data_out;
    reg data_out_en;

    // 写操作
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            ctrl_reg <= 16'h0000;
            loopback_reg <= 16'h0000;
        end else if (!cs && !we) begin
            case (addr[3:0])
                4'h0: ctrl_reg <= data;
                4'h2: status_reg <= data;  // 允许外部写状态(测试用)
                4'h4: loopback_reg <= data;
            endcase
        end
    end

    // 读操作
    always @(*) begin
        data_out = 16'h0000;
        data_out_en = 1'b0;
        if (!cs && !oe) begin
            case (addr[3:0])
                4'h0: begin data_out = ctrl_reg; data_out_en = 1'b1; end
                4'h2: begin data_out = status_reg; data_out_en = 1'b1; end
                4'h4: begin data_out = loopback_reg; data_out_en = 1'b1; end
            endcase
        end
    end

    assign data = data_out_en ? data_out : 16'hZZZZ;

endmodule

运行与验证

  1. 硬件连接:将DSP EMIF接口与FPGA引脚按原理图连接,确保FPGA程序已烧录且状态寄存器输出0x0001(bit0=1表示FPGA就绪)。
  2. 编译烧录:在CCS中编译DSP工程并烧录至DSP,运行程序。
  3. 验证方法:
    • 观察GPIO31输出:高电平表示回环测试通过,低电平表示失败
    • 在CCS的Expressions窗口添加FPGA_CTRL、FPGA_LOOPBACK变量,单步执行后确认写入值与读取值一致
    • 使用逻辑分析仪抓取EMIF总线时序,确认CS2、WE、OE信号与读写周期匹配
  4. 通过标准:回环测试返回1且GPIO31输出高电平,同时状态寄存器bit0为1,即判定通信链路正常。

常见问题

  • 数据全为0xFF:检查EMIF片选地址是否映射正确,FPGA侧cs信号是否有效连接
  • 写入无响应:确认EMIF时序参数(建立/选通/保持周期)是否满足FPGA侧时序要求,必要时增加等待周期
  • GPIO复用冲突:确保所有EMIF引脚已正确配置为外设功能,未被其他外设占用