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.

SSI0 & DMA - End of Transfer interrupt implementation

Other Parts Discussed in Thread: TM4C123GH6PM

I want to use DMA to send a packet of data through SSI0 exceeding the maximum DMA size. I decided to break the transfer into multiple DMA transactions.

I've found some documentation for UART. Is it correct to do this:

    uDMAIntRegister(UDMA_CHANNEL_SSI0TX, SSI0TransferCompleteInt);

to set up a DMA interrupt for EOT on SSI0? The interrupt handler SSI0TransferCompleteInt is implemented by me. The interrupt will initiate a new transfer immediately and decrease the bytes remaining counter, and I don't mind about the short interrupt time.

Alternatively, do I use the uDMA software interrupt and set up the uDMA flags somewhere? If I do this, I need to poll the uDMA registers to find out which transaction caused this (I have two nearly simultaneous transfers on SSI0 & SSI1, offset by a few hundred cycles so I can be sure the two interrupts won't clash.)

The uDMA module appears to be sparsely documented... at least for the Tiva libraries which I prefer over direct register access. Am I missing anything...? Most of this is guesses derived from looking at other code and driverlib/udma.h.

Thanks

  • Hello Tom,

    Which device are you using: TM4C123 or TM4C129?

    If it is TM4C123 then, please do refer to this post for SSI+DMA.

    http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/339017/1184584.aspx#1184584

    If it is a TM4C129, then some modifications to the same code would be needed which we can work out.

    Regards

    Amit

  • Sorry forget to mention it's a TM4C123. (The one on the Launchpad - TM4C123GH6PM.)

    I'll have a look, thanks.

  • Bitten again by errata, luckily I haven't committed to a PCB yet. (I should read errata more often.)

    I do need to use two SSI ports simultaneously.

    Is every silicon revision affected? I'm working on a late model Tiva C series launchpad at the moment, purchased about a month ago. I guess I will have to switch to SSI0 & SSI2.

  • Hello Tom,

    TM4C123 has this as errata for all revisions. Good that I got this thread to you. Using SSI-0 and SSI-2 would be the best option as it is not affected by this issue.

    Regards

    Amit

  • OK, I've read over that thread a few times, but I figure I'm missing out on something.

    I've got DMA transfer working in a loop, if I build in a fixed delay it works fine (as expected). But I don't get any interrupt firing at the end of the transfer. (I know this because the LED output doesn't toggle looking at the scope. The toggle function works in a loop, though.)

    Interrupt:

    void SSI0TransferCompleteInt()
    {
    	gpio_led_ctrl(1, 1);
    	gpio_led_ctrl(1, 0);
    	// Clear the interrupt flag.
    	SSIIntClear(SSI0_BASE, SSIIntStatus(SSI0_BASE, true));
    	// If there's data remaining then initiate next transfer.
    	if(ssi0_length > 0) {
    		uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (unsigned char *)ssi0_txdata, (void *)(SSI0_BASE + SSI_O_DR), MIN(ssi0_length, DMA_TRANSFER_SIZE));
    		uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);
    	}
    	// Clear interrupt flag & set up next interrupt if necessary.
    	// ...
    	ssi0_length -= DMA_TRANSFER_SIZE;
    }

    Initialisation:

    void init_ssi_dma()
    {
    	// Setup the DMA module
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    	uDMAEnable();
    	uDMAControlBaseSet(udma_ctrltbl);
    	// Initialise the SSI module
    	init_ssi();
    	SSIEnable(SSI0_BASE);
    	SSIDMAEnable(SSI0_BASE, SSI_DMA_TX);
    	uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
    	uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE	| UDMA_ARB_4);
    	uDMAIntRegister(UDMA_CHANNEL_SSI0TX, SSI0TransferCompleteInt);
    	IntEnable(INT_UDMA);
    }
    

    To start a transfer I'm using this (this works - data comes out as expected):

    uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (unsigned char *)tx_data, (void *)(SSI0_BASE + SSI_O_DR), DMA_TRANSFER_SIZE);
    uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);

    The interrupt is included in the table for the entry "SSI0 Rx and Tx".

    Thanks

  • Ah! I forgot to add IntEnable(INT_SSI0) to my initialisation routine. It seems to work fairly well now. Thanks for the info in that thread, seems that you need to explicitly tell the DMA controller to route certain IRQs through, but you also need to turn on the interrupt itself (of course...)

  • Hello Tom,

    The interrupt enable process involves enabling the interrupt in the NVIC and then enabling the Interrupt propagation from the NVIC to the CPU IRQ line.

    I would thank the original poster for having put back the code on the forum.

    Regards

    Amit

  • Hello Amit,

    Which modifications would be needed with de TM4C129?

    Thank you.

  • Hello vmartinmora,

    For the SSI+UDMA? or in general for SSI. Can you please describe the issue you are facing,

    As for the thread here, the workaround is to disable the SSIDMA enable bits if the DONE bit is set in the SSIMIS only to be enabled after reconfiguring the uDMA channel and then enabling the DMA channel in the SSIDMA register.

    Regards

    Amit