Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 8 of 8

Thread: Teensy 4.0 SPI Clock Speed

  1. #1

    Teensy 4.0 SPI Clock Speed

    I am trying to use the Teensy 4.0 to read an ADC over SPI (data sheet here: https://datasheets.maximintegrated.c...s/MAX11100.pdf)

    The max clock speed for this device is 4 MHz, but the highest SPI divider available through Arduino is 128 giving a SPI clock of 600/128 or 4.68 MHz.

    Any suggestions on how to get around this?

    Thanks in advance,
    John

  2. #2
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    3,873

    Cool

    Ummm, you should not be using SPI clock dividers as those are deprecated for use on Teensys.

    Instead you should use SPI transactions, which includes a SPIsettings object that you can specify the SPI bus speed, SPI bit order, and the SPI mode directly. On a 3.5, I used this to tune a SPI display to different spi speeds from 8Mhz to 21Mhz (19Mhz was the sweet spot for that particular configuration, until I put in pull-up resistors on the CS/DC pins).


    In particular:

    Transactional SPI configuration
    A common problem used to be that different SPI devices needed different, incompatible settings. Your sketch had to take care of saving and restoring the SPI settings before communicating with each SPI device. If any SPI device was accessed from an interrupt, this could result in data corruption if another SPI device was communicating at the time.

    With the new SPI library, configure each SPI device once as an SPISettings object. Also, if that device will be called from an interrupt, say so with SPI.usingInterrupt(interruptNumber). To communicate with a specific SPI device, use SPI.beginTransaction which automatically uses the settings you declared for that device. In addition, it will disable any interrupts that use SPI for the duration of the transaction. Once you are finished, use SPI.endTransaction() which re-enables any SPI-using interrupts.

  3. #3
    Hey Michael,

    This fixed it thanks!

    I guess it goes without saying that I'm new to Teensy

  4. #4
    Junior Member
    Join Date
    Mar 2020
    Posts
    7
    I am working with the Teensy4.0 and compiling in both Arduino IDE and using Visual Studio with Visual Micro plugin (shame the debug does not work!!!)
    Arduino 1.8.13 and TeensyDuino 1.53

    Anyway using SPIClass to communicate on SPI channel0 to a DAC8775 development board. The SPI links are very short. The CS Pin is Pin 15
    I think there is an issue with the SPI Library for Teensy and the SPI.BeginTransaction(SPISettings(spi_speed, bit_order, mode)) is not setting the SPI clock speed correctly.
    This was found as using the Teensy4 at 150MHz and has a few issues. From using the Logic logic analyzer on the SPI and fixed a few timing issues by placing a delayMicroseconds(2) after setting CSPin LOW and then after SPI.Transfer(data) another delay delayMicroseconds(2) before setting the CSPin HIGH again. The code for writing (of course there is a method for readings):

    void DAC8775Control:AC8775SPIWrite(byte registryAdr, uint16_t data)
    {
    SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE1));

    #if DEEP_DEBUG_LEVEL_TWO
    digitalWrite(_csPin, LOW); //Mark for Logic Analyzer for testing and speed of switching, not needed for normal use
    digitalWrite(_csPin, HIGH);
    delayMicroseconds(2);
    #endif

    digitalWrite(_csPin, LOW);
    delayMicroseconds(2); //This delay is absolutely needed to ensure timings

    SPI.transfer(registryAdr);
    SPI.transfer16(data); //Data is always 16bit for the DAC8775

    delayMicroseconds(2); //This delay is absolutely needed to ensure timings

    digitalWrite(_csPin, HIGH);
    SPI.endTransaction();
    }

    I can get this to work for 150MHz and confirm this by writing to a registry (UserBit) on the DAC8775 and then reading it back to confirm an SPI Comms check.

    However, if I now crank up the Teensy speed up to above 150MHz it falls over. Does NOT work for 450MHz or 600MHz regardless of what speed I put in the SPISettings.
    Played around for a long time (36 hours) with timings and delays and SPISettings. It always fails above 150Mhz.

    So I then used the following:

    SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE1));
    SPI.setClockDivider(SPI_CLOCK_DIV64);

    And I get it to consistently pass at 600Mhz, also works with SPI_CLOCK_DIV32. But fails at 600Mhz with SPI_CLOCK_DIV16 (not unexpected).

    So in conclusion, I think that the SPI library and in particular the SPISettings is not setting the correct SPI clock speed.

    atb Jim

  5. #5
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,593
    SPI.BeginTransaction(SPISettings(spi_speed, bit_order, mode)) is not setting the SPI clock speed correctly
    So what does your logic analyzer report for the SPI clock rate when your beginTrasaction() sets clock to 4mhz?

    if i run your SPI transfers, scope on SPI CLK (pin 13) shows 4 mhz clock for various MCU speeds.

    if the DAC is not keeping up, maybe try sending the 16-bit data item with two 8-bit transfers
    Last edited by manitou; 10-11-2020 at 05:42 PM.

  6. #6
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,868
    A couple of different things...

    Visual Studio and VisualMicro... There are some capabilities for debug using GDBStubs... More details up on VisualMicro and in a few threads here like:
    https://forum.pjrc.com/threads/61499...VS-Integration

    Code:
    SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE1))
    Tries to set SPI clock speed to be the fastest speed it can be that does not exceed 4mbs (4000000)

    SPI.setClockDivider(SPI_CLOCK_DIV64) says:
    Code:
    	void setClockDivider(uint8_t clockDiv) {
    		if (clockDiv == SPI_CLOCK_DIV2) {
    			setClockDivider_noInline(12000000);
    		} else if (clockDiv == SPI_CLOCK_DIV4) {
    			setClockDivider_noInline(4000000);
    		} else if (clockDiv == SPI_CLOCK_DIV8) {
    			setClockDivider_noInline(2000000);
    		} else if (clockDiv == SPI_CLOCK_DIV16) {
    			setClockDivider_noInline(1000000);
    		} else if (clockDiv == SPI_CLOCK_DIV32) {
    			setClockDivider_noInline(500000);
    		} else if (clockDiv == SPI_CLOCK_DIV64) {
    			setClockDivider_noInline(250000);
    		} else { /* clockDiv == SPI_CLOCK_DIV128 */
    			setClockDivider_noInline(125000);
    		}
    	}
    Max SPI speed is .25mbs or about 1/16th the speed you asked for in the beginTransaction.
    Likewise the SPI_CLOCK_DIV32 is .5mbs ...

    I believe regardless of speed you run the processor SPI is setup to be using the 720mhz ( // PLL3 PFD0) clock as the main clock so I don't believe CPU speed should influence it.

    Note: I ran simple program:
    Code:
    #include <SPI.h>
    void setup () {
      SPI.begin();
      pinMode(10, OUTPUT);
    }
    
    void loop() {
      
      SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE1));
      digitalWrite(10, LOW);
      for (uint8_t i = 0; i< 8; i++) SPI.transfer(i);
      digitalWrite(10, HIGH);
      SPI.endTransaction();
      delay(250);
    }
    And it shows:
    Click image for larger version. 

Name:	screenshot.jpg 
Views:	8 
Size:	57.4 KB 
ID:	22046
    And you will see in the anotation that the clock is running at about 4mhz as expected. I believe the spec sheet for that chip says it can go up to about 25mhz.

  7. #7
    Junior Member
    Join Date
    Mar 2020
    Posts
    7

    SPI Clock Speeds

    OK, like all digital problems there seems to analog gremlin.
    Thanks to some of the replies, and one asking for logic anlayser outputs, it seems I can not reproduce the issue.
    Using the code
    SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE1));
    without any follow on SPI.setClockDivider(SPI_CLOCK_DIV64);
    I have had this compiled and running satisfactory; strange.
    The logic analyser attached shows approx 8Mhz

    Click image for larger version. 

Name:	Teensy@600Mhz_SPI@8Mhz.jpg 
Views:	6 
Size:	32.9 KB 
ID:	22050

    I have also compiled and run at 816Mhz and SPI is showing 8MHz

    Click image for larger version. 

Name:	Teensy@816Mhz_SPI@8Mhz.jpg 
Views:	6 
Size:	36.0 KB 
ID:	22051

    However, in my defence, as I don't normally go into writing unless I really need to, the screenshot of the Teensy at 150Mhz and SPI set to 4MHz does not show 4MHz on the Logic Analyser but approx 1Mhz

    Click image for larger version. 

Name:	Teensy@150Mhz_SPI@4Mhz.jpg 
Views:	9 
Size:	33.5 KB 
ID:	22052

    Oh and by the way, I did test with and without logic analyser connected, just in case we were getting a probe effect!!!

    It seems this issue has digitally disappeared, which is not logical!!!

  8. #8
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,593
    Quote Originally Posted by JDC762 View Post

    However, in my defence, as I don't normally go into writing unless I really need to, the screenshot of the Teensy at 150Mhz and SPI set to 4MHz does not show 4MHz on the Logic Analyser but approx 1Mhz
    For me, T4@150mhz and SPI @4mhz, my scope still sees 4 mhz on pin 13 (nothing connected to SPI pins except scope to pin 13). As KurtE noted, T4 SPI clock is independent of MCU clock.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •