我正在制作一个带有 pi pico 的录音机以及通过 SPI 连接的 SD 卡。 Core0 从 ADC 获取样本并将其发送到处理 SD 写入的 core1。 我已将问题隔离到 f_write。我评论标记了有问题的部分。 请注意,当我注释掉该部分时,代码将按预期运行,否则它将冻结。该文件显示在 SD 上,但它是空的。
这是 core1 中导致问题的代码部分。
START_REC、STOP_REC 和 QUIT 只是大于 adc 范围(4096<)
)的数字的#definevoid 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:");
}
还有一点需要注意的是,fr 似乎会返回 FR_OK 或者提前崩溃,因为 LCD 不显示“!F WRITE”。
解决方案是在 f_write() 中传入指向数据缓冲区的指针,并将缓冲区大小降低到 512 或 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:");
}