Hi,
we are using the nRF52 DK (nRF52832) to read data from the i2s bus and store it as a wave-file on the connected SD-Card. When pressing button 1 on the DK, recording starts. When button 1 is pressed again, recording stops and the file should be closed. However, before we can close the file, we need to update the wave-header with the actual size of the file. For doing this, we use f_lseek to move the read/write pointer to the correct location. However during this operation something fails and the programm does not continue. I.e. it keeps running or is "waiting" for something.
As far as I could debug the problem the read/write pointer is changed correctly. The problem occurs at this line (nr. 4071)
if (disk_read(fs->drv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
in ff.c. the disk_read function is defined in diskio_blkdev.c (line 188). The program stops at this point (line 8 in the code embedded here):
m_drives[drv].busy = true; ret_code_t err_code = nrf_blk_dev_read_req(m_drives[drv].config.p_block_device, &req); if (err_code == NRF_SUCCESS) { while (m_drives[drv].busy) { m_drives[drv].config.wait_func(); } if (m_drives[drv].last_result == NRF_BLOCK_DEV_RESULT_SUCCESS) { return RES_OK; } } return RES_ERROR;
It seems that there is a disk I/O operation going on and not finishing, which causes the program to repeatedly call the wait function.
Since this function itself is called multiple times before we start recording (e.g. to list the content of the SD-card), I assume that our error is how we are handling the file or how we are writing to it. Therefore, I add the main functions of our program below:
// global variables static FIL file; uint32_t bytes_written; FRESULT ff_result; int main(void) { uint32_t err_code = NRF_SUCCESS; uint8_t sample_data; uint8_t response; bool detected_device = false; static struct tm time_keep; static struct tm time_fetched; uint8_t write_data[10] = {0x58}; // Data array to be written to the RTC slave // First register address in RTC slave to write to/read from uint8_t read_data[10]; // Data array to be read from the RTC slave APP_ERROR_CHECK(NRF_LOG_INIT(NULL)); NRF_LOG_DEFAULT_BACKENDS_INIT(); fatfs_init(); write_PCM_header(&file, FrameCount); twi_configuration(); gpio_init(); // Fs = 44.5kHz if 32DIV15 // Fs = 31.75 if 32DIV21 // Fs = 15.87KHz if 32DIV42 nrf_drv_i2s_config_t config = NRF_DRV_I2S_DEFAULT_CONFIG; config.sdin_pin = I2S_SDIN_PIN; config.sdout_pin = NRFX_I2S_PIN_NOT_USED; config.mck_pin = NRFX_I2S_PIN_NOT_USED; config.mck_setup = NRF_I2S_MCK_32MDIV15; config.ratio = NRF_I2S_RATIO_48X; config.format = NRF_I2S_FORMAT_I2S; config.sample_width = NRF_I2S_SWIDTH_24BIT; config.channels = NRF_I2S_CHANNELS_LEFT; err_code = nrf_drv_i2s_init(&config, i2s_data_handler); APP_ERROR_CHECK(err_code); for (;;) { mode = 0x00; // standby/stop mode m_blocks_transferred = 0; // counter to keep no of blocks transfer mp_block_to_check = NULL; // Wait for an event. __WFE(); // Clear the event register. __SEV(); __WFE(); while (mode == 0x01) { if (init_file) { init_file = 0; } if (mp_block_to_check) { check_rx_data(mp_block_to_check); mp_block_to_check = NULL; } if (mode != 0x01) { break; } } } } static void fatfs_init() { static FATFS fs; static DIR dir; static FILINFO fno; DSTATUS disk_state = STA_NOINIT; // Initialize FATFS disk I/O interface by providing the block device. static diskio_blkdev_t drives[] = { DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)}; diskio_blockdev_register(drives, ARRAY_SIZE(drives)); printf("Initializing disk 0 (SDC)..."); for (uint32_t retries = 3; retries && disk_state; --retries) { disk_state = disk_initialize(0); } if (disk_state) { printf("Disk initialization failed with disk state: %d", disk_state); return; } uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size; uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb; printf("Capacity: %d MB", capacity); printf("Mounting volume..."); ff_result = f_mount(&fs, "", 1); if (ff_result) { printf("Mount failed."); return; } } // handling the button input void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { nrf_drv_gpiote_out_toggle(PIN_OUT); if (mode == 0x00) { nrf_drv_i2s_buffers_t const initial_buffers = { .p_tx_buffer = NULL, .p_rx_buffer = m_buffer_rx[0], }; ret_code_t err_code = nrf_drv_i2s_start(&initial_buffers, I2S_DATA_BLOCK_WORDS, 0); APP_ERROR_CHECK(err_code); mode = 0x01; // Recording mode } else if (mode == 0x01) { mode = 0x00; // Stop recording nrf_drv_i2s_stop(); bsp_board_leds_off(); // nrf_delay_ms(PAUSE_TIME); printf("closing file \n"); //Closing the file after re-writing RIFF with total file size close_file(); } } static void check_rx_data(uint32_t const *p_block) { ++m_blocks_transferred; if (!m_error_encountered) { m_error_encountered = !check_samples(p_block); } if (m_error_encountered) { bsp_board_led_off(LED_OK); bsp_board_led_invert(LED_ERROR); } else { bsp_board_led_off(LED_ERROR); bsp_board_led_invert(LED_OK); } } static bool check_samples(uint32_t const *p_block) { //each data word contains one 24-bit samples uint16_t i; uint8_t decomp_sample[DATA_BLOCK_WORDS_IN_BYTES]; uint8_t const *p_decomp = &decomp_sample[0]; printf("Checking samples \n"); for (i = 0; i < I2S_DATA_BLOCK_WORDS; ++i) { uint32_t const *p_word = &p_block[i]; //Decompose 32 bit data to 8 bit data and store only 24 bit data discarding the msb 8bits. decomp_sample[3 * i + 0] = ((uint8_t *)p_word)[0]; decomp_sample[3 * i + 1] = ((uint8_t *)p_word)[1]; decomp_sample[3 * i + 2] = ((uint8_t *)p_word)[2]; } //Writing the decomposed block to the file. write_the_block(p_decomp); return true; } static bool write_the_block(uint8_t const *p_decomp) { ff_result = f_write(&file, p_decomp, DATA_BLOCK_WORDS_IN_BYTES, (UINT *)&bytes_written); if (ff_result != FR_OK) { return false; } else { //NRF_LOG_INFO("%d bytes written.", bytes_written); printf("%d bytes written. \n", bytes_written); printf("Total file size = %d \n", f_size(&file)); return true; } } void close_file(void) { uint32_t total_size = f_size(&file); uint32_t chunky; chunky = (total_size - 8); ff_result = f_lseek(&file, 4); if (ff_result != FR_OK) { printf("Seek failed"); } ff_result = f_write(&file, &chunky, sizeof(chunky), (UINT *)&bytes_written); if (ff_result != FR_OK) { printf("Write failed"); } chunky = total_size; ff_result = f_lseek(&file, 40); if (ff_result != FR_OK) { printf("Seek failed"); } ff_result = f_write(&file, &chunky, sizeof(chunky), (UINT *)&bytes_written); if (ff_result != FR_OK) { printf("Write failed"); } (void)f_close(&file); }
The problem occurs when the f_lseek in line 194 (of the embedded code above) is called.
I'm using nRF5 SDK 17.1.0 and Segger Embedded Studio.
I will be happy to provide more information, I tried to not overload this post.
Any help or hints are highly appreciated!