This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Problem about fatfs and QSPI on nRF52840

static bool fatfs_init(void)
{
	FRESULT ff_result;
	bool    init_result = true;
	DSTATUS disk_state = STA_NOINIT;
	bool flag = false;

	memset(&m_filesystem, 0, sizeof(FATFS));

	// Initialize FATFS disk I/O interface by providing the block device.
	static diskio_blkdev_t drives[] =
	{
#if USE_SD_CARD
		DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)
#else
			DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_qspi, block_dev), NULL)
#endif
	};

	diskio_blockdev_register(drives, ARRAY_SIZE(drives));

	NRF_LOG_INFO("Initializing disk 0 (QSPI)...");

	disk_state = disk_initialize(0);
	if (disk_state)
	{
		NRF_LOG_ERROR("Disk initialization failed.");
		return false;
	}

	NRF_LOG_INFO("Mounting volume...");
	ff_result = f_mount(&m_filesystem, "", 1);
	if (ff_result != FR_OK)
	{
		if (ff_result == FR_NO_FILESYSTEM)
		{
			NRF_LOG_ERROR("Mount failed. Filesystem not found. Please format device.");

		}
		else
		{
			NRF_LOG_ERROR("Mount failed: %u", ff_result);
        
		}

		ff_result = fatfs_mkfs();
		if (ff_result != FR_OK)
		{

			init_result = false;
		}
		else
		{
#ifdef RECORD_ERR
			m_log_buf_len =   sprintf((char *)m_log_buf, "f_mount failed,then fatfs_mkfs sucessfully, fatfs_mkfs result %d\r\n", ff_result);
			record_stat_data(0);
#endif			
			flag = true;

		}
	}
	else
	{
		flag = true;
#ifdef RECORD_ERR
		m_log_buf_len =   sprintf((char *)m_log_buf, "Initializing disk 0 (QSPI) completed,ff_result %d\r\n",ff_result);
		record_stat_data(1);
#endif
	}

	return init_result;
}

Hi, I was using nRF52840 , flash is mx25L25645GM2, I used fatfs with QSPI ,but I found fatfs was unstable,After some time, the stored file would dispear.Sometime there were scrambling symbols in my files

Parents Reply Children
  • sdk :nRF5_SDK_15.2.0_9412b96  

    revision of the nRF52840 : cortex-m4 nrf52840_xxAA 1024KB+4KB 256KB  PCA10056

  • Hi,

    Could you share your definition of the block_dev? And the functions where you open read/write and close the files.

    Regards

    Jared 

  • /**
     * @brief  QSPI block device definition
     */
    NRF_BLOCK_DEV_QSPI_DEFINE(
        m_block_dev_qspi,
        NRF_BLOCK_DEV_QSPI_CONFIG(
            512,
            NRF_BLOCK_DEV_QSPI_FLAG_CACHE_WRITEBACK,
            NRF_DRV_QSPI_DEFAULT_CONFIG
         ),
         NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "QSPI", "1.00")
    );
    static uint32_t file_open(const char*filename)
    {
        static FIL file;
        FRESULT ff_result;
    
        NRF_LOG_INFO("Opening file: %s.", NRF_LOG_PUSH(filename));
        if(get_record_disabled()){
            return NRF_ERROR_BUSY;
        }
        ff_result = f_open(&file, filename, FA_READ | FA_WRITE | FA_OPEN_APPEND);
        if (ff_result != FR_OK)
        {
           NRF_LOG_INFO("Unable to open or create file: %d", ff_result);
           return NRF_ERROR_BUSY;
        }
        m_opened_file = &file;
        return NRF_SUCCESS;
    }
    static uint32_t file_write(const uint8_t *buf, uint32_t len)
    {
        uint32_t written = 0;
        FRESULT ff_result;
        if(m_opened_file == NULL){
            NRF_LOG_ERROR("Sorry, open file first");
            return NRF_ERROR_BUSY;
        }
        NRF_LOG_HEXDUMP_DEBUG(buf, len);
        if(get_record_disabled()){
            return NRF_ERROR_BUSY;
        }
    	f_lseek(m_opened_file,f_size(m_opened_file));
        ff_result = f_write(m_opened_file, buf, len, (UINT *) &written);
        if (ff_result != FR_OK || written != len)
        {
            NRF_LOG_ERROR("Failed to write, ff_result: %d, written: %d", ff_result, written);
            return NRF_ERROR_NULL;
        }
        else
        {
            NRF_LOG_DEBUG("%d bytes written.", written);
        }
        f_sync(m_opened_file);
        return NRF_SUCCESS;
    }

  • The above code was the code you decribed, but I am afraid the could not be enough, so I attach all my code  in the following .

  • main.h
    
    #ifndef MAIN_H
    #define MAIN_
    #include <stdint.h>
    #include <stdbool.h>
    #include <stddef.h>
    #include <inttypes.h>
    #include <stdlib.h>
    
    #include "nrf.h"
    #include "nrf_block_dev.h"
    #include "nrf_block_dev_ram.h"
    #include "nrf_block_dev_empty.h"
    #include "nrf_block_dev_qspi.h"
    #include "nrf_block_dev_sdc.h"
    #include "nrf_drv_usbd.h"
    #include "nrf_drv_clock.h"
    #include "nrf_gpio.h"
    #include "nrf_atomic.h"
    #include "nrf_drv_power.h"
    
    #include "ff.h"
    #include "diskio_blkdev.h"
    
    #include "app_usbd.h"
    #include "app_usbd_core.h"
    #include "app_usbd_string_desc.h"
    #include "app_usbd_msc.h"
    #include "app_error.h"
    #include "app_timer.h"
    
    #include "bsp.h"
    
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "recorder.h"
    #include "gnss.h"
    
    #define NEED_NMEAPARSE
    #ifdef NEED_NMEAPARSE
    #include "minmea.h"
    #endif
    
    #include "boards.h"
    #include "nrf_delay.h"
    
    #define RESULT_SUCESS "sucessfully!"
    #define RESULT_FAILED "failed!"
    #define  ACTION_NAME "init"
    
    #define  LOG_ACTION_NAME "Log"
    #define  CLOCK_ACTION_NAME "Clock"
    #define  TIMER_ACTION_NAME "Timer"
    #define  BSP_ACTION_NAME "BSP"
    
    
    
    #define BUFFER_SIZE                     180
    #define  IS_ASCII(x) ((((unsigned char)(x)) & 0x80 ) == 0x80 ?  false : true)
    /**@file
     * @defgroup usbd_msc_example main.c
     * @{
     * @ingroup usbd_msc_example
     * @brief USBD MSC example
     *
     */
    
    #define LED_USB_RESUME   (BSP_BOARD_LED_0)
    #define LED_USB_START    (BSP_BOARD_LED_1)
    
    #define BTN_RANDOM_FILE  0
    #define BTN_LIST_DIR     1
    #define BTN_MKFS         2
    
    #define KEY_EV_RANDOM_FILE_MSK (1U << BTN_RANDOM_FILE)
    #define KEY_EV_LIST_DIR_MSK    (1U << BTN_LIST_DIR   )
    #define KEY_EV_MKFS_MSK        (1U << BTN_MKFS       )
    
    /**
     * @brief Enable power USB detection
     *
     * Configure if example supports USB port connection
     */
    #ifndef USBD_POWER_DETECTION
    #define USBD_POWER_DETECTION true
    #endif
    
    /**
     * @brief SD card enable/disable
     */
    #define USE_SD_CARD       0
    
    /**
     * @brief FatFS for QPSI enable/disable
     */
    #define USE_FATFS_QSPI    1
    
    /**
     * @brief Mass storage class user event handler
     */
    static void msc_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                    app_usbd_msc_user_event_t     event);
    
    
    /**
     * @brief Ram block device size
     *
     * @note Windows fails to format volumes smaller than 190KB
     */
    #define RAM_BLOCK_DEVICE_SIZE (380 * 512)
    
    /**
     * @brief  RAM block device work buffer
     */
    static uint8_t m_block_dev_ram_buff[RAM_BLOCK_DEVICE_SIZE];
    
    /**
     * @brief  RAM block device definition
     */
    NRF_BLOCK_DEV_RAM_DEFINE(
        m_block_dev_ram,
        NRF_BLOCK_DEV_RAM_CONFIG(512, m_block_dev_ram_buff, sizeof(m_block_dev_ram_buff)),
        NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "RAM", "1.00")
    );
    
    
    /**
     * @brief Empty block device definition
     */
    NRF_BLOCK_DEV_EMPTY_DEFINE(
        m_block_dev_empty,
        NRF_BLOCK_DEV_EMPTY_CONFIG(512, 1024 * 1024),
        NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "EMPTY", "1.00")
    );
    
    
    /**
     * @brief  QSPI block device definition
     */
    NRF_BLOCK_DEV_QSPI_DEFINE(
        m_block_dev_qspi,
        NRF_BLOCK_DEV_QSPI_CONFIG(
            512,
            NRF_BLOCK_DEV_QSPI_FLAG_CACHE_WRITEBACK,
            NRF_DRV_QSPI_DEFAULT_CONFIG
         ),
         NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "QSPI", "1.00")
    );
    
    #if USE_SD_CARD
    #if 0
    #define SDC_MISO_PIN    (19)        ///< SDC serial data out (DO) pin.
    #define SDC_SCK_PIN     (20)        ///< SDC serial clock (SCK) pin.
    #define SDC_MOSI_PIN    (21)        ///< SDC serial data in (DI) pin.
    #define SDC_CS_PIN      (22)        ///< SDC chip select (CS) pin.
    #else
    //NOT OK
    // #define SDC_MISO_PIN    (31)        ///< SDC serial data out (DO) pin.
    // #define SDC_SCK_PIN     (30)        ///< SDC serial clock (SCK) pin.
    // #define SDC_MOSI_PIN    (29)        ///< SDC serial data in (DI) pin.
    // #define SDC_CS_PIN      (28)        ///< SDC chip select (CS) pin.
    
    
    //OK
    #define SDC_MISO_PIN    (28)         ///< SDC serial data out (DO) pin.
    #define SDC_SCK_PIN     (31)        ///< SDC serial clock (SCK) pin.
    #define SDC_MOSI_PIN    (30)        ///< SDC serial data in (DI) pin.
    #define SDC_CS_PIN      (29)   ///< SDC chip select (CS) pin.
    
    
    // #define SDC_MISO_PIN    (31)         ///< SDC serial data out (DO) pin.
    // #define SDC_SCK_PIN     (26)        ///< SDC serial clock (SCK) pin.
    // #define SDC_MOSI_PIN    (27)        ///< SDC serial data in (DI) pin.
    // #define SDC_CS_PIN      (04)   ///< SDC chip select (CS) pin.
    
    
    
    
    #endif
    /**
     * @brief  SDC block device definition
     */
    NRF_BLOCK_DEV_SDC_DEFINE(
        m_block_dev_sdc,
        NRF_BLOCK_DEV_SDC_CONFIG(
            SDC_SECTOR_SIZE,
            APP_SDCARD_CONFIG(SDC_MOSI_PIN, SDC_MISO_PIN, SDC_SCK_PIN, SDC_CS_PIN)
         ),
         NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00")
    );
    
    
    /**
     * @brief Block devices list passed to @ref APP_USBD_MSC_GLOBAL_DEF
     */
    #if 0
    #define BLOCKDEV_LIST() (                                   \
    
        NRF_BLOCKDEV_BASE_ADDR(m_block_dev_ram, block_dev),     \
        NRF_BLOCKDEV_BASE_ADDR(m_block_dev_empty, block_dev),   \
        NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev)      \
    )
    #else
    #define BLOCKDEV_LIST() (                                   \
        NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev)      \
    )
    #endif
    
    #else
    #if 0
    #define BLOCKDEV_LIST() (                                   \
        NRF_BLOCKDEV_BASE_ADDR(m_block_dev_ram, block_dev),     \
        NRF_BLOCKDEV_BASE_ADDR(m_block_dev_empty, block_dev),   \
        NRF_BLOCKDEV_BASE_ADDR(m_block_dev_qspi, block_dev)     \
    )
    #else
    #define BLOCKDEV_LIST() (                                   \
        NRF_BLOCKDEV_BASE_ADDR(m_block_dev_qspi, block_dev)     \
    )
    #endif
    #endif
    
    /**
     * @brief Endpoint list passed to @ref APP_USBD_MSC_GLOBAL_DEF
     */
    #define ENDPOINT_LIST() APP_USBD_MSC_ENDPOINT_LIST(1, 1)
    
    /**
     * @brief Mass storage class work buffer size
     */
    #define MSC_WORKBUFFER_SIZE (1024)
    
    /*lint -save -e26 -e64 -e123 -e505 -e651*/
    /**
     * @brief Mass storage class instance
     */
    APP_USBD_MSC_GLOBAL_DEF(m_app_msc,
                            0,
                            msc_user_ev_handler,
                            ENDPOINT_LIST(),
                            BLOCKDEV_LIST(),
                            MSC_WORKBUFFER_SIZE);
    
    /*lint -restore*/
    
    /**
     * @brief Events from keys
     */
    static nrf_atomic_u32_t m_key_events;
    
    /**
     * @brief  USB connection status
     */
    static bool m_usb_connected = false;
    static FRESULT  fatfs_mkfs(void);
    // #define SDC_SCK_PIN     (30)        ///< SDC serial clock (SCK) pin.
    // #define SDC_MOSI_PIN    (29)        ///< SDC serial data in (DI) pin.
    // #define SDC_CS_PIN      (28)        ///< SDC chip select (CS) pin.
    
    
    //OK
    #define SDC_MISO_PIN    (28)         ///< SDC serial data out (DO) pin.
    #define SDC_SCK_PIN     (31)        ///< SDC serial clock (SCK) pin.
    #define SDC_MOSI_PIN    (30)        ///< SDC serial data in (DI) pin.
    #define SDC_CS_PIN      (29)   ///< SDC chip select (CS) pin.
    
    
    // #define SDC_MISO_PIN    (31)         ///< SDC serial data out (DO) pin.
    // #define SDC_SCK_PIN     (26)        ///< SDC serial clock (SCK) pin.
    // #define SDC_MOSI_PIN    (27)        ///< SDC serial data in (DI) pin.
    // #define SDC_CS_PIN      (04)   ///< SDC chip select (CS) pin.
    
    void record_stat_data(int close_flag);
    void delay_ms(unsigned short time);
    void delay_us(unsigned short time);
    uint32_t app_uart_get(uint8_t * p_byte);
    
    #endif
    
    
    main.c
    
    int main(void)
    {
        ret_code_t ret;
        FRESULT ff_result; 
        int mode = 0;
        //char m_log_buf[256] = {0}; 
        int loop_cnt = 0;
    
        uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events.
        uint32_t time_ticks;
        uint32_t err_code = NRF_SUCCESS;
    
        bool    init_result = true;
    
        static const app_usbd_config_t usbd_config =
        {
            .ev_state_proc = usbd_user_ev_handler
        };
    
        /*******************************************************************
         * Step 1: System init
         *******************************************************************/
    
        ret = NRF_LOG_INIT(app_usbd_sof_timestamp_get);
        APP_ERROR_CHECK(ret);
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        ret = nrf_drv_clock_init();
        APP_ERROR_CHECK(ret);
    
        if(ret)
        {
       
            return -1;
        }
        /* Fill whole RAM block device buffer */
        for (size_t i = 0; i < sizeof(m_block_dev_ram_buff); ++i)
        {
            m_block_dev_ram_buff[i] = i;
        }
    
        /* Configure LEDs and buttons */
        nrf_drv_clock_lfclk_request(NULL);
        ret = app_timer_init();
        APP_ERROR_CHECK(ret);
    
        ret = bsp_init(BSP_INIT_BUTTONS, bsp_event_callback);
        APP_ERROR_CHECK(ret);
       
    
    
        bsp_board_init(BSP_INIT_LEDS);
    
    
    
        //Configure all leds on board.
    
    #if 1
        ret = fatfs_init();
    
        APP_ERROR_CHECK(!ret);
        if(ret!=true)
        {
    
            ff_result = fatfs_mkfs();
            if (ff_result != FR_OK)
            {
           
                init_result = false;
                return -1;
            }
    		
            bsp_board_led_off(BSP_BOARD_LED_1);
    nrf_delay_ms(30*1000);
    //        sleep(30);//while(1);
        
        }
    	nrf_delay_ms(10);
    
        fatfs_ls();
    
    #endif
    
        bsp_board_led_on(BSP_BOARD_LED_0);
        nrf_delay_ms(3000);
        bsp_board_led_off(BSP_BOARD_LED_0);
    
        ret = gnss_init();
    #if 0
        m_log_buf_len =   sprintf( (char *) m_log_buf, "%s %s %s : %d.\r\n",BSP_ACTION_NAME,ACTION_NAME,(NRF_SUCCESS==ret)?RESULT_SUCESS:RESULT_FAILED, ret );
        record_stat_data(0);
    #endif
        if(ret)
        {
           // m_log_buf_len =   sprintf( (char *) m_log_buf, "Step 1:System  init failed,because of gnss.\r\n" );
            return -1;
        }
        /*******************************************************************
         * Step 2: System configure GPS
         *******************************************************************/
    
        ret = init_param();
        if(NRF_SUCCESS != ret)
        {
        ff_result = fatfs_mkfs();
        if(!ff_result)
        {
          ret = init_param();
          if(NRF_SUCCESS != ret)
          {
            return ret;
          }
        }else
        {
    
    
            return ret;
            }
        }
        mode = get_mode_from_param();
    
        if(mode <0 || mode >4)
        {
     
    		NRF_LOG_ERROR("GNSS mode from config err: %d", mode);
            return mode;
        }
    
        NRF_LOG_INFO("GNSS mode from config: %d", mode);
        ret = gnss_set_mode(mode);
        if(NRF_SUCCESS != ret)
        {
    
            return ret;
        }
        //        set_gnss_mode(mode);
        // fatfs_file_create();
    
        /*******************************************************************
         * Step 3: System configure USB 
         *******************************************************************/
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(ret);
        if(NRF_SUCCESS != ret)
        {
    
        }
        app_usbd_class_inst_t const * class_inst_msc = app_usbd_msc_class_inst_get(&m_app_msc);
        ret = app_usbd_class_append(class_inst_msc);
        APP_ERROR_CHECK(ret);
        if(NRF_SUCCESS != ret)
        {
    
        }
        NRF_LOG_INFO("USBD configure  finished.");
    
        //    gnss_set_callback(on_uart_receive);
    
        if (USBD_POWER_DETECTION)
        {
            ret = app_usbd_power_events_enable();
            APP_ERROR_CHECK(ret);
        }
        else
        {
            NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now");
    
            app_usbd_enable();
            app_usbd_start();
            m_usb_connected = true;
        }
    
    
        /*******************************************************************
         * Step 4: 
         *******************************************************************/
        while (true)
        {
            while (app_usbd_event_queue_process() && loop_cnt<100)
            {
            #if 0
                /* Nothing to do */
                m_log_buf_len =   sprintf( (char *) m_log_buf, "Step 4: Enter app_usbd_event_queue_process loop .\r\n");
    		  
                record_stat_data(0);
    		#endif
                loop_cnt++;
    			
            }
    
            /* Process BSP key events flags.*/
            uint32_t events = nrf_atomic_u32_fetch_store(&m_key_events, 0);
            if (events & KEY_EV_RANDOM_FILE_MSK)
            {
                //            fatfs_file_create();
                //            recorder_stest();
                mode = 0;
                init_param();
                mode = get_mode_from_param();
                NRF_LOG_INFO("GNSS mode from config: %d", mode);
    
            }
    
            if (events & KEY_EV_LIST_DIR_MSK)
            {
                //            fatfs_ls();
                recorder_fatfs_ls();
            }
    
            if (events & KEY_EV_MKFS_MSK)
            {
                fatfs_mkfs();
            }
    
            uart_data_process();
    
            UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
            /* Sleep CPU only if there was no interrupt since last loop processing */
            __WFE();
        }
    }
    record.c
    
    #include "recorder.h"
    #include "ff.h"
    #include "diskio_blkdev.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_delay.h"
    #include "ini.h"
    
    #define NRF_LOG_MODULE_NAME recorder
    #include <nrf_log.h>
    NRF_LOG_MODULE_REGISTER();
    
    #define LEN_FILENAME 128
    /*每次记录完是不是关闭文件*/
    #define CLOSE_FILE_AFTER_RECORDED 0
    
    #define CONFIG_FILE "CONFIG.INI"
    #define CONFIG_CONTENT \
    ";---------------------------------------------------\r\n"\
    ";-----do not delete these lines with no meaning-----\r\n"\
    ";---------------------------------------------------\r\n"\
    ";--------these lines may fix some bugs--------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";---------------------------------------------------\r\n"\
    ";config starts--------------------------------------\r\n"\
    ";---mode\r\n"\
    ";------1\tGPS only\r\n"\
    ";------2\tGLONASS only\r\n"\
    ";------3\tGPS+GLONASS\r\n"\
    ";------4\tGPS+BDS(default)\r\n"\
    ";------5\tBDS only\r\n"\
    ";------6\tGPS+GLONASS+Galileo\r\n"\
    "mode=4\r\n"
    
    #define CONFIG_KEYWORD "config starts"
    #define CONFIG_CONTENT_LENGTH_MAX 4096
    
    
    #define PARAM_MODE_KEY "mode"
    
    typedef struct {
        int mode;
    }param_t;
    
    static bool m_record_disabled;
    static FIL* m_opened_file = NULL;
    static char m_filename[LEN_FILENAME] = "default.csv";
    static char m_endline[] = "\n";
    static param_t m_param = {0};
    
    
    uint32_t init_config_file();
    static uint32_t file_close();
    
    void set_record_disabled(bool disabled)
    {
        m_record_disabled = disabled;
        if(m_opened_file){
            file_close();
        }
    }
    
    bool get_record_disabled()
    {
        return m_record_disabled;
    }
    
    
    
    uint32_t recorder_fatfs_ls(void)
    {
       DIR dir;
       FRESULT ff_result;
       FILINFO fno;
    
       if (m_record_disabled)
       {
           NRF_LOG_ERROR("Unable to operate on filesystem while USB is connected");
           return NRF_ERROR_BUSY;
       }
    
       NRF_LOG_INFO("\r\nListing directory: /");
       if(get_record_disabled()){
           return NRF_ERROR_BUSY;
       }
       ff_result = f_opendir(&dir, "/");
       if (ff_result != FR_OK)
       {
           NRF_LOG_ERROR("Directory listing failed: %u", ff_result);
           return NRF_ERROR_FORBIDDEN;
       }
    
       uint32_t entries_count = 0;
       do
       {
           ff_result = f_readdir(&dir, &fno);
           if (ff_result != FR_OK)
           {
               NRF_LOG_ERROR("Directory read failed: %u", ff_result);
               return NRF_ERROR_NULL;
           }
    
           if (fno.fname[0])
           {
               if (fno.fattrib & AM_DIR)
               {
                   NRF_LOG_RAW_INFO("   <DIR>   %s\r\n",(uint32_t)fno.fname);
               }
               else
               {
                   NRF_LOG_RAW_INFO("%9lu  %s\r\n", fno.fsize, (uint32_t)fno.fname);
               }
           }
    
           ++entries_count;
           NRF_LOG_FLUSH();
       } while (fno.fname[0]);
    
       NRF_LOG_RAW_INFO("Entries count: %u\r\n", entries_count);
       return NRF_SUCCESS;
    }
    
    
    static uint32_t file_close()
    {
        FRESULT ff_result = f_close(m_opened_file);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to close file: %u", ff_result);
            NRF_LOG_FLUSH();
            return NRF_ERROR_NULL;
        }
        
        NRF_LOG_INFO("closed %x.", (uint32_t)m_opened_file);
        m_opened_file = NULL;
        return NRF_SUCCESS;
    
    }
    
    static uint32_t file_open(const char*filename)
    {
        static FIL file;
        FRESULT ff_result;
    
        NRF_LOG_INFO("Opening file: %s.", NRF_LOG_PUSH(filename));
        if(get_record_disabled()){
            return NRF_ERROR_BUSY;
        }
        ff_result = f_open(&file, filename, FA_READ | FA_WRITE | FA_OPEN_APPEND);
        if (ff_result != FR_OK)
        {
           NRF_LOG_INFO("Unable to open or create file: %d", ff_result);
           return NRF_ERROR_BUSY;
        }
        m_opened_file = &file;
        return NRF_SUCCESS;
    }
    static uint32_t file_write(const uint8_t *buf, uint32_t len)
    {
        uint32_t written = 0;
        FRESULT ff_result;
        if(m_opened_file == NULL){
            NRF_LOG_ERROR("Sorry, open file first");
            return NRF_ERROR_BUSY;
        }
        NRF_LOG_HEXDUMP_DEBUG(buf, len);
        if(get_record_disabled()){
            return NRF_ERROR_BUSY;
        }
    	f_lseek(m_opened_file,f_size(m_opened_file));
        ff_result = f_write(m_opened_file, buf, len, (UINT *) &written);
        if (ff_result != FR_OK || written != len)
        {
            NRF_LOG_ERROR("Failed to write, ff_result: %d, written: %d", ff_result, written);
            return NRF_ERROR_NULL;
        }
        else
        {
            NRF_LOG_DEBUG("%d bytes written.", written);
        }
        f_sync(m_opened_file);
        return NRF_SUCCESS;
    }
    
    uint32_t set_record_filename(const char* name)
    {
        if(name[0] == '\0'){
            return NRF_ERROR_NULL;
        }
        memset(m_filename, 0x00, LEN_FILENAME);
        int n = snprintf(m_filename, LEN_FILENAME, "%s.csv", name);
        NRF_LOG_INFO("Set record file name:")
        NRF_LOG_HEXDUMP_INFO(m_filename, n + 1);
        if(m_opened_file){
            file_close();
        }
        return file_open(m_filename);
    }
    
    uint32_t record_one_line(uint8_t *buf, uint32_t len)
    {
        uint32_t ret;
        bool result = false;
        if(m_opened_file == NULL)
        {
            #if CLOSE_FILE_AFTER_RECORDED
            if(get_record_disabled()){
                return NRF_ERROR_BUSY;
            }
            ret = file_open(m_filename);
            if(ret != NRF_SUCCESS){
                return NRF_ERROR_BUSY;
            }
            #endif
             return NRF_ERROR_NULL;
        }
        result = get_record_disabled();
        if(result == true)
        {
            return NRF_ERROR_BUSY;
        }
    	
        ret = file_write(buf, len);
        if(ret != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Failed1 to record one line");
            return NRF_ERROR_NULL;
        }
        
        ret = file_write(&m_endline, sizeof(m_endline) - 1);
        if(ret != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Failed to record one line");
            return NRF_ERROR_NULL;
        }
    #if CLOSE_FILE_AFTER_RECORDED
       file_close();
    #endif
        NRF_LOG_WARNING("Recorded one line: %d", len);
        return NRF_SUCCESS;
    }
    
    
    static void show_file_info()
    {
    //    NRF_LOG_INFO("m_opened_file: %X.", m_opened_file);
    }
    
    
    static void fatfs_example()
    {
        static FATFS fs;
        static DIR dir;
        static FILINFO fno;
        static FIL file;
    
        uint32_t bytes_written;
        FRESULT ff_result;
        DSTATUS disk_state = STA_NOINIT;
    #define FILE_NAME "heheda"
    #define TEST_STRING "123"
    
        D_RETURN_VALUE(NRF_LOG_PROCESS());
        file_open(m_filename);
        while(1){   
            file_write(TEST_STRING, sizeof(TEST_STRING) - 1);
            nrf_delay_ms(500);
        }
    
        (void) f_close(&file);
        return;
    }
    
    void recorder_test()
    {
    #if 0
        char random_file_name[32];
        memset(random_file_name, 0x00, 32);
    
        snprintf(random_file_name, sizeof(random_file_name), "%08x.txt", rand());
        new_file_create(random_file_name, false);
    #endif
        char random_data[32] __attribute__ ((aligned (4)));
        int n = snprintf(random_data, sizeof(random_data), "%08x", rand() * rand());
        record_one_line(random_data, n);
        show_file_info();
    }
    
    bool is_file_opened()
    { 
        return NULL != m_opened_file;
    }
    
    uint32_t paser_mode_from_config(const char* data, int len, int* mode)
    {
    #define MODE_CONFIG_PREFIX "mode="
        if(!data || !mode)
            return NRF_ERROR_INVALID_PARAM;
        char *input = data;
        int index = 0;
        int line_start = index;
        int line_len = 0;
        bool is_valid = true;
        static char c;// static for debug
    
        while(index < len){
            c = input[index];
            if(c == ';'){ // this is comment
                is_valid = false;
            }
            else if(c == '\r' || c == '\n'){ // this is the end of line
                input[index] = '\0';
                if(is_valid){ // check "mode="
                    line_len = index - line_start;
                    if(0 == strncasecmp(input + line_start, MODE_CONFIG_PREFIX, sizeof(MODE_CONFIG_PREFIX) - 1)){
                        int m = atoi(input + line_start + sizeof(MODE_CONFIG_PREFIX) - 1);
                        NRF_LOG_INFO("Success to read mode from config: %d", m);
                        *mode = m;
                        break;
                    }
                }
                is_valid = true;
                line_start = index + 1;
            }
            index++;
        }
    
        return NRF_SUCCESS;
    }
    
    int User;
    char Prev_section[50];
    
    int dumper(void* user, const char* section, const char* name,
               const char* value)
    {
        User = *((int*)user);
        if (strcmp(section, Prev_section))
        {
            strncpy(Prev_section, section, sizeof(Prev_section));
            Prev_section[sizeof(Prev_section) - 1] = '\0';
        }
        NRF_LOG_INFO("... %s=%s;\n", NRF_LOG_PUSH(name), NRF_LOG_PUSH(value));
    
        if(0 == strncasecmp(name, PARAM_MODE_KEY, sizeof(PARAM_MODE_KEY) - 1))
        {
            int m = atoi(value);
            NRF_LOG_INFO("Success to read mode from config: %d", m);
            m_param.mode = m;
        }
        return 1;
    }
    
    int get_mode_from_param()
    {
    
        if(m_param.mode == 0)
    	{
            init_config_file();
        }
        return m_param.mode;
    }
    static uint32_t read_from_config_file()
    {
        FIL file;
        FRESULT ff_result;
        UINT read = 0;
        char buffer[CONFIG_CONTENT_LENGTH_MAX] = {0};
        int e;
        static int u = 100;
        *Prev_section = '\0';
    
        NRF_LOG_INFO("Opening config file");
        if(get_record_disabled()){
            return NRF_ERROR_BUSY;
        }
        ff_result = f_open(&file, CONFIG_FILE, FA_READ | FA_OPEN_EXISTING);
        if (ff_result != FR_OK)
        {
           NRF_LOG_INFO("Unable to open file: %d", ff_result);
           return NRF_ERROR_BUSY;
        }
    
        ff_result = f_read(&file, buffer, CONFIG_CONTENT_LENGTH_MAX, &read);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("Failed to read, ff_result: %d, read: %d", ff_result, read);
            return NRF_ERROR_NULL;
        }
        NRF_LOG_INFO("read from config file: %d", read);
    //    NRF_LOG_HEXDUMP_INFO(buffer, read);
    
        if(NULL == strnstr(buffer, CONFIG_KEYWORD, CONFIG_CONTENT_LENGTH_MAX))
        {
            NRF_LOG_INFO("config key word not found");
            goto exit;
        }
    
        e = ini_parse_string(buffer, dumper, &u);
        NRF_LOG_INFO("e=%d user=%d\n", e, User);
    
        // if(NRF_SUCCESS != paser_mode_from_config(buffer, read, mode)){
        //     *mode = 0;
        // }
        
    exit:
        ff_result = f_close(&file);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to close config file: %u", ff_result);
            NRF_LOG_FLUSH();
            return NRF_ERROR_NULL;
        }
        
        NRF_LOG_INFO("closed config file");
    
        return NRF_SUCCESS;
    }
    
    uint32_t init_config_file_prefix(const char*filename)
    {
        FIL file;
        FRESULT ff_result;
        UINT written;
    
        NRF_LOG_INFO("Creating config file");
        if(get_record_disabled()){
            return NRF_ERROR_BUSY;
        }
        ff_result = f_open(&file, filename, FA_WRITE | FA_CREATE_ALWAYS);
        if (ff_result != FR_OK)
        {
           NRF_LOG_INFO("Unable to create file: %d", ff_result);
           return NRF_ERROR_BUSY;
        }
    
        if(get_record_disabled()){
            return NRF_ERROR_BUSY;
        }
        ff_result = f_write(&file, CONFIG_CONTENT, sizeof(CONFIG_CONTENT), (UINT *) &written);
        if (ff_result != FR_OK || written != sizeof(CONFIG_CONTENT))
        {
            NRF_LOG_ERROR("Failed to write, ff_result: %d, written: %d", ff_result, written);
            return NRF_ERROR_NULL;
        }
        else
        {
            NRF_LOG_INFO("["CONFIG_CONTENT"] %d bytes written.", written);
        }
    
        ff_result = f_close(&file);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to close config file: %u", ff_result);
            NRF_LOG_FLUSH();
            return NRF_ERROR_NULL;
        }
        
        NRF_LOG_INFO("closed config file");
        
        return NRF_SUCCESS;
    }
    
    uint32_t init_config_file()
    {
        uint32_t ret = -1;
        ret = init_config_file_prefix("fake");
        if(NRF_SUCCESS != ret)
        {
            NRF_LOG_ERROR("Failed to init_config_file_prefix fake, result: %d", ret);
            return ret;
        }
        ret = init_config_file_prefix(CONFIG_FILE);
        if(NRF_SUCCESS != ret)
        {
            NRF_LOG_ERROR("Failed to init_config_file_prefix %s, result: %d",CONFIG_FILE, ret);
            return ret;
        }
    }
    
    static uint32_t open_config_file()
    {
        return !NRF_SUCCESS;
    }
    
    int read_mode_from_record()
    {
        int mode= 0;
        int count = 5;
        uint32_t ret = NRF_SUCCESS;
        ret = read_mode_from_config_file(&mode);
        #if 1
        if(NRF_SUCCESS != ret){
        #else
        if(1){
        #endif
            NRF_LOG_INFO("Initing config file");
            init_config_file();
            return 0;
        }
        return mode;
    }
    
    
    uint32_t init_param()
    {
        uint32_t ret = -1;
    
        ret = read_from_config_file();
        if(NRF_SUCCESS != ret)
    	{
            ret = init_config_file();
            if(NRF_SUCCESS == ret) /* read config file again */
            {
                ret = read_from_config_file();
                if(NRF_SUCCESS != ret)
                {
                    NRF_LOG_ERROR("read config file failed again.");
                    return ret;
                }
    
            }
            else
            {
    
                NRF_LOG_ERROR("init config file failed. ");
                return  ret;
            }
        }
    
        NRF_LOG_INFO("Initing param sucessfully");
        return NRF_SUCCESS;
    }
    

Related