Teensy 3.6 SPI problem with Teensyduino 1.40 but not 1.35

Status
Not open for further replies.

jarkman

Member
We have some SPI code which works when built with Arduino 1.8.1 / Teensyduino 1.35 but fails (apparently either reads the wrong data, but hard to be certain) when built with Arduino 1.8.1 / Teensyduino 1.40 and when build with Arduino 1.8.5 and Teensyduino 1.40

We're running on a Teensy 3.6, we've repeated the experiment when building on Windows 7 & on Linux.

I can't post the code as-is, but i can make a cut-down sample if that would help.

Are there any known issues with SPI and Teensyduino 1.40 ? I'm new to the Teensy world, I may not have looked in all the right places.

And, is there any way to get hold of a Mac installer for 1.35, that being the platform I really need to build this on now... :)

Thanks,

Richard
 
Might help to know more information, like are you using standard pins or alternate pins? Anything else special?

Obviously seeing the code would help to debug.
 
The biggest change between TD 1.35 and TD 1.40 is most probably the newer toolchain, using C++14 now instead of C++11 before. This should normally not be a problem if your code is clean and state of the art. If parts of your code were problematic under this aspect, you‘d have seen compiler warnings and you had most probably fixed your code already.

If your code compiles in TD1.40 without warnings, and SPI still does not work, I‘d really like to see a code snipped which allows to reproduce the problem, preferably using a MOSI/MISO loop whee the sent data will immediately be read back and verified with what was just sent.
 
Thanks, both. I'll see if I can get the problem to show in a smaller snippet.

No, no warnings, and nothing leaps out at me as suspicious in the code.

In the meantime, do you have any idea where I might find TD 1.35 for Mac ?

Thanks,

Richard
 
Just a quick partial update - looking at the SPI traffic with my Salaea, it looks as though the 1.35 builds are sending/receiving the expected 8 bytes from the code below, the 1.40 builds are sending & receiving 3 bytes. I'm an SPI noob, so this may well yet be something ridiculous in the code. Anyhow, code and screenshot:

I'll see if I can make a standalone sample that demonstrates the problem.

Code:
digitalWrite(slaveSelectPin,LOW);
delayMicroseconds(1);
for (i=0; i<8; i++)
	inbuffer[i] = SPI.transfer(outbuffer[i]);
delayMicroseconds(1);
digitalWrite(slaveSelectPin,HIGH);

SPI setup is

Code:
pinMode (slaveSelectPin, OUTPUT);
digitalWrite(slaveSelectPin,HIGH);
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV4);
SPI.setDataMode(SPI_MODE1);


Screen Shot 2017-12-07 at 18.35.59.jpg
 
Here's a screenshot of the same code built with 1.35 for comparison:
View attachment 12185

Not sure what is going on in your case.
I tried this, based off of your code above:
Code:
#include <SPI.h>
#define slaveSelectPin 10
void setup() {
  Serial.begin(115200);
  pinMode (slaveSelectPin, OUTPUT);
  digitalWrite(slaveSelectPin, HIGH);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  SPI.setDataMode(SPI_MODE1);
}

uint8_t outbuffer[8]= {0, 1, 2, 3, 4, 5,6, 7};
uint8_t inbuffer[8];

void loop() {
  digitalWrite(slaveSelectPin, LOW);
  delayMicroseconds(1);
  for (uint8_t i = 0; i < 8; i++)
    inbuffer[i] = SPI.transfer(outbuffer[i]);
  delayMicroseconds(1);
  digitalWrite(slaveSelectPin, HIGH);
  delay(10);
}
I ran it on a T3.6 using current SPI stuff. My version is current with Paul's. The latest change was to allow pin 45 as a Chip select pin.

Here is the output from logic Analyzer.
screenshot.jpg

You might want to check to see if you have a different version of SPI library sitting around. In particular in your <arduino sketch folders>/libraries/SPI
 
the sketch in post #8 works for me on T3.5 (1.8.4/1.40), MISO jumpered to MOSI. Verified with logic analyzer, too.
spitmp1.jpg
 
I also tried the code from message #8, with the very latest (unreleased/github) Teensyduino code. Here's what I see.

file.png
(click for full size)

This is yet another case where I need to remind about the "Forum Rule". When you post only code fragments, someone (Kurt in this case) has to do extra work to fill in the rest of the code. This almost always results in not reproducing the problem.

Please, do yourself a favor, post a COMPLETE program in your message. It will help us get to the bottom of the problem you're seeing. Complete programs save everyone's valuable time. Otherwise we just waste effort testing code that don't really reproduce the problem, and writing more messages. All that effort could have gone into actually finding and fixing whatever is really wrong. Please please please, follow the Forum Rule by posting a complete program that anyone can copy and paste into Arduino and run the exact same thing you tested. Don't make us have to guess the rest of the code!
 
Looking at the screenshots, this might be a simple case of the test gear sampling too slowly.

I see only 5 MHz in messages #6 & #7. Kurt used 25 MHz in message #8. Manitou used 16 MHz in message #10. My oscilloscope sampled at 2500 MHz. ;)

Comparing the images in #6 and #7, it looks like Teensyduino 1.35 used a slower SPI clock. The data spans ~50 microseconds in #7. All of our tests with version 1.40, even #6, show the data spanning ~18 microseconds with Teensyduino 1.40.

The 5 MHz sampling setting used in #6 is much too slow for this faster SPI data rate.
 
Sorry, my bad with the sample. Thank you all for your help.

I've just done a bit more leisurely a/b testing, and confirmed both of Paul's suspicions.

This is running Kurt's sample (with MOSI and MISO connected to our test hardware, not wired together), and with the Salaea sampling faster.

Building with 1.35 on Windows 7, I get an SPI clock at 1.25MHz
teensy_1_35_karl_1_25_mhz.jpg

Building with 1.40 on OSX, I get a clock at 3.8MHz
teensy_1_40_karl_3_86_mhz.jpg
 
Doing it with the transaction API, thus:

#include <SPI.h>
#define slaveSelectPin 10

SPISettings settingsA(2000000, MSBFIRST, SPI_MODE1);

void setup() {
Serial.begin(115200);
pinMode (slaveSelectPin, OUTPUT);
digitalWrite(slaveSelectPin, HIGH);
SPI.begin();
//SPI.setBitOrder(MSBFIRST);
//SPI.setClockDivider(SPI_CLOCK_DIV4);
//SPI.setDataMode(SPI_MODE1);
}

uint8_t outbuffer[8]= {0, 1, 2, 3, 4, 5,6, 7};
uint8_t inbuffer[8];

void loop() {
SPI.beginTransaction(settingsA);
digitalWrite(slaveSelectPin, LOW);
//delayMicroseconds(1);
for (uint8_t i = 0; i < 8; i++)
inbuffer = SPI.transfer(outbuffer);
SPI.endTransaction();
digitalWrite(slaveSelectPin, HIGH);
delay(10);
}

I get good behaviour with both

1.35

teensy_1_35_transactions_2mhz.jpg

and 1.40:

teensy_1_40_transactions_2_mhz.jpg
 

Attachments

  • teensy_1_35_transactions_2_mhz.jpg
    teensy_1_35_transactions_2_mhz.jpg
    77.7 KB · Views: 106
  • teensy_1_40_transactions_2_mhz.jpg
    teensy_1_40_transactions_2_mhz.jpg
    71.6 KB · Views: 102
Last edited:
And, applying the new API to our original code brings it back to working in 1.40! Which means I'm very happy, we can get back to work.

Just to get to the end of the story, is the underlying clock rate that the old API divides down actually different in 1.40 ?

Thanks, all!

Richard
 
Also I find if you need to run your Saleae at lower speeds, it shows SPI data up when your capture rate is a multiple of the actual rate that the bits are generated. Not sure if that makes sense.

So what I am trying to say is, if you are asking to generate a signal at 2mhz, the SPI code says this is the maximum it is allowed to generate and it will choose the fastest speed up to what you asked for.

So if you are running at the default 180mhz, the buss speed is set to 60mhz. If you ask for 2mhz, the default code looks for the right setting. So it checks:
Code:
...
				t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
			} else if (clock >= F_BUS / 20) {
				t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(0);
			} else if (clock >= F_BUS / 24) {
				t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
			} else if (clock >= F_BUS / 32) {
				t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(3);
...
So it checks (Note I am reducing numbers here): if (2 >= 60/24) NO... is 2 >= 60/32 Yes... So actual speed is: 1.875mhz...

Now suppose you instead configure the T3.6 to run at 192mhz, which has the default bus speed of 48mhz. So from above:
if (2 >= 48/24) YES - And it generates exactly 2mhz signal.

So for example if you can probably capture reasonably well at 2mhz, but for sure at 4mhz...

and sort of out of off topic, but yesterday I discovered that Saleae had released newer updates 1.2.17... Which included some very nice speed improvements for their PRO versions.
 
Thanks. I was only running too slow because I hadn't noticed what it was set to, will try not to make that mistake again! :)

Wonder if they could provide some visual cue that you're near the limit, sloping edges on the logic signals or some such ?
 
Status
Not open for further replies.
Back
Top