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

Thread: Teensy LC SD Card SCK mapping broken

  1. #1
    Member capricorn one's Avatar
    Join Date
    Oct 2014
    Location
    Los Angeles
    Posts
    51

    Teensy LC SD Card SCK mapping broken

    I've found a few posts that point to similar issues, but they look like they were addressed years ago and fixed.

    The problem I'm having is trying to re-assign the SCK0 pin to 14 (default is 13). I've done this in the past without any issues, calling SPI.setSCK(14) before SD.begin(CS_PIN), however on the Teensy LC, no matter what I try, I always see the LED (pin 13) blinking trying to start the SD card.

    Surprised this hasn't come up before, haven't been able to find it in the forum posts.

    Thanks in advance!
    Last edited by capricorn one; 02-12-2019 at 12:25 AM.

  2. #2
    Member capricorn one's Avatar
    Join Date
    Oct 2014
    Location
    Los Angeles
    Posts
    51
    Should include some more info I realized, I'm using the standard <SD.h> library with Teensyduino 1.45, Arduino 1.8.8.

    I've read that the <SD.h> library doesn't work with SPI1, although that may be outdated now, either way, I'm trying to use SPI0, just change SCK to pin 14. I've used this same code and hardware with a Teensy 3.2 without issue.

    If I run the CardInfo.ino example sketch, adding the line:
    Code:
    SPI.setSCK(14);         //Re-assign SPI SCK pin from default value
    Before initializing the SD card, I see the led blinking every time I restart, meaning, the SD.h library is using pin 13 (default) not 14.
    Last edited by capricorn one; 02-12-2019 at 12:27 AM.

  3. #3
    Junior Member
    Join Date
    Jan 2017
    Posts
    6
    I have the same issue. This used to work with Teensy LC using Arduino 1.6.12 and Teensyduino 1.31. Something in between seem to have broken this functionality. Now with Arduino 1.8.11 and Teensyduino 1.50 it does not work anymore. I have started to debug what could be the problem.
    Could you solve the problem?

  4. #4
    Senior Member
    Join Date
    Dec 2013
    Posts
    265
    @ rumar
    I cannot replicate the issue on my side

    Teensy LC
    Windows 10
    Arduino 1.8.10
    Teensy Loader 1.49

    Exemple code:
    Code:
    #include <SPI.h>  // include the SPI library:
    
    // set the slaveSelectPin
    const int slaveSelectPin = 10; // TEENSY LC, PIN 10 (PWM-CS0-TX2)
    // set up the speed, mode and endianness of each device
    SPISettings settingsA(2000000, MSBFIRST, SPI_MODE1);
    
    void setup() {
      // set the slaveSelectPin as an output:
      pinMode (slaveSelectPin, OUTPUT);
    
    
      // SPI.setSCK(13); // default 13
      SPI.setSCK(14);  //   re-assign to 14
    
      // initialize SPI:
      SPI.begin();
    }
    
    void loop() {
      // go through the six channels of the digital pot:
      for (int channel = 0; channel < 6; channel++) {
        // change the resistance on this channel from min to max:
        for (int level = 0; level < 255; level++) {
          digitalPotWrite(channel, level);
          delay(1);
        }
        // wait a second at the top:
        delay(10);
        // change the resistance on this channel from max to min:
        for (int level = 0; level < 255; level++) {
          digitalPotWrite(channel, 255 - level);
          delay(1);
        }
      }
    }
    
    int digitalPotWrite(int address, int value) {
    
      SPI.beginTransaction(settingsA);
      // take the SS pin low to select the chip:
      digitalWrite(slaveSelectPin, LOW);
      //  send in the address and value via SPI:
      SPI.transfer(address);
      SPI.transfer(value);
      // take the SS pin high to de-select the chip:
      digitalWrite(slaveSelectPin, HIGH);
      SPI.endTransaction();
    }

  5. #5
    Junior Member
    Join Date
    Jan 2017
    Posts
    6
    Hi Chris

    Thanks for looking into this. For me it always happened in combination with using the SD library. I will try your code on my side this evening and reply back

  6. #6
    Junior Member
    Join Date
    Jan 2017
    Posts
    6
    I have checked your Sketch on my side and it is working fine. I did not have any SPI device to test but using PIN 14 for SCK the led does not blink which indicates that the change is working. But in combination with the SD library it does not seem to work (see code below). Any idea?

    Code:
    /*
      SD card basic file example
     
     This example shows how to create and destroy an SD card file   
     The circuit:
     * SD card attached to SPI bus as follows:
     ** MOSI - pin 11, pin 7 on Teensy with audio board
     ** MISO - pin 12
     ** CLK - pin 13, pin 14 on Teensy with audio board
     ** CS - pin 4, pin 10 on Teensy with audio board
     
     created   Nov 2010
     by David A. Mellis
     modified 9 Apr 2012
     by Tom Igoe
     
     This example code is in the public domain.
       
     */
    #include <SD.h>
    #include <SPI.h>
    
    File root;
    
    // change this to match your SD shield or module;
    // Arduino Ethernet shield: pin 4
    // Adafruit SD shields and modules: pin 10
    // Sparkfun SD shield: pin 8
    // Teensy audio board: pin 10
    // Teensy 3.5 & 3.6 on-board: BUILTIN_SDCARD
    // Wiz820+SD board: pin 4
    // Teensy 2.0: pin 0
    // Teensy++ 2.0: pin 20
    const int chipSelect = 4;
    
    void setup()
    {
      //UNCOMMENT THESE TWO LINES FOR TEENSY AUDIO BOARD:
      //SPI.setMOSI(7);  // Audio shield has MOSI on pin 7
      SPI.setSCK(14);  // Audio shield has SCK on pin 14  
      
      // Open serial communications and wait for port to open:
      Serial.begin(9600);
       while (!Serial) {
        ; // wait for serial port to connect. Needed for Leonardo only
      }
    
      Serial.print("Initializing SD card...");
    
      if (!SD.begin(chipSelect)) {
        Serial.println("initialization failed!");
        return;
      }
      Serial.println("initialization done.");
    
      root = SD.open("/");
      
      printDirectory(root, 0);
      
      Serial.println("done!");
    }
    
    void loop()
    {
      // nothing happens after setup finishes.
    }
    
    void printDirectory(File dir, int numTabs) {
       while(true) {
         
         File entry =  dir.openNextFile();
         if (! entry) {
           // no more files
           //Serial.println("**nomorefiles**");
           break;
         }
         for (uint8_t i=0; i<numTabs; i++) {
           Serial.print('\t');
         }
         Serial.print(entry.name());
         if (entry.isDirectory()) {
           Serial.println("/");
           printDirectory(entry, numTabs+1);
         } else {
           // files have sizes, directories do not
           Serial.print("\t\t");
           Serial.println(entry.size(), DEC);
         }
         entry.close();
       }
    }

  7. #7
    Senior Member
    Join Date
    Dec 2013
    Posts
    265
    Any idea?
    Well if you are not afraid of editing one file in SD library I got idea.

    Edit file: Sd2Card.cpp
    Location on MS WIN10: C:\Users\-- YOU --\ --- \arduino-1.8.10\hardware\teensy\avr\libraries\SD\utility
    @ about line 253
    My changes are marked in RED

    Teensy LC hard-coded SPI CLK pin 14, untested code as I don't have SD Card connected to Teensy LC.

    Code:
    uint8_t Sd2Card::SD_init(uint8_t sckRateID, uint8_t chipSelectPin) {
      type_ = 0;
      chipSelectPin_ = chipSelectPin;
      // 16-bit init start time allows over a minute
      unsigned int t0 = millis();
      uint32_t arg;
    
      digitalWrite(chipSelectPin_, HIGH);
      pinMode(chipSelectPin_, OUTPUT);
      digitalWrite(chipSelectPin_, HIGH);
    
    #if defined(USE_TEENSY3_SPI)
      spiBegin();
      spiInit(6);
    #elif defined(USE_TEENSY4_SPI)
      spiInit(6);
      pinMode(SS_PIN, OUTPUT);
      digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin
      
    // ----- Teensy LC --- SET SCK PIN
    #elif defined(KINETISL) && defined(__MKL26Z64__) // Teensy LC
    #pragma message ( "Teensy LC hard-coded SPI CLK pin 14 ---> Sd2Card.cpp !!!!" )
      pinMode(SPI_MISO_PIN, INPUT);
      pinMode(SPI_MOSI_PIN, OUTPUT);
      // CORE_PIN13_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); // disable pin
      // CORE_PIN14_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); // enable pin
      SPI.setSCK(14);  // Set SCK pin 14
      pinMode(14, OUTPUT); // SCK pin
      settings = SPISettings(250000, MSBFIRST, SPI_MODE0);
      SPI.begin();
    // ^^^^^  Teensy LC ^^^ SCK pin SET
    
    #else
      // set pin modes
      pinMode(SPI_MISO_PIN, INPUT);
      pinMode(SPI_MOSI_PIN, OUTPUT);
      pinMode(SPI_SCK_PIN, OUTPUT);
      
      // SS must be in output mode even it is not chip select
      pinMode(SS_PIN, OUTPUT);
      digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin
      // Enable SPI, Master, clock rate f_osc/128
      SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
      // clear double speed
      SPSR &= ~(1 << SPI2X);
    #ifdef SPI_HAS_TRANSACTION
      settings = SPISettings(250000, MSBFIRST, SPI_MODE0);
    #endif
    #endif  // not USE_TEENSY3_SPI
      // must supply min of 74 clock cycles with CS high.
    #ifdef SPI_HAS_TRANSACTION
      SPI.beginTransaction(settings);
    #endif
      for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
    #ifdef SPI_HAS_TRANSACTION
      SPI.endTransaction();
    #endif
      chipSelectLow();
      // command to go idle in SPI mode
      while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
        unsigned int d = millis() - t0;
        if (d > SD_INIT_TIMEOUT) {
          goto fail; // SD_CARD_ERROR_CMD0
        }
      }
      // check SD version
      if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
        type_ = SD_CARD_TYPE_SD1;
      } else {
        // only need last byte of r7 response
        for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
        if (status_ != 0XAA) {
          goto fail; // SD_CARD_ERROR_CMD8
        }
        type_ = SD_CARD_TYPE_SD2;
      }
      // initialize card and send host supports SDHC if SD2
      arg = (type_ == SD_CARD_TYPE_SD2) ? 0X40000000 : 0;
      while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
        // check for timeout
        unsigned int d = millis() - t0;
        if (d > SD_INIT_TIMEOUT) {
          goto fail; // SD_CARD_ERROR_ACMD41
        }
      }
      // if SD2 read OCR register to check for SDHC card
      if (type_ == SD_CARD_TYPE_SD2) {
        if (cardCommand(CMD58, 0)) {
          goto fail; // SD_CARD_ERROR_CMD58
        }
        if ((spiRec() & 0XC0) == 0XC0) type_ = SD_CARD_TYPE_SDHC;
        // discard rest of ocr - contains allowed voltage range
        for (uint8_t i = 0; i < 3; i++) spiRec();
      }
      chipSelectHigh();
      return setSckRate(sckRateID);
    
    fail:
      chipSelectHigh();
      return false;
    }

  8. #8
    Junior Member
    Join Date
    Jan 2017
    Posts
    6
    Awesome, this is working fine for me, thanks a lot.

    I was actually going through this file last night but had quite some trouble understanding it. It seems a bit odd to me that a subset of SPI library function is used but at other places there is direct access to the registers (or the teensy emulated versions).
    Would you happen to know the reason for this. Is this maybe to keep it as close as possible to the original Arduino library?
    I am tempted to change the SD library and use the SPI library directly.

  9. #9
    Senior Member
    Join Date
    Dec 2013
    Posts
    265
    Would you happen to know the reason for this. Is this maybe to keep it as close as possible to the original Arduino library?
    My best guess If it ain't broke don't fix it.
    Because Teensy LC was not define it was basically using a AVR to ARM Teensy emulation, at least that's how I see it.

  10. #10
    Junior Member
    Join Date
    Jan 2017
    Posts
    6
    Just for other people who might run into the same issue as I did. I changed the SD library to always use the SPI library. This is actually already done for some other boards so there is already support there. For me it looks like one could simplify and clean up Sd2Card.cpp a bit. Anyway I have pushed my fix to https://github.com/rutmarti/SD and issued a pull request https://github.com/PaulStoffregen/SD/pull/22. A nice side effect of the change is that it increases read performance by a factor of 2 for the Teensy LC

    Thanks again Chris for your support.

Posting Permissions

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