SPI delay

Technical questions regarding the xTIMEcomposer, xSOFTip Explorer and Programming with XMOS.
User avatar
XCore Addict
Posts: 174
Joined: Wed May 31, 2017 6:55 pm

Re: SPI delay

Postby CousinItt » Wed Aug 21, 2019 5:16 pm

Good work. I hope xmos takes note for their next release.
Experienced Member
Posts: 67
Joined: Fri Oct 05, 2018 4:26 pm

Postby RedDave » Wed Aug 21, 2019 5:29 pm

I have now transferred the code over to my actual application and the phenomenon has resurfaced.

The ADC read is triggered every 10us for 10 triggers. It then waits 10ms before another block of 10 triggers. This is so that a laser that is being fired is eye safe. Final application will be continuous 10us firing.

When I trigger the 'scope I sometimes see that the 10 reads happen successfully in good time (~8us per ADC read) and are ready for the following read.
Most of the time this is not the case, it will perform a few reads at 8us per read and then perform one or two 600us.

As far as I can tell in my test application the reads were consistently 8us.

Any explanation of what the sync() is waiting for in the spi_master would be very helpful.
User avatar
XCore Legend
Posts: 1699
Joined: Thu Jun 10, 2010 11:43 am

Postby mon2 » Thu Aug 22, 2019 1:35 pm

sync operation is explained inside the following document:

https://www.google.com/url?sa=t&rct=j&q ... z3IIwt2nQZ
Experienced Member
Posts: 67
Joined: Fri Oct 05, 2018 4:26 pm

Postby RedDave » Fri Aug 23, 2019 12:45 pm

There is nothing that I can find in that document that explains the 600us wait for the sync. I could understand a few clock cycles, but not many thousands!

I have configured the ssn port with a different clock, since otherwise the clock that drives the chip select line is being stopped and started with the SPI clock. This is not desirable. However, this did not help.

Anecdotally, when the tile is busy the phenomenon is worse. One of the cores has a "default" case in its looped select. It is continually polling for new data. If this default is removed then the SPI read (in a different task) happens a lot more reliably. I have refactored that task to not use the default. This is good because it has resulted in more lean code.

But I am left with SPI reads that work correctly and in good time about 99.5% of the time. Roughly 5 in every 1000 reads takes this massive 600us. I still have no real explanation for that.

I have modified the lib_spi as a test.

I have replaced this block

Code: Select all

                p_ss[selected_device] <: 1 @ time;

                //TODO should this be allowed? (0.6ms max without it)
                if(ss_deassert_time > 0xffff)

                time += ss_deassert_time;

                p_ss[selected_device] @ time <: 1;
with an immediate write

Code: Select all

p_ss[selected_device] <: 1;

This seems to fix things and the write is now reliable.

But I do not understand why the original causes problems. I am passing ss_deassert_time=4. So my understanding of the code is this.

1) Write 1 to the port and record the time of the write in 'time'
2) If statement will not be entered because my value is small.
3) add 4 ticks to time.
4) Cause 1 to be written to the port, 4 ticks after the previous write. This will have no effect [writing the same value], but will mean that the sync() or writing of the 0 in the subsequent begin_transaction cannot happen until the dessert period.

So, the original code and my code, is that the next transaction cannot be run for a further 83ns. (given 48MHz clock). This is insufficient machine cycles to get around to it anyway.
Experienced Member
Posts: 67
Joined: Fri Oct 05, 2018 4:26 pm

Postby RedDave » Fri Aug 23, 2019 12:53 pm

New hypothesis.

My deassert time is too low.

By the time this line

Code: Select all

p_ss[selected_device] @ time <: 1;
is executing the time has already passed. The system therefore waits for the port clock to completely loop around. Could that be 600us?

[Edit: Just noticed the comment in the code I posted above. It makes a mention of 0.6ms being the maximum deassert time without the delay_ticks. This implies that is the wrap around time.]

This would explain why the phenomenon is worse when the tile is busy as the chance of not getting to that line within 83ns is increased.

Changing deassert time to 10 and using a 48MHz clock on the port and all seems to be working (for now).
Experienced Member
Posts: 67
Joined: Fri Oct 05, 2018 4:26 pm

Postby RedDave » Tue Aug 27, 2019 11:13 am

After some testing, this has been confirmed.

The deassert time passed to end_transaction must be at least enough time for it to calculate when the end of that deassert is. Otherwise it waits for the clock to wrap around to that value again (0.6ms).

With the 48MHz clock that I have set up and a deassert time of 4, this was usually enough time, depending on tile load. It was thus failing ~0.5% of the time. A value of 10 was sufficient to make it reliable.


I perceive this as a bug in the lib_spi code.

Who is online

Users browsing this forum: No registered users and 7 guests