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.

uDMA Bus Error



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);

  • The uDMA bus error is basically an address fault.  It means the DMA controller is generating an invalid address.  It sounds like your first task completes okay so the problem is not there.  Either the transfer to load the second task, or the second task itself is causing the problem.  Are you able to examine state of the controller when this happens?  See if you can tell if has loaded the second task yet or not.  Actually, if you examine the control structures, it is possible to tell more or less what the DMA controller is doing when the bus error occurred.  I suggest you look closely at your addresses being used for the second task.  BTW the DMA controller cannot transfer from flash so make sure you are not trying to do that.