DMA Read and Write to USART MSPI

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I have a question about DMA reading and writing to a USART Master SPI port, more specifically about writing.

 

I can read the MSPI perfectly well using DMA, but I can't think of a  way to write to it easily since the device needs its CS de-asserted/re-asserted.

 

The best I could think of without interrupts (which takes too much of the CPU time) is to have a DMA (1) to de-assert the CS, a DMA (2) to write to the MSPI, a DMA (3) to read the SPI, and a DMA (4) to re-assert the CS, but that doesn't seem very 'elegant'.

 

Is there a better way to do this? * Yeah. Ask it in the XMega forum for a start. Moderator. *

Last Edited: Sat. Sep 9, 2017 - 08:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You set up DMA, make CS active, start DMA.
On completion of DMA, there will be an interrupt. Disable CS in that ISR().
Untested.
Small command sequences require you to read the reply to each TX byte. Not suitable for DMA.
Many SPI devices want a TX block. Or return data in a RX block. e.g. an EEPROM memory or TFT controller.
These BIG sequences work well with DMA.
.
What device are you using?
.
David.

Last Edited: Sat. Sep 9, 2017 - 07:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've used DMA to send data to a pcd8544 display from an xmega32e5. Using a timer interrupt to start the transfer and this at the end

ISR(EDMA_CH0_vect)
{
    // CLEAR INTERRUPT FLAG
    EDMA.CH0.CTRLB = EDMA_CH_TRNIF_bm | EDMA_CH_TRNINTLVL_LO_bm;
    // Wait for last character to be transmitted
    while ((USARTC0_STATUS & USART_TXCIF_bm) == 0)
        ;
    USARTC0_STATUS = USART_TXCIF_bm;
    LCD_PORT |= PIN_SCE;
    dma_busy = 0;
}

Not elegant with while loops in an ISR, but IIRC there will be no loop, the last char is transmitted when it comes to that point. Anyway, it works.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey David,

 

I'll try that tomorrow. On first thought, I'm hesitant just because I believe the CS has to be de-asserted/re-asserted with each SPI burst.

For example, this is temporary/test code I'm running where, in main, I poll the SPI port, getting it to de-assert/re-assert the CS to extract data while letting the DMA SPI read do its thing.

	// Enable DMA MSPI read (transports SPI data to data buffer)
	DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm;

        // Manual write to MSPI port to trigger data sampling and fill data buffer
	for (uint16_t i = 0; i < (SAMPLE_COUNT*3); i++) {

		PORTB.OUTCLR = PIN2_bm;// Bring CS low
		SPI_Data_Transfer(0xd0);
		SPI_Data_Transfer(0x00);
		SPI_Data_Transfer(0x00);
		PORTB.OUTSET = PIN2_bm; // Bring CS high
	}

	DMA.CH0.CTRLA &= ~DMA_CH_ENABLE_bm; // Disable the DMA

On the other hand, taking the CS commands outside the code only allows the first conversion


	// Enable DMA SPI read
	DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm; // Start DMA transfer

	PORTB.OUTCLR = PIN2_bm;// Bring CS low
	for (uint16_t i = 0; i < (SAMPLE_COUNT*3); i++) {

		SPI_Data_Transfer(0xd0);
		SPI_Data_Transfer(0x00);
		SPI_Data_Transfer(0x00);

	}
	PORTB.OUTSET = PIN2_bm; // Bring CS high

	DMA.CH0.CTRLA &= ~DMA_CH_ENABLE_bm; // Disable the DMA

(I'm using an Atxmega256a3bu, and a TI ADS8332)

 

Thanks,

Mitch

 

Edit: code typo

Last Edited: Sat. Sep 9, 2017 - 08:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Snigelen,

I see where you re-assert CS, but where do you de-assert it?

 

Mitch

Last Edited: Sat. Sep 9, 2017 - 08:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The PCD8544 is a 48x84 monochrome controller.   e.g. in Nokia 3310 displays.

There is little point in DMA for a small screen e.g. 504 bytes for the whole screen.

On a 240x320 ILI9341 colour screen,  you send 153600 bytes.   (230400 to read the whole screen)

 

From memory,  the PCD8544 does not need CS for each byte.   Just at the begin and end of the long sequence.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I see, thanks.

I wish there was an option for CS lol.

 

But the worst case scenario is I'll use an ISR to write to the SPI, so not a big problem

Last Edited: Sat. Sep 9, 2017 - 09:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am not at a PC. You always have to control CS manually on most chips.
Some ARM chips can disable CS when the shift register has completed.
.
For a monochrome display, libraries often manipulate a shadow buffer in SRAM. Then blit the whole buffer to screen in one go.
It is a lot easier to address individual pixels in the SRAM buffer than doing RMW on a screen. In fact a lot of display controllers are write-only. So the buffer strategy is the only way that you can write transparent text.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Mitch:

> I see where you re-assert CS, but where do you de-assert it?

 

David:

> From memory,  the PCD8544 does not need CS for each byte.   Just at the begin and end of the long sequence.

 

Yes, I do a CS in a timer ISR before engaging the DMA, and /CS in the DMA-complete interrupt.

I use the DMA for convenience, just write to the SRAM buffer and the display update is handled in the background.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, I do a CS in a timer ISR before engaging the DMA, and /CS in the DMA-complete interrupt.

I use the DMA for convenience, just write to the SRAM buffer and the display update is handled in the background.

Okay I see - that's good to know.

I'm going to poll the ADC's CS, toggling it up and down in a loop several times to get samples, and then process the samples right after, but I may try your method when that gets up and running. Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Most SPI devices have active-low Chip Select.   (but not all)

 

Most ADC devices will let you start an ADC conversion (with an SPI command).   The conversion often starts when /CS goes high.

You can go off and do other things.  e.g. start DMA on your LCD,   calculate the meaning of life...

Then access your ADC to read the finished conversion.

 

In other words,   ADC transactions on the SPI bus are short and sweet.   Possibly 10us or less.

DMA transactions are used for long sequences on the bus.

 

You check DMA for completion before accessing any other SPI device.

 

David.