libquadflash/hardware timer conflicts? Topic is solved

If you have a simple question and just want an answer.
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

What is the speed of the SPI clock for this flash device?

Is the flash device close on the PCB to the CPU?

Multi-layer PCB?

Which quad flash device are you using? If not an XMOS factory supported flash and to rule out the flash device itself, can you source such a device for similar testing? A few years ago we did a review of the flash devices with the XMOS processors and found assorted pin drive issues across vendors. Back then, found that Spansion (aka Cypress now) had excellent signal quality for our rather long but shielded logic analyzer probes (sold by Zeroplus). Winbond kept failing with value mismatches under the same conditions and cables. Then Winbond sampled us another die of the flash memory but this new device offered a pin drive strength register. We were testing SPI and QSPI modes of the flash devices.

For giggles, consider to source and test out the QSPI FRAM device from Cypress:

http://www.cypress.com/documentation/ap ... qspi-f-ram

Code: Select all

http://www.cypress.com/documentation/application-notes/an218375-designing-cypress-quad-spi-qspi-f-ram
Attachments
xmos_quadflash.png
(102.48 KiB) Not downloaded yet
xmos_quadflash.png
(102.48 KiB) Not downloaded yet


View Solution
cjameshuff
Member++
Posts: 22
Joined: Mon Sep 26, 2016 6:08 pm
Contact:

Post by cjameshuff »

...again, the project that demonstrates the problem is for the xCORE-200 MC Audio eval board. The problem was noticed on a completely different board using XMOS parts with on-chip flash. The flash speed is that used by the XMOS library. The issue is not the SPI clock rate or pin drive.

The issue is some form of conflict between the interrupt and the flash code when both are running on the same core. There are no errors when the interrupt is not running, and the error rate tracks the interrupt rate. There are also no errors if the interrupt runs on another core.
User avatar
infiniteimprobability
XCore Legend
Posts: 1126
Joined: Thu May 27, 2010 10:08 am
Contact:

Post by infiniteimprobability »

Hi,
a few thoughts.

Firstly, nice work on the ASM. As you know, interrupts are not natively supported in XC (in favour of events), so getting them going requires a reasonable amount of savvy and effort..

My first idea was that your ISR was trampling over memory, but from a first look, it seems sensible and your stack is sufficient (it has to be allocated manually).

Looking at your example further though I'm fairly sure what is happening is that your ISR is upsetting the low level flash timing. Since interfaces (eg. SPI/QSPI) in XMOS are done using software, interrupting that may break the functionality.

For example, quadflashlib is developed from this repo: https://github.com/xcore/sc_flash/blob/ ... i_flash.xc

You'll see lots of this sort of thing:

Code: Select all

   p.CS <: CS_HI @ time;
    time += 10;
    p.CS @ time <: CS_LO;
    p.DQ @ time <: instruction;
That is using timed ports. First line grabs the timestamp, then further outputs are triggered by a future time event (10 app clocks later). The thing about timed ports is that, if you miss the compare match (because the CPU is not able to setup the timed IO in time) it takes 2^16 application clock cycles until it happens. The code is written to assume an ISR does NOT happen.. You will probably see stuff randomly stretch out when you get unlucky.

You could try slowing the flash right down (which would hopefully give your ISR time to complete inside timed IO sequences) to see if it works around the issue.

I am afraid in general, timing critical code and ISRs do not mix well particularly if the timing is tight. You could mask/umask interrupts as needed else move the ISR to something that doesn't mind a bunch of cycles being stolen in large chunks.. Can you move the ISR to a different thread?
cjameshuff
Member++
Posts: 22
Joined: Mon Sep 26, 2016 6:08 pm
Contact:

Post by cjameshuff »

I didn't write the original assembly (and had a response similar to your avatar's when first confronted with it), I just stripped it down for the test program.

I did not expect the SPI code to be timing sensitive, but had not considered that it might use timed ports to synchronize multiple ports. Moving to another logical core should be possible, I just wanted to avoid doing something that would only cover up an issue by moving it somewhere not as easily detectable.
cjameshuff
Member++
Posts: 22
Joined: Mon Sep 26, 2016 6:08 pm
Contact:

Post by cjameshuff »

infiniteimprobability wrote:Hi,
a few thoughts.

Firstly, nice work on the ASM. As you know, interrupts are not natively supported in XC (in favour of events), so getting them going requires a reasonable amount of savvy and effort..

My first idea was that your ISR was trampling over memory, but from a first look, it seems sensible and your stack is sufficient (it has to be allocated manually).

Looking at your example further though I'm fairly sure what is happening is that your ISR is upsetting the low level flash timing. Since interfaces (eg. SPI/QSPI) in XMOS are done using software, interrupting that may break the functionality.

For example, quadflashlib is developed from this repo: https://github.com/xcore/sc_flash/blob/ ... i_flash.xc

You'll see lots of this sort of thing:

Code: Select all

   p.CS <: CS_HI @ time;
    time += 10;
    p.CS @ time <: CS_LO;
    p.DQ @ time <: instruction;
That is using timed ports. First line grabs the timestamp, then further outputs are triggered by a future time event (10 app clocks later). The thing about timed ports is that, if you miss the compare match (because the CPU is not able to setup the timed IO in time) it takes 2^16 application clock cycles until it happens. The code is written to assume an ISR does NOT happen.. You will probably see stuff randomly stretch out when you get unlucky.

You could try slowing the flash right down (which would hopefully give your ISR time to complete inside timed IO sequences) to see if it works around the issue.

I am afraid in general, timing critical code and ISRs do not mix well particularly if the timing is tight. You could mask/umask interrupts as needed else move the ISR to something that doesn't mind a bunch of cycles being stolen in large chunks.. Can you move the ISR to a different thread?
Testing with the simulator (someone else's work, not mine) has shown the cause to be something similar to this. From my understanding, it appears the SPI clock is being set up to free run, and the data handling code has to keep up with it. It thus does not deal well with interruptions.

This doesn't change anything with regards to the possible solutions, but at least makes it clear that they are actual solutions, and that the interrupt isn't doing something obscure that will cause other problems in the future.
User avatar
akp
XCore Expert
Posts: 578
Joined: Thu Nov 26, 2015 11:47 pm

Post by akp »

It seems to me the easiest thing since you're SPI master is simply to bit bang SPI clock synchronously from your code maybe with a timeafter or something if you don't need to push the SPI timing too much. The FLASH should be able to handle a lot of jitter on its SPI clock.
Post Reply