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.

MSP430FR5994: Random SPI/DMA data corruption

Part Number: MSP430FR5994

Hello,

I read data from an SPI flash using DMA.

Randomly, there is one byte in the read buffer that is corrupted.  The corrupted byte is always equal to 0xFC.

It happens more frequently as the transfer size increases.  Under 20 bytes read, it never happens.

At first, I though about a messy pointer but that can't be as the code waits for DMA transfer completion with:

while((SPI_TX_DMACTL & DMAIFG) == 0){};
while((SPI_RX_DMACTL & DMAIFG) == 0){};
SPI_TX_DMACTL = SPI_DMA_STOP;
SPI_RX_DMACTL = SPI_DMA_STOP;
while((SPI_UCBxSTATW & UCBUSY) != 0){}; 

The corrupted byte is present immediately when the transfer finishes.

Oscilloscope probing of the SPI bus at the MSP pins reveals no corrupted bytes.  There is no 0xFC transferred on the SPI bus at any time.  Never.  Data read from flash is exactly what it must be.

It really looks like the DMA or SPI is behaving wrong internally.

SPI clock is 8MHz.

The problem occurs on all of our devices so it is not related to a damaged part.

Absolutely unusual.

Any thoughts?

Regards,

Frederic

  • Where in the buffer does the erroneous byte show up? That might (or might not) be a clue.

    In the F2 series I always had to set the Rx channel to higher priority than the Tx channel to avoid overruns. I suppose the substitute here would be DMACTL4:ROUNDROBIN.

  • With SPI one thing I have to keep reminding myself is to double check clock phase and polarity. I forget that for a while with an OLED display. The data sheet said it didn't care about the idle state of the clock. It did. Not enough to make it inoperative but enough to make it erratic.

  • Erroneous bytes tend to show up at the same offset (ie: 22, 37 and 41 for a 50 bytes read).  It is not absolute but there are definitely offsets more error prone.  I thought is was a clue at first but I can't make sense of it.

    I'll have a look at the overrun theory.  Other DMA transfers might be at work in the system...  Thanks for the clue.

  • I believe a wrong phase/polarity would cause problem on the first byte and many other bytes would be wrong too.

  • It occurred to me that 0xFC also looks somewhat like a "bit-smear" which could come from (as David mentions) clock-phase conflict or simple propagation delay. How long are your wires? I've seen it using 12" wires at 8MHz.

  • As stated, the signals are all good at the MCU pins.  It's on a PCB with about 2 inches traces.  I get 0xFC no matter what byte has been pushed on the line.  I am using values like 0x0, 0x01 or 0x80.  If any would turn into 0xFC, it would be quite obvious oscilloscope.  When reading zeros, MISO is absolutely flat.  No glitch whatsoever that could be interpreted as 0xFC.

    Clock signal is also clean.

    Slowing down SPI clock changes the error rate and erroneous offsets but not is a consistent way. It is just different.

    Swapping channels 0 for RX and 1 for TX, roundrobin or not, I can't see any improvement.  

    So that goes against the overrun theory,

    Anyhow, running SPI at 8MHz is likely too fast for an MCLK at 16MHz in a system that may required DMA elsewhere at the same moment.  At least, that bug put that into light.

    Maybe something major is blocking the DMA for long.  However, NMI are disabled and DMA abort flag is never set.  Unlikely either.

    Your help is appreciated.  Any branstorming can help.

  • Hi Fred,

    How are you observing the 0xFC value, are you just checking the stored values in your buffer after the read from your SPI Flash is complete?

    Is the debugger running and connected when you are reading the SPI Flash? Is there any other functionality in your code that is running simultaneously?

    Best Regards,
    Brandon Fisher

  • I observe 0xFC both through the debugger and from a print on the UART.

    The same behavior occurs with and without debugger connected.

    We do have a lot of things going on simultaneously. The FRAM usage is about 95% with level 2 optimization on "application" code and no optimization on drivers (hence, NO optimization on code accessing SPI and DMA registers).

    I tried moving around in memory all the buffers that are used for reading/writing to/from SPI.  Behavior is the same.  That mostly rules out a memory corruption issue.

    CPU is in active mode all the time.  No LPM used.

    Thanks for joining the discussion.

  • I'll poke at David's hypothesis one more time, then I'll stop. Clock phase errors don't necessarily show up all the time, nor even consistently, since tiny bits of timing slop and/or bit combinations can hide the condition. A few times (faced with an inscrutable data sheet) I've resorted to just trying all (4x) combinations of CPHA/CPOL, to see if the symptom changes. I expect you know this, but I'll mention it anyway: CPHA and UCCKPH are opposite polarity, i.e. CPHA=0 means UCCKPH=1.

    Thinking more about it, an overrun (either SPI or DMA) would typically result in a DMA stall, since not enough (Rx) bytes arrive. That would tend to point into the SPI (eUSCI), but I don't know what that would be.

    May I ask what flash device you're talking to?

  • I can't imagine clock phase having any impact when sampling hundreds of consecutive zeros.

    I did try all other phase and polarity settings:  total mayhem.  Wrong bytes dramatically increase.  The command sent to the flash is likely misinterpreted from the start and whatever follows is garbage.

    Flash is Winbond W25Q256JVEIQ.

    Your though about DMA overrun that would lead to a stall makes sense. 

    It leaves us with an eUSCI issue or one of the weirdest code bug I ever came across.

    Equally unlikely.

    My my my...

    Regards,

    Frederic

  • Hi Fred,

    Based on your testing it seems like there isn't an obvious cause for this. As ugly as it is, at this point I'd try removing other functions from a copy of my project to see if any of them have an effect on the observed error.

    Obviously starting with anything else involving the eUSCI (but not your SPI peripheral since you seem to have done some debug there already) or the DMA is an ideal starting place. 

    Best Regards,
    Brandon Fisher

  • We are travelling back in time (commits) to see for how long this bug has been around unoticed.

    If we ever come down to stripping everything else than the SPI code and that we still have the bug, I'll share it with you.  It might be easier to spot the problem at this point.

    Thanks all for you support.

  • I dug up that data sheet and there should be two combinations of clock/phase that work since it claims to not care about idle clock state. Both of the 0,0 or 1,1 phase/polarity combinations should work the same.

    The one thing that struck me about that part is that it is built for speed which can cause trouble.

  • I don't see your symptom using a very simple but analogous experiment: S/MCLK=16MHz, SPI clock=8MHz, UCA3, DMA channels 4/5, W25Q128JV (Adafruit breakout board; 3-byte addresses), wires ~6". The program just writes one page (256B), reads a different page (cleanses the palate), reads the written page, then compares Tx vs Rx data and halts.

    There is nothing else going on. I suppose that's the largest difference.

  • We found out the very single line that sparked the bug in a 2 years old commit!

    We started allowing nested interrupts in a UART ISR.  Commenting that _enable_interrupt() call solves all the wrong read over SPI.

    Why did we start to allow nested interrupts and do we really need that is under investigation.

    But why does it mess SPI reads handled by DMA??

    Anyone have an explanation for that?

  • Hi Fred,

    In general we don't recommend the use of nested interrupts on MSP430 as they can get pretty messy and are difficult to debug.

    I suspect there is a way to work around the use of that nested UART ISR, and as a result you won't have to worry about recursion causing stack overflow or the first ISR's execution time being artificially extended. I can't say exactly why it would cause SPI/DMA issues, but there are a lot of caveats to nested interrupts. 

    Best Regards,
    Brandon Fisher

**Attention** This is a public forum