2021-05-27 06:27 AM
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) {}
}
}
2021-05-27 07:11 AM
Disable interrupts while performing an eMMC operation. You could also use DMA operations to mitigate.
2021-05-27 07:13 AM
But if i disable interrupts then i think i will miss samples. How would DMA mitigate this?
2021-05-27 07:19 AM
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.