/* For shared rx/tx DMA requests, when there are commands, create a software TCD of
enabling rx dma and disabling tx dma, which will be chained onto the commands transfer,
and create another software TCD of transfering data and chain it onto the last TCD.
Notice that in this situation assume tx/rx uses same channel */
Hello @alonbl,
Sorry for taking a while to get back to you. Answering your questions:
Q1: Is there any available documentation on how to perform multiple send/receive sequences using iDMA and LPI2C in RT1xxx?
Does not exist a specific documentation that talks about this. However, you can find more information in the chapter 69 called "Low Power Inter-Integrated Circuit (LPI2C)" in the RM.
Q2: Why should the TX in MDER must be disabled to receive data using DMA?
In order to support you better, can you provide me the SDK (version 2.16) code where the TX is disabled in the MDER register?
Q3: If it is required to disable the TX in MDER, how can TX re-enable it without using the CPU?
Since the MDER is a configuration register it can only be written via the CPU
BR,
Habib
Hello @Habib_MS ,
Thank you for reviewing the question.
Q1: I have reviewed the RM in deep, had I found a solution in there or online, I would not have posted this thread
Q2: Please refer to the following block in the SDK code:
https://github.com/nxp-mcuxpresso/mcux-sdk/blob/main/drivers/lpi2c/fsl_lpi2c_edma.c#L386
/* For shared rx/tx DMA requests, when there are commands, create a software TCD of
enabling rx dma and disabling tx dma, which will be chained onto the commands transfer,
and create another software TCD of transfering data and chain it onto the last TCD.
Notice that in this situation assume tx/rx uses same channel */
#if defined FSL_EDMA_DRIVER_EDMA4 && FSL_EDMA_DRIVER_EDMA4
EDMA_TcdResetExt(handle->rx->base, tcd);
EDMA_TcdSetTransferConfigExt(handle->rx->base, tcd, &transferConfig, NULL);
EDMA_TcdEnableInterruptsExt(handle->rx->base, tcd, (uint32_t)kEDMA_MajorInterruptEnable);
#else
EDMA_TcdReset(tcd);
EDMA_TcdSetTransferConfig(tcd, &transferConfig, NULL);
EDMA_TcdEnableInterrupts(tcd, (uint32_t)kEDMA_MajorInterruptEnable);
#endif
transferConfig.srcAddr = (uint32_t)&lpi2c_edma_RecSetting;
transferConfig.destAddr = (uint32_t) & (base->MDER);
transferConfig.srcTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.destTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.srcOffset = 0;
transferConfig.destOffset = (int16_t)sizeof(uint8_t);
transferConfig.minorLoopBytes = sizeof(uint8_t);
transferConfig.majorLoopCounts = 1;
edma_tcd_t *tcdSetRxClearTxDMA = (edma_tcd_t *)((uint32_t)(&handle->tcds[2]) & (~ALIGN_TCD_SIZE_MASK));
#if defined FSL_EDMA_DRIVER_EDMA4 && FSL_EDMA_DRIVER_EDMA4
EDMA_TcdResetExt(handle->rx->base, tcdSetRxClearTxDMA);
EDMA_TcdSetTransferConfigExt(handle->rx->base, tcdSetRxClearTxDMA, &transferConfig, tcd);
#else
EDMA_TcdReset(tcdSetRxClearTxDMA);
EDMA_TcdSetTransferConfig(tcdSetRxClearTxDMA, &transferConfig, tcd);
#endif
linkTcd = tcdSetRxClearTxDMA;
Q3: Since the MDER is a configuration register it can only be written via the CPU
Understanding the platform better than I, maybe you can suggest creative way to solve this.
I thought about a trigger when DMA done via XBAR to trigger DMA to reset the `MDER` or have a chained DMA that is memory-to-memory, or perform TCD that triggers DMA start to move 1 into `MDER`.
Or in short, I would like to think that NXP LPI2C allows somehow to perform multiple I2C commands without CPU involvement in their advanced MCUs as it was supported by the previous generation.
Regards,
Alon
Hello @alonbl,
Unfortunately, SDK (version 2.16) only provides the solution to disable Tx in the MDER register. Also, there is not existing documentation that specifically talks about this.
Creating a solution to increase performance must be by custom implementation, however I can suggest a solution. I understand that you are currently using the RT1170, you can use the cortex M4 to make this process or increase the core clock in order to execute instructions faster.
Also, you mentioned that the peripheral LPI2C only can use a single DMA channel, however, SDK(version 2.16) offers an alternative to use different TX and RX DMA channel using the next macro:
BR
Habib.
Hello @Habib_MS ,
Thank you for trying to assist, however, I would like to note that I am looking for someone that is deeply familiar with the architecture to assist me with this fundamental question of how to perform multiple I2C read/write transactions using DMA.
I am aware that there is no explicit documentation of how to establish this, or why the SDK implemented the way it is. Otherwise, I would have probably found it already and act upon it. This is why I seek help in NXP forum to reach out NXP professionals.
The issue is not performance (BTW: we use 1171 without cm4), the issue is how to use the hardware correctly, and what the engineer thought when they disabled the multi-channel DMA for the LPI2C, as in the Kinetis series it was supported, I would like to guess a solution exists and that it is not documented properly.
The architecture itself is a single DMA channel, it is not a software to decide how many DMA channels a peripheral has, you can also review that this is hard-coded using a simple `git grep` command:
devices/MIMXRT1176/MIMXRT1176_cm4_features.h:#define FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(x) (0)
devices/MIMXRT1176/MIMXRT1176_cm7_features.h:#define FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(x) (0)
As you can see there is no alternative to use multiple channels in this architecture, it is also clearly abstracted in the NXP config tool.
I am looking forward to deeply discuss this issue and find creative solutions, maybe disabling the MDER is incorrect and there is an alternative, I am unsure why it is done by the SDK. Can you please consult with your peers to understand exactly what the sequence is?
Regards,
Alon
Hello again @alonbl,
Corroborating the information that you provided me, LPI2C in the RT1176 only has one DMA channel, also, unfortunately the SDK team does not provide related information regarding the propose of their changes.
In this app note explains how optimize the i.MX RT series in the chapter 4 called "How to improve performance", that could be helpful.
Also, it is important to take in consideration that each jump into functions takes time, and in order to optimize the performance you can use only registers and avoid using jumps into functions.
Sorry for the inconvenience this may cause.
BR
Habib.