I'm trying to use FlexIO I2C with DMA. Blocking transfers do work correctly, so I know polling mode is working.
FlexIO I2C is configured with "I2c DMA Used" and "I2c DMA Optimize Mode"
DMA is configured with 3 channels (Tx, Rx, Timer), each with Global Config enabled at default values, and Tx and Timer configure with 3 and 4 Scatter/Gather lists each:
Tx element 0 (dmaLogicChannelConfig_ScatterGatherArrayType_0) element link = /Dma_Ip/Dma/MclConfig/dmaLogicChannel_Type_3_FlexioI2cTx/dmaLogicChannel_ConfigType/dmaLogicChannel_ScatterGatherConfigType/dmaLogicChannelConfig_ScatterGatherArrayType_1
Tx element 1 (dmaLogicChannelConfig_ScatterGatherArrayType_1) element link = /Dma_Ip/Dma/MclConfig/dmaLogicChannel_Type_3_FlexioI2cTx/dmaLogicChannel_ConfigType/dmaLogicChannel_ScatterGatherConfigType/dmaLogicChannelConfig_ScatterGatherArrayType_2
(and so on, similarly for Timer)
Rx only has a single Scatter/Gather element (though perhaps none is needed?)
Am I missing some key configuration setting or initialization function call?
With the configuration changes to "add channel", I have been able to get Flexio I2C working with Optimize DMA. However, I think this patch is additionally needed, else the returned status is always a timeout (since it appears to check the wrong clock):
--- a/Flexio_I2c_Ip.c
+++ b/Flexio_I2c_Ip.c
@@ -1421,7 +1421,14 @@ static void Flexio_I2c_Ip_MasterCheckStatus(uint8 Instance,
ResourceIndex = Master->FlexioCommon.ResourceIndex;
boolean EscapeFunction = FALSE;
+ uint8 TimerScl;
+#if (STD_ON == FLEXIO_I2C_IP_DMA_OPTIMIZE_ENABLE)
+ TimerScl = Master->SclAddChannel;
+ (void)ResourceIndex;
+#else
+ TimerScl = SCL_TIMER(ResourceIndex);
+#endif
/* Check for errors */
if (Flexio_Mcl_Ip_GetShifterErrorStatus(BaseAddr, TX_SHIFTER(ResourceIndex)))
{
@@ -1472,7 +1479,7 @@ static void Flexio_I2c_Ip_MasterCheckStatus(uint8 Instance,
}
}
/* Check if the transfer is over */
- if ((Flexio_Mcl_Ip_GetTimerStatus(BaseAddr, SCL_TIMER(ResourceIndex))) && (FALSE == EscapeFunction))
+ if ((Flexio_Mcl_Ip_GetTimerStatus(BaseAddr, TimerScl)) && (FALSE == EscapeFunction))
{
Master->EventCount--;
Looks like the hard fault was due to the lack of "Enable User Mode Support" in the DMA module.
I also realized that Flexio for SCL and SDA each need a "Add Channel" configured. Now I'm able to see SCL toggle for a DMA transfer, but nothing on SDA.
It looks like it is tripping over task privileges and MPU protections, even though the MPU appears to be configured to allow read/write access to the configuration register space, when trying to write to the DMA TCD from an unprivileged task, I see the hardfault. If I make the task privileged, there's no hardfault.
Before Clock_Ip_Init() - MC_ME and TCD[4] registers:
Immediately after stepping over Clock_Ip_Init(). You can see MC_ME has clocks enabled, and TCD is now readable:
Successfully writing to TCD during DmaInit():
Successful read during MasterSendData:
HardFault: