TMS320F28335: DMA的数据传输问题

Part Number: TMS320F28335
Other Parts Discussed in Thread: TLV320ADC3140

我用TMS320F28335的McBSP读取8个通道的数据,每个通道都是32位,然后用DMA读取到rdata数组中rdata是1024个int32数组。结果我实验的过程中发现,正常读取数据是没有问题的,但是当我中断的时候,就是DMA可以配置接收1024个数据进行中断处理,我把这1024个数据进行了求补码的操作,几个rdata中的数据发生了移位,比如本来是0 1 2 3 4...1027,现在成了2 3 4 5 ...1027 0 1就是向后移了几个顺序,而且顺序一直在变,不是固定的。这样我就没法把每个通道对应的数据取出来了,因为我不知rdata的第几个数据对应的是通道一,那个对应的是通道二,所以这是为什么会发生这样的情况呢,我该怎么解决呢。

void init_dma_32()
{
  EALLOW;
  DmaRegs.DMACTRL.bit.HARDRESET = 1;
  asm(" NOP");
  // Channel 2, McBSPA Receive
    DmaRegs.CH2.BURST_SIZE.all = 1;       // 2 words/burst
    DmaRegs.CH2.SRC_BURST_STEP = 1;       // Increment 1 16-bit addr. btwn words
    DmaRegs.CH2.DST_BURST_STEP = 1;       // Increment 1 16-bit addr. btwn words
    DmaRegs.CH2.TRANSFER_SIZE = 1023;       // Interrupt every 63 bursts/transfer
    DmaRegs.CH2.SRC_TRANSFER_STEP = 0xFFFF;   // Decrement  back to DRR2
    DmaRegs.CH2.DST_TRANSFER_STEP = 1;    // Move to next word in buffer after each word in a burst
    DmaRegs.CH2.SRC_ADDR_SHADOW = (Uint32) &McbspaRegs.DRR2.all;          // Start address = McBSPA DRR
    DmaRegs.CH2.SRC_BEG_ADDR_SHADOW = (Uint32) &McbspaRegs.DRR2.all;      // Not needed unless using wrap function
    DmaRegs.CH2.DST_ADDR_SHADOW = (Uint32) &rdata[0];     // Start address = Receive buffer (for McBSP-A)
    DmaRegs.CH2.DST_BEG_ADDR_SHADOW = (Uint32) &rdata[0]; // Not needed unless using wrap function
    DmaRegs.CH2.CONTROL.bit.SYNCCLR = 1;      // Clear sync flag
    DmaRegs.CH2.CONTROL.bit.ERRCLR = 1;   // Clear sync error flag
    DmaRegs.CH2.DST_WRAP_SIZE = 1023;       // Put to maximum - don't want destination wrap
    DmaRegs.CH2.SRC_WRAP_SIZE = 1023;       // Put to maximum - don't want source wrap
    DmaRegs.CH2.MODE.bit.CHINTE = 1;          // Enable channel interrupt
    DmaRegs.CH2.MODE.bit.CHINTMODE = 1;       // Interrupt at end of transfer
    DmaRegs.CH2.MODE.bit.PERINTE = 1;         // Enable peripheral interrupt event
    DmaRegs.CH2.MODE.bit.PERINTSEL = DMA_MREVTA;  // Peripheral interrupt select = McBSP MRSYNCA
    DmaRegs.CH2.CONTROL.bit.PERINTCLR = 1;        // Clear any spurious interrupt flags
    DmaRegs.CH2.MODE.bit.ONESHOT = 0;
    EDIS;
}

以上是DMA的配置,因为数据是TLV320ADC3140芯片传过来的,只需要配置接收通道就行。

interrupt void local_DINTCH2_ISR(void)  // DMA Ch2
{
/*
    Uint16 i;
    //原始数据有问题,需要交换高低16位数据,比如0xFFFF0000,需要变为0X0000FFFF
    for(i = 0;i<1024;i++)
    {
        CorrectDATA[i] = ((rdata[i] & 0xFFFF0000) >> 16) | ((rdata[i] & 0x0000FFFF) << 16);
    }
    for(i = 0;i<128;i++)
    {
        //x1
        if(CorrectDATA[i*8] < 0)
        {
            x1[i] = ~CorrectDATA[i*8] + 1;
            if (x1[i] & 0x8000)//符号位不变,上一步取反把符号位也取反了,这里是还原符号位
            {
                x1[i] &= 0xefff; // 清除符号位
            }
            else
            {
                x1[i] |= 0x8000;
            }
        }
        else
        {
            x1[i] = CorrectDATA[i*8];
        }
        //x2
        if(CorrectDATA[i*8 + 1] < 0)
        {
            x2[i] = ~CorrectDATA[i*8 + 1] + 1;
            if (x2[i] & 0x8000)//符号位不变,上一步取反把符号位也取反了,这里是还原符号位
            {
                x2[i] &= 0xefff; // 清除符号位
            }
            else
            {
                x2[i] |= 0x8000;
            }
        }
        else
        {
            x2[i] = CorrectDATA[i*8 + 1];
        }
        //x3
        if(CorrectDATA[i*8 + 2] < 0)
        {
            x3[i] = ~CorrectDATA[i*8 + 2] + 1;
            if (x3[i] & 0x8000)//符号位不变,上一步取反把符号位也取反了,这里是还原符号位
            {
                x3[i] &= 0xefff; // 清除符号位
            }
            else
            {
                x3[i] |= 0x8000;
            }
        }
        else
        {
            x3[i] = CorrectDATA[i*8 + 2];
        }
        //x4
        if(CorrectDATA[i*8 + 3] < 0)
        {
            x4[i] = ~CorrectDATA[i*8 + 3] + 1;
            if (x4[i] & 0x8000)//符号位不变,上一步取反把符号位也取反了,这里是还原符号位
            {
                x4[i] &= 0xefff; // 清除符号位
            }
            else
            {
                x4[i] |= 0x8000;
            }
        }
        else
        {
            x4[i] = CorrectDATA[i*8 + 3];
        }
    }
*/
    EALLOW;                                 // NEED TO EXECUTE EALLOW INSIDE ISR !!!
        DmaRegs.CH2.CONTROL.bit.RUN = 1;        // Re-enable DMA CH2. Should be done every transfer
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // To receive more interrupts from this PIE group, acknowledge this interrupt
    EDIS;
    return;
}

这是DMA的中断服务程序,我把注释掉的程序运行的时候就会出现我所说的情况,如果中断服务程序什么也不做,那数据就是正常的,rdata【0】就是第一个通道rdata【7】就是第八个通道,依次循环。
还请各路豪杰,指点迷津

  • 您好

    可能的原因

    1. DMA配置问题‌:

      • 确保DMA的传输配置正确,特别是数据传输数量(NDT寄存器)和源地址(CPARx寄存器)及目标地址(CMARx寄存器)的设置。
      • 检查DMA的优先级(PL位)和传输模式(如循环模式或自动重加载模式)是否满足你的需求。
    2. 中断处理不当‌:

      • 在中断服务例程中,确保你正确处理了DMA传输完成的中断。
      • 检查是否有其他中断干扰了DMA的传输过程。
    3. 数据对齐和宽度问题‌:

      • 你提到每个通道的数据是32位的,确保在DMA配置中数据宽度设置为32位。
      • AHB到APB的数据传输可能会按32位对齐处理,但请确保这不会影响你的数据读取逻辑。
    4. 外部干扰或硬件故障‌:

      • 检查硬件电路是否有潜在的干扰源,如电磁干扰或电源波动。
      • 确认所有硬件连接都正确无误,包括McBSP和DMA的接口。

    解决方案

    1. 重新检查DMA配置‌:

      • 确保DMA的传输数量、源地址和目标地址设置正确。
      • 如果可能,尝试简化DMA的配置,例如先尝试单通道数据传输,确认无误后再扩展到多通道。
    2. 优化中断处理‌:

      • 在中断服务例程中添加更多的调试信息,以便跟踪数据的处理过程。
      • 确保中断服务例程足够快,不会阻塞DMA的传输。
    3. 验证数据对齐和宽度‌:

      • 在软件中添加数据对齐和宽度的检查逻辑,确保数据在传输过程中没有被意外修改。
    4. 硬件故障排查‌:

      • 使用示波器或逻辑分析仪等工具检查硬件信号,确认信号完整性和时序。
      • 如果可能,尝试更换硬件模块或设备,以排除硬件故障的可能性。

    官方给的例程: