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.

MSP430F5342 DMA with SPI (UCB0/UCB1)

Greetings I've been attempting DMA to and from a device using DMA whereas DMA too the device works fine. DMA from the device does not.

DMA To (works)

//!DONE	DMA macro definitions for module
#define	SR_DMATX			DMACTL0_L
#define	SR_DMARX			DMACTL0_H
#define	SR_DMATXCTL			DMA0CTL
#define	SR_DMATXTRG			DMACTL0_L
#define	SR_DMATXSA			DMA0SA
#define	SR_DMATXDA			DMA0DA
#define	SR_DMATXSZ			DMA0SZ
#define	SR_DMARXCTL			DMA1CTL
#define	SR_DMARXTRG			DMACTL0_H
#define	SR_DMARXSA			DMA1SA
#define	SR_DMARXDA			DMA1DA
#define	SR_DMARXSZ			DMA1SZ
#define	SR_DMA_RX_TRIG		DMA0TSEL__USCIB1RX
#define	SR_DMA_TX_TRIG		DMA0TSEL__USCIB1TX
#define	SR_DMA_BA			__MSP430_BASEADDRESS_USCI_B1__
#define	SR_BRATE			UCB1BRW

		// disable DMA
		SR_DMATXCTL = 0;
		// now set up the DMA
		SR_DMATXSA =	(void *)((uint8_t *)source);
		SR_DMATXDA =	(void*)&UCB1TXBUF;
		// set size
		SR_DMATXSZ =	size;
		//SR_DMARXSZ =	size;
		// set triggers
		//SR_DMATX =		SR_DMA_TX_TRIG;
		// set DMA to be interleaved with CPU activity
		DMACTL4 = 		ENNMI | DMARMWDIS;
		SR_DMARXCTL =	0;
		//SR_DMARX =		SR_DMA_RX_TRIG;
		DMACTL0 = 		((DMA0TSEL_0)<<8)|SR_DMA_TX_TRIG;
		// byte to byte source++ dest single transfer
		SR_DMATXCTL=	DMASBDB | DMASRCINCR_3 | DMADSTINCR_0 | DMADT_0 | DMAEN;
		// clear any interrupt flags
		SR_DMATXCTL &= ~DMAIFG;
		// initial trigger
		//UCB1TXBUF = *((uint8_t *)source);
		// toggle trigger to start DMA
		UCB1IFG &= ~UCTXIFG;
		UCB1IFG |= UCTXIFG;

DMA From Does not work

		// disable TX DMA
		SR_DMATXCTL = 0;
		// now set up the DMA
		SR_DMATXSA =	(void *)&temp;
		SR_DMATXDA =	(void*)&UCB1TXBUF;
		// set size
		SR_DMATXSZ =	size;
		SR_DMARXSZ =	size;
		// set DMA to be interleaved with CPU activity
		DMACTL4 = 		DMARMWDIS;
		// disable RX DMA
		SR_DMARXCTL =	0;
		// note this can only be written as a word and both triggers
		// must be written simultaneously
		//DMACTL0 = (SR_DMA_RX_TRIG)<<8|SR_DMA_TX_TRIG;
		DMACTL0 =	DMA1TSEL__USCIB1RX | DMA0TSEL__USCIB1TX;
		//__data20_write_long
		SR_DMARXSA =	(void *)&UCB1RXBUF;
		SR_DMARXDA =	destination;
		// byte to byte source dest  single transfer
		SR_DMARXCTL =	DMASBDB | DMASRCINCR_0 | DMADSTINCR_3 | DMADT_0 | DMAEN;
		// byte to byte source++ dest  single transfer
		SR_DMATXCTL=	DMASBDB | DMASRCINCR_0 | DMADSTINCR_0 | DMADT_0 | DMAEN;
		// initial trigger
		UCB1IFG &= ~UCTXIFG;
		UCB1IFG |= UCTXIFG;

A few things of note

  1. No errata is given (but likely should be) for the fact that DMACTL0_L and DMACTL0_H cannot be individually written to as this will wipe out DMACTL0_H regardless of which you try to write too. These appear to be 16bit ONLY registers and should only be written to as a 16bit register or strange things will happen.
  2. The compiler complains for my assignments however it DOES correctly assign 20bit address values to the 20bit registers. This generates straight forward code, the special intrinsic code for this generates some "interesting" code, that works but is far more verbose.
  3. DMA To works, but DMA From, the device doesn't do anything. Some of the variable definitions are "missing"  because I pruned out stuff that's quite uninteresting. The DMA From just sends 0 paded data to the transmitter (temp variable), and stores the from data from the receive register (with increment), should work but doesn't even start the DMA transfer. Is it because 2 DMA channels are involved? 
  4. For some reason there is no DMA example code for the F5342.

If you have an idea please let me know, I've got it partially working, which isn't all bad. Just confused why the receive code doesn't even start the SPI clock.

Thanks!

Stephen

  • There is lots of mixed TX and RX stuff. Why?

    Is the SPI master or slave?
  • Clemens Ladisch said:
    There is lots of mixed TX and RX stuff. Why?

    First set of code is transmit only second set of code is to receive data.

    Transmitting data does not require one to read the RX register.

    Receiving data requires one to SEND data, due to the fact UCRXIFG will never trigger unless data is being sent as well (TX thus controls the SCLK)

    The code is supposed to do something like this:

    Copy I data to UCB1TXBUF until N bytes transitted.

    Copy received data until N bytes received.

    It doesn't do anything (I could show you a trace of /CS toggling and nothing happening if you like).

    Perhaps what I should try first is modify the existing transmit code without increment (IE send 0's) then work on the receive end of things.

    Since I'm using single transfer the Size registers should update correct? IE if I sent all N bytes the size register should read 0.

    Clemens Ladisch said:
    Is the SPI master or slave?

    The MSP430 acts as master only, the bus is not multi-master.

  • Since I'm using single transfer the Size registers should update correct?

    The DMAxSZ register is reinitialized after the transfers are complete.

    No errata is given (but likely should be) for the fact that DMACTL0_L and DMACTL0_H cannot be individually written to

    See table 11-4 in the User's Guide.

    The compiler complains for my assignments however it DOES correctly assign 20bit address values to the 20bit registers.

    Convert the pointers to uintptr_t.

    For some reason there is no DMA example code for the F5342.

    The DMA is the same in all 5xx devices. See MSP430F55xx_dma_03.c (which uses level-sensitive triggers).

**Attention** This is a public forum