为什么 f_write 会导致程序在 pi pico 上冻结?

问题描述 投票:0回答:1

我正在制作一个带有 pi pico 的录音机以及通过 SPI 连接的 SD 卡。 Core0 从 ADC 获取样本并将其发送到处理 SD 写入的 core1。 我已将问题隔离到 f_write。我评论标记了有问题的部分。 请注意,当我注释掉该部分时,代码将按预期运行,否则它将冻结。该文件显示在 SD 上,但它是空的。

这是 core1 中导致问题的代码部分。

START_REC、STOP_REC 和 QUIT 只是大于 adc 范围(4096<)

)的数字的#define
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:");
}

还有一点需要注意的是,fr 似乎会返回 FR_OK 或者提前崩溃,因为 LCD 不显示“!F WRITE”。

c sdk raspberry-pi-pico fatfs
1个回答
0
投票

解决方案是在 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:");
}
© www.soinside.com 2019 - 2024. All rights reserved.