Hi,
I have problems to use the DMA controller of the microcontroller ot transfer 3200 halfwords (16 bits each) to SSI peripheral in SPI mode to transmit the data to the display.
The transmission simply doesn't work depending on the fact, I cannot see any pixels sent to the display.
The SSI1 peripheral is configured for 16-bit transfer in motorola mode and works without DMA controller.
Here my code, any help is very appreciated.
uint32_t g_ui32uDMAErrCount;
void uDMAErrorHandler(void)
{
uint32_t ui32Status;
//
// Check for uDMA error bit
//
ui32Status = MAP_uDMAErrorStatusGet();
//
// If there is a uDMA error, then clear the error and increment
// the error counter.
//
if(ui32Status)
{
MAP_uDMAErrorStatusClear();
g_ui32uDMAErrCount++;
}
}
void uDMA_init(void)
{
uint32_t trashBin[1] = {0};
//
// Enable the uDMA controller at the system level.
//
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA))
{
}
//
// Enable the uDMA controller error interrupt. This interrupt will occur
// if there is a bus error during a transfer.
//
MAP_IntEnable(INT_UDMAERR);
//
// Enable the uDMA controller.
//
MAP_uDMAEnable();
//
// Point at the control table to use for channel control structures.
//
MAP_uDMAControlBaseSet(pui8ControlTable);
//
// Enable the uDMA interface for TX channel.
//
MAP_SSIDMAEnable(SSI1_BASE, SSI_DMA_TX);
//****************************************************************************
//uDMA SSI1 TX
//****************************************************************************
//
// Put the attributes in a known state for the uDMA SSI1TX channel. These
// should already be disabled by default.
//
MAP_uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI1TX,
UDMA_ATTR_ALTSELECT |
UDMA_ATTR_HIGH_PRIORITY |
UDMA_ATTR_REQMASK);
//
// Set the USEBURST attribute for the uDMA SSI1TX channel. This will
// force the controller to always use a burst when transferring data from
// the TX buffer to the SSI1. This is somewhat more effecient bus usage
// than the default which allows single or burst transfers.
//
MAP_uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI1TX, UDMA_ATTR_USEBURST);
//
// Configure the control parameters for the SSI1 TX.
//
MAP_uDMAChannelControlSet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT,
UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE |
UDMA_ARB_1024);
/* Clear SSI1 RX Buffer */
while (MAP_SSIDataGetNonBlocking(SSI1_BASE, &trashBin[0])) {}
MAP_IntMasterEnable();
}
Now the transmission trigger function
void SSI1IntHandler(void)
{
uint32_t ui32Status;
uint32_t ui32Mode;
ui32Status = MAP_SSIIntStatus(SSI1_BASE, 1);
MAP_SSIIntClear(SSI1_BASE, ui32Status);
ui32Mode = MAP_uDMAChannelModeGet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT);
}
The DMA transfer function is called frequently.
void init_DMA_transfer(void){
//while(MAP_uDMAChannelModeGet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT) != UDMA_MODE_STOP){}
while(MAP_uDMAChannelIsEnabled(UDMA_CHANNEL_SSI1TX)){}
if(pixelpointer == pixelbuffer1)
pixelpointer = pixelbuffer2;
else
pixelpointer = pixelbuffer1;
//
// Set up the transfer parameters for the uDMA SSI1 TX channel. This will
// configure the transfer source and destination and the transfer size.
// Basic mode is used because the peripheral is making the uDMA transfer
// request. The source is the TX buffer and the destination is the SSI1
// data register.
//
MAP_uDMAChannelTransferSet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT,
UDMA_MODE_BASIC, pixelpointer,
(void *)(SSI1_BASE + SSI_O_DR),
3200);
//
// Now the uDMA SSI1 TX channel are primed to start a
// transfer. As soon as the channel are enabled, the peripheral will
// issue a transfer request and the data transfers will begin.
//
MAP_uDMAChannelEnable(UDMA_CHANNEL_SSI1TX);
//
// Enable the SSI1 DMA TX interrupt.
//
MAP_SSIIntEnable(SSI1_BASE, SSI_DMATX);
//
// Enable the SSI1 peripheral interrupts.
//
MAP_IntEnable(INT_SSI1);
// Requests a uDMA channel to start a transfer.
//MAP_uDMAChannelRequest(UDMA_CHANNEL_SSI1TX);
}
I have assigend the interrupt-handler-functions to the interrupt vector table.