E70 SPI transfer 24 bits using DMA

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

Hi there I am trying to interface the E70 with the AD5290 DAC by updating all 16 channels at regular intervals.

 

The serial protocol for this chip requires a total of 24 bits to be sent in each transfer to update one channel (i.e. NPCS must rise every 24 clock cycles). Therefore, what I want the DMA to do is send 24 bit packets 16 times to the chip without processor intervention.

 

I see in section 41.7.3.9 of the data sheet (Peripheral Deselection with DMA) that CSAAT and LASTXFER must be used with DMA. But if I am doing this every other transfer (e.g. breaking the 24 bit transfer into two 12 bit transfers) this will require a lot of processor intervention, which defeats the purpose of the DMA. I am totally confused about what is being presented in Figure 41-11, so not sure if the answer is in there somewhere.

 

Any ideas?

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

you could try to setup a XDMAC LinkedList -> create one dma job to transfer the 3 bytes, point to the next dma job to transfer the next 3 byte, point to ....

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

Thanks very much for your reply. This looks like it might be what I'm after. 

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

Hi Patrick,

you can prepare an array of 24 (32bit) words where each word contains one transfer byte and additional values for the SPI's control register(s).

If you send this array at once (no linked list) via DMA, for each byte some control registers will be set.

(with this mode LASTXFER can be set after every 3 bytes, even switching between different chip selects is possible)

You have to configure a special mode in the SPI to process such array, see 'SPI Direct Access Memory Controller (DMAC)' in the datasheet.

 

Regards,

Martin

 

 

 

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


Hi Martin,

Thank you for your reply as well, it seems like an easier solution. I have studied the section of the datasheet you referred to, as well as "Peripheral deselection with DMA", and used SPI_MR.PS = 1 and SPI_CSR0.CSAAT = 1. However what I am finding is that when I try to make three SPI transfers (three transfers of two uint32_ts), the chip select does not rise when SPI_TDR.LASTXFER = 1 and I just end up with the chip select low for all transfers. In the logic analyser shot below and corresponding variables going to SPI_TDR. Note that every other uint32 has LASTXFER = 1 so I expected the transfer below to happen in three parts, not just one.

 

However, I am finding that if I manually paste the 32 bit integers into the SPI_TDR register in debug mode, then NPCS stays low if LASTXFER = 0 and then rises again if LASTXFER = 1. So I thought maybe the DMA is not transferring all 32 bits, but XDMAX_CC.DWIDTH is definitely set to 32 bit.

 

Do you have any other hints on how to implement this?

 

Many thanks in advance!

 

 

 

SPI setup code:

        SPI0->SPI_MR |= SPI_MR_MSTR | SPI_MR_DLYBCS(0x1F) | SPI_MR_PS;
        SPI0->SPI_CSR[0] = SPI_CSR_BITS_16_BIT | SPI_CSR_SCBR(0x49) | SPI_CSR_CSAAT | SPI_CSR_NCPHA | SPI_CSR_CPOL;

XDMAC CC setup:

XDMAC->XDMAC_CHID[DMA_CH_SPI0_TX].XDMAC_CC = (XDMAC_CC_TYPE_PER_TRAN |			// memory to peripheral transcation
		XDMAC_CC_MBSIZE_SINGLE |													// Memory burst size 1
		XDMAC_CC_SAM_INCREMENTED_AM |												        // Source address increment (buffer)
		XDMAC_CC_DAM_FIXED_AM |														// Dest address fixed (SPI TDR)
		XDMAC_CC_DSYNC_MEM2PER |													// Mem to peripheral transfer
		XDMAC_CC_CSIZE_CHK_1 |														// Chunk size 1
		XDMAC_CC_DWIDTH_WORD |														// 32 bit data width
		XDMAC_CC_SIF_AHB_IF0 |														// See datasheet section 19.2.3 for system bus connections
		XDMAC_CC_DIF_AHB_IF1 |
		XDMAC_CC_PERID(DMA_CH_SPI0_TX));

 

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

Hi Patrick,

 

your case is described in the second chapter of 'Peripheral Deselection with DMA'.

 

DMA reloads the data register very fast (before the old word has been shifted out) so the LASTXFER bit will not work except if CSNAAT is 1.

 

Figure 40-11 shows this at the end.

According to this you have to set CSAAT=0 and CSNAAT=1.

 

Hope this helps,

Martin

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

 

Hi Martin,

Yes, I did notice the datasheet specifies that, but also that under the SPI_TDR register description it states that "The current NPCS is deasserted after the transfer of the character written in TD. When SPI_CSRx.CSAAT is set, the communication with the current serial peripheral can be closed by raising the corresponding NPCS line as soon as TD transfer is completed.". It's a little confusing too, as I do want the chip select to remain active after the transfer, unless LASTXFER = 1...

 

Anyway, I tried all possible combinations of CSAAT and CSNAAT, although CSNAAT is ignored if CSAAT = 1. Below is the result if CSAAT = 0 and CSNAAT = 1. Each word gets its own toggle of NPCS.

 

 

Last Edited: Sat. Dec 14, 2019 - 09:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Patrick,

 

I my Software I have three devices connected to different chip selects.

 

So CSAAT=1 worked for me, the chip select remains low until the next device is selected.

May be that setting of LASTXFER on the last Transfer word is not necessary in this case.

 

I have no idea why LASTXFER doesn't work in your case.

As a Workaround You could put a dummy word with another chip select between each transfer block (if you don't Need all chip select lines).

But there should be a better solution.

 

 

You set the Variable Peripheral Select Mode:

SPI_MR_PS

Perhaps this Setting interferes with LASTXFER, and both Settings cannot be used together ?

In Variable Peripheral Select Mode the chip select can be put into the 32bit data, deselecting occurs automatically when the next device is selected.

In Fixed Peripheral Select Mode you Need LASTXFER to explicitely deselect THE SAME device betwenn each transfer.

So you could try SPI_MR_PS=0.

 

Regards,

Martin

 

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

 

Hi Martin,

When using different NPCS in the SPI_TDR register I can repeat what you are seeing, as shown below where I am transmitting 2x16 bits on NPCS0 then NPCS1 and then NPCS2 in that order. This would give me what I was after if I add a dummy transfer on another chip select after each tranfer on NPCS0, which is obviously very inefficient. However, SPI_TDR.LASTXFER appears to be ineffective in raising NPCS.

 

Thank you very much for taking the time to respond to me.

 

 

Last Edited: Tue. Dec 17, 2019 - 08:58 AM