Having an issue with LM4F230 uDMA using scattergather mode with multiple channels. Receiving a bus error on the Rx channel. The first channel is setup to put data into the SSI data register every 20us from GPIO dma trigger. This channel is setup to run circular so the task list never completes which and is working fine. The second channel is setup the same way with the SSI Rx Buff as the channel trigger source which reads data from the SSI data register and moves it to memory. I'm receiving a bus error on this channel after the completion of the first task, so basically it completes the first transfer from the SSI data register to memory and the second task never executes which should copy the primary control structure to loop the task list. The Tx channel continues to run as expected. There isn't much to look at to determine the source of the bus error other than the flag is set and the Rx channel is shutdown. Do you see anything wrong with what I'm trying to do here?
#pragma DATA_ALIGN(controlTable, 1024)
UINT8 controlTable[1024];
#define MEM_BUFFER_SIZE 1024
#define SENSORDATA_WORD_SIZE 6
#define PRIMARY_CONTROL_STRUCT_SIZE 16
#define DMA_CH4_PRIM_CONTROL_OFFSET 64
#define DMA_CH10_PRIM_CONTROL_OFFSET 160
struct dmaContext
{
UINT16 txBuff[SENSORDATA_WORD_SIZE];
UINT16 txDummyBuff[SENSORDATA_WORD_SIZE];
UINT16 rxDummyBuff[SENSORDATA_WORD_SIZE];
UINT16 rxSensorData[SENSORDATA_WORD_SIZE];
UINT8 txCircularBuff[PRIMARY_CONTROL_STRUCT_SIZE];
UINT8 rxCircularBuff[PRIMARY_CONTROL_STRUCT_SIZE];
};
tDMAControlTable taskTableSSITx[] =
{
uDMATaskStructEntry(SENSORDATA_WORD_SIZE, UDMA_SIZE_16,
UDMA_SRC_INC_NONE, dma.txDummyBuff,
UDMA_DST_INC_NONE, (void *)(SSI0_BASE + SSI_O_DR),
UDMA_ARB_16, UDMA_MODE_PER_SCATTER_GATHER),
uDMATaskStructEntry(PRIMARY_CONTROL_STRUCT_SIZE, UDMA_SIZE_8,
UDMA_SRC_INC_8, dma.txCircularBuff,
UDMA_DST_INC_8, &(controlTable[DMA_CH4_PRIM_CONTROL_OFFSET]),
UDMA_ARB_16, UDMA_MODE_MEM_SCATTER_GATHER),
uDMATaskStructEntry(1, UDMA_SIZE_16,
UDMA_SRC_INC_NONE, dma.txDummyBuff,
UDMA_DST_INC_NONE, dma.rxDummyBuff,
UDMA_ARB_2, UDMA_MODE_AUTO)
};
tDMAControlTable taskTableSSIRx[] =
{
uDMATaskStructEntry(SENSORDATA_WORD_SIZE, UDMA_SIZE_16,
UDMA_SRC_INC_NONE, (void *)(SSI0_BASE + SSI_O_DR),
UDMA_DST_INC_16, dma.rxSensorData,
UDMA_ARB_2, UDMA_MODE_PER_SCATTER_GATHER),
uDMATaskStructEntry(PRIMARY_CONTROL_STRUCT_SIZE, UDMA_SIZE_8,
UDMA_SRC_INC_8, dma.rxCircularBuff,
UDMA_DST_INC_8, &(controlTable[DMA_CH10_PRIM_CONTROL_OFFSET]),
UDMA_ARB_2, UDMA_MODE_MEM_SCATTER_GATHER),
uDMATaskStructEntry(1, UDMA_SIZE_16,
UDMA_SRC_INC_NONE, dma.txDummyBuff,
UDMA_DST_INC_NONE, dma.rxDummyBuff,
UDMA_ARB_2, UDMA_MODE_AUTO)
};
ROM_GPIOIntTypeSet(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_FALLING_EDGE);
ROM_GPIOPinIntClear(GPIO_PORTA_BASE, GPIO_PIN_3);
ROM_SSIDisable(SSI0_BASE);
ROM_SSIClockSourceSet(SSI0_BASE, SSI_CLOCK_SYSTEM);
ROM_SSIConfigSetExpClk(SSI0_BASE, ROM_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, SPI_BITRATE, 16);
ROM_SSIEnable(SSI0_BASE);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); // Enable uDMA controller at system level
ROM_uDMAEnable(); // Enable the uDMA controller
ROM_uDMAControlBaseSet(controlTable); // Point at the control table to use for channel control structures
ROM_uDMAChannelDisable(UDMA_CH4_GPIOA); // Ensure channel is disabled before modifying register
ROM_uDMAChannelAssign(UDMA_CH4_GPIOA);
ROM_GPIODMATriggerEnable(GPIO_PORTA_BASE, GPIO_PIN_3);
ROM_uDMAChannelAttributeDisable(UDMA_CH4_GPIOA,
UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
UDMA_ATTR_HIGH_PRIORITY |
UDMA_ATTR_REQMASK);
ROM_uDMAChannelScatterGatherSet(UDMA_CH4_GPIOA, 3, taskTableSSITx, TRUE);
for(ii=0; ii<sizeof(dma.txCircularBuff); ii++)
{
dma.txCircularBuff[ii] = controlTable[ii + DMA_CH4_PRIM_CONTROL_OFFSET];
}
ROM_uDMAChannelDisable(UDMA_CH10_SSI0RX); // Ensure channel is disabled before modifying register
ROM_uDMAChannelAssign(UDMA_CH10_SSI0RX);
ROM_SSIDMAEnable(SSI0_BASE, SSI_DMA_RX);
ROM_uDMAChannelAttributeDisable(UDMA_CH10_SSI0RX,
UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
UDMA_ATTR_HIGH_PRIORITY |
UDMA_ATTR_REQMASK);
ROM_uDMAChannelScatterGatherSet(UDMA_CH10_SSI0RX, 3, taskTableSSIRx, TRUE);
for(ii=0; ii<sizeof(dma.rxCircularBuff); ii++)
{
dma.rxCircularBuff[ii] = controlTable[ii + DMA_CH10_PRIM_CONTROL_OFFSET];
}
ROM_uDMAErrorStatusClear();
ROM_uDMAChannelEnable(UDMA_CH10_SSI0RX);
ROM_uDMAChannelEnable(UDMA_CH4_GPIOA);