stm32duino / STM32SD

Enables reading and writing on SD card using SD card slot of the STM32 Board.
157 stars 23 forks source link

SD card write errors with hardware timer #45

Closed Bambofy closed 3 years ago

Bambofy commented 3 years ago

The program must write to the SD card 30000 bytes at a time, while the hardware timer collects samples at 16,000Hz. The problem is that the SD card write function returns an error when writing.

Here's is the code:

#include "PeripheralPins.h"
#include "Sysclock_Config.h"

#include <STM32SD.h>
#include <HardwareTimer.h>

#include "stm32l4xx_hal.h"
#include "stm32l4xx_hal_sd.h"

#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line) 
{
    /* Infinite loop /
    / Use GDB to find out why we're here */
    while (1);
}
#endif

void _Error_Handler(const char* filename, int line)
{
    Serial2.println(F("*** [ERROR HANDLED] ***"));
    Serial2.printf("%s\r\n", filename);
    Serial2.printf("%i\r\n", line);
}

uint32_t SD_CMD = PD2;
uint32_t SD_CLK = PC12;
uint32_t SD_D3 = PC11;
uint32_t SD_D2 = PC10;
uint32_t SD_D1 = PC9;
uint32_t SD_D0 = PC8;

uint32_t SD1 = PA15;

uint32_t DEBUG_RX = PA3;
uint32_t DEBUG_TX = PA2;

Sd2Card card;
SdFatFs fatFs; 
File testFile;

uint8_t dataStack[30000] = { 0 };
int dataStackTop = 0;

HardwareTimer timer(TIM2);

void setup() 
{
    Serial2.begin(115200);  // print starting notification
    Serial2.println("Started");

    pinMode(SD1, OUTPUT); // turn the sd card on
    digitalWrite(SD1, HIGH);

    delay(5000); // wait for the debugger

    Serial2.print("Initializing SD card...");

    if (!SD.begin()) // start the Sd card library
    {
        Serial2.println("initialization failed!");

        while (1) {};
    }

    testFile = SD.open("T.TXT", FILE_WRITE); // create a new file called T.txt

    timer.setMode(1, TIMER_OUTPUT_COMPARE, NC); // setup a 16,000Hz timer to simulate sampling an ADC
    timer.setOverflow(16000, HERTZ_FORMAT);
    timer.detachInterrupt();
    timer.attachInterrupt(timerCallback);
    timer.resume();
}

void timerCallback()
{
    dataStack[dataStackTop] = 1; // push 3 bytes to the stack.
    dataStackTop++;
    dataStack[dataStackTop] = 1;
    dataStackTop++;
    dataStack[dataStackTop] = 1;
    dataStackTop++;

    if (dataStackTop == 30000) // stack is full reset the top to overwrite.
    {
        dataStackTop = 0;
    }
}

void loop()
{
    size_t bytes_wrote;

    bytes_wrote = testFile.write(dataStack, 30000); // empty the data stack to the sd card.

    if (bytes_wrote == 0) // if the write command failed to write any data then print an error message.
    {
        Serial2.println("Error writing to the SD card.");
        Serial2.flush();
        while (1) {}
    }
}

Notes: I have found that changing the SD write size to 512 bytes resolves the error. And also if i remove the hardware timer then the error is resolved and the write() can write more than 512 bytes. Perhaps the interrupt is breaking the SD card if it is raised while a write is being performed?

fpistm commented 3 years ago

Hi @Bambofy

your issue is not properly filled (boards, core version, library exact error,....).
Debugging user program is not an library issue. You can use the forum to eventually have some help. Writing 30k in a SD and being interrupt several times per ms seems really not a good idea... I guess FatFs or SDMMC have some timeouts and you probably reach them... as you said changing the write solves your issue.