This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28377S:McBSP SPI 从器件 DMA Rx

Guru**** 2468460 points
Other Parts Discussed in Thread: TMS320F28377S, TMS320F28386D, C2000WARE

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1319640/tms320f28377s-mcbsp-spi-slave-dma-rx

器件型号:TMS320F28377S
主题中讨论的其他器件: TMS320F28386DC2000WARE

您好!

我正在尝试将 TMS320F28377S McBSP 一个端口用作 SPI 从器件并使用 DMA CH6接收数据。   TMS320F28377S 上的 McBSP SPI 从器件是否支持 DMA?  我注意到、McBSP 寄存器 DRR1确实会从主器件传输中获得第一个16位字、但好像 DMA 控制器没有移动数据。  我将使用16位字进行数据传输。  如果我使用传输大小1和突发大小1、我将获得 DMA 中断、但不会从 DRR1读取数据。

其他要点

  • 我能够作为从器件通过 McBSP A SPI 端口使用中断在 TMS320F28377S 上发送和接收数据、而无需 DMA。 这工作正常。
  • 我能够将 TMS320F28386D McBSP B 端口用作 SPI 主器件并进行 TX/Rx DMA 传输。  就表示工作正常。

void main(void)
{
    //
    // Initialize device clock and peripherals
    //
    Device_init();

    GPIO_Setup();

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    McBSP_SPI_DMA_Setup();

    IER = 0x60;

    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;

    while(true)
    {
        //Loop forever
    }
}

#include "driverlib.h"
#include "device.h"
#include <stdint.h>
#include <string.h>


#pragma DATA_SECTION(txData, "ramgs0");  // map the TX data to memory
#pragma DATA_SECTION(rxData, "ramgs0");  // map the RX data to memory


#define MCBSP_PING_PONG_SIZE                2
#define BURST                               1
//#define TRANSFER                          512
//#define TRANSFER                          5         //For Testing to See 5 uint16_t on the scope
#define TRANSFER                            1         //Transfer size of 1 causes an interrupt

volatile uint16_t txData[TRANSFER];
volatile uint16_t rxData[TRANSFER];

uint32_t base_mcbsp=MCBSPA_BASE;
uint32_t base_dma_tx=DMA_CH5_BASE;
uint32_t base_dma_rx=DMA_CH6_BASE;


//
// Define to select delay in clock cycles.
//
#define MCBSP_CYCLE_NOP0(n)  __asm(" RPT #(" #n ") || NOP")
#define MCBSP_CYCLE_NOP(n)   MCBSP_CYCLE_NOP0(n)


__interrupt void DMA_CH5_ISR();
__interrupt void DMA_CH6_ISR();

static void McBSP_SPI_DMA_Setup_McBSP()
{

    //
    // Reset FS generator, sample rate generator, transmitter, receiver.
    //
    McBSP_resetFrameSyncLogic(base_mcbsp);
    McBSP_resetSampleRateGenerator(base_mcbsp);
    McBSP_resetTransmitter(base_mcbsp);
    McBSP_resetReceiver(base_mcbsp);

    //
    // Set Rx sign-extension and justification mode.
    //
    McBSP_setRxSignExtension(base_mcbsp, MCBSP_RIGHT_JUSTIFY_FILL_ZERO);

    //
    // Enable clock stop mode.
    //
    McBSP_setClockStopMode(base_mcbsp, MCBSP_CLOCK_SPI_MODE_NO_DELAY);

    //
    // Set Rx & Tx delay to 0 cycle.
    //
    McBSP_setRxDataDelayBits(base_mcbsp, MCBSP_DATA_DELAY_BIT_0);
    McBSP_setTxDataDelayBits(base_mcbsp, MCBSP_DATA_DELAY_BIT_0);

    //
    // Set CLKX & FSX as inputs
    //
    McBSP_setTxClockSource(base_mcbsp, MCBSP_EXTERNAL_TX_CLOCK_SOURCE);
    McBSP_setTxFrameSyncSource(base_mcbsp, MCBSP_TX_EXTERNAL_FRAME_SYNC_SOURCE);

    //
    // Set Tx and Rx clock and frame-sync polarity.
    //
    McBSP_setTxFrameSyncPolarity(base_mcbsp, MCBSP_TX_FRAME_SYNC_POLARITY_LOW);
    McBSP_setTxClockPolarity(base_mcbsp, MCBSP_TX_POLARITY_RISING_EDGE);
    McBSP_setRxClockPolarity(base_mcbsp, MCBSP_RX_POLARITY_FALLING_EDGE);

    //
    // Initialize McBSP data length.
    //
    McBSP_setRxDataSize(base_mcbsp, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_16, 0);
    McBSP_setTxDataSize(base_mcbsp, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_16, 0);

    //
    // Set LSPCLK as input source for sample rate generator.
    //
    McBSP_setTxSRGClockSource(base_mcbsp, MCBSP_SRG_TX_CLOCK_SOURCE_LSPCLK);

    //
    // Set Divide down value for CLKG.
    //
    McBSP_setSRGDataClockDivider(base_mcbsp, 1);

    //
    // Enable Rx interrupt
    //
    //McBSP_enableRxInterrupt(base_mcbsp);

    //McBSP_enableTxInterrupt(base);
    //
    // Set no external clock sync for CLKG.
    //
    McBSP_disableSRGSyncFSR(base_mcbsp);

    //
    // Wait for CPU cycles equivalent to 2 SRG cycles-init delay.
    // Total cycles required = 2*(SYSCLK/LSPCLK). In this example
    // LSPCLK = SYSCLK/4.
    //
    MCBSP_CYCLE_NOP(8);

    //
    // Enable Sample rate generator and wait for at least 2 CLKG clock cycles.
    //
    McBSP_enableSampleRateGenerator(base_mcbsp);
    McBSP_enableFrameSyncLogic(base_mcbsp);

    //
    // Wait for CPU cycles equivalent to 2 CLKG cycles-init delay.
    // Total cycles required = 2*(SYSCLK/(LSPCLK/(1+CLKGDV_VAL))). In this
    // example LSPCLK = SYSCLK/4 and CLKGDV_VAL = 1.
    //
    MCBSP_CYCLE_NOP(16);

    //
    // Release Rx, Tx and frame-sync generator from reset.
    //
    McBSP_enableTransmitter(base_mcbsp);
    McBSP_enableReceiver(base_mcbsp);

    //
    // Wait for CPU cycles equivalent to 2 SRG cycles-init delay.
    // Total cycles required = 2*(SYSCLK/LSPCLK). In this example
    // LSPCLK = SYSCLK/4.
    //
    MCBSP_CYCLE_NOP(8);

    //Interrupt_register(INT_MCBSPA_RX, McBSP_SPI_Rx_Interrupt);
    //Interrupt_enable(INT_MCBSPA_RX);

}


static void McBSP_SPI_DMA_Setup_DMA_Tx()
{
    //
    // Configure DMA Channel 1 (16 - bit datasize).
    //
    DMA_disableInterrupt(base_dma_tx);

    //
    // Configure 1 word per burst.
    //
    DMA_configBurst(base_dma_tx, BURST, 0U, 0U);

    //
    // Configure 127 bursts per transfer.
    //
    DMA_configTransfer(base_dma_tx, TRANSFER, 1, 0);

    //
    // Src start address = buffer & dest start address = MCBSPA DXR
    //
    DMA_configAddresses(base_dma_tx, (const void*)(base_mcbsp + MCBSP_O_DXR1), (const void*)(&(txData[0])));

    //
    // Clear peripheral interrupt event flag.
    //
    DMA_clearTriggerFlag(base_dma_tx);

    //
    // Clear sync error flag.
    //
    DMA_clearErrorFlag(base_dma_tx);

    //
    // Configure wrap size to maximum to avoid wrapping.
    //
    DMA_configWrap(base_dma_tx, 0x10000U, 0, 0x10000U, 0);


    Interrupt_register(INT_DMA_CH5, DMA_CH5_ISR);

    //
    // Enable channel interrupt.
    //
    DMA_enableInterrupt(base_dma_tx);

    //
    // Interrupt at end of the transfer.
    //
    DMA_setInterruptMode(base_dma_tx, DMA_INT_AT_END);

    //
    // Enable selected peripheral trigger to start a DMA transfer on DMA
    // channel 1.
    //
    DMA_enableTrigger(base_dma_tx);

    //
    // Configure DMA trigger source as McBSPA Tx EVT.
    //
    //DMA_configMode(base_dma_tx, DMA_TRIGGER_MCBSPAMXEVT, DMA_CFG_ONESHOT_ENABLE);
    DMA_configMode(base_dma_tx, DMA_TRIGGER_MCBSPAMXEVT, DMA_CFG_ONESHOT_DISABLE);

    //
    // Clear any spurious Peripheral interrupts flags.
    //
    DMA_clearTriggerFlag(base_dma_tx);

    //
    // Enable interrupts in PIE block.
    //
    Interrupt_enable(INT_DMA_CH5);
}


static void McBSP_SPI_DMA_Setup_DMA_Rx()
{
    //
    // Configure DMA Channel 2 (16 - bit datasize).
    //
    DMA_disableInterrupt(base_dma_rx);

    //
    // Configure 1 word per burst.
    //
    DMA_configBurst(base_dma_rx, BURST, 0U, 0U);

    //
    // Configure 127 bursts per transfer.
    //
    DMA_configTransfer(base_dma_rx, TRANSFER, 0, 1);

    //
    // Dest start address = buffer & Src start address = MCBSPA DRR
    //
    DMA_configAddresses(base_dma_rx,(const void*)(&(rxData[0])), (const void*)(MCBSPA_BASE + MCBSP_O_DRR2));

    //
    // Clear peripheral interrupt event flag.
    //
    DMA_clearTriggerFlag(base_dma_rx);

    //
    // Clear sync error flag.
    //
    DMA_clearErrorFlag(base_dma_rx);

    //
    // Configure wrap size to maximum to avoid wrapping.
    //
    DMA_configWrap(base_dma_rx, 0x10000U, 0, 0x10000U, 0);


    Interrupt_register(INT_DMA_CH6, DMA_CH6_ISR);

    //
    // Enable channel interrupt.
    //
    DMA_enableInterrupt(base_dma_rx);

    //
    // Interrupt at end of the transfer.
    //
    DMA_setInterruptMode(base_dma_rx, DMA_INT_AT_END);

    //
    // Enable selected peripheral trigger to start a DMA transfer on DMA
    // channel 2.
    //
    DMA_enableTrigger(base_dma_rx);

    //
    // Configure DMA trigger source as McBSPA Tx EVT.
    //
    //DMA_configMode(base_dma_rx, DMA_TRIGGER_MCBSPAMREVT, 0);
    DMA_configMode(base_dma_rx, DMA_TRIGGER_MCBSPAMREVT, DMA_CFG_ONESHOT_DISABLE);
    //DMA_configMode(base_dma_rx, DMA_TRIGGER_MCBSPAMREVT, DMA_CFG_ONESHOT_ENABLE);
    //DMA_configMode(base_dma_rx, DMA_TRIGGER_MCBSPAMREVT, DMA_CFG_CONTINUOUS_ENABLE);

    //DMA_configMode(DMA_CH6_BASE, DMA_TRIGGER_SOFTWARE, DMA_CFG_ONESHOT_ENABLE);

    //
    // Clear any spurious Peripheral interrupts flags.
    //
    DMA_clearTriggerFlag(base_dma_rx);

    //
    // Enable interrupts in PIE block.
    //
    Interrupt_enable(INT_DMA_CH6);

}



void McBSP_SPI_DMA_Setup()
{

    McBSP_SPI_DMA_Setup_McBSP();

    McBSP_SPI_DMA_Setup_DMA_Rx();
    McBSP_SPI_DMA_Setup_DMA_Tx();

    txData[0]=1;
    txData[1]=2;
    txData[2]=3;
    txData[3]=4;
    txData[4]=5;

    DMA_startChannel(base_dma_rx);
    DMA_startChannel(base_dma_tx);
}





__interrupt void DMA_CH5_ISR()
{
    //DMA_clearTriggerFlag(base_dma_tx);
    //done=1;
    DMA_stopChannel(base_dma_tx);
}



__interrupt void DMA_CH6_ISR()
{
    volatile uint16_t rx_count=0;
    volatile uint16_t r0, r1, r2, r3, r4;
    rx_count=1;
    r0=rxData[0];
    r1=rxData[1];
    r2=rxData[2];
    r3=rxData[3];
    r4=rxData[4];


    DMA_stopChannel(base_dma_rx);


    //
    // Dest start address = buffer & Src start address = MCBSPA DRR
    //
    DMA_configAddresses(base_dma_rx,(const void*)(&(rxData[0])), (const void*)(base_mcbsp + MCBSP_O_DRR1));

    DMA_startChannel(base_dma_rx);
    DMA_clearTriggerFlag(base_dma_rx);
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尼古拉斯、您好!

    Unknown 说:
     TMS320F28377S 上的 McBSP SPI 从器件是否支持 DMA?

    我认为 McBSP 应该具有对寄存器的 DMA 访问支持、F2838x 可以对这些寄存器进行 DMA 访问、并且两个器件都具有相同的 DMA 类型。 此外、DRR1的寄存器描述表明它可以由 CPU 或 DMA 读取、您说  McBSP 寄存器 DRR1获取传输中的第一个16位字时、您说 DMA 读取第一个字、而不是后面的字吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我通过 SPI 从主器件(TMS320F28386D)传输5个 uint16s 至从器件(TMS320F28377S)。  0x0004、0x0005、0x0006、0x0007、0x0008。  我在从器件的 McBSP DRR1中看到了0x0004。  但是、不会将任何内容复制到全局共享 RAM 中的 DMA Rx 缓冲区。  附加的图片。

    如果我将从器件突发设置为1、我将获得 DMA 中断、但没有数据从 DRR1复制到 RAM。

    我不知道 DMA 为什么不进行复制。  我将尝试仅使用 TMS320F28377S 上的 DMA 将数据从 RAM 传输到 RAM、以便在 TMS320F28377S 上正确配置 DMA、并且我可以使用 McBSP 从器件/DMA 将其范围缩小至包含以下内容的范围。 如果您有任何建议、请告诉我。  谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尼古拉斯、您好!

    我将尝试仅使用 TMS320F28377S 上的 DMA 将数据从 RAM 传输到 RAM,以使 DMA 在 TMS320F28377S 上正确配置,我可以使用 McBSP Slave/DMA 将其范围缩小为其他类型。

    是的、我认为这是一件很好的测试。 如果您不想重写整个不同的项目、C2000Ware 中实际上提供了一个适用于 F2837xS 的 DMA 示例。

    另外、请尝试更改传输大小和突发计数、以便进行单次5次脉冲传输、而不是进行5次1次脉冲传输。 如果您发现任何内容、请告诉我。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Omer:

    我已经能够使用 TMS320F28377S 上的 DMA 在 RAM 内进行传输。  但是、我很难在 TMS320F28377S 上使用 DMA 与 McBSP SPI 配合使用。  我通过 McBSP SPI 将 TMS320F28386D 连接至 TMS320F28377S。  TMS320F28386D 与 McBSP SPI DMA 配合使用作为主器件。  我曾尝试使用 McBSP SPI DMA 切换角色并使 TMS320F28377S 成为主设备、但实际没有工作。  代码几乎与我在 TMS320F28386D 上运行的代码相同(我在 TMS320F28386D 上使用了 SYS/BIOS)。  因此、TMS320F2877S McBSP SPI DMA 不能供我用作主设备或从设备。  如果我从图片中取出 DMA、McBSP SPI 就可以工作。  此外、我还在芯片选择、时钟和数据线路上放置了一个示波器、以便我可以查看总线上发生的情况。  我使用 DMA CH5和 DMA CH6。

    我在下面提供了一个测试摘要表。

    以下是我的问题。

    1. TI 能否100%确认使用带有 DMA 的 McBSP SPI 在 TMS320F28377S 上工作?  我们可以把这个问题推给可能认识的人吗?

    2. 如果问题1是、TI 可以修改 C2000ware 示例 McBSP_ex6_spi_ext_loopback.c 以便使用 DMA 吗?

    谢谢

    e2e.ti.com/.../mcbsp_5F00_ex6_5F00_spi_5F00_ext_5F00_loopback.c

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尼古拉斯、您好!

    1.  TI 能否100%确认使用带有 DMA 的 McBSP SPI 在 TMS320F28377S 上工作?  我们可以将这个问题推送给可能认识的人吗?

    我将向我们的设计团队提出这个问题、看看他们是否可以重现此问题或确认发生此问题的原因。

    2.  如果问题1是、TI 可以修改 C2000ware 示例 McBSP_ex6_spi_ext_loopback.c 以便使用 DMA 吗?

    如果他们找到这方面的解释、我会 向软件团队提出解决方法。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Omer、关于何时需要对此问题作出回应的任何更新?   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Nicholas:

    没有更新、我已经向设计团队发送了电子邮件。 我将再次对它们执行 Ping 操作、以尝试获得响应。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我收到了设计团队的回复、好像 他们有一个 driverlib 测试用例、但失败了、因此他们目前正在研究该用例。 但是、他们注意到在下面的行中、DRR1应该是 DRR2:

    dma_configAddresses (base_dma_rx、(const void*)(&(rxData[0]))、(const void*)(MCBSPA_base + McBSP_O_DRR2);

    我将在获得更多更新后继续跟进。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢、我将尝试使用 DRR2。  根据 C2000Ware_4_00_00_00 McBSP_ex2_loopback_dma.c、我认为 DRR2适用于32位传输。  我将尝试 DRR2以及32位传输。  我一直使用16位传输。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、根据我们的验证团队的意见、我已经确认 driverlib 测试用例似乎没有通过、我将联系设计专家和软件专家以了解可能的原因。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Nicholas:

    我与软件专家确认、问题似乎是由于在示例中没有将 DMA 配置为外设帧2的辅助控制器引起的。 此修复程序已提交、将在下一个版本中更新。

    e2e.ti.com/.../mcbsp_5F00_ex2_5F00_loopback_5F00_dma.c

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Omer、 那是个诀窍。  我现在可以使用 McBSP SPI 作为从器件来获取 DMA 中断。