Reputation: 135
I'm making an audio recorder with a pi pico along with an SD card connected via SPI. Core0 gets samples from the ADC and sends them to core1 which handles SD writing. I've isolated the issue to f_write. I commented to mark the problematic section. Note that when I comment out that section the code runs as expected otherwise it freezes. The file shows up on the SD but it is empty.
This is the section of code from core1 that is causing the issue.
START_REC, STOP_REC, and QUIT are just #define's of numbers larger than the adc range (4096<)
void core1_main()
{
sleep_ms(1000); // ensures there is no conflict with core0 when working w/ LCD
bool brk = false;
uint buf_size = 32000;
uint16_t data_buffer[buf_size];
uint buf_pos = 0;
uint bytes_read = 0;
uint val = 0;
FRESULT fr;
FATFS fs;
FIL fil;
unsigned short file_num = 0;
char filename[20];
filename_gen(&filename[0], file_num);
// Init sd driver
if (!sd_init_driver())
{
clrLCD();
setString("!INIT");
posCursor(12, 1);
brk = true;
}
// mount sd
fr = f_mount(&fs, "0:", 1);
if (fr != FR_OK)
{
clrLCD();
setString("!MOUNT");
posCursor(12, 1);
brk = true;
}
// open file for writing
fr = f_open(&fil, filename, FA_WRITE | FA_CREATE_ALWAYS);
if (fr != FR_OK)
{
clrLCD();
setString("!F OPEN");
posCursor(12, 1);
brk = true;
}
if (!brk)
{
setString("Ready.");
}
bool rec = false;
while (!brk)
{
val = multicore_fifo_pop_blocking();
switch (val)
{
case QUIT:
brk = true;
break;
case START_REC:
if (!rec)
{
rec = true;
}
break;
case STOP_REC:
if (rec)
{
rec = false;
}
break;
default:
if (val < 4096)
{
data_buffer[buf_pos] = val;
buf_pos++;
}
if (buf_pos > buf_size - 1)
{
// problematic section
fr = f_write(&fil, data_buffer, buf_size*2, &bytes_read);
if (fr != FR_OK)
{
clrLCD();
setString("!F WRITE");
posCursor(12, 1);
rec = false;
}
f_sync(&fil); // flush sync. Prevents data loss if program fails before f_close
// end of problematic section
buf_pos = 0;
}
break;
}
}
f_close(&fil);
// unmount drive
f_unmount("0:");
}
Another thing to note is that fr seemingly returns FR_OK or crashes beforehand because the LCD does not display "!F WRITE".
Upvotes: 0
Views: 142
Reputation: 135
The solution was to pass in the pointer to the data buffer in f_write() and lower the buffer size to 512 or 1024.
void core1_main()
{
sleep_ms(1000);
bool brk = false;
uint buf_size = 512;
uint16_t data_buffer[buf_size];
uint buf_pos = 0;
uint bytes_read = 0;
uint val = 0;
FRESULT fr;
FATFS fs;
FIL fil;
unsigned short file_num = 0;
char filename[20];
filename_gen(&filename[0], file_num);
// Init sd driver
if (!sd_init_driver())
{
clrLCD();
setString("!INIT");
posCursor(12, 1);
brk = true;
}
// mount sd
fr = f_mount(&fs, "0:", 1);
if (fr != FR_OK)
{
clrLCD();
setString("!MOUNT");
posCursor(12, 1);
brk = true;
}
// open file for writing
//file_num++;
//filename_gen(&filename[0], file_num);
fr = f_open(&fil, filename, FA_WRITE | FA_CREATE_ALWAYS);
if (fr != FR_OK)
{
clrLCD();
setString("!F OPEN");
posCursor(12, 1);
brk = true;
}
if (!brk)
{
setString("Ready.");
}
bool rec = false;
while (!brk)
{
val = multicore_fifo_pop_blocking();
switch (val)
{
case QUIT:
brk = true;
break;
case START_REC:
if (!rec)
{
rec = true; // rec value is a bit redundant but will be useful later
}
break;
case STOP_REC:
if (rec)
{
rec = false;
}
break;
default:
if (val < 4096)
{
data_buffer[buf_pos] = val;
buf_pos++;
}
if (buf_pos >= buf_size)
{
if (rec)
{
fr = f_write(&fil, &data_buffer, buf_size*2, &bytes_read);
if (fr != FR_OK)
{
getFSerr(fr);
rec = false;
}
f_sync(&fil); // flush sync. Prevents data loss if program fails before f_close
}
buf_pos = 0;
}
break;
}
}
f_close(&fil);
// unmount drive
f_unmount("0:");
}
Upvotes: 1