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

Thread: Fastest way to send 6 bytes over SPI on Teensy 3.2

  1. #1

    Fastest way to send 6 bytes over SPI on Teensy 3.2

    What's the fastest way to send 6 bytes over SPI? I see DmaSpi, SPIFIFO, and some other libs.

    I am using a Teensy 3.2. My application is transmit only, always 6 bytes, and no other devices/libs will be using SPI. No chip selects needed. No completion callback needed. Transmissions are on a fixed timer, so the tx fifo is guaranteed to be empty. I do need to use the alternate SCK pin, though.

    I want to do this inside a 5us interval timer, if possible.

  2. #2
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,281
    Hi,
    use transfer(void *buf, size_t count) - that's the fastest.

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,091
    SPIFIFO isn't really recommended anymore, but I decided to give it a quick try just to see how much of the CPU time on a Teensy 3.2 would remain unused if an IntervalTimer uses it every 5 microseconds.

    Here's the code I tried. Hopefully this is pretty obvious. It toggles a pin in loop(), so we can see how much of the time is spent in the main loop versus the IntervalTimer interrupt.

    Code:
    #include <SPIFIFO.h>
    
    IntervalTimer mytimer;
    
    void setup() {
      SPIFIFO.begin(10, SPI_CLOCK_24MHz);
      mytimer.begin(transmit, 5);
      pinMode(2, OUTPUT);
    }
    
    void transmit() {
      SPIFIFO.clear();
      SPIFIFO.write16(0x5AA5);
      SPIFIFO.write16(0x5AA5);
      SPIFIFO.write16(0x5AA5);
    }
    void loop() {
      while (1) {
        digitalToggleFast(2);
      }
    }
    And here's the result my oscilloscope sees. Better than I thought it would be.

    Click image for larger version. 

Name:	file.png 
Views:	29 
Size:	47.4 KB 
ID:	24446

  4. #4
    Thanks so much, Frank and Paul. ~50% cpu will be great!

  5. #5
    Quote Originally Posted by PaulStoffregen View Post
    Click image for larger version. 

Name:	file.png 
Views:	29 
Size:	47.4 KB 
ID:	24446
    Hi Paul. The bottom trace looks like 64 clocks @ 16 MHz, is that right?

    What cpu speed did you use for the test? I've heard the 3.2 is pretty stable at 96 MHz and 24 MHz SPI would be great (slave Fmax=25 MHz). My application is mounted open-air in an office/lab environment. That should be perfectly stable at 96, yeah?

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,091
    Quote Originally Posted by ryanrs View Post
    Hi Paul. The bottom trace looks like 64 clocks @ 16 MHz, is that right?
    The bottom (green) trace isn't SPI at all. It's from this:

    Code:
    void loop() {
      while (1) {
        digitalToggleFast(2);
      }
    }
    The idea is to gauge how much of the CPU time is spent inside the interrupt versus the main program.

  7. #7
    Oh wow, that's even better! I thought you were probing SCK, not MOSI. So it's more like 20% CPU usage in the interrupt.

  8. #8
    What do I need to change in SPIFIFO.h to use Teensy 3.2 alternate SCK on pin 14? I tried looking through SPI.cpp, but I'm having trouble understanding how the pin mux(?) is setup.

    I'm just looking to hardcode SCK to the alternate pin 14, not add arbitrary setSCK() functionality.

  9. #9
    Answering my own question:

    Code:
        // We don't care about CS, so set it to unused pin 24 (bottom side smd pad)
        SPIFIFO.begin(24, SPI_CLOCK_24MHz);
    
        // assign SCK to alternate pin 14
        CORE_PIN14_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
    
        // restore pin 13 digital functionality
        pinMode(PIN_LED, OUTPUT);
    Incidentally, assigning SCK to pin 14 is why I'm using a Teensy 3.2 for this project instead of a Teensy 4.0. This is for a light controller, and the T4.0 can't do SPI without glowing in the dark!

  10. #10
    And the transmit code:

    Code:
    const uint16_t* p = framebuffer.phases[y][ph].data.shorts;
    KINETISK_SPI0.PUSHR = p[0] | SPI_PUSHR_CTAS(1);
    KINETISK_SPI0.PUSHR = p[1] | SPI_PUSHR_CTAS(1);
    KINETISK_SPI0.PUSHR = p[2] | SPI_PUSHR_CTAS(1);
    I do not check the fifo status because I know it is empty when I start. This code runs so fast that I can increase my interrupt rate from 5us to 2.5us.

  11. #11
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,091
    Quote Originally Posted by ryanrs View Post
    Incidentally, assigning SCK to pin 14 is why I'm using a Teensy 3.2 for this project instead of a Teensy 4.0.
    With Teensy 4.0 / 4.1 you could do this using SPI1 on pins 26 & 27.

    But with Teensy 4.0 those pins are on the bottom side pads which aren't as convenient as the outside edge pins. The SPI hardware registers are very different on Teensy 4 also, so completely different code would be needed. On the plus side, the SPI FIFO on Teensy 4 is larger and supports 32 bit words.

    Whether transmitting 200,000 or 400,000 times per second for lighting controller is worthwhile is of course a completely different question. If you're sending to addressable LEDs, they internally use PWM at a much slower rate, and the rate at which humans can perceive changes in light is much slower still.

  12. #12
    They're just plain old red LEDs in a 25x11 matrix. I use 2x 595s + mosfets as row drivers, and 2x CAT4016 current sinks to drive the columns.

    1.0 / (5us * 255 brightness levels * 11 rows) = 71.3 Hz

    71 Hz looks pretty smooth, but you can see a bit of strobing/flicker in your peripheral vision for certain patterns. Speeding it up a bit should take care of it. There's also a huge speedup to be had by splitting up the longer duration pulses to reduce that 255 factor, but I haven't done that yet.

  13. #13
    My main complaint right now is that the first prototype worked so well that it was put into use 2 days after I built it. So now I'm waiting on a digikey order so I can make another one and continue firmware development.

    Teensy has been an amazing tool for the R&D work I do at my company. It makes board bringup so much faster and more predictable.

Posting Permissions

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