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.

why two peripheral can not use DMA synchronously?

I use a share buffer to recv Enthernet  and write SD card synchronously。the buffer designed like a fifo,after write a 512 bytes block, mark it。when block is full enough ,begin sd write。both of them use SPI port,SD is SSI0, Enthernet is SSI1。 but when two DMA work together,the data to operate in wrong length,maybe lost some byte。

I create a test project,and begin two SSI DMA。in vary length,One SSI send right data,the other lost some。

is it can not work together?

  • Hello Pony,

    UDMA can transfer data on two different channels one after the other. If you can send a simplified test code, it would be useful for us to review the same.

    Regards

    Amit

  • hi Amit,

    thank you reply。my demo is below。

    MAP_IntEnable(INT_SSI0);
    MAP_IntEnable(INT_SSI1);

    uDMAChannelDisable(UDMA_CHANNEL_SSI0TX);
    uDMAChannelDisable(UDMA_CHANNEL_SSI0RX);

    uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_ALL);
    uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_ALL);

    uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1);

    uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);


    uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
    UDMA_MODE_BASIC, src, (void*)(SSI0_BASE + SSI_O_DR), 1000);

    SSIDMAEnable(SSI0_BASE, SSI_DMA_TX);


    //-------------------- udma ssi1 ------------------------------
    uDMAChannelDisable(UDMA_CHANNEL_SSI1TX);
    uDMAChannelDisable(UDMA_CHANNEL_SSI1RX);

    uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI1RX, UDMA_ATTR_ALL);
    uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI1TX, UDMA_ATTR_ALL);

    uDMAChannelControlSet(UDMA_CHANNEL_SSI1RX | UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1);

    uDMAChannelControlSet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);


    uDMAChannelTransferSet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT,
    UDMA_MODE_BASIC, dst, (void*)(SSI1_BASE + SSI_O_DR), 1000);

    SSIDMAEnable(SSI1_BASE, SSI_DMA_TX);

    uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);
    uDMAChannelEnable(UDMA_CHANNEL_SSI1TX);

    while(1)
    {
        if (!uDMAChannelSizeGet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT))
        {
         uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
         UDMA_MODE_BASIC, src, (void*)(SSI0_BASE + SSI_O_DR), 100);
         uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);
         }


         if (!uDMAChannelSizeGet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT))
        {
             uDMAChannelTransferSet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT,
             UDMA_MODE_BASIC, dst, (void*)(SSI1_BASE + SSI_O_DR), 100);


              uDMAChannelEnable(UDMA_CHANNEL_SSI1TX);
         }

         SysCtlDelay(300);
    }

    i  use this test two DMA work together。is  udma only work one by one?  it ‘s low efficiency。

  • Hello Pony,

    Are you using TM4C129 (just to confirm)?

    If yes, then you have to wait for the DMADONE Interrupt from SSI and then disable the SSI TXDMAREQ, before re-enabling the DMA Channel

    Also the SSI Init code is not present. It would be better if you can zip the CCS project.

    The UDMA will complete one channel Arbitration Size worth of transfer and then process the next channel. The two channels will alternate till they are not done.

    Regards

    Amit

  • hi Amit:

          I use TM4C123. When I use DMA to recv data from SSI. the TX RX channel all enabled,and they work well.

    so is DMA work one peripheral done then another.

          it can do two channel simultaneously on one peripheral, like SSI0's TX and RX.

          my total Main()

    int main()
    {
    MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);

    //////// SSI0 set ///////

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5);

    // GPIODirModeSet(GPIO_PORTA_BASE, GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5, GPIO_DIR_MODE_HW);

    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_2, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);

    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_1,
    SSI_MODE_MASTER, 20000000, 8);

    SSIEnable(SSI0_BASE);

    ////// SSI1 F port set ///////


    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    int reglock = HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK);
    HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK) = 0x4C4F434B;
    reglock = HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK);

    HWREG(GPIO_PORTF_BASE+GPIO_O_CR) = 1;

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);

    GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_2|GPIO_PIN_0|GPIO_PIN_1);

    GPIOPinConfigure(GPIO_PF2_SSI1CLK);
    GPIOPinConfigure(GPIO_PF0_SSI1RX);
    GPIOPinConfigure(GPIO_PF1_SSI1TX);

    GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_2|GPIO_PIN_0|GPIO_PIN_1, GPIO_DIR_MODE_HW);

    SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3,
    SSI_MODE_MASTER, 20000000, 8);

    SSIEnable(SSI1_BASE);



    //// DMA test /////////////////////

    memset(src, 0x01, 100);
    memset(dst, 0, 100);

    uDMAChannelDisable(UDMA_CHANNEL_SSI0TX);

    uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_ALL);


    uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);


    uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
    UDMA_MODE_BASIC, src, (void*)(SSI0_BASE + SSI_O_DR), 1000);

    SSIDMAEnable(SSI0_BASE, SSI_DMA_TX);


    //-------------------- udma ssi1 ------------------------------
    uDMAChannelDisable(UDMA_CHANNEL_SSI1RX);

    uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI1TX, UDMA_ATTR_ALL);

    uDMAChannelControlSet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);


    uDMAChannelTransferSet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT,
    UDMA_MODE_BASIC, dst, (void*)(SSI1_BASE + SSI_O_DR), 1000);

    uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);
    uDMAChannelEnable(UDMA_CHANNEL_SSI1TX);

    while(1)
    {
    if (!uDMAChannelSizeGet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT))
    {
    uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
    UDMA_MODE_BASIC, src, (void*)(SSI0_BASE + SSI_O_DR), 100);
    uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);
    }


    if (!uDMAChannelSizeGet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT))
    {
    uDMAChannelTransferSet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT,
    UDMA_MODE_BASIC, dst, (void*)(SSI1_BASE + SSI_O_DR), 100);
    uDMAChannelEnable(UDMA_CHANNEL_SSI1TX);
    }

    SysCtlDelay(300);
    }
    }

  • Hello Pony,

    On TM4C123 there is errata for the same. Can you please check the Errata DMA#01 for TM4C123!!

    Regards

    Amit