cancel
Showing results for 
Search instead for 
Did you mean: 

SDMMC breaks when interrupted during writing?

RBamf.1
Associate III

Hi,

I'm trying to sample data inside an ISR, write it to a buffer, and then write the data in the buffer to an SD card. The SD interface uses the SDMMC devices.

It seems that when the ISR interrupts the SDMMC performing a write, the SDMMC errors and returns a FR_DISK_ERR.

Does anyone know what to do about this? Thanks!

#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) {}
    }
}

3 REPLIES 3
TDK
Guru

Disable interrupts while performing an eMMC operation. You could also use DMA operations to mitigate.

If you feel a post has answered your question, please click "Accept as Solution".
RBamf.1
Associate III

But if i disable interrupts then i think i will miss samples. How would DMA mitigate this?

The SD Cards have zero tolerance for you wandering off task mid-transfer. There is a FIFO, but the card expects a specific number of clocks, and a specific number of bytes.

Stop using Polled mode and use DMA, the DMA will transfer the whole data blocks without distraction.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..