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.

EK-TM4C1294XL: looking for an example doing I2C DMA

Part Number: EK-TM4C1294XL

Deal Support

Need to transfer/receive some data on I2C with DMA, is there an example to follow please like UART one?

Thanks 

Ping

  • Hi Ping,

      We don't have a I2C specific example for uDMA module. However, you should be able to reference the UART example and modify the channel assignment accordingly for I2C. For example, if you are going to use I2C0RX on uDMA channel 0 then you will use uDMAChannelAssign() API to configure channel 0 for I2C0RX. See below example. 

    uDMAChannelAssign(UDMA_CH0_I2C0RX);
    uDMAChannelAttributeDisable(UDMA_CH0_I2C0RX,
    UDMA_ATTR_ALTSELECT |
    UDMA_ATTR_HIGH_PRIORITY |
    UDMA_ATTR_REQMASK);

  • Hi, Charles

    Thanks for reply!

    I drafted the code, however it is not working, below is the code for just send a few byte down to I2C, I call I2C_Trigger_Tx when I need to send some data, anything wrong with that? DMA module and I2C are already initialised before calling I2C_DMA_Init().

    void I2C_DMA_init(void)
    {
        // Configure the DMA channel for I2C2_BASE only 
        uDMAChannelAssign(UDMA_CH5_I2C2TX);
        uDMAChannelAttributeDisable(UDMA_CH5_I2C2TX ,
                                    UDMA_ATTR_ALTSELECT |
                                    UDMA_ATTR_HIGH_PRIORITY |
                                    UDMA_ATTR_REQMASK);
    
       // uDMAChannelAttributeEnable(UDMA_CH5_I2C2TX, UDMA_ATTR_USEBURST);
        uDMAChannelControlSet(UDMA_CH5_I2C2TX  | UDMA_PRI_SELECT,
                              UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE |
                              UDMA_ARB_8); 
        uDMAChannelEnable(UDMA_CH5_I2C2TX);                      
    }
    void I2C_Trigger_Tx(uint8_t *TxData, uint8_t size)
    {
        while(uDMAChannelIsEnabled(UDMA_CH5_I2C2TX)) {}  //wait for last Tx complete
        //    Set the DMA source address to the transmit data buffer
        uDMAChannelTransferSet(UDMA_CH5_I2C2TX  | UDMA_PRI_SELECT,
                               UDMA_MODE_BASIC, TxData,
                               (void *)(QP_I2C_BASE + I2C_O_MDR), size);
        uDMAChannelEnable(UDMA_CH5_I2C2TX);
        // Start the I2C write transmission
        I2CMasterSlaveAddrSet(QP_I2C_BASE,I2C_Status[I2C_CHANNEL_QP].SlaveAddr, false); // Read operation
        I2CMasterControl(QP_I2C_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    }

    Does the DMA channel needs to be enabled initially or late when trigger a sending? Does it disable after transmission like UART one? how about the UDMA_ARB_4 in uDMAChannelControlSet, I am intend to send at least 2 bytes or more. 

    Thank you!

    Ping

  • I see your uDMAChannelAttributeEnable() is commented out on line 10. 

  • Hi, Charles

    It was there, and not working, so I commented out to try and still not working, anything else you spotted?

    When I trigger multiple bytes sending, I need to call I2CMasterControl(QP_I2C_BASE, I2C_MASTER_CMD_BURST_SEND_START); afterwards do i still need to call   I2CMasterControl(QP_I2C_BASE, I2C_MASTER_CMD_BURST_SEND_CONT) and     I2CMasterControl(QP_I2C_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH)? according to the number of bytes left to go?

    By the way, with the above code I see slave address write on the bus followed by a data 0, and then no more.

    is the DMA channel disabled after transfer? Shall i enable it always or only before transfer trigger?

    Thank you for your reply!

    Ping

  • When I trigger multiple bytes sending, I need to call I2CMasterControl(QP_I2C_BASE, I2C_MASTER_CMD_BURST_SEND_START); afterwards do i still need to call   I2CMasterControl(QP_I2C_BASE, I2C_MASTER_CMD_BURST_SEND_CONT) and     I2CMasterControl(QP_I2C_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH)? according to the number of bytes left to go?

    Let's say you are going to write 8 bytes. You would need call:

    Write one data to the I2C TXFIFO.

    call I2C_MASTER_CMD_BURST_SEND_START 

    Write six data to the I2C TXFIFO

    call I2C_MASTER_CMD_BURST_SEND_CONT

    Write one last data to the I2C TXFIFO

    call I2C_MASTER_CMD_BURST_SEND_FINISH

    The above sequence is for CPU operation though. 

    I think using uDMA for I2C will be much more complex. You will need to somehow weight the benefit of using uDMA. I think you will be mixing CPU operations like like sending the slave address, setting up the control using I2CMasterControl and call uDMA to transfer the data to the FIFO. If you are going to transfer two byes of data, I don't think uDMA will provide the benefit you are looking for. However, I don't have the benchmark to quantify it. You might want to try just using CPU vs. using mix of CPU and uDMA and see if you are getting the right throughput. 

    By the way, with the above code I see slave address write on the bus followed by a data 0, and then no more.

     Is data 0 what you intend to write or there is no data in the TXFIFO? I will suggest you begin with a simple uDMA setup like sending just one byte and get it working first and later expand it. As I said, doing few bytes like one or two bytes of transfer may not bring you much throughput improvement because CPU still need to step into to control the I2C state machine. 

  • Thank for your explain and patience, Charles

    The CPU operation is currently implemented in products, and my recent task is to rewrite them use DMA, as you said it is more complex, for now, I am not to a point which I can  compare the benefit yet until  I can get it working.

    So comes to the sequence of how to trigger a DMA transfer, seems that is the reason for it not working, as you suggest, we will do 1 byte transfer only for now - of my previous trigger code, I wonder what is the correct sequence, and which line of code to trigger a transfer by DMA exactly? Do i still need to call I2CMasterDataPut()? or should it replaced by DMA transfer trigger?

    Talking about TXFIFO register, shall i put the DMA to TXFIFO instead of MDR?

    Regards!

    Ping 

  • I wonder what is the correct sequence, and which line of code to trigger a transfer by DMA exactly? Do i still need to call I2CMasterDataPut()? or should it replaced by DMA transfer trigger?

    Hi Ping,

      Yes, you need to replace I2CMasterDataPut() with a DMA trigger so the uDMA can load the TXFIFO before call I2CMasterControl. This is why I said it is a mix of CPU and DMA which is cumbersome in my opinion in order for the I2C to work.  I've haven't really seen anyone using uDMA for I2C and I don't have an example for it. You will need to explore a bit on your own. 

    Talking about TXFIFO register, shall i put the DMA to TXFIFO instead of MDR?

    From the DMA or CPU point of view, it is the MDR that you need to write to. MDR is the front door to the FIFO. As you write to MDR, the data is pushed to the FIFO.