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.

SSI Slave 16B DMA

I'm trying to DMA 16B to the TX FIFO, and I need some advice.

Can I request a single 16B DMA transfer upon CS active? i.e. will the DMA timeout before room is created within the FIFO?

It seems the first 8B transfer fine; however the second 8B seems to underrun. I can resolve this using burst mode and setting my arbitration to 1 - this seems opposite to my understanding as I would have figured using an arbitration value of 16 would lock the uDMA controller to the TX channel for the entire transfer.

Tx,

Brad

  • Hi Bradley,

    Can you please share the SSI and DMA configuration you are doing in the test code?

    Regards

    Amit

  • void DMA_Init( void )
    {
    	memset( &tDMADev, 0x0, sizeof( dma_dev_t ) );
    
    	// Reset the DMA controller
    	ROM_SysCtlPeripheralReset( SYSCTL_PERIPH_UDMA );
    
    	// Enable the DMA controller at the system level
    	ROM_SysCtlPeripheralEnable( SYSCTL_PERIPH_UDMA );
    	ROM_SysCtlPeripheralSleepEnable( SYSCTL_PERIPH_UDMA );
    
    	// Enable the uDMA Error interrupt
    	ROM_IntEnable( INT_UDMAERR );
    
    	// Enable the DMA controller
    	ROM_uDMAEnable();
    
    	// Point at the control table to use for channel control structures
    	ROM_uDMAControlBaseSet( tDMADev.pDMACtrlTable );
    }

    void Slave_SSIInit( void )
    {
    	// Reset the SSI peripheral (clears the FIFOs)
        ROM_SysCtlPeripheralReset( SYSCTL_PERIPH_SSI0 );
    
        // Initialise the SPI Controllers
        //  SPI0 - Slave mode host SPI Interface
        // Enable port PA2 for SSI0 CLK
        // Enable port PA3 for SSI0 CS_F
        // Enable port PA4 for SSI0 RX
        // Enable port PA5 for SSI0 TX
        ROM_SysCtlPeripheralEnable( SYSCTL_PERIPH_SSI0 );
        ROM_SSIDisable( tSlaveDev.uiBase );
        ROM_GPIOPinConfigure( GPIO_PA2_SSI0CLK );
        ROM_GPIOPinConfigure( GPIO_PA3_SSI0FSS );
        ROM_GPIOPinConfigure( GPIO_PA4_SSI0RX );
        ROM_GPIOPinConfigure( GPIO_PA5_SSI0TX );
        ROM_GPIOPinTypeSSI( GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2 );
        ROM_SSIClockSourceSet( tSlaveDev.uiBase, SSI_CLOCK_SYSTEM );
        ROM_SSIConfigSetExpClk( tSlaveDev.uiBase, ROM_SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_SLAVE, SLAVE_SPI_BIT_RATE, SLAVE_SPI_DATA_WIDTH );
        ROM_SSIEnable( tSlaveDev.uiBase );
    
        Slave_Flush();
    
        // Configure the interrupt
        ROM_IntDisable( tSlaveDev.uiIRQ );
        ROM_IntPrioritySet( tSlaveDev.uiIRQ, IRQ_PRIORITY_SLAVE_SSI );
    //    SSIIntEnable( tSlaveDev.uiBase, SSI_DMATX | SSI_DMARX );
        ROM_IntEnable( tSlaveDev.uiIRQ );
    }

    void Slave_DMAInit( void )
    {
    	// ************************************************************************
    	// RX DMA
    	// ************************************************************************
    	ROM_uDMAChannelAssign( UDMA_CH10_SSI0RX );
    
    	// Put the attributes in a known state for the uDMA SSI0 RX channel.
    	// These should already be disabled by default.
    	ROM_uDMAChannelAttributeDisable( UDMA_CHANNEL_SSI0RX, UDMA_ATTR_ALL );
    
    	// Configure the control parameters for the primary and alternate control
    	// structures for the SSI RX channel. The transfer data size is 8
    	// bits, the source address does not increment since it will be reading
    	// from a register. The destination address increment is byte 8-bit bytes.
    	// The arbitration size is set to 4 to match the RX FIFO trigger threshold.
    	// The uDMA controller will use a 4 byte burst transfer if possible. This
    	// will be somewhat more efficient that single byte transfers.
    	ROM_uDMAChannelControlSet( UDMA_CHANNEL_SSI0RX, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4 );
    
    	// ************************************************************************
    	// TX DMA
    	// ************************************************************************
    	ROM_uDMAChannelAssign( UDMA_CH11_SSI0TX );
    
    	// Put the attributes in a known state for the uDMA SSI0 TX channel.
    	// These should already be disabled by default.
    	ROM_uDMAChannelAttributeDisable( UDMA_CHANNEL_SSI0TX, UDMA_ATTR_ALL );
    
    	// Set the HIGH_PRIORITY attribute for the uDMA SSI TX channel.
    	ROM_uDMAChannelAttributeEnable( UDMA_CHANNEL_SSI0TX, UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_USEBURST );
    
    	// Configure the control parameters for the SSI TX.  The uDMA SSI TX
    	// channel is used to transfer a block of data from a buffer to the SSI.
    	// The data size is 8 bits.  The source address increment is 8-bit bytes
    	// since the data is coming from a buffer.  The destination increment is
    	// none since the data is to be written to the SSI data register.  The
    	// arbitration size is set to 4, which matches the SSI TX FIFO trigger
    	// threshold.
    	ROM_uDMAChannelControlSet( UDMA_CHANNEL_SSI0TX, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1 );
    
    	ROM_SSIDMAEnable( tSlaveDev.uiBase, SSI_DMA_RX | SSI_DMA_TX );
    }

  • Hi Bradley,

    There is no DMA Timeout. The SSI has 8 location deep FIFO, hence when transferring data to the FIFO, the arbitration size has to be set to 8. If you set it to 16 then the UDMA will simply overwrite the data causing the next 8 Bytes to get lost.

    What can be done is you can use Arbitration Size of 8. When there is space for 8 locations after the first 8 have been transferred it will transfer the next 8.

    Regards

    Amit Ashara