Teensy 4 SPI polling issue

Status
Not open for further replies.

tonton81

Well-known member
Just added the 128gpio setup to teensy 4.0 in my car project and in its test stages of wiring everything was fine. When i started adding consistant SPI polling in the loop controlling the MCP23S17s, within several seconds I would lose control over the chips. At first I thought it was the thread, so I put everything in the loop(), same issue. I then went into the MCP23S17 library and added a 5ms delay() after each endTransaction, and now everything is responding properly. Is there something hindering back-to-back SPI transactions? I am using very short jumper cables between the MCP23S17s, and tested them with the car off so noise is not an issue. if I remove the delay, I cant control the gpios after the back-to-back SPI writes, until i reboot or reprogram again
 
What SPI speed?
What TD version?
There have been recent notes on SPI timing:

> Was it @KurtE? showing the transition on SPI was 5-10 times faster? Not leaving needed dwell time on CS IIRC ??

> Another user could use 1 Mbps with TD 1.48 but building with TD 1.53 failed - then moving to 4 Mbps worked.
 
note: the spi accesses are not ran from interrupt routines or threads, so loop only. i tried 10mhz, 8mhz, 2mhz, 1mhz, 100khz, same issue, so i dont think its about speed, more like the clock line at next assertion. i know it corrupts the data sometimes as a random other gpio asserts when im not even calling it, so it's a communication issue, but with 5 delay i dont have this issue. i tried delayMicroseconds 50 up to 500, all still failed, i didnt try any less delay and stopped at 5ms because it seems stable now, and since nothing is timing critical in loop the delay is not a concern for this project currently, but it is a sign of an issue. perhaps the clock may rarely not be at right level when CS drops, i dont know. also note i am using digitalwritefast for spi transactions.

TD is 1.53 on arduino 1.8.9, t4.0 600mhz,faster
spi pins: 10,11,12,13
 
Last edited:
I guess the question may be is it SPI or the device that is having issues.

Knowing who is asking this, I already assume you reviewed the datasheet for the device.

Again I don't think I have played with this chip.

Wonder if there is a speed of if you keep talking to it as fast as possible, that it leaves it no time to actually look at its IO pins and has issues?

The chip says that it can do 10mhz I think... Sounds like you have done all of the normal things. If I had it, I would probably hook up LA (or Scope) and watch the signals to get an idea of maybe what is happening.

Might help to see the code...
 
yes maybe tomorrow when i get back on laptop i can zip up the code, but its mostly digitalwrites consistantly on the SPI port expander. I used to use the DIP versions of 'em on T3.5 and they never had issue with constant chip writing directly after each transaction, consistantly. now im using the surface mount versions on T4. either way code or no code, a simple delay on the transaction fixes the spi communication issue, so being a sketch issue is highly improbable, seeing as its just digitalwriting endlessly in the loop, everything falls back on spi. if you dont have the port expander i can have one shipped to you, i just dont have a scope to see what exactly is going on on the SPI lines.
my MCP23S17 library is on github, and I must actually say it uses both transfer and transfer16 when necessary, so if anything can be seen it wont be from a sketch running mcp.digitalWrite(pin) constantly in loop, so this narrows issue down to transfer, transfer16, or mcp23s17 digitalWrite functions... or like you said, maybe chip needs time to access gpio registers. As for the board im using:

s-l400-3.jpg

also the gpio that activated but code wasnt actually using it at all in sketch, followed by no response till reset/reprogram to me sounds like the spi data was corrupted and sent bad data back to the port expander. and after the delay(5) right after endTransactions, it's all happy

2 days tested with delay without issues
no delay, i can make it crash just by polling the spi lines
 
Back to recent SPI notes - KurtE knows about - there was a change made where alternating transfer and transfer16 could leave the MCU's SPI set improperly so the next transfer would end up ejecting 16 bits.

That may have been a specific issue - but seems it was in the library.

Looking at KurtE's github - or current SPI PR's may show that ...
 
that may be a possibility, however the digitalwrite section only uses transfer16, just checked, some other functions use both, but they're not running by the time the loop is hit. but by the time the loop is hit, code functions till it stalls, unless i add the delay. even if there was a TCR issue it doesn't make sense that a delay ressolves that :p

mcp23s17 function:
Code:
MCP23S17_FUNC void MCP23S17_OPT::digitalWrite(uint8_t pin, bool level) {
  if ( pin >= (__builtin_popcount(detectedChips) * 16U) ) return;
  for ( uint8_t i = 0; i < 8; i++ ) {
    if ( !(detectedChips & (1U << i)) ) continue;
    if ( pin > 15 ) {
      pin -= 16;
      continue;
    }

    if (micros() - counter_GPIO[i] > gpioCacheTimeout) {
      bus->beginTransaction(SPISettings(speed,MSBFIRST,SPI_MODE0)); /* read port register */
      ::digitalWriteFast(chipSelect, LOW);
[COLOR="#FF0000"]      bus->transfer16(((0x41 | (i << 1)) << 8) | 0x12);
      uint16_t data = __builtin_bswap16(bus->transfer16(0xFFFF));[/COLOR] /* Read GPIOs */
      ::digitalWriteFast(chipSelect, HIGH);
      bus->endTransaction(); [COLOR="#0000FF"]delay(5);[/COLOR]
      checkInterrupt(i, data);
    }

    chipData[i][9] = (chipData[i][9] & ~(1UL << pin)) | (level << pin);

    bus->beginTransaction(SPISettings(speed,MSBFIRST,SPI_MODE0)); /* write port register */
    ::digitalWriteFast(chipSelect, LOW);
[COLOR="#FF0000"]    bus->transfer16(((0x40 | (i << 1)) << 8) | 0x12);
    bus->transfer16(__builtin_bswap16(chipData[i][9]));[/COLOR]
    ::digitalWriteFast(chipSelect, HIGH);
    bus->endTransaction(); [COLOR="#0000FF"]delay(5);[/COLOR]

    break;
  }
}

blue is what i added to fix the issue
 
Last edited:
the post just triggered the possibility ... just another SPI issue this month ...

Indeed a simple delay doesn't make sense - but there is a race in how the 8 .vs. 16 is tested/reset ... based on reading the post - maybe the delay lets the queue empty and the test for 8/16 set that was fooled by queued commands doesn't fail.

Though 500 us should have been enough to let that pass? Or it could be the delay lets the hardware recover from the spare byte ...
 
delayMicroseconds(500) still failed, i havn't went lower than 5ms to test more but i must be near that sweet spot between 500us and 5ms
 
The issue with 8 vs 16 was, the code before when you you do a transfer16, would grab the TCR register, change it to 16 bits do your transfer16 and try to set it back...
But if you then do another transfer16 it would again read the TCR register, and do it again. The issue is that writing to TCR does not happen when you do the write, it simply puts it into a FIFO queue, but the read of it is the current setting... So it shows 16... Fix was to remember was the last thing I did an 8 or an 16 and change if I need to...

So I don't think this is related.

Is your issues easily replicate without the hardware on the SPI port? i.e. do you have a small sketch one can run to reproduce it?
 
ill show you the sketch soon, but it's basically once the ISR sets a volatile variable, it runs the digitalwrite from loop(), like

Code:
void loop() {
  if (var) {
    mcp.digitalWrite(35, HIGH);
  }
  else {
    mcp.digitalWrite(35,LOW);
  }
}

EDIT: here is my arduino sketch, it has tabs, but the loop is pretty basic:

Code:
[ATTACH]21523._xfImport[/ATTACH]

You will see that MCP gpio 35 (sunroof open), which is NOT used in code runtime (except setting it to output during setup), without the delay in the library endtransactions, the sunroof would open when rolling down the other windows before the chips stop responding to input. This led me to believe the SPI data was corrupted somehow. with the delay, sunroof doesnt open by itself and the chips never loose communication
 
Last edited:
Status
Not open for further replies.
Back
Top