More XMEGA SPI problems

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

My setup:
I have a SPI connection between two AVRs, an XMEGA 128a1 and an AT90USB162. The AT90, running at 8MHz, is the master. The SPI runs at 4MHz. The reason for making the AT90 master is 1) I can run SPI at 4MHz, 2) I can use DMA for SPI on the XMEGA (slave only), and 3) easier for the slower AT90 to be master. I am sending packets of 32 bytes and am using SPI F.

Problem background:
DMA transfers are non-deterministic due to the fact that the CPU has priority. Thus, if the cpu spends a long time accessing the SRAM, the DMA must wait to become bus master. I only need the DMA to transfer 1 byte at a time, each triggered by SPI transfer complete.

As a slave, the XMEGA has a small amount of time to write to the SPI data register before the the AT90 begins shifting it out. If the DMA writes to the data register too late, the write collision flag should be set. My code detects this. Furthermore, if the write is delayed an integer multiple, the collision flag will not be set, but the bytes will be out of sync. My code detects this as well (using a timeout timer, as the DMA transfer complete interrupt will not fire in this case due to pending transfers). Either of these cases will trigger a packet re-transmission.

Problem #1:
While this is an XMEGA, the AVR151 app note suggests that if a write into the SPI data register would cause a collision, the WCOL flag is set and the write aborted so as not to cause corruption. In my case, the DMA corrupts the data.

Problem #2:
When a write collision occurs, the WRCOL flag seems to be set most of the time, but not all. Maybe this is because multiple collisions are occurring in each packet. I would expect the flag to be only set by hardware, and cleared only by reading the status register then the data register (or reset).

My question:
Does anyone have any experience with slave SPI and DMA on the XMEGA, that can shed some light on these problems? When I have time, I will prepare a minimal amount of code to reproduce the problem to send to Atmel, but I am not fond of doing this given there are two programs on two chips, so I thought I would ask here first.

While I'm posting, I should point out that the XMEGA loses the SPI interrupt when waking from sleep if both interrupt and DMA are used (ie: DMA write, interrupt read) (Atmel confirmed).

BTW, my code on the AT90 is purposely inefficient to space out the individual bytes for now (I am using global variables which require SRAM access, rather than autos that can be put into registers). It is only when I decrease the time between bytes (I can see this on my scope) that these problems occur.

EDIT: Problem #1 is not really a problem as long as WRCOL is set. I just didn't expect that behavior.

https://www.mattairtech.com/
ARM Cortex M and XMEGA development boards / Gentoo Linux

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

So, how fast is your XMEGA running? Is it fast enough? When running your SPI at 4MHz you only have 250ns to get your data if you run back-to-back data. If you try to slow down the speed does it work then?

bngn

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

I am running the XMEGA at 32MHz. The problem can occur even if I have a 1us gap between bytes, it all depends on what other code the XMEGA is executing when the DMA wants the SRAM bus. The problem will apparently go away if I reduce the SPI clock speed or increase the space between bytes. But, the problem theoretically still exists in these cases because the DMA could be delayed for a long time. It seems to me that the only 100% reliable solution is to detect when a collision occurs. I haven't been able to reliably detect collisions when using DMA for writes to the SPI data register.

https://www.mattairtech.com/
ARM Cortex M and XMEGA development boards / Gentoo Linux

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

32MHz must be fast enough and 1us inter-byte-gap gives you up to 32 instructions to move one single byte. So that's obviously not the problem.
When reading the XMEGA manual about DMA it says "...the bus arbiter will wait until the AVR CPU is not using the data bus and permit the DMA Controller to transfer data". Normally this means a wait no more than until the current instruction using the same memory bus is ready, but if your observation is correct this seem to mean 'until the CPU is ready with all consecutive data memory operations'. That sounds like a silicon bug to me, as that pretty much makes the DMA useless in same cases. Even though it's highly unlikely to write code that blocks data memory for longer times it induces undeterministic behavior when timing is critical.
So if you can isolate the code and report to Atmel it would be interesting to hear their comments.

bngn

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

physicist wrote:
DMA transfers are non-deterministic due to the fact that the CPU has priority. Thus, if the cpu spends a long time accessing the SRAM, the DMA must wait to become bus master.

What's the longest number of consecutive cycles the CPU can lock the SRAM, and what type of access does it use? The bus priority section of the XMEGA manual states that a burst bus master request has priority over a regular bus master request, which assuming the CPU does not use burst accesses would mean the DMA transfer gets priority.

The DMA transfer would have to take at least 8 clock cycles to be delayed one SPI bit.

(Edit: The last bit isn't true, is it? Since the SPI data is read and written on opposite clock edges you only have four cycles to get the new data into the shift register. One SRAM read and one I/O write already take 3 cycles, so any additional delays would blow your timing.)