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

Thread: SD.flush() does not return

  1. #1

    SD.flush() does not return

    Hello!
    I have written a program that takes audio samples from the Audio shield and writes them onto the build-in SD card on a Teensy 4.1.
    Everything runs perfect if the executing instance is "loop()". If I let the recording&writing function to be executed by a thread ("TeensyThreads.h") I run more or less often into a situation where the SD card "flush()" does not return.
    I debugged it down to
    while (!(SDHC_IRQSTAT & SDHC_IRQSTAT_TC)) { } // wait for transfer to complete
    from file "NXP_SDHC.cpp" which runs endlessly. Obviously waiting for the transfer complete flag which stays unset.
    Is this a known issue? Does anybody made a similar experience?
    Does it really have to do with threads or is this just a coincidence? (I tested it for more than 100.000 times...)

    Uwe

  2. #2
    Maybe someone wants to reproduce it?
    Code:
    #include <Audio.h>
    #include <SD.h>
    #include <TeensyThreads.h>
    
    // GUItool: begin automatically generated code
    AudioInputI2S            i2s2;           //xy=105,63
    AudioAnalyzePeak         peak1;          //xy=278,108
    AudioRecordQueue         queue1;         //xy=281,63
    AudioPlaySdRaw           playRaw1;       //xy=302,157
    AudioOutputI2S           i2s1;           //xy=470,120
    AudioConnection          patchCord1(i2s2, 0, queue1, 0);
    AudioConnection          patchCord2(i2s2, 0, peak1, 0);
    AudioConnection          patchCord3(playRaw1, 0, i2s1, 0);
    AudioConnection          patchCord4(playRaw1, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=265,212
    
    // The file where data is recorded
    File frec;
    
    void setup() {
      Serial.begin(9600);
      while (!Serial) ;
      
      // Audio connections require memory, and the record queue
      // uses this memory to buffer incoming audio.
      AudioMemory(60);
    
      // Enable the audio shield, select input, and enable output
      sgtl5000_1.enable();
      sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN);
      sgtl5000_1.volume(0.5);
    
      if (!(SD.begin(BUILTIN_SDCARD))) {
        // stop here if no SD card, but print a message
        while (1) {
          Serial.println("Unable to access the SD card");
          delay(500);
        }
      }
    }
    
    int recCounter = 0;
    int recRunning = 0;
    void doRec(){
      startRecording();
      while(recCounter < 20){
        continueRecording();
      }
      stopRecording();
      recRunning = 0;
    }
    
    
    void loop() {
      recRunning = 1;
      //doRec(); // use this for main loop only 
      threads.addThread(doRec); // use this for thread operation
      do{
        delay(1);
      }while(recRunning);
    }
    
    
    int loopCounter = 0;
    void startRecording() {
      Serial.print("startRecording:");
      Serial.println(loopCounter);
      if (SD.exists("RECORD.RAW")) {
        // The SD library writes new data to the end of the
        // file, so to start a new recording, the old file
        // must be deleted before new data is written.
        SD.remove("RECORD.RAW");
      }
      frec = SD.open("RECORD.RAW", FILE_WRITE);
      if (frec) {
        queue1.begin();
        loopCounter++;
      }
    }
    
    byte buffer[512];
    void continueRecording() {
      if (queue1.available() >= 2) {
        memcpy(buffer, queue1.readBuffer(), 256);
        queue1.freeBuffer();
        memcpy(buffer+256, queue1.readBuffer(), 256);
        queue1.freeBuffer();
        // write all 512 bytes to the SD card
    //    elapsedMicros usec = 0;
        frec.write(buffer, 512);
    //    if (usec > 17000){
    //      Serial.print("SD write, us=");
    //      Serial.println(usec);
    //    }
        recCounter++;
      }
    }
    
    void stopRecording() {
      Serial.println("stopRecording");
      queue1.end();
      while (queue1.available() > 0) {
        frec.write((byte*)queue1.readBuffer(), 256);
        queue1.freeBuffer();
      }
      frec.close();
      recCounter = 0;
    }
    This code is taken from Paul Stoffregens sample code for a simple play/recording. I deleted some functions (e.g. "play") that are not needed.
    In the main loop you have two possibilities to start the recoding:
    a) doRec();
    which does the recording controlled by the main loop
    or:
    b) threads.addThread(doRec);
    which uses Threads for it.
    In both cases the same code is being executed. In case a) it is working, case b) freezes after some time. Could be some hundred, maybe some thousand runs.

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    25,490
    2 questions

    Can you reproduce the problem without TeensyThreads? These libraries usually aren't thread safe.

    Which version of Teensyduino are you using? This matters because the old SD library was replaced by a thing wrapper for SdFat starting with version 1.54.

  4. #4
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    497
    What's a "thing wrapper"?

  5. #5
    No, I can't. If I run the code from "loop" the error does not occur.

    I'm using version 1.8.13 (I took this from the install path ".../arduino-1.8.13/...". Is this the version you asked for?

  6. #6
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    497
    No, Paul asked "Which version of Teensyduino are you using?"

  7. #7
    Where is this version number?

  8. #8
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    497
    Quote Originally Posted by Uwe View Post
    Where is this version number?
    Name:  TeensyDuino Prog about screen.png
Views: 55
Size:  45.4 KB
    Click "Help" then "about" to find version number.

  9. #9
    I looked into the version number of the Teensy loader and it displays 1.53. That is the right number, isn't it?
    I decided to update to 1.55 then.
    Now I have another problem: My thread version does not work at all anymore. The second time it wants to execute "queue1.available()" in procedure "continueRecording()" it does not return from there.

  10. #10
    Overlapped. I found it by myself. Thank you!

  11. #11
    I supposed that version 1.55 needs more thread stack so I set the stack size to 30k.
    Code:
      threads.addThread(doRec, 30000);
    but that also does not help.
    Further investigating makes me believe that "queue1.available()" freezes (does not return) when the first audio data becomes available.
    Could anybody reproduce that?

    Again: This freezing of "queue1.available()" does not happen in Teensyduino version 1.53 but (only?) in version 1.55!

  12. #12
    I was able to get the code to run also under 1.55. I had to remove the SD operations from "startRecording()":
    Code:
      if (SD.exists("RECORD.RAW")) {
        // The SD library writes new data to the end of the
        // file, so to start a new recording, the old file
        // must be deleted before new data is written.
        SD.remove("RECORD.RAW");
      }
      frec = SD.open("RECORD.RAW", FILE_WRITE);
    If I move this to "loop()" the freezing of the audio unit does not happen anymore. This looks to be a problem in the combination of Audio+SD+Teensythreads in version 1.55.
    If somebody could tell me where to get version 1.54 I could try to find out if this also happens in 1.54.

    Now I can start to investigate if my essential problem (SD.flush() freezing) also happens in 1.55.
    Last edited by Uwe; 12-06-2021 at 11:15 AM.

  13. #13
    Junior Member
    Join Date
    Dec 2021
    Location
    South Coast, UK
    Posts
    7
    I wonder if that is somewhat related to the issue I have here:

    https://forum.pjrc.com/threads/68868...-LVGL-use-SDIO

    Where I cannot access a file outside of the Teensy Audio library whilst a WAV is running, but can easily play multiple WAVs at the same time, or show multiple images and GIFs when a WAV is not running.

    I've stripped out LVGL and have a posted a simple code that shows where a small TXT file access crashes T4.1 for me when playing a WAV file via Audio.

  14. #14
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,990
    Quote Originally Posted by Uwe View Post
    I was able to get the code to run also under 1.55. I had to remove the SD operations from "startRecording()":
    Code:
      if (SD.exists("RECORD.RAW")) {
        // The SD library writes new data to the end of the
        // file, so to start a new recording, the old file
        // must be deleted before new data is written.
        SD.remove("RECORD.RAW");
      }
      frec = SD.open("RECORD.RAW", FILE_WRITE);
    If I move this to "loop()" the freezing of the audio unit does not happen anymore. This looks to be a problem in the combination of Audio+SD+Teensythreads in version 1.55.
    If somebody could tell me where to get version 1.54 I could try to find out if this also happens in 1.54.

    Now I can start to investigate if my essential problem (SD.flush() freezing) also happens in 1.55.
    If you wish for it to open at the start of the file, you can do it like you did.

    Alternatively you could: frec = SD.open("RECORD.RAW", FILE_WRITE_BEGIN);
    This will open an existing file and not position to the end...

    There is also an example in the SD Library which shows you how you can use other options for open from the underlying SDFat library if needed.

    Not sure about flush. Sounds like there is probably some place that is not thread safe...

    But also not really sure what you are running as your first post mentions:
    while (!(SDHC_IRQSTAT & SDHC_IRQSTAT_TC)) { } // wait for transfer to complete
    from file "NXP_SDHC.cpp" which runs endlessly. Obviously waiting for the transfer complete flag which stays unset.
    And I know that file is not part of Teensyduino, and I don't see the line you mention anywhere in the code.

  15. #15
    Quote Originally Posted by KurtE View Post
    And I know that file is not part of Teensyduino, and I don't see the line you mention anywhere in the code.
    And I can't find this file in my 1.55 installation! I really don't know where it came from in my 1.53 installation???
    But that was the file where the SD file functions ended in.(the file path was "../hardware/teensy/avr/libraries/SD/utility/"

    The problem with the file function SD.open(...)is not the parameters (nevertheless thank you for pointing out).
    The problem is if I call SD.open (regardless of the parameters) in a thread instead of the main "loop" than my whole program freezes when audio data become available.
    The last observation I made was that the system function "delay" does not return. For me it looks like that the OS task switcher has a problem.

  16. #16
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,990
    Sounds like old or random stuff...

    That is if you look at the current SD library: https://github.com/PaulStoffregen/Sd
    There is no utility directory...

    That is from the earlier version of stuff before the newer stuff with 1.55 which uses SDFat. (Current default branch: Juse_Use_SdFat) not master.

Posting Permissions

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