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.

[参考译文] TM4C1294NCPDT:DMA 传输至 UART 外设、发送随机字节

Guru**** 2616675 points

Other Parts Discussed in Thread: TM4C1294NCPDT

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1045665/tm4c1294ncpdt-dma-transfer-to-uart-peripheral-sending-random-bytes

器件型号:TM4C1294NCPDT

大家好、团队、

我正在处理到 TM4C1294NCPDT (定制板)中 UART 外设的 DMA 传输。 从 Pkt2 (大小为312字节的阵列)向另一个控制器发送字节时遇到问题。 但问题是 DMA 传输函数无法按预期正常工作、它发送的随机字节与实际字节相比。
 
1) 1)我将填充一个数组、以将这些字节传输到另一个控制器。
2)在一个数组(程序中指定的 Pkt2)中填充312个字节后、我将使用 " MAP_uDMAChannelEnable (UDMA_CH17_UART3TX);"来启动 DMA 传输。
3) 3)发生错误的地方、我无法识别。 有人能不能帮助我 DMA 在这种情况下的工作方式、并帮助我 解决这个问题。
我想使用 DMA_Tx 将312个数据字节从内部阵列(Pkt2)发送到另一个微控制器、而不会丢失任何数据。  

同时连接 DMA Rx 和 Tx 以及输出 I GOT 的配置。 任何帮助都是非常感谢的。  

void Init_UART3()
{
//
// Enable the GPIO Peripheral used by the UART.
//
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

//
// Enable UART3.
//
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART3);

//
// Enable processor interrupts.
//
    IntMasterEnable();

//
// Configure GPIO Pins for UART mode.
//
    GPIOPinConfigure(GPIO_PA4_U3RX);
    GPIOPinConfigure(GPIO_PA5_U3TX);

    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_4 | GPIO_PIN_5);

//
// Initialize the UART for console I/O.
//
    MAP_UARTConfigSetExpClk(UART3_BASE, gu32SysClk, 230400,
                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                            UART_CONFIG_PAR_NONE));

    HWREG(UART3_BASE + UART_O_CTL) |= UART_CTL_RXE;

    HWREG(UART3_BASE + UART_O_CTL) |= UART_CTL_TXE;
//    HWREG(UART3_BASE + UART_O_CTL) |= UART_CTL_LBE;


// Make sure there is no junk left in the FIFO
    while (UARTCharGetNonBlocking(UART3_BASE) != -1);

    MAP_UARTFIFOEnable(UART3_BASE);

    MAP_UARTFIFOLevelSet(UART3_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);

// Make sure there is no junk left in the FIFO
    while (UARTCharGetNonBlocking(UART3_BASE) != -1);
}

void Init_UART3_DMA(void)
{

    MAP_uDMAChannelAssign(UDMA_CH16_UART3RX);

    MAP_uDMAChannelAssign(UDMA_CH17_UART3TX);

    //
    // Enable the UART for operation, and enable the uDMA interface for both TX
    // and RX channels.
    //
    MAP_UARTDMAEnable(UART3_BASE, UART_DMA_RX);

    MAP_UARTDMAEnable(UART3_BASE, UART_DMA_TX);
    //
    // Put the attributes in a known state for the uDMA UART1RX channel.  These
    // should already be disabled by default.
    //
    MAP_uDMAChannelAttributeDisable(UDMA_CH16_UART3RX,
    UDMA_PRI_SELECT | UDMA_ATTR_USEBURST |
    UDMA_ATTR_HIGH_PRIORITY |
    UDMA_ATTR_REQMASK);


    //
    // Configure the control parameters for the primary control structure for
    // the UART RX channel.  The primary contol structure is used for the "A"
    // part of the ping-pong receive.  The transfer data size is 8 bits, the
    // source address does not increment since it will be reading from a
    // register.  The destination address increment is byte 8-bit bytes.  The
    // arbitration size is set to 4 to match the RX FIFO trigger threshold.
    // The uDMA controller will use a 4 byte burst transfer if possible.  This
    // will be somewhat more effecient that single byte transfers.
    //
    MAP_uDMAChannelControlSet(UDMA_CH16_UART3RX | UDMA_PRI_SELECT,
    UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_2);

    MAP_uDMAChannelTransferSet(
    UDMA_CH16_UART3RX | UDMA_PRI_SELECT,
                               UDMA_MODE_BASIC,
                               (void*) (UART3_BASE + UART_O_DR), gu16Array,
                               sizeof(gu16Array) >> 1u);

    MAP_uDMAChannelAttributeEnable(UDMA_CH16_UART3RX,
    UDMA_PRI_SELECT | UDMA_ATTR_USEBURST);

    /* Tx DMA setting */
    /* clear any previous defined attribute */
    uDMAChannelAttributeDisable(UDMA_CH17_UART3TX ,  UDMA_PRI_SELECT
                                | UDMA_ATTR_USEBURST |
                                UDMA_ATTR_REQMASK);

    MAP_uDMAChannelAttributeEnable(UDMA_CH17_UART3TX, UDMA_ATTR_USEBURST);//  UDMA_PRI_SELECT

    /* set the control pars */
    uDMAChannelControlSet(UDMA_CH17_UART3TX | UDMA_PRI_SELECT , UDMA_SIZE_16 |
                          UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_2);

    uDMAChannelTransferSet(UDMA_CH17_UART3TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC,
                                   Pkt2, (void *)(UART3_BASE + UART_O_DR),
                                   312);



    /////////////////////////////////////////////////


    MAP_UARTDMAEnable(UART3_BASE, UART_DMA_RX);
    MAP_UARTDMAEnable(UART3_BASE, UART_DMA_TX);

    MAP_uDMAChannelEnable(UDMA_CH16_UART3RX);

    //
    // Enable the UART DMA TX/RX interrupts.
    //
    MAP_UARTIntEnable(UART3_BASE, UART_INT_DMARX | UART_INT_DMATX);

    MAP_UARTEnable(UART3_BASE);

    //
    // Enable the UART interrupt.
    //
    MAP_UARTIntEnable(UART3_BASE, UART_INT_RX | UART_INT_RT);   //UART_INT_RX |
}

uint16_t Pkt2[312];
int main()
{

Init_SysClk();
Init_GPIO();
Init_UART3();
Init_UART3_DMA();

//uint8_t lu8Index;
uint8_t lu8Checksum;
uint8_t inc = 0;
uint16_t lu16PktIndex = 0;
    
while(1)
{
   // Preparing 312 bytes in Pkt2 Array 
    for (i = 0; i < 52; i++)
    {
        Pkt2[lu16PktIndex] = gu8Command2;
        lu8Checksum ^= Pkt2[lu16PktIndex];
        lu16PktIndex++;
        lu16PktIndex &= 0x01FF;

        Pkt2[lu16PktIndex] = gu8Data2 + inc;
        inc++;
        lu8Checksum ^= Pkt2[lu16PktIndex];
        lu16PktIndex++;
        lu16PktIndex &= 0x01FF;


        OnTime1 = gu16SineArray[0][i]; //One ON Long Time
        OffTime1 = gu16SineArray[1][i];

        Pkt2[lu16PktIndex] = (OnTime1 & 0x7F);
        lu8Checksum ^= Pkt2[lu16PktIndex];
        lu16PktIndex++;
        lu16PktIndex &= 0x01FF;

        Pkt2[lu16PktIndex] = ((OnTime1 >> 7) & 0x03);
        Pkt2[lu16PktIndex] = Pkt2[lu16PktIndex] | ((OffTime1 << 2) & 0x7F);
        Pkt2[lu16PktIndex] = (Pkt2[lu16PktIndex] & 0x7F);
        lu8Checksum ^= Pkt2[lu16PktIndex];
        lu16PktIndex++;
        lu16PktIndex &= 0x01FF;

        Pkt2[lu16PktIndex] = ((OffTime1 >> 5) & 0x0F);
        Pkt2[lu16PktIndex] = (Pkt2[lu16PktIndex] | ((Mode << 5) & 0x60));
        Pkt2[lu16PktIndex] = (Pkt2[lu16PktIndex] & 0x7F);
        lu8Checksum ^= Pkt2[lu16PktIndex];
        lu16PktIndex++;
        lu16PktIndex &= 0x01FF;

        lu8Checksum = lu8Checksum & 0x7F;
        Pkt2[lu16PktIndex++] = lu8Checksum;
        lu16PktIndex &= 0x01FF;

    }

// After i = 52 initiating DAM transfer
    if (i >= 52)
    {
          MAP_uDMAChannelEnable(UDMA_CH17_UART3TX);
    }
}
}

下面是 DMA 传输的数据、它是随机传输的/不是预期传输的数据。

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

    HELO Vamshi、

    正在尝试使用 UDMA_SIZE 而不是 UDMA_SIZE。 我认为您正在获取垃圾数据、因为当缓冲区以8位的增量发送数据时、您尝试发送16位数据。 这也是 使用 UDMA_ARB_4而不是 UDMA_ARB_2的原因。

    此致、
    Ralph Jacobi

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

    感谢您的回复 Ralph Jacobi、

    我参考了 TM4C 数据表、然后我必须知道、

    我的阵列大小为16、因此我必须使用  UDMA_SIZE_16以及源增量、仅限 UDMA_SRC_INC_16。
    此处的主要角色是仲裁、由于  不丢失数据、我需要将其设置为 UDMA_ARB_1。


    " uDMAChannelControlSet (UDMA_CH17_UART3TX | UDMA_PRI_SELECT、UDMA_SIZE_16 |
                         UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_1);"

    上述函数中的参数解决了我的问题。

    谢谢、
    Vamshi

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

    您好、Vamshi、

    我看到  、我没有注意到 RX 和 TX 的 UDMA_SRC_INC_8和 UDMA_SRC_INC_16上的不匹配。 对于仲裁、如果增加 RX FIFO 触发器、以便它不会过快标记 DMA 以进行传输、则可以使用更高的触发器。 我们的示例代码使用 UART_FIFO_RX4_8和 UART_FIFO_TX4_8、然后使用 UDMA_ARB_4。

    此致、

    Ralph Jacobi

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

    是的、感谢您提供 Ralph Jacobi 的信息。