USB MSC code, windows not able to access drive.

I am using the USB MSC code in my project. The project works fine and I am able to see the file system mounted and file being created in the logs. When I plug in the device into my laptop, I can see the device as a drive. However, when I click to access the drive, it asks me to format the drive and I am not able to view the contents of the drive. What might be causing this issue?

Parents
  • Hi

    The file system will need to be formatted in order for the device to be able to mount the file system and operate correctly. If it's not already formatted you can use the f_mkfsI() function to format your drive. That function is documented here: http://elm-chan.org/fsw/ff/doc/mkfs.html

    Best regards,

    Simon

  • Hi Simon,

                I have already used this function in my code. Please take a look at this file. I have used the format function "f_mkfsI()" inside the "fatfs_init()" function. 

    /**
     
     *
     */
    
    #include <stdint.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf.h"
    #include "app_error.h"
    #include "ble.h"
    #include "ble_hci.h"
    #include "ble_srv_common.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_bas.h"
    #include "ble_dis.h"
    #include "ble_conn_params.h"
    #include "sensorsim.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "nrf_sdh_freertos.h"
    #include "app_timer.h"
    #include "peer_manager.h"
    #include "peer_manager_handler.h"
    #include "bsp_btn_ble.h"
    
    #include "fds.h"
    #include "ble_conn_state.h"
    #include "ble_dfu.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_drv_wdt.h"
    #include "nrf_drv_clock.h"
    #include "nrf_ble_gatt.h"
    #include "nrf_ble_qwr.h"
    #include "nrf_power.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "product_config.h"
    #include "ble_clinitraq.h"
    #include "task_led_button.h"
    #include "task_clinitraq_ble.h"
    #include "task_id_accessory.h"
    #include "task_psf_comm.h"
    #include "device_storage.h"
    #include "nrf_drv_gpiote.h"
    #include "battery.h"
    #include "version.h"
    #include "clinitraq_app.h"
    #include "psf_comm.h"
    #include "nrf_drv_twi.h"
    #include "psf_i2c.h"
    #include "task_led_button.h"
    #include "app_button.h"
    
    #include "bq24292i.h"
    #include "max17201_i2c.h"
    #include "nrf_dfu_ble_svci_bond_sharing.h"
    #include "nrf_svci_async_function.h"
    #include "nrf_svci_async_handler.h"
    #include "nrf_bootloader_info.h"
    #include "usb_msc.h"
    #include "bsp.h"
    #include "spi.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 "nrf_block_dev_spi.h"
    
    
    #define MAIN_DEVICE_NAME                         LE_DEVICE_NAME                            /**< Name of device. Will be included in the advertising data. */
    #define MANUFACTURER_NAME                   "test"                   /**< Manufacturer. Will be passed to Device Information Service. */
    
    #define APP_BLE_OBSERVER_PRIO               3                                       /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    #define APP_BLE_CONN_CFG_TAG                1                                       /**< A tag identifying the SoftDevice BLE configuration. */
    
    #define APP_ADV_INTERVAL                    300 //300                                     /**< The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */
    #define APP_ADV_DURATION                    18000 //0                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    
    #define RTC_INTERVAL                        1000                                    /**< RTC interval (ms). */
    #define MIN_BATTERY_LEVEL                   81                                      /**< Minimum simulated battery level. */
    #define MAX_BATTERY_LEVEL                   100                                     /**< Maximum simulated battery level. */
    
    #define MIN_CONN_INTERVAL                   MSEC_TO_UNITS(200, UNIT_1_25_MS)        /**< Minimum acceptable connection interval (0.4 seconds). */
    #define MAX_CONN_INTERVAL                   MSEC_TO_UNITS(300, UNIT_1_25_MS)        /**< Maximum acceptable connection interval (0.65 second). */
    #define SLAVE_LATENCY                       3                                       /**< Slave latency. */
    #define CONN_SUP_TIMEOUT                    MSEC_TO_UNITS(5000, UNIT_10_MS)         /**< Connection supervisory time-out (4 seconds). */
    
    #define FIRST_CONN_PARAMS_UPDATE_DELAY      5000                                    /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
    #define NEXT_CONN_PARAMS_UPDATE_DELAY       30000                                   /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
    #define MAX_CONN_PARAMS_UPDATE_COUNT        3                                       /**< Number of attempts before giving up the connection parameter negotiation. */
    
    #define SEC_PARAM_BOND                      0                                       /**< Perform bonding. */
    #define SEC_PARAM_MITM                      0                                       /**< Man In The Middle protection not required. */
    #define SEC_PARAM_LESC                      0                                       /**< LE Secure Connections not enabled. */
    #define SEC_PARAM_KEYPRESS                  0                                       /**< Keypress notifications not enabled. */
    #define SEC_PARAM_IO_CAPABILITIES           BLE_GAP_IO_CAPS_NONE                    /**< No I/O capabilities. */
    #define SEC_PARAM_OOB                       0                                       /**< Out Of Band data not available. */
    #define SEC_PARAM_MIN_KEY_SIZE              16                                      /**< Minimum encryption key size. */
    #define SEC_PARAM_MAX_KEY_SIZE              16                                      /**< Maximum encryption key size. */
    
    #define DEAD_BEEF                           0xDEADBEEF                              /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    
    #define OSTIMER_WAIT_FOR_QUEUE              2                                       /**< Number of ticks to wait for the timer queue to be ready */
    
    #define DEVICEID_SIZE           16
    uint8_t device_id[DEVICEID_SIZE+1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    
    extern uint8_t adv_led_button;
    extern uint8_t led_on_duration;
    extern uint8_t led_grn_pwr_active;
    extern uint8_t led_grn_pwr_state;
    extern uint8_t led_blue_pwr_active ;
    extern uint8_t led_blue_pwr_state ;
    int8_t rssi;
    extern int wireless_charging_on;
    
    static char app_fw_version[32];
    static char pulsecount[20];
    //uint8_t rclr_data_buf[256] = {0};
    uint8_t rcbr_data_buf[256] = {0};
    //uint16_t rclr_data_cnt = 0;
    uint16_t rcbr_data_cnt = 0;
    
    extern bq24292i_charge_state_t charge_state;
    
    
    BLE_RCBR_DEF(m_rcbr, NRF_SDH_BLE_TOTAL_LINK_COUNT);                  /**< BLE R3charge borrower service instance. */
    
    BLE_BAS_DEF(m_bas);                                                 /**< Battery service instance. */
    NRF_BLE_GATT_DEF(m_gatt);                                           /**< GATT module instance. */
    NRF_BLE_QWR_DEF(m_qwr);                                             /**< Context for the Queued Write module.*/
    BLE_ADVERTISING_DEF(m_advertising);                                 /**< Advertising module instance. */
    
    nrfx_wdt_channel_id m_channel_id;
    
    ////////////Added for bonding///////////
    // Static passkey
    #define STATIC_PASSKEY    "123456" 
    static ble_opt_t    m_static_pin_option;
    uint8_t passkey[] = STATIC_PASSKEY; 
    ////////////Added for bonding///////////
    static uint16_t m_conn_handle         = BLE_CONN_HANDLE_INVALID;    /**< Handle of the current connection. */
    int adv_success = 0;
    
    static ble_uuid_t m_adv_uuids[] =                                   /**< Universally unique service identifiers. */
    {
        {BLE_UUID_RCBR_SERVICE, BLE_UUID_TYPE_VENDOR_BEGIN}
    };
    
    
    
    
    /**@brief Handler for shutdown preparation.
     *
     * @details During shutdown procedures, this function will be called at a 1 second interval
     *          untill the function returns true. When the function returns true, it means that the
     *          app is ready to reset to DFU mode.
     *
     * @param[in]   event   Power manager event.
     *
     * @retval  True if shutdown is allowed by this power manager handler, otherwise false.
     */
    static bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event)
    {
        switch (event)
        {
            case NRF_PWR_MGMT_EVT_PREPARE_DFU:
                NRF_LOG_INFO("Power management wants to reset to DFU mode.");
                // YOUR_JOB: Get ready to reset into DFU mode
                //
                // If you aren't finished with any ongoing tasks, return "false" to
                // signal to the system that reset is impossible at this stage.
                //
                // Here is an example using a variable to delay resetting the device.
                //
                // if (!m_ready_for_reset)
                // {
                //      return false;
                // }
                // else
                //{
                //
                //    // Device ready to enter
                //    uint32_t err_code;
                //    err_code = sd_softdevice_disable();
                //    APP_ERROR_CHECK(err_code);
                //    err_code = app_timer_stop_all();
                //    APP_ERROR_CHECK(err_code);
                //}
                break;
    
            default:
                // YOUR_JOB: Implement any of the other events available from the power management module:
                //      -NRF_PWR_MGMT_EVT_PREPARE_SYSOFF
                //      -NRF_PWR_MGMT_EVT_PREPARE_WAKEUP
                //      -NRF_PWR_MGMT_EVT_PREPARE_RESET
                return true;
        }
    
        NRF_LOG_INFO("Power management allowed to reset to DFU mode.");
        return true;
    }
    
    //lint -esym(528, m_app_shutdown_handler)
    /**@brief Register application shutdown handler with priority 0.
     */
    NRF_PWR_MGMT_HANDLER_REGISTER(app_shutdown_handler, 0);
    
    
    static void buttonless_dfu_sdh_state_observer(nrf_sdh_state_evt_t state, void * p_context)
    {
        if (state == NRF_SDH_EVT_STATE_DISABLED)
        {
            // Softdevice was disabled before going into reset. Inform bootloader to skip CRC on next boot.
            nrf_power_gpregret2_set(BOOTLOADER_DFU_SKIP_CRC);
    
            //Go to system off.
            nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
        }
    }
    
    /* nrf_sdh state observer. */
    NRF_SDH_STATE_OBSERVER(m_buttonless_dfu_state_obs, 0) =
    {
        .handler = buttonless_dfu_sdh_state_observer,
    };
    
    
    static void advertising_config_get(ble_adv_modes_config_t * p_config)
    {
        memset(p_config, 0, sizeof(ble_adv_modes_config_t));
    
        p_config->ble_adv_fast_enabled  = true;
        p_config->ble_adv_fast_interval = APP_ADV_INTERVAL;
        p_config->ble_adv_fast_timeout  = APP_ADV_DURATION;
    }
    
    
    static void disconnect(uint16_t conn_handle, void * p_context)
    {
        UNUSED_PARAMETER(p_context);
    
        ret_code_t err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_WARNING("Failed to disconnect connection. Connection handle: %d Error: %d", conn_handle, err_code);
        }
        else
        {
            NRF_LOG_DEBUG("Disconnected connection handle %d", conn_handle);
        }
    }
    
    static TimerHandle_t m_rtc_timer;                               /**< Definition of battery timer. */
    
    #if NRF_LOG_ENABLED
    static TaskHandle_t m_logger_thread;                                /**< Definition of Logger thread. */
    #endif
    
    //static void advertising_start(void * p_erase_bonds);
    static void nrf_nvmc_write_word(uint32_t address, uint32_t value);
    
    //ble_rclr_t * get_rclr_service(void)
    //{
    //    return &m_rclr;
    //}
    
    ble_rcbr_t * get_rcbr_service(void)
    {
        return &m_rcbr;
    }
    
    
    uint16_t get_conn_handle(void)
    {
        return m_conn_handle;
    }
    
    
    //uint8_t * get_rclr_rcv_buffer(void)
    //{
    //    return rclr_data_buf;
    //}
    
    //uint16_t get_rclr_rcv_cnt(void)
    //{
    //    return rclr_data_cnt;
    //}
    
    uint8_t * get_rcbr_rcv_buffer(void)
    {
        return rcbr_data_buf;
    }
    
    uint16_t get_rcbr_rcv_cnt(void)
    {
        return rcbr_data_cnt;
    }
    
    /**@brief Callback function for asserts in the SoftDevice.
     *
     * @details This function will be called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and does not fit a final product. You need to analyze
     *          how your product is supposed to react in case of Assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in]   line_num   Line number of the failing ASSERT call.
     * @param[in]   file_name  File name of the failing ASSERT call.
     */
    void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(DEAD_BEEF, line_num, p_file_name);
    }
    
    
    void wdt_event_handler(void)
    {
    
    }
    
    #define NRFX_WDT_DEAFULT_CONFIG_1                                             \
        {                                                                         \
            .behaviour          = WDT_CONFIG_BEHAVIOUR,                           \
            .reload_value       = WDT_CONFIG_RELOAD_VALUE,                   \
            NRFX_WDT_IRQ_CONFIG                                                   \
        }
    
    void wdt_init(void)
    {
      uint32_t err_code = NRF_SUCCESS;
    
      nrfx_wdt_config_t w_config  = NRFX_WDT_DEAFULT_CONFIG;
      
      err_code = nrfx_wdt_init(&w_config, NULL);
      APP_ERROR_CHECK(err_code);
    
      err_code = nrfx_wdt_channel_alloc(&m_channel_id);
      APP_ERROR_CHECK(err_code);
    
      nrfx_wdt_enable();
    
     
    
    }
    
    /**@brief Function for handling Peer Manager events.
     *
     * @param[in] p_evt  Peer Manager event.
     */
    static void pm_evt_handler(pm_evt_t const * p_evt)
    {
        bool delete_bonds = false;
    
        pm_handler_on_pm_evt(p_evt);
        pm_handler_flash_clean(p_evt);
    
        switch (p_evt->evt_id) {
        case PM_EVT_PEERS_DELETE_SUCCEEDED:
            //..advertising_start(&delete_bonds);
            advertising_start(false);
            break;
    
        default:
            break;
        }
    }
    
    
    /**@brief Function for performing battery measurement and updating the Battery Level characteristic
     *        in Battery Service.
     */
     extern uint8_t SOC;
    
    void battery_level_update(void)
    {
        ret_code_t err_code;
        uint8_t  battery_level;
    
        //battery_level = battery_get_percentage(); /* Update TODO */
        battery_level = SOC; //battery_get_percentage(); /* Update TODO */
    
        err_code = ble_bas_battery_level_update(&m_bas, battery_level, BLE_CONN_HANDLE_ALL);
        if ((err_code != NRF_SUCCESS) &&
                (err_code != NRF_ERROR_INVALID_STATE) &&
                (err_code != NRF_ERROR_RESOURCES) &&
                (err_code != NRF_ERROR_BUSY) &&
                (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
           ) {
            APP_ERROR_HANDLER(err_code);
        }
    }
    
    
    
    
    
    uint32_t rtc_val = 0;
    
    uint32_t get_system_rtc(void)
    {
        return rtc_val;
    }
    
    /**@brief Function for handling the RTC event
     *
     * @details This function will be called each time the RTC timer expires.
     *
     * @param[in] xTimer Handler to the timer that called this function.
     *                   You may get identifier given to the function xTimerCreate using pvTimerGetTimerID.
     */
    static void rtc_timeout_handler(TimerHandle_t xTimer)
    {
        UNUSED_PARAMETER(xTimer);
        rtc_val++;
    }
    
    
    static StaticTimer_t xRTCTimer;
    
    
    /**@brief Function for the GAP initialization.
     *
     * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
     *          device including the device name, appearance, and the preferred connection parameters.
     */
    
    static void gap_params_init(void)
    {
        ret_code_t              err_code;
        ble_gap_conn_params_t   gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        //commented for adding device id.
        //err_code = sd_ble_gap_device_name_set(&sec_mode,
        //                                      (const uint8_t *)DEVICE_NAME,
        //                                      strlen(DEVICE_NAME));
    
    #ifdef USE_DEVICEID_ON_SRDATA
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));
    #else
        uint8_t basename_size = strlen(MAIN_DEVICE_NAME);
        uint8_t devicename[DEVICEID_SIZE+1+basename_size+1];
            
        memcpy(&devicename[0], (const uint8_t *)MAIN_DEVICE_NAME, basename_size);
        devicename[basename_size] = '-';
        memcpy(&devicename[basename_size+1], device_id, DEVICEID_SIZE);
        memset(&devicename[basename_size+1+DEVICEID_SIZE], 0x00, 1);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)devicename,
                                              strlen(devicename));
    #endif
    
    
    
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_UNKNOWN);
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
        gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
        gap_conn_params.slave_latency     = SLAVE_LATENCY;
        gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    /*sne    ////////Added for bonding ///////////
        m_static_pin_option.gap_opt.passkey.p_passkey = &passkey[0]; 
        err_code =  sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option); 
        APP_ERROR_CHECK(err_code);
        ////////Added for bonding /////////// sne*/
    
    
    }
    
    
    /**@brief Function for initializing the GATT module. */
    static void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling Queued Write Module errors.
     *
     * @details A pointer to this function will be passed to each service which may need to inform the
     *          application about an error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void nrf_qwr_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    
    //static void rclr_data_handler(ble_rclr_evt_t * p_evt)
    //{
    //    if (p_evt->type == BLE_RCLR_EVT_RX_DATA) {
    //        uint32_t err_code;
    
    //        if(p_evt->params.rx_data.length < sizeof(rclr_data_buf)) {
    //            memset(rclr_data_buf, 0, sizeof(rclr_data_buf));
    //            memcpy(rclr_data_buf, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
    //            rclr_data_cnt = p_evt->params.rx_data.length;
    
    //            /* Inform lender Task we have a command */
    //            lender_task_queue_event(LENDER_TASK_EVT_SETTING_CMD);
    //        }
    //    } else if(p_evt->type == BLE_RCLR_EVT_NOTIF_ENABLED) {
    //        /* Inform lender Task notifications have begun */
    //        lender_task_queue_event(LENDER_TASK_EVT_NOTIF_EN);
    //    }
    //}
    
    
    static void rcbr_data_handler_new(ble_rcbr_evt_t * p_evt)
    {
        psf_comm_task_evt_t evt;
    
        if (p_evt->type == BLE_RCBR_EVT_RX_DATA) {
            uint32_t err_code;
    
            if(p_evt->params.rx_data.length < MAX_FRAME_PAYLOAD_SIZE) {
              
                evt.evt_id = PSF_COMM_TASK_EVT_PSF_DATA;
                evt.length = p_evt->params.rx_data.length;
                memcpy(evt.payload, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);            
    
                psf_comm_task_queue_event(&evt);
            }
        } else if(p_evt->type == BLE_RCBR_EVT_NOTIF_ENABLED) {
            /* Inform Toilet Task notifications have begun */
            // toilet_task_queue_event(TOILET_TASK_EVT_NOTIF_EN);
        }
    }
    
    
    
    static void rcbr_data_handler(ble_rcbr_evt_t * p_evt)
    {
        if (p_evt->type == BLE_RCBR_EVT_RX_DATA) {
            uint32_t err_code;
    
            if(p_evt->params.rx_data.length < sizeof(rcbr_data_buf)) {
                memset(rcbr_data_buf, 0, sizeof(rcbr_data_buf));
                memcpy(rcbr_data_buf, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
                rcbr_data_cnt = p_evt->params.rx_data.length;
    
                /* Inform borrower Task we have a command */
                clinitraq_task_queue_event(CLINITRAQ_TASK_EVT_SETTING_CMD);
            }
        } else if(p_evt->type == BLE_RCBR_EVT_NOTIF_ENABLED) {
            /* Inform borrower Task notifications have begun */
            clinitraq_task_queue_event(CLINITRAQ_TASK_EVT_NOTIF_EN);
        }
    }
    
    
    static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
    {
        switch (event)
        {
            case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
            {
                NRF_LOG_INFO("Device is preparing to enter bootloader mode.");
    
                // Prevent device from advertising on disconnect.
                ble_adv_modes_config_t config;
                advertising_config_get(&config);
                config.ble_adv_on_disconnect_disabled = true;
                ble_advertising_modes_config_set(&m_advertising, &config);
    
                // Disconnect all other bonded devices that currently are connected.
                // This is required to receive a service changed indication
                // on bootup after a successful (or aborted) Device Firmware Update.
                uint32_t conn_count = ble_conn_state_for_each_connected(disconnect, NULL);
                NRF_LOG_INFO("Disconnected %d links.", conn_count);
                break;
            }
    
            case BLE_DFU_EVT_BOOTLOADER_ENTER:
                // YOUR_JOB: Write app-specific unwritten data to FLASH, control finalization of this
                //           by delaying reset by reporting false in app_shutdown_handler
                NRF_LOG_INFO("Device will enter bootloader mode.");
                break;
    
            case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED:
                NRF_LOG_ERROR("Request to enter bootloader mode failed asynchroneously.");
                // YOUR_JOB: Take corrective measures to resolve the issue
                //           like calling APP_ERROR_CHECK to reset the device.
                break;
    
            case BLE_DFU_EVT_RESPONSE_SEND_ERROR:
                NRF_LOG_ERROR("Request to send a response to client failed.");
                // YOUR_JOB: Take corrective measures to resolve the issue
                //           like calling APP_ERROR_CHECK to reset the device.
                APP_ERROR_CHECK(false);
                break;
    
            default:
                NRF_LOG_ERROR("Unknown event from ble_dfu_buttonless.");
                break;
        }
    }
    
    /**@brief Function for initializing services that will be used by the application.
     *
     * @details Initialize the Heart Rate, Battery and Device Information services.
     */
    static void services_init(void)
    {
        ret_code_t         err_code;
       // ble_rclr_init_t    rclr_init;
        ble_rcbr_init_t    rcbr_init;
        ble_bas_init_t     bas_init;
        ble_dis_init_t     dis_init;
        nrf_ble_qwr_init_t qwr_init = {0};
        ble_dfu_buttonless_init_t dfus_init = {0};
    
        // Initialize Queued Write Module.
        qwr_init.error_handler = nrf_qwr_error_handler;
    
        err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
        APP_ERROR_CHECK(err_code);
    
        // Initialize Battery Service.
        memset(&bas_init, 0, sizeof(bas_init));
    
        // Here the sec level for the Battery Service can be changed/increased.
        bas_init.bl_rd_sec        = SEC_OPEN;
        bas_init.bl_cccd_wr_sec   = SEC_OPEN;
        bas_init.bl_report_rd_sec = SEC_OPEN;
    
        bas_init.evt_handler          = NULL;
        bas_init.support_notification = true;
        bas_init.p_report_ref         = NULL;
        bas_init.initial_batt_level   = 100;
    
        err_code = ble_bas_init(&m_bas, &bas_init);
        APP_ERROR_CHECK(err_code);
    
        // Initialize Device Information Service.
        memset(&dis_init, 0, sizeof(dis_init));
    
        ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, (char *)MANUFACTURER_NAME);
        ble_srv_ascii_to_utf8(&dis_init.model_num_str, (char *)DEVICE_MODEL_NUM);
        ble_srv_ascii_to_utf8(&dis_init.serial_num_str, (char *)device_id);
        ble_srv_ascii_to_utf8(&dis_init.hw_rev_str, (char *)DEVICE_HW_VER);
        ble_srv_ascii_to_utf8(&dis_init.fw_rev_str, (char *)app_fw_version);
    
    
        dis_init.dis_char_rd_sec = SEC_OPEN;
    
    
        err_code = ble_dis_init(&dis_init);
        APP_ERROR_CHECK(err_code);
    
    
        // Initialize RCLR- LENDER Service
        //memset(&rclr_init, 0, sizeof(rclr_init));
    
        //rclr_init.data_handler = rclr_data_handler;
    
        //err_code = ble_rclr_init(&m_rclr, &rclr_init);
        //APP_ERROR_CHECK(err_code);
    
       // Initialize RCBR - BORROWER Service
        memset(&rcbr_init, 0, sizeof(rcbr_init));
    
        rcbr_init.pulsecount   = 100;
        rcbr_init.data_handler = rcbr_data_handler;
    
        err_code = ble_rcbr_init(&m_rcbr, &rcbr_init);
        APP_ERROR_CHECK(err_code);
    
    
        // Initialize the Nordic DFU Buttonless Service
        dfus_init.evt_handler = ble_dfu_evt_handler;
    
        err_code = ble_dfu_buttonless_init(&dfus_init);
        APP_ERROR_CHECK(err_code);
    
    
    }
    
    
    
    /**@brief   Function for starting application timers.
     * @details Timers are run after the scheduler has started.
     */
    static void application_timers_start(void)
    {
        // Start application timers.
        if (pdPASS != xTimerStart(m_rtc_timer, OSTIMER_WAIT_FOR_QUEUE)) {
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
    }
    
    
    /**@brief Function for handling the Connection Parameters Module.
     *
     * @details This function will be called for all events in the Connection Parameters Module which
     *          are passed to the application.
     *          @note All this function does is to disconnect. This could have been done by simply
     *                setting the disconnect_on_fail config parameter, but instead we use the event
     *                handler mechanism to demonstrate its use.
     *
     * @param[in]   p_evt   Event received from the Connection Parameters Module.
     */
    static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
    {
        ret_code_t err_code;
    
        if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) {
            err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    /**@brief Function for handling a Connection Parameters error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    /**@brief Function for initializing the Connection Parameters module. */
    static void conn_params_init(void)
    {
        ret_code_t             err_code;
        ble_conn_params_init_t cp_init;
    
        memset(&cp_init, 0, sizeof(cp_init));
    
        cp_init.p_conn_params                  = NULL;
        cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
        cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
        cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
        cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
        cp_init.disconnect_on_fail             = false;
        cp_init.evt_handler                    = on_conn_params_evt;
        cp_init.error_handler                  = conn_params_error_handler;
    
        err_code = ble_conn_params_init(&cp_init);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for putting the chip into sleep mode.
     *
     * @note This function will not return.
     */
     int sleep = 0;
    
    static void sleep_mode_enter(void)
    {
        ret_code_t err_code;
        sleep = 1;adv_success = 0;
        NRF_LOG_INFO("SLEEP MODE ENTER\r\n");
    
          nrf_gpio_pin_set(LED_RC_1);    
          nrf_gpio_pin_set(LED_RC_2);  
          nrf_gpio_pin_set(LED_RC_3);  
        
        err_code = bsp_indication_set(BSP_INDICATE_IDLE);
        APP_ERROR_CHECK(err_code);
    
    
        // Prepare wakeup buttons.
        //err_code = bsp_btn_ble_sleep_mode_prepare();
        //APP_ERROR_CHECK(err_code);
    
        // Go to system-off mode (this function will not return; wakeup will cause a reset).
        err_code = sd_power_system_off();
        //nrf_power_system_off();
       
    }
    
    
    /**@brief Function for handling advertising events.
     *
     * @details This function will be called for advertising events which are passed to the application.
     *
     * @param[in] ble_adv_evt  Advertising event.
     */
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
    {
        uint32_t err_code;
    
        switch (ble_adv_evt) {
        case BLE_ADV_EVT_FAST:
            NRF_LOG_INFO("Fast advertising.");
            err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            APP_ERROR_CHECK(err_code);
            break;
    
        case BLE_ADV_EVT_IDLE:
             {
               //sleep_mode_enter();
             }
            break;
    
        default:
            break;
        }
    }
    
    
    extern uint8_t led_all_active;
    extern uint8_t led_all_state;
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        uint32_t err_code;
        led_btn_task_evt_t evt;
    
        switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED:
            NRF_LOG_INFO("APP is Connected\n\r");
            //err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            //APP_ERROR_CHECK(err_code);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
            APP_ERROR_CHECK(err_code);
    
            adv_led_button =1;
            led_blue_pwr_active = 1;rtc_val=0;
            led_on_duration = get_system_rtc();
            evt.id = LED_TASK_EVT_PROCESS_LED_RC1; // glow green led to indicate successful connection of the app.
    
            led_btn_task_queue_event(evt);
    
    
            break;
    
        case BLE_GAP_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected");
           // turn_off_wireless_charging();
                led_on_duration = 0;
                adv_led_button = 0;
                led_blue_pwr_active = 0;
                led_blue_pwr_state = 0;
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            break;
    
        case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
            NRF_LOG_DEBUG("PHY update request.");
            ble_gap_phys_t const phys = {
                .rx_phys = BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_AUTO,
            };
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
        }
        break;
    
        case BLE_GATTC_EVT_TIMEOUT:
            // Disconnect on GATT Client timeout event.
            NRF_LOG_DEBUG("GATT Client Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
    
        case BLE_GATTS_EVT_TIMEOUT:
            // Disconnect on GATT Server timeout event.
            NRF_LOG_DEBUG("GATT Server Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
    
        default:
            // No implementation needed.
            break;
        }
    }
    
    
    
    static void ble_evt_handler1111(ble_evt_t const * p_ble_evt, void * p_context)
    {
        char        passkey[BLE_GAP_PASSKEY_LEN + 1];
        uint16_t    role = ble_conn_state_role(m_conn_handle);
    
     //   pm_handler_secure_on_connection(p_ble_evt);
    
        uint32_t err_code;
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; //$$ new
    
        switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED:
            NRF_LOG_INFO("Connected");
            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            APP_ERROR_CHECK(err_code);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
            APP_ERROR_CHECK(err_code);
    
            //adv_led_button =1;
            //led_grn_pwr_active = 1;
            //led_on_duration = get_system_rtc();
            //led_btn_task_evt_t evt;
            //evt.id = LED_TASK_EVT_PROCESS_LED_RC2;
    
            //led_btn_task_queue_event(evt);
    
    
            err_code = sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle,1,2); //$$ new
            APP_ERROR_CHECK(err_code); //$$ new      
          
        break;
    
        case BLE_GAP_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected");
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            break;
    #if 1
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                //NRF_LOG_INFO("%s: BLE_GAP_EVT_SEC_PARAMS_REQUEST", nrf_log_push(roles_str[role]));
                break;
    
    
            //case BLE_GAP_EVT_PASSKEY_DISPLAY:
            //    memcpy(passkey, p_ble_evt->evt.gap_evt.params.passkey_display.passkey, BLE_GAP_PASSKEY_LEN);
            //    passkey[BLE_GAP_PASSKEY_LEN] = 0x00;
            //    NRF_LOG_INFO("%s: BLE_GAP_EVT_PASSKEY_DISPLAY: passkey=%s match_req=%d",
            //                 nrf_log_push(roles_str[role]),
            //                 nrf_log_push(passkey),
            //                 p_ble_evt->evt.gap_evt.params.passkey_display.match_request);
    
            //    if (p_ble_evt->evt.gap_evt.params.passkey_display.match_request)
            //    {
            //        on_match_request(m_conn_handle, role);
            //    }
            //    break;
    
         /*sne   case BLE_GAP_EVT_PASSKEY_DISPLAY:
            {
                //char passkey[16 + 1];
                memcpy(passkey, p_ble_evt->evt.gap_evt.params.passkey_display.passkey, 16);
                passkey[16] = 0;
                // Don't send delayed Security Request if security procedure is already in progress.
                //err_code = app_timer_stop(m_sec_req_timer_id);
                //APP_ERROR_CHECK(err_code);
    
                NRF_LOG_INFO("Passkey: %s", nrf_log_push(passkey));
            } break; sne */
    
      /*sne      case BLE_GAP_EVT_AUTH_KEY_REQUEST:
               // NRF_LOG_INFO("%s: BLE_GAP_EVT_AUTH_KEY_REQUEST", nrf_log_push(roles_str[role]));
                break;
    
            case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
                //NRF_LOG_INFO("%s: BLE_GAP_EVT_LESC_DHKEY_REQUEST", nrf_log_push(roles_str[role]));
                break;
    
             case BLE_GAP_EVT_AUTH_STATUS:
                 //NRF_LOG_INFO("%s: BLE_GAP_EVT_AUTH_STATUS: status=0x%x bond=0x%x lv4: %d kdist_own:0x%x kdist_peer:0x%x",
                 //             nrf_log_push(roles_str[role]),
                              //p_ble_evt->evt.gap_evt.params.auth_status.auth_status,
                              //p_ble_evt->evt.gap_evt.params.auth_status.bonded,
                              //p_ble_evt->evt.gap_evt.params.auth_status.sm1_levels.lv4,
                              //*((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_own),
                              //*((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_peer));
                break; sne*/
    #endif
    
        case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
            NRF_LOG_DEBUG("PHY update request.");
            ble_gap_phys_t const phys = {
                .rx_phys = BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_AUTO,
            };
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
        }
        break;
    
        case BLE_GATTC_EVT_TIMEOUT:
            // Disconnect on GATT Client timeout event.
            NRF_LOG_DEBUG("GATT Client Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
    
        case BLE_GATTS_EVT_TIMEOUT:
            // Disconnect on GATT Server timeout event.
            NRF_LOG_DEBUG("GATT Server Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
    
        case BLE_GAP_EVT_RSSI_CHANGED:
             rssi = p_ble_evt->evt.gap_evt.params.rssi_changed.rssi;
            // NRF_LOG_INFO("RSSI: %d", p_ble_evt->evt.gap_evt.params.rssi_changed.rssi);
            break;
    
        default:
            // No implementation needed.
            break;
        }
    }
    
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    
    /**@brief Function for handling events from the BSP module.
     *
     * @param[in]   event   Event generated by button press.
     */
    static void bsp_event_handler(bsp_event_t event)
    {
        ret_code_t err_code;
    
        switch (event) {
        case BSP_EVENT_SLEEP:
           // sleep_mode_enter();
            break;
    
        case BSP_EVENT_DISCONNECT:
            err_code = sd_ble_gap_disconnect(m_conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            if (err_code != NRF_ERROR_INVALID_STATE) {
                APP_ERROR_CHECK(err_code);
            }
            break;
    
        case BSP_EVENT_WHITELIST_OFF:
            if (m_conn_handle == BLE_CONN_HANDLE_INVALID) {
                err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                if (err_code != NRF_ERROR_INVALID_STATE) {
                    APP_ERROR_CHECK(err_code);
                }
            }
            break;
        default:
            break;
        }
    }
    
    /**@brief Function for handling events from the GATT library. */
    //void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
    //{
    //    if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
    //    {
    //        m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
    //        NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
    //    }
    //    NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
    //                  p_gatt->att_mtu_desired_central,
    //                  p_gatt->att_mtu_desired_periph);
    //}
    
    
    /**@brief Function for the Peer Manager initialization. */
    static void peer_manager_init(void)
    {
        ble_gap_sec_params_t sec_param;
        ret_code_t           err_code;
    
        err_code = pm_init();
        APP_ERROR_CHECK(err_code);
    
    
    
        memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
    
        // Security parameters to be used for all security procedures.
        sec_param.bond           = SEC_PARAM_BOND;
        sec_param.mitm           = SEC_PARAM_MITM;
        sec_param.lesc           = SEC_PARAM_LESC;
        sec_param.keypress       = SEC_PARAM_KEYPRESS;
        sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
        sec_param.oob            = SEC_PARAM_OOB;
        sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
        sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
        sec_param.kdist_own.enc  = 0;
        sec_param.kdist_own.id   = 0;
        sec_param.kdist_peer.enc = 0;
        sec_param.kdist_peer.id  = 0;
    
        err_code = pm_sec_params_set(&sec_param);
        APP_ERROR_CHECK(err_code);
    
        err_code = pm_register(pm_evt_handler);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Clear bond information from persistent storage. */
    static void delete_bonds(void)
    {
        ret_code_t err_code;
    
        NRF_LOG_INFO("Erase bonds!");
    
        err_code = pm_peers_delete();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing the Advertising functionality. */
    
    
    static void advertising_init(void)
    {
        ret_code_t             err_code;
        ble_advertising_init_t init;
    
        memset(&init, 0, sizeof(init));
    
        init.advdata.name_type               = BLE_ADVDATA_NO_NAME;
        init.advdata.include_appearance      = false;
        init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;//BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        init.advdata.uuids_more_available.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.advdata.uuids_more_available.p_uuids  = m_adv_uuids;
    
        init.config.ble_adv_fast_enabled  = true;
        init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
        init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    
    
        init.srdata.name_type = BLE_ADVDATA_FULL_NAME;
    
        init.evt_handler = on_adv_evt;
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    
    
    /**@brief Function for initializing the nrf log module.
     */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
       // ret_code_t err_code = NRF_LOG_INIT(app_timer_cnt_get); //..snehal
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    /**@brief Function for starting advertising. */
    void advertising_start(void * p_erase_bonds)
    {
        bool erase_bonds = *(bool*)p_erase_bonds;
        ret_code_t err_code;
    
        if (erase_bonds) {
            delete_bonds();
            // Advertising is started by PM_EVT_PEERS_DELETE_SUCCEEDED event.
        } else {
            err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
            APP_ERROR_CHECK(err_code);
        }
    
        NRF_LOG_INFO("ERROR CODE adv IS %d\r\n",err_code);
        if(err_code == 0)
        {
          adv_success  = 1;
        }
        else
        {
          adv_success  = 0;
        }
    }
    
    /* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
    implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
    used by the Idle task. */
    void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
                                        StackType_t **ppxIdleTaskStackBuffer,
                                        uint32_t *pulIdleTaskStackSize )
    {
        /* If the buffers to be provided to the Idle task are declared inside this
        function then they must be declared static - otherwise they will be allocated on
        the stack and so not exists after this function exits. */
        static StaticTask_t xIdleTaskTCB;
        static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
    
        /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
        state will be stored. */
        *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
    
        /* Pass out the array that will be used as the Idle task's stack. */
        *ppxIdleTaskStackBuffer = uxIdleTaskStack;
    
        /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
        Note that, as the array is necessarily of type StackType_t,
        configMINIMAL_STACK_SIZE is specified in words, not bytes. */
        *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
    }
    
    /* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
    application must provide an implementation of vApplicationGetTimerTaskMemory()
    to provide the memory that is used by the Timer service task. */
    void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
                                         StackType_t **ppxTimerTaskStackBuffer,
                                         uint32_t *pulTimerTaskStackSize )
    {
        /* If the buffers to be provided to the Timer task are declared inside this
        function then they must be declared static - otherwise they will be allocated on
        the stack and so not exists after this function exits. */
        static StaticTask_t xTimerTaskTCB;
        static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
    
        /* Pass out a pointer to the StaticTask_t structure in which the Timer
        task's state will be stored. */
        *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
    
        /* Pass out the array that will be used as the Timer task's stack. */
        *ppxTimerTaskStackBuffer = uxTimerTaskStack;
    
        /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
        Note that, as the array is necessarily of type StackType_t,
        configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
        *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
    }
    
    void vApplicationMallocFailedHook( void )
    {
        NRF_LOG_INFO("Malloc Failed");
    }
    
    void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char *pcTaskName )
    {
    
       for( ;; );
    }
    
    
    #if NRF_LOG_ENABLED
    /**@brief Thread for handling the logger.
     *
     * @details This thread is responsible for processing log entries if logs are deferred.
     *          Thread flushes all log entries and suspends. It is resumed by idle task hook.
     *
     * @param[in]   arg   Pointer used for passing some arbitrary information (context) from the
     *                    osThreadCreate() call to the thread.
     */
    static void logger_thread(void * arg)
    {
        UNUSED_PARAMETER(arg);
    
        while (1) {
            NRF_LOG_FLUSH();
    
            vTaskSuspend(NULL); // Suspend myself
        }
    }
    #endif //NRF_LOG_ENABLED
    
    /**@brief A function which is hooked to idle task.
     * @note Idle hook must be enabled in FreeRTOS configuration (configUSE_IDLE_HOOK).
     */
    void vApplicationIdleHook( void )
    {
    #if NRF_LOG_ENABLED
        vTaskResume(m_logger_thread);
    #endif
    }
    
    
    /**@brief Function for initializing the clock.
     */
    static void clock_init(void)
    {
        ret_code_t err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
    }
    
    #define LOGGER_TASK_STACK_SIZE 512
    #define LOGGER_TASK_PRIORITY   1
    /* Structure that will hold the TCB of the task being created. */
    StaticTask_t xLoggerTaskBuffer;
    
    /* Buffer that the task being created will use as its stack.  Note this is
    an array of StackType_t variables.  The size of StackType_t is dependent on
    the RTOS port. */
    StackType_t xLoggerStack[ LOGGER_TASK_STACK_SIZE ];
    
    
    /**@brief Function for application main entry.
     */
    /////////////////// USB MSC CODE /////////////////////////////////////
    
    bool g_test_open = false;
    uint32_t g_idle_s = 0;
    uint16_t rx_index;
    uint8_t m_rx = {0};
    uint8_t rx_buff[1024];
    
    #define CLOSE_FILE_BY_TIMER   0
    #define CLOSE_FILE_BY_STRING  1
    
    APP_TIMER_DEF(file_close_timer_id);
    #define USE_FATFS_SPI    1
    
    #ifndef USBD_POWER_DETECTION
    #define USBD_POWER_DETECTION true
    #endif
    
    static void msc_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                    app_usbd_msc_user_event_t     event);
    
    
    
    #define FR_FILE_OPENED 1
    #define FR_FILE_CLOSED 2
    
    const char my_filename[] = "test1.xls";
    
    
    NRF_BLOCK_DEV_SPI_DEFINE(
        m_block_dev_spi,
        NRF_BLOCK_DEV_SPI_CONFIG(
            512,
            NRF_BLOCK_DEV_SPI_FLAG_CACHE_WRITEBACK,
            NRF_DRV_SPI_DEFAULT_CONFIG
         ),
         NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SPI", "1.00")
    );
    
    #define BLOCKDEV_LIST() (                                   \
        NRF_BLOCKDEV_BASE_ADDR(m_block_dev_spi, block_dev)     \
    )
    
    /**
     * @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)
    
    /**
     * @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);
    
    static nrf_atomic_u32_t m_key_events;
    static bool m_usb_connected = false;
    
    
    
    static FATFS m_filesystem;
    
    void fatfs_mkfs(void)
    {
        FRESULT ff_result;
    
        if (m_usb_connected)
        {
            NRF_LOG_ERROR("Unable to operate on filesystem while USB is connected");
            return;
        }
    
        NRF_LOG_INFO("\r\nCreating filesystem...");
         uint8_t buf[4096] = {0};
      //  ff_result = f_mkfs("", FM_FAT, 1024, buf, sizeof(buf));
       // ff_result = f_mkfs("", FM_FAT, 4096, buf, sizeof(buf));
      ff_result = f_mkfs("", FM_FAT | FM_SFD, 4096, buf, sizeof(buf));
    
    
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("Mkfs failed with error %d",ff_result);
            return;
        }
    
        NRF_LOG_INFO("Mounting volume...");
        ff_result = f_mount(&m_filesystem, "", 1);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("Mount failed err %d",ff_result);
            return;
        }
    
        NRF_LOG_INFO("Done");
    }
    
    
    
    
    static bool fatfs_init(void)
    {
        FRESULT ff_result;
        DSTATUS disk_state = STA_NOINIT;
    
        memset(&m_filesystem, 0, sizeof(FATFS));
    
        // 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_spi, block_dev), NULL)
        };
    
        diskio_blockdev_register(drives, ARRAY_SIZE(drives));
    
        NRF_LOG_INFO("Initializing disk 0 (SPI)...");
        disk_state = disk_initialize(0);
        if (disk_state)
        {
            NRF_LOG_ERROR("Disk initialization failed.disk_state<%d>", disk_state);
            return false;
        }
        NRF_LOG_ERROR("disk_state <%d>", disk_state);
        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.");
                fatfs_mkfs();// flash is new, should execute this here once, and then it can be annotated 
            }
            else
            {
                NRF_LOG_ERROR("Mount failed: %u", ff_result);
            }
            return false;
        }
    
        return true;
    }
    
    
    
    static void fatfs_ls(void)
    {
        DIR dir;
        FRESULT ff_result;
        FILINFO fno;
    
        if (m_usb_connected)
        {
            NRF_LOG_ERROR("Unable to operate on filesystem while USB is connected");
            return;
        }
    
        NRF_LOG_INFO("\r\nListing directory: /");
        ff_result = f_opendir(&dir, "/");
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("Directory listing failed: %u", ff_result);
            return;
        }
    
        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;
            }
    
            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);
    }
    
    
    
    
    static void fatfs_file_create(void)
    {
        FRESULT ff_result;
        FIL file;
    
    
        if (m_usb_connected)
        {
            NRF_LOG_ERROR("Unable to operate on filesystem while USB is connected");
            return;
        }
    
        NRF_LOG_RAW_INFO("Creating random file: %s ...", (uint32_t)my_filename);
        NRF_LOG_FLUSH();
    
        ff_result = f_open(&file, my_filename, FA_CREATE_ALWAYS | FA_WRITE);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to open or create file: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
    
    //write a string
    
        static BYTE test_string[] = "christophe\t1995\t0707\r\nsid\t1997\t1234\r\n";
        UINT data_len_written = 0;
        ff_result = f_write(&file, test_string, (UINT)strlen(test_string), &data_len_written);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to write data: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
    
    
        ff_result = f_close(&file);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to close file: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
        NRF_LOG_RAW_INFO("done\r\n");
    
    }
    
    
    static FRESULT my_file_open(FIL* my_file)
    {
        FRESULT ff_result;
        ret_code_t err_code;
    
        if (g_test_open)
        {
            return FR_FILE_OPENED;
        }
    
        ff_result = f_open(my_file, my_filename, FA_OPEN_ALWAYS | FA_WRITE | FA_OPEN_APPEND);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to open or create file: %u", ff_result);
            NRF_LOG_FLUSH();
            return ff_result;
        }
    
    #if CLOSE_FILE_BY_TIMER
        err_code = app_timer_start(file_close_timer_id, CLOSE_INTERVAL, NULL);
        APP_ERROR_CHECK(err_code);
    #endif
    
        g_test_open = true;
    
          return ff_result;
    }
    
    #if 0
    static void my_file_write(void)
    {
        FRESULT ff_result;
        FIL file;
    
        ff_result = f_write(&file, test, (UINT)strlen(test), &written);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to write data: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
    
    }
    #endif
    
    static FRESULT my_file_close(FIL * my_file)
    {
        FRESULT ff_result;
    
        if (g_test_open == false)
        {
            return FR_FILE_CLOSED;
           
        }
    
        ff_result = f_close(my_file);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to close file: %u", ff_result);
            NRF_LOG_FLUSH();
            return ff_result;
        }
        NRF_LOG_RAW_INFO("done\r\n");
    
        g_test_open = false;
    #if CLOSE_FILE_BY_TIMER
        //app_timer_stop(file_close_timer_id);
    #endif
        NRF_LOG_RAW_INFO("file closed!\r\n"); 
        NRF_LOG_FLUSH();
    
         return ff_result;
    
    }
    
    
    static void my_write_data(void)
    {
    
        FRESULT ff_result;
        FIL file;
    
        ff_result = f_open(&file, my_filename, FA_CREATE_ALWAYS | FA_WRITE);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to open or create file: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
    
    //write a string
    
    #if 1
    //    ff_result = f_lseek(&file, file.obj->fs.fsize));
    //    if (ff_result != FR_OK)
    //    {
    //        NRF_LOG_ERROR("\r\nUnable to write data: %u", ff_result);
    //        NRF_LOG_FLUSH();
    //        return;
    //    }
    
    
        static BYTE test[] = "1111\t2222\t3333\r\n4444\t5555\t6666\r\n";
        UINT written = 0;
        ff_result = f_write(&file, test, (UINT)strlen(test), &written);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to write data: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
    
        ff_result = f_close(&file);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to close file: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
        NRF_LOG_RAW_INFO("done\r\n");
    
    }
    
    static void fatfs_uninit(void)
    {
        NRF_LOG_INFO("Un-initializing disk 0 (SPI)...");
        UNUSED_RETURN_VALUE(disk_uninitialize(0));
    }
    
    
    /**
     * @brief Class specific event handler.
     *
     * @param p_inst    Class instance.
     * @param event     Class specific event.
     */
    static void msc_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                    app_usbd_msc_user_event_t     event)
    {
        UNUSED_PARAMETER(p_inst);
        UNUSED_PARAMETER(event);
    }
    
    
    /**
     * @brief USBD library specific event handler.
     *
     * @param event     USBD library event.
     */
    static void usbd_user_ev_handler(app_usbd_event_type_t event)
    {
        switch (event)
        {
            case APP_USBD_EVT_DRV_SUSPEND:
                //bsp_board_led_off(LED_USB_RESUME);
                break;
            case APP_USBD_EVT_DRV_RESUME:
                //bsp_board_led_on(LED_USB_RESUME);
                break;
            case APP_USBD_EVT_STARTED:
                //bsp_board_led_on(LED_USB_START);
                break;
            case APP_USBD_EVT_STOPPED:
                UNUSED_RETURN_VALUE(fatfs_init());
                app_usbd_disable();
                //bsp_board_leds_off();
                break;
            case APP_USBD_EVT_POWER_DETECTED:
                NRF_LOG_INFO("USB power detected");
    
                if (!nrf_drv_usbd_is_enabled())
                {
                    fatfs_uninit();
                    app_usbd_enable();
                }
                break;
            case APP_USBD_EVT_POWER_REMOVED:
                NRF_LOG_INFO("USB power removed");
                app_usbd_stop();
                m_usb_connected = false;
                //memset(&m_rx, 0, sizeof(m_rx));
                break;
            case APP_USBD_EVT_POWER_READY:
                NRF_LOG_INFO("USB ready");
                app_usbd_start();
                m_usb_connected = true;
                break;
            default:
                break;
        }
    }
    
    
    #endif
    
    
    static void close_file_handler(void * p_context)
    {
        UNUSED_PARAMETER(p_context);
        g_idle_s++;
    
    }
    
    
    static void timers_init(void)
    {
        // Initialize timer module.
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
        err_code = app_timer_create(&file_close_timer_id,
                                    APP_TIMER_MODE_REPEATED,
                                    close_file_handler);
        APP_ERROR_CHECK(err_code);
    
        // Create timers.
        m_rtc_timer = xTimerCreateStatic("RTC",
                                         RTC_INTERVAL,
                                         pdTRUE,
                                         NULL,
                                         rtc_timeout_handler,
                                         &xRTCTimer);
    
        /* Error checking */
        if (NULL == m_rtc_timer) {
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
    }
    
    
    //////////////////////////////////////////////////////////////////////
    
    int main(void)
    {
        FRESULT ff_result;
        FIL file;
    
        ret_code_t ret;
        static const app_usbd_config_t usbd_config = {
            .ev_state_proc = usbd_user_ev_handler
        };
    
        // Initialize modules.
        log_init();
        clock_init();
        nrf_drv_clock_lfclk_request(NULL);
        
        ret = NRF_LOG_INIT(app_timer_cnt_get);
        APP_ERROR_CHECK(ret);
        NRF_LOG_INFO("TESTING NEW FIRMWARE");
       
        ret = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(ret);
        
        gpio_init();
        timers_init();    
        application_timers_start();
    
        NRF_LOG_INFO("Firmware Starting");
        NRF_LOG_INFO("FW Version: %s", app_fw_version);
        
        nrf_gpio_pin_set(EN_SUPPLY);
     
        start_charging();
        // stop_charging();
        nrf_delay_ms(1000);
        spi_init();
        nrf_delay_ms(2000);
    
        if (fatfs_init())
        {
              fatfs_ls();
              fatfs_file_create();
    
        }
              fatfs_ls();
              fatfs_file_create();
              fatfs_ls();
                  
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(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);
    
        NRF_LOG_FLUSH();
    
        NRF_LOG_INFO("USBD MSC example started.");
    
        if (true)
        {
            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;
        }
        
        uint8_t write_cnt = 0;       
    
        while (true)
        {
    
            while (app_usbd_event_queue_process())
            {
                /* Nothing to do */
            }
              NRF_LOG_FLUSH();
        }         
    
    }
    
    static void nrf_nvmc_write_word(uint32_t address, uint32_t value)
    {
        // Enable write.
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
        __ISB();
        __DSB();
    
        *(uint32_t*)address = value;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {;}
    
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
        __ISB();
        __DSB();
    }
    
    
    uint32_t app_timer_cnt_get(void)
    {
        return xTaskGetTickCount();
    }
    
    uint32_t app_timer_cnt_diff_compute(uint32_t   ticks_to,
                                        uint32_t   ticks_from)
    {
        return ((ticks_to - ticks_from) & RTC_COUNTER_COUNTER_Msk);
    }
    
    

    Thanks.

Reply
  • Hi Simon,

                I have already used this function in my code. Please take a look at this file. I have used the format function "f_mkfsI()" inside the "fatfs_init()" function. 

    /**
     
     *
     */
    
    #include <stdint.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf.h"
    #include "app_error.h"
    #include "ble.h"
    #include "ble_hci.h"
    #include "ble_srv_common.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_bas.h"
    #include "ble_dis.h"
    #include "ble_conn_params.h"
    #include "sensorsim.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "nrf_sdh_freertos.h"
    #include "app_timer.h"
    #include "peer_manager.h"
    #include "peer_manager_handler.h"
    #include "bsp_btn_ble.h"
    
    #include "fds.h"
    #include "ble_conn_state.h"
    #include "ble_dfu.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_drv_wdt.h"
    #include "nrf_drv_clock.h"
    #include "nrf_ble_gatt.h"
    #include "nrf_ble_qwr.h"
    #include "nrf_power.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "product_config.h"
    #include "ble_clinitraq.h"
    #include "task_led_button.h"
    #include "task_clinitraq_ble.h"
    #include "task_id_accessory.h"
    #include "task_psf_comm.h"
    #include "device_storage.h"
    #include "nrf_drv_gpiote.h"
    #include "battery.h"
    #include "version.h"
    #include "clinitraq_app.h"
    #include "psf_comm.h"
    #include "nrf_drv_twi.h"
    #include "psf_i2c.h"
    #include "task_led_button.h"
    #include "app_button.h"
    
    #include "bq24292i.h"
    #include "max17201_i2c.h"
    #include "nrf_dfu_ble_svci_bond_sharing.h"
    #include "nrf_svci_async_function.h"
    #include "nrf_svci_async_handler.h"
    #include "nrf_bootloader_info.h"
    #include "usb_msc.h"
    #include "bsp.h"
    #include "spi.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 "nrf_block_dev_spi.h"
    
    
    #define MAIN_DEVICE_NAME                         LE_DEVICE_NAME                            /**< Name of device. Will be included in the advertising data. */
    #define MANUFACTURER_NAME                   "test"                   /**< Manufacturer. Will be passed to Device Information Service. */
    
    #define APP_BLE_OBSERVER_PRIO               3                                       /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    #define APP_BLE_CONN_CFG_TAG                1                                       /**< A tag identifying the SoftDevice BLE configuration. */
    
    #define APP_ADV_INTERVAL                    300 //300                                     /**< The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */
    #define APP_ADV_DURATION                    18000 //0                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    
    #define RTC_INTERVAL                        1000                                    /**< RTC interval (ms). */
    #define MIN_BATTERY_LEVEL                   81                                      /**< Minimum simulated battery level. */
    #define MAX_BATTERY_LEVEL                   100                                     /**< Maximum simulated battery level. */
    
    #define MIN_CONN_INTERVAL                   MSEC_TO_UNITS(200, UNIT_1_25_MS)        /**< Minimum acceptable connection interval (0.4 seconds). */
    #define MAX_CONN_INTERVAL                   MSEC_TO_UNITS(300, UNIT_1_25_MS)        /**< Maximum acceptable connection interval (0.65 second). */
    #define SLAVE_LATENCY                       3                                       /**< Slave latency. */
    #define CONN_SUP_TIMEOUT                    MSEC_TO_UNITS(5000, UNIT_10_MS)         /**< Connection supervisory time-out (4 seconds). */
    
    #define FIRST_CONN_PARAMS_UPDATE_DELAY      5000                                    /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
    #define NEXT_CONN_PARAMS_UPDATE_DELAY       30000                                   /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
    #define MAX_CONN_PARAMS_UPDATE_COUNT        3                                       /**< Number of attempts before giving up the connection parameter negotiation. */
    
    #define SEC_PARAM_BOND                      0                                       /**< Perform bonding. */
    #define SEC_PARAM_MITM                      0                                       /**< Man In The Middle protection not required. */
    #define SEC_PARAM_LESC                      0                                       /**< LE Secure Connections not enabled. */
    #define SEC_PARAM_KEYPRESS                  0                                       /**< Keypress notifications not enabled. */
    #define SEC_PARAM_IO_CAPABILITIES           BLE_GAP_IO_CAPS_NONE                    /**< No I/O capabilities. */
    #define SEC_PARAM_OOB                       0                                       /**< Out Of Band data not available. */
    #define SEC_PARAM_MIN_KEY_SIZE              16                                      /**< Minimum encryption key size. */
    #define SEC_PARAM_MAX_KEY_SIZE              16                                      /**< Maximum encryption key size. */
    
    #define DEAD_BEEF                           0xDEADBEEF                              /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    
    #define OSTIMER_WAIT_FOR_QUEUE              2                                       /**< Number of ticks to wait for the timer queue to be ready */
    
    #define DEVICEID_SIZE           16
    uint8_t device_id[DEVICEID_SIZE+1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    
    extern uint8_t adv_led_button;
    extern uint8_t led_on_duration;
    extern uint8_t led_grn_pwr_active;
    extern uint8_t led_grn_pwr_state;
    extern uint8_t led_blue_pwr_active ;
    extern uint8_t led_blue_pwr_state ;
    int8_t rssi;
    extern int wireless_charging_on;
    
    static char app_fw_version[32];
    static char pulsecount[20];
    //uint8_t rclr_data_buf[256] = {0};
    uint8_t rcbr_data_buf[256] = {0};
    //uint16_t rclr_data_cnt = 0;
    uint16_t rcbr_data_cnt = 0;
    
    extern bq24292i_charge_state_t charge_state;
    
    
    BLE_RCBR_DEF(m_rcbr, NRF_SDH_BLE_TOTAL_LINK_COUNT);                  /**< BLE R3charge borrower service instance. */
    
    BLE_BAS_DEF(m_bas);                                                 /**< Battery service instance. */
    NRF_BLE_GATT_DEF(m_gatt);                                           /**< GATT module instance. */
    NRF_BLE_QWR_DEF(m_qwr);                                             /**< Context for the Queued Write module.*/
    BLE_ADVERTISING_DEF(m_advertising);                                 /**< Advertising module instance. */
    
    nrfx_wdt_channel_id m_channel_id;
    
    ////////////Added for bonding///////////
    // Static passkey
    #define STATIC_PASSKEY    "123456" 
    static ble_opt_t    m_static_pin_option;
    uint8_t passkey[] = STATIC_PASSKEY; 
    ////////////Added for bonding///////////
    static uint16_t m_conn_handle         = BLE_CONN_HANDLE_INVALID;    /**< Handle of the current connection. */
    int adv_success = 0;
    
    static ble_uuid_t m_adv_uuids[] =                                   /**< Universally unique service identifiers. */
    {
        {BLE_UUID_RCBR_SERVICE, BLE_UUID_TYPE_VENDOR_BEGIN}
    };
    
    
    
    
    /**@brief Handler for shutdown preparation.
     *
     * @details During shutdown procedures, this function will be called at a 1 second interval
     *          untill the function returns true. When the function returns true, it means that the
     *          app is ready to reset to DFU mode.
     *
     * @param[in]   event   Power manager event.
     *
     * @retval  True if shutdown is allowed by this power manager handler, otherwise false.
     */
    static bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event)
    {
        switch (event)
        {
            case NRF_PWR_MGMT_EVT_PREPARE_DFU:
                NRF_LOG_INFO("Power management wants to reset to DFU mode.");
                // YOUR_JOB: Get ready to reset into DFU mode
                //
                // If you aren't finished with any ongoing tasks, return "false" to
                // signal to the system that reset is impossible at this stage.
                //
                // Here is an example using a variable to delay resetting the device.
                //
                // if (!m_ready_for_reset)
                // {
                //      return false;
                // }
                // else
                //{
                //
                //    // Device ready to enter
                //    uint32_t err_code;
                //    err_code = sd_softdevice_disable();
                //    APP_ERROR_CHECK(err_code);
                //    err_code = app_timer_stop_all();
                //    APP_ERROR_CHECK(err_code);
                //}
                break;
    
            default:
                // YOUR_JOB: Implement any of the other events available from the power management module:
                //      -NRF_PWR_MGMT_EVT_PREPARE_SYSOFF
                //      -NRF_PWR_MGMT_EVT_PREPARE_WAKEUP
                //      -NRF_PWR_MGMT_EVT_PREPARE_RESET
                return true;
        }
    
        NRF_LOG_INFO("Power management allowed to reset to DFU mode.");
        return true;
    }
    
    //lint -esym(528, m_app_shutdown_handler)
    /**@brief Register application shutdown handler with priority 0.
     */
    NRF_PWR_MGMT_HANDLER_REGISTER(app_shutdown_handler, 0);
    
    
    static void buttonless_dfu_sdh_state_observer(nrf_sdh_state_evt_t state, void * p_context)
    {
        if (state == NRF_SDH_EVT_STATE_DISABLED)
        {
            // Softdevice was disabled before going into reset. Inform bootloader to skip CRC on next boot.
            nrf_power_gpregret2_set(BOOTLOADER_DFU_SKIP_CRC);
    
            //Go to system off.
            nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
        }
    }
    
    /* nrf_sdh state observer. */
    NRF_SDH_STATE_OBSERVER(m_buttonless_dfu_state_obs, 0) =
    {
        .handler = buttonless_dfu_sdh_state_observer,
    };
    
    
    static void advertising_config_get(ble_adv_modes_config_t * p_config)
    {
        memset(p_config, 0, sizeof(ble_adv_modes_config_t));
    
        p_config->ble_adv_fast_enabled  = true;
        p_config->ble_adv_fast_interval = APP_ADV_INTERVAL;
        p_config->ble_adv_fast_timeout  = APP_ADV_DURATION;
    }
    
    
    static void disconnect(uint16_t conn_handle, void * p_context)
    {
        UNUSED_PARAMETER(p_context);
    
        ret_code_t err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_WARNING("Failed to disconnect connection. Connection handle: %d Error: %d", conn_handle, err_code);
        }
        else
        {
            NRF_LOG_DEBUG("Disconnected connection handle %d", conn_handle);
        }
    }
    
    static TimerHandle_t m_rtc_timer;                               /**< Definition of battery timer. */
    
    #if NRF_LOG_ENABLED
    static TaskHandle_t m_logger_thread;                                /**< Definition of Logger thread. */
    #endif
    
    //static void advertising_start(void * p_erase_bonds);
    static void nrf_nvmc_write_word(uint32_t address, uint32_t value);
    
    //ble_rclr_t * get_rclr_service(void)
    //{
    //    return &m_rclr;
    //}
    
    ble_rcbr_t * get_rcbr_service(void)
    {
        return &m_rcbr;
    }
    
    
    uint16_t get_conn_handle(void)
    {
        return m_conn_handle;
    }
    
    
    //uint8_t * get_rclr_rcv_buffer(void)
    //{
    //    return rclr_data_buf;
    //}
    
    //uint16_t get_rclr_rcv_cnt(void)
    //{
    //    return rclr_data_cnt;
    //}
    
    uint8_t * get_rcbr_rcv_buffer(void)
    {
        return rcbr_data_buf;
    }
    
    uint16_t get_rcbr_rcv_cnt(void)
    {
        return rcbr_data_cnt;
    }
    
    /**@brief Callback function for asserts in the SoftDevice.
     *
     * @details This function will be called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and does not fit a final product. You need to analyze
     *          how your product is supposed to react in case of Assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in]   line_num   Line number of the failing ASSERT call.
     * @param[in]   file_name  File name of the failing ASSERT call.
     */
    void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(DEAD_BEEF, line_num, p_file_name);
    }
    
    
    void wdt_event_handler(void)
    {
    
    }
    
    #define NRFX_WDT_DEAFULT_CONFIG_1                                             \
        {                                                                         \
            .behaviour          = WDT_CONFIG_BEHAVIOUR,                           \
            .reload_value       = WDT_CONFIG_RELOAD_VALUE,                   \
            NRFX_WDT_IRQ_CONFIG                                                   \
        }
    
    void wdt_init(void)
    {
      uint32_t err_code = NRF_SUCCESS;
    
      nrfx_wdt_config_t w_config  = NRFX_WDT_DEAFULT_CONFIG;
      
      err_code = nrfx_wdt_init(&w_config, NULL);
      APP_ERROR_CHECK(err_code);
    
      err_code = nrfx_wdt_channel_alloc(&m_channel_id);
      APP_ERROR_CHECK(err_code);
    
      nrfx_wdt_enable();
    
     
    
    }
    
    /**@brief Function for handling Peer Manager events.
     *
     * @param[in] p_evt  Peer Manager event.
     */
    static void pm_evt_handler(pm_evt_t const * p_evt)
    {
        bool delete_bonds = false;
    
        pm_handler_on_pm_evt(p_evt);
        pm_handler_flash_clean(p_evt);
    
        switch (p_evt->evt_id) {
        case PM_EVT_PEERS_DELETE_SUCCEEDED:
            //..advertising_start(&delete_bonds);
            advertising_start(false);
            break;
    
        default:
            break;
        }
    }
    
    
    /**@brief Function for performing battery measurement and updating the Battery Level characteristic
     *        in Battery Service.
     */
     extern uint8_t SOC;
    
    void battery_level_update(void)
    {
        ret_code_t err_code;
        uint8_t  battery_level;
    
        //battery_level = battery_get_percentage(); /* Update TODO */
        battery_level = SOC; //battery_get_percentage(); /* Update TODO */
    
        err_code = ble_bas_battery_level_update(&m_bas, battery_level, BLE_CONN_HANDLE_ALL);
        if ((err_code != NRF_SUCCESS) &&
                (err_code != NRF_ERROR_INVALID_STATE) &&
                (err_code != NRF_ERROR_RESOURCES) &&
                (err_code != NRF_ERROR_BUSY) &&
                (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
           ) {
            APP_ERROR_HANDLER(err_code);
        }
    }
    
    
    
    
    
    uint32_t rtc_val = 0;
    
    uint32_t get_system_rtc(void)
    {
        return rtc_val;
    }
    
    /**@brief Function for handling the RTC event
     *
     * @details This function will be called each time the RTC timer expires.
     *
     * @param[in] xTimer Handler to the timer that called this function.
     *                   You may get identifier given to the function xTimerCreate using pvTimerGetTimerID.
     */
    static void rtc_timeout_handler(TimerHandle_t xTimer)
    {
        UNUSED_PARAMETER(xTimer);
        rtc_val++;
    }
    
    
    static StaticTimer_t xRTCTimer;
    
    
    /**@brief Function for the GAP initialization.
     *
     * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
     *          device including the device name, appearance, and the preferred connection parameters.
     */
    
    static void gap_params_init(void)
    {
        ret_code_t              err_code;
        ble_gap_conn_params_t   gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        //commented for adding device id.
        //err_code = sd_ble_gap_device_name_set(&sec_mode,
        //                                      (const uint8_t *)DEVICE_NAME,
        //                                      strlen(DEVICE_NAME));
    
    #ifdef USE_DEVICEID_ON_SRDATA
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));
    #else
        uint8_t basename_size = strlen(MAIN_DEVICE_NAME);
        uint8_t devicename[DEVICEID_SIZE+1+basename_size+1];
            
        memcpy(&devicename[0], (const uint8_t *)MAIN_DEVICE_NAME, basename_size);
        devicename[basename_size] = '-';
        memcpy(&devicename[basename_size+1], device_id, DEVICEID_SIZE);
        memset(&devicename[basename_size+1+DEVICEID_SIZE], 0x00, 1);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)devicename,
                                              strlen(devicename));
    #endif
    
    
    
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_UNKNOWN);
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
        gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
        gap_conn_params.slave_latency     = SLAVE_LATENCY;
        gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    /*sne    ////////Added for bonding ///////////
        m_static_pin_option.gap_opt.passkey.p_passkey = &passkey[0]; 
        err_code =  sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option); 
        APP_ERROR_CHECK(err_code);
        ////////Added for bonding /////////// sne*/
    
    
    }
    
    
    /**@brief Function for initializing the GATT module. */
    static void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling Queued Write Module errors.
     *
     * @details A pointer to this function will be passed to each service which may need to inform the
     *          application about an error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void nrf_qwr_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    
    //static void rclr_data_handler(ble_rclr_evt_t * p_evt)
    //{
    //    if (p_evt->type == BLE_RCLR_EVT_RX_DATA) {
    //        uint32_t err_code;
    
    //        if(p_evt->params.rx_data.length < sizeof(rclr_data_buf)) {
    //            memset(rclr_data_buf, 0, sizeof(rclr_data_buf));
    //            memcpy(rclr_data_buf, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
    //            rclr_data_cnt = p_evt->params.rx_data.length;
    
    //            /* Inform lender Task we have a command */
    //            lender_task_queue_event(LENDER_TASK_EVT_SETTING_CMD);
    //        }
    //    } else if(p_evt->type == BLE_RCLR_EVT_NOTIF_ENABLED) {
    //        /* Inform lender Task notifications have begun */
    //        lender_task_queue_event(LENDER_TASK_EVT_NOTIF_EN);
    //    }
    //}
    
    
    static void rcbr_data_handler_new(ble_rcbr_evt_t * p_evt)
    {
        psf_comm_task_evt_t evt;
    
        if (p_evt->type == BLE_RCBR_EVT_RX_DATA) {
            uint32_t err_code;
    
            if(p_evt->params.rx_data.length < MAX_FRAME_PAYLOAD_SIZE) {
              
                evt.evt_id = PSF_COMM_TASK_EVT_PSF_DATA;
                evt.length = p_evt->params.rx_data.length;
                memcpy(evt.payload, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);            
    
                psf_comm_task_queue_event(&evt);
            }
        } else if(p_evt->type == BLE_RCBR_EVT_NOTIF_ENABLED) {
            /* Inform Toilet Task notifications have begun */
            // toilet_task_queue_event(TOILET_TASK_EVT_NOTIF_EN);
        }
    }
    
    
    
    static void rcbr_data_handler(ble_rcbr_evt_t * p_evt)
    {
        if (p_evt->type == BLE_RCBR_EVT_RX_DATA) {
            uint32_t err_code;
    
            if(p_evt->params.rx_data.length < sizeof(rcbr_data_buf)) {
                memset(rcbr_data_buf, 0, sizeof(rcbr_data_buf));
                memcpy(rcbr_data_buf, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
                rcbr_data_cnt = p_evt->params.rx_data.length;
    
                /* Inform borrower Task we have a command */
                clinitraq_task_queue_event(CLINITRAQ_TASK_EVT_SETTING_CMD);
            }
        } else if(p_evt->type == BLE_RCBR_EVT_NOTIF_ENABLED) {
            /* Inform borrower Task notifications have begun */
            clinitraq_task_queue_event(CLINITRAQ_TASK_EVT_NOTIF_EN);
        }
    }
    
    
    static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
    {
        switch (event)
        {
            case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
            {
                NRF_LOG_INFO("Device is preparing to enter bootloader mode.");
    
                // Prevent device from advertising on disconnect.
                ble_adv_modes_config_t config;
                advertising_config_get(&config);
                config.ble_adv_on_disconnect_disabled = true;
                ble_advertising_modes_config_set(&m_advertising, &config);
    
                // Disconnect all other bonded devices that currently are connected.
                // This is required to receive a service changed indication
                // on bootup after a successful (or aborted) Device Firmware Update.
                uint32_t conn_count = ble_conn_state_for_each_connected(disconnect, NULL);
                NRF_LOG_INFO("Disconnected %d links.", conn_count);
                break;
            }
    
            case BLE_DFU_EVT_BOOTLOADER_ENTER:
                // YOUR_JOB: Write app-specific unwritten data to FLASH, control finalization of this
                //           by delaying reset by reporting false in app_shutdown_handler
                NRF_LOG_INFO("Device will enter bootloader mode.");
                break;
    
            case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED:
                NRF_LOG_ERROR("Request to enter bootloader mode failed asynchroneously.");
                // YOUR_JOB: Take corrective measures to resolve the issue
                //           like calling APP_ERROR_CHECK to reset the device.
                break;
    
            case BLE_DFU_EVT_RESPONSE_SEND_ERROR:
                NRF_LOG_ERROR("Request to send a response to client failed.");
                // YOUR_JOB: Take corrective measures to resolve the issue
                //           like calling APP_ERROR_CHECK to reset the device.
                APP_ERROR_CHECK(false);
                break;
    
            default:
                NRF_LOG_ERROR("Unknown event from ble_dfu_buttonless.");
                break;
        }
    }
    
    /**@brief Function for initializing services that will be used by the application.
     *
     * @details Initialize the Heart Rate, Battery and Device Information services.
     */
    static void services_init(void)
    {
        ret_code_t         err_code;
       // ble_rclr_init_t    rclr_init;
        ble_rcbr_init_t    rcbr_init;
        ble_bas_init_t     bas_init;
        ble_dis_init_t     dis_init;
        nrf_ble_qwr_init_t qwr_init = {0};
        ble_dfu_buttonless_init_t dfus_init = {0};
    
        // Initialize Queued Write Module.
        qwr_init.error_handler = nrf_qwr_error_handler;
    
        err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
        APP_ERROR_CHECK(err_code);
    
        // Initialize Battery Service.
        memset(&bas_init, 0, sizeof(bas_init));
    
        // Here the sec level for the Battery Service can be changed/increased.
        bas_init.bl_rd_sec        = SEC_OPEN;
        bas_init.bl_cccd_wr_sec   = SEC_OPEN;
        bas_init.bl_report_rd_sec = SEC_OPEN;
    
        bas_init.evt_handler          = NULL;
        bas_init.support_notification = true;
        bas_init.p_report_ref         = NULL;
        bas_init.initial_batt_level   = 100;
    
        err_code = ble_bas_init(&m_bas, &bas_init);
        APP_ERROR_CHECK(err_code);
    
        // Initialize Device Information Service.
        memset(&dis_init, 0, sizeof(dis_init));
    
        ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, (char *)MANUFACTURER_NAME);
        ble_srv_ascii_to_utf8(&dis_init.model_num_str, (char *)DEVICE_MODEL_NUM);
        ble_srv_ascii_to_utf8(&dis_init.serial_num_str, (char *)device_id);
        ble_srv_ascii_to_utf8(&dis_init.hw_rev_str, (char *)DEVICE_HW_VER);
        ble_srv_ascii_to_utf8(&dis_init.fw_rev_str, (char *)app_fw_version);
    
    
        dis_init.dis_char_rd_sec = SEC_OPEN;
    
    
        err_code = ble_dis_init(&dis_init);
        APP_ERROR_CHECK(err_code);
    
    
        // Initialize RCLR- LENDER Service
        //memset(&rclr_init, 0, sizeof(rclr_init));
    
        //rclr_init.data_handler = rclr_data_handler;
    
        //err_code = ble_rclr_init(&m_rclr, &rclr_init);
        //APP_ERROR_CHECK(err_code);
    
       // Initialize RCBR - BORROWER Service
        memset(&rcbr_init, 0, sizeof(rcbr_init));
    
        rcbr_init.pulsecount   = 100;
        rcbr_init.data_handler = rcbr_data_handler;
    
        err_code = ble_rcbr_init(&m_rcbr, &rcbr_init);
        APP_ERROR_CHECK(err_code);
    
    
        // Initialize the Nordic DFU Buttonless Service
        dfus_init.evt_handler = ble_dfu_evt_handler;
    
        err_code = ble_dfu_buttonless_init(&dfus_init);
        APP_ERROR_CHECK(err_code);
    
    
    }
    
    
    
    /**@brief   Function for starting application timers.
     * @details Timers are run after the scheduler has started.
     */
    static void application_timers_start(void)
    {
        // Start application timers.
        if (pdPASS != xTimerStart(m_rtc_timer, OSTIMER_WAIT_FOR_QUEUE)) {
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
    }
    
    
    /**@brief Function for handling the Connection Parameters Module.
     *
     * @details This function will be called for all events in the Connection Parameters Module which
     *          are passed to the application.
     *          @note All this function does is to disconnect. This could have been done by simply
     *                setting the disconnect_on_fail config parameter, but instead we use the event
     *                handler mechanism to demonstrate its use.
     *
     * @param[in]   p_evt   Event received from the Connection Parameters Module.
     */
    static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
    {
        ret_code_t err_code;
    
        if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) {
            err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    /**@brief Function for handling a Connection Parameters error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    /**@brief Function for initializing the Connection Parameters module. */
    static void conn_params_init(void)
    {
        ret_code_t             err_code;
        ble_conn_params_init_t cp_init;
    
        memset(&cp_init, 0, sizeof(cp_init));
    
        cp_init.p_conn_params                  = NULL;
        cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
        cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
        cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
        cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
        cp_init.disconnect_on_fail             = false;
        cp_init.evt_handler                    = on_conn_params_evt;
        cp_init.error_handler                  = conn_params_error_handler;
    
        err_code = ble_conn_params_init(&cp_init);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for putting the chip into sleep mode.
     *
     * @note This function will not return.
     */
     int sleep = 0;
    
    static void sleep_mode_enter(void)
    {
        ret_code_t err_code;
        sleep = 1;adv_success = 0;
        NRF_LOG_INFO("SLEEP MODE ENTER\r\n");
    
          nrf_gpio_pin_set(LED_RC_1);    
          nrf_gpio_pin_set(LED_RC_2);  
          nrf_gpio_pin_set(LED_RC_3);  
        
        err_code = bsp_indication_set(BSP_INDICATE_IDLE);
        APP_ERROR_CHECK(err_code);
    
    
        // Prepare wakeup buttons.
        //err_code = bsp_btn_ble_sleep_mode_prepare();
        //APP_ERROR_CHECK(err_code);
    
        // Go to system-off mode (this function will not return; wakeup will cause a reset).
        err_code = sd_power_system_off();
        //nrf_power_system_off();
       
    }
    
    
    /**@brief Function for handling advertising events.
     *
     * @details This function will be called for advertising events which are passed to the application.
     *
     * @param[in] ble_adv_evt  Advertising event.
     */
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
    {
        uint32_t err_code;
    
        switch (ble_adv_evt) {
        case BLE_ADV_EVT_FAST:
            NRF_LOG_INFO("Fast advertising.");
            err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            APP_ERROR_CHECK(err_code);
            break;
    
        case BLE_ADV_EVT_IDLE:
             {
               //sleep_mode_enter();
             }
            break;
    
        default:
            break;
        }
    }
    
    
    extern uint8_t led_all_active;
    extern uint8_t led_all_state;
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        uint32_t err_code;
        led_btn_task_evt_t evt;
    
        switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED:
            NRF_LOG_INFO("APP is Connected\n\r");
            //err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            //APP_ERROR_CHECK(err_code);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
            APP_ERROR_CHECK(err_code);
    
            adv_led_button =1;
            led_blue_pwr_active = 1;rtc_val=0;
            led_on_duration = get_system_rtc();
            evt.id = LED_TASK_EVT_PROCESS_LED_RC1; // glow green led to indicate successful connection of the app.
    
            led_btn_task_queue_event(evt);
    
    
            break;
    
        case BLE_GAP_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected");
           // turn_off_wireless_charging();
                led_on_duration = 0;
                adv_led_button = 0;
                led_blue_pwr_active = 0;
                led_blue_pwr_state = 0;
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            break;
    
        case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
            NRF_LOG_DEBUG("PHY update request.");
            ble_gap_phys_t const phys = {
                .rx_phys = BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_AUTO,
            };
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
        }
        break;
    
        case BLE_GATTC_EVT_TIMEOUT:
            // Disconnect on GATT Client timeout event.
            NRF_LOG_DEBUG("GATT Client Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
    
        case BLE_GATTS_EVT_TIMEOUT:
            // Disconnect on GATT Server timeout event.
            NRF_LOG_DEBUG("GATT Server Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
    
        default:
            // No implementation needed.
            break;
        }
    }
    
    
    
    static void ble_evt_handler1111(ble_evt_t const * p_ble_evt, void * p_context)
    {
        char        passkey[BLE_GAP_PASSKEY_LEN + 1];
        uint16_t    role = ble_conn_state_role(m_conn_handle);
    
     //   pm_handler_secure_on_connection(p_ble_evt);
    
        uint32_t err_code;
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; //$$ new
    
        switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED:
            NRF_LOG_INFO("Connected");
            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            APP_ERROR_CHECK(err_code);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
            APP_ERROR_CHECK(err_code);
    
            //adv_led_button =1;
            //led_grn_pwr_active = 1;
            //led_on_duration = get_system_rtc();
            //led_btn_task_evt_t evt;
            //evt.id = LED_TASK_EVT_PROCESS_LED_RC2;
    
            //led_btn_task_queue_event(evt);
    
    
            err_code = sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle,1,2); //$$ new
            APP_ERROR_CHECK(err_code); //$$ new      
          
        break;
    
        case BLE_GAP_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected");
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            break;
    #if 1
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                //NRF_LOG_INFO("%s: BLE_GAP_EVT_SEC_PARAMS_REQUEST", nrf_log_push(roles_str[role]));
                break;
    
    
            //case BLE_GAP_EVT_PASSKEY_DISPLAY:
            //    memcpy(passkey, p_ble_evt->evt.gap_evt.params.passkey_display.passkey, BLE_GAP_PASSKEY_LEN);
            //    passkey[BLE_GAP_PASSKEY_LEN] = 0x00;
            //    NRF_LOG_INFO("%s: BLE_GAP_EVT_PASSKEY_DISPLAY: passkey=%s match_req=%d",
            //                 nrf_log_push(roles_str[role]),
            //                 nrf_log_push(passkey),
            //                 p_ble_evt->evt.gap_evt.params.passkey_display.match_request);
    
            //    if (p_ble_evt->evt.gap_evt.params.passkey_display.match_request)
            //    {
            //        on_match_request(m_conn_handle, role);
            //    }
            //    break;
    
         /*sne   case BLE_GAP_EVT_PASSKEY_DISPLAY:
            {
                //char passkey[16 + 1];
                memcpy(passkey, p_ble_evt->evt.gap_evt.params.passkey_display.passkey, 16);
                passkey[16] = 0;
                // Don't send delayed Security Request if security procedure is already in progress.
                //err_code = app_timer_stop(m_sec_req_timer_id);
                //APP_ERROR_CHECK(err_code);
    
                NRF_LOG_INFO("Passkey: %s", nrf_log_push(passkey));
            } break; sne */
    
      /*sne      case BLE_GAP_EVT_AUTH_KEY_REQUEST:
               // NRF_LOG_INFO("%s: BLE_GAP_EVT_AUTH_KEY_REQUEST", nrf_log_push(roles_str[role]));
                break;
    
            case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
                //NRF_LOG_INFO("%s: BLE_GAP_EVT_LESC_DHKEY_REQUEST", nrf_log_push(roles_str[role]));
                break;
    
             case BLE_GAP_EVT_AUTH_STATUS:
                 //NRF_LOG_INFO("%s: BLE_GAP_EVT_AUTH_STATUS: status=0x%x bond=0x%x lv4: %d kdist_own:0x%x kdist_peer:0x%x",
                 //             nrf_log_push(roles_str[role]),
                              //p_ble_evt->evt.gap_evt.params.auth_status.auth_status,
                              //p_ble_evt->evt.gap_evt.params.auth_status.bonded,
                              //p_ble_evt->evt.gap_evt.params.auth_status.sm1_levels.lv4,
                              //*((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_own),
                              //*((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_peer));
                break; sne*/
    #endif
    
        case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
            NRF_LOG_DEBUG("PHY update request.");
            ble_gap_phys_t const phys = {
                .rx_phys = BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_AUTO,
            };
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
        }
        break;
    
        case BLE_GATTC_EVT_TIMEOUT:
            // Disconnect on GATT Client timeout event.
            NRF_LOG_DEBUG("GATT Client Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
    
        case BLE_GATTS_EVT_TIMEOUT:
            // Disconnect on GATT Server timeout event.
            NRF_LOG_DEBUG("GATT Server Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
    
        case BLE_GAP_EVT_RSSI_CHANGED:
             rssi = p_ble_evt->evt.gap_evt.params.rssi_changed.rssi;
            // NRF_LOG_INFO("RSSI: %d", p_ble_evt->evt.gap_evt.params.rssi_changed.rssi);
            break;
    
        default:
            // No implementation needed.
            break;
        }
    }
    
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    
    /**@brief Function for handling events from the BSP module.
     *
     * @param[in]   event   Event generated by button press.
     */
    static void bsp_event_handler(bsp_event_t event)
    {
        ret_code_t err_code;
    
        switch (event) {
        case BSP_EVENT_SLEEP:
           // sleep_mode_enter();
            break;
    
        case BSP_EVENT_DISCONNECT:
            err_code = sd_ble_gap_disconnect(m_conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            if (err_code != NRF_ERROR_INVALID_STATE) {
                APP_ERROR_CHECK(err_code);
            }
            break;
    
        case BSP_EVENT_WHITELIST_OFF:
            if (m_conn_handle == BLE_CONN_HANDLE_INVALID) {
                err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                if (err_code != NRF_ERROR_INVALID_STATE) {
                    APP_ERROR_CHECK(err_code);
                }
            }
            break;
        default:
            break;
        }
    }
    
    /**@brief Function for handling events from the GATT library. */
    //void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
    //{
    //    if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
    //    {
    //        m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
    //        NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
    //    }
    //    NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
    //                  p_gatt->att_mtu_desired_central,
    //                  p_gatt->att_mtu_desired_periph);
    //}
    
    
    /**@brief Function for the Peer Manager initialization. */
    static void peer_manager_init(void)
    {
        ble_gap_sec_params_t sec_param;
        ret_code_t           err_code;
    
        err_code = pm_init();
        APP_ERROR_CHECK(err_code);
    
    
    
        memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
    
        // Security parameters to be used for all security procedures.
        sec_param.bond           = SEC_PARAM_BOND;
        sec_param.mitm           = SEC_PARAM_MITM;
        sec_param.lesc           = SEC_PARAM_LESC;
        sec_param.keypress       = SEC_PARAM_KEYPRESS;
        sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
        sec_param.oob            = SEC_PARAM_OOB;
        sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
        sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
        sec_param.kdist_own.enc  = 0;
        sec_param.kdist_own.id   = 0;
        sec_param.kdist_peer.enc = 0;
        sec_param.kdist_peer.id  = 0;
    
        err_code = pm_sec_params_set(&sec_param);
        APP_ERROR_CHECK(err_code);
    
        err_code = pm_register(pm_evt_handler);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Clear bond information from persistent storage. */
    static void delete_bonds(void)
    {
        ret_code_t err_code;
    
        NRF_LOG_INFO("Erase bonds!");
    
        err_code = pm_peers_delete();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing the Advertising functionality. */
    
    
    static void advertising_init(void)
    {
        ret_code_t             err_code;
        ble_advertising_init_t init;
    
        memset(&init, 0, sizeof(init));
    
        init.advdata.name_type               = BLE_ADVDATA_NO_NAME;
        init.advdata.include_appearance      = false;
        init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;//BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        init.advdata.uuids_more_available.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.advdata.uuids_more_available.p_uuids  = m_adv_uuids;
    
        init.config.ble_adv_fast_enabled  = true;
        init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
        init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    
    
        init.srdata.name_type = BLE_ADVDATA_FULL_NAME;
    
        init.evt_handler = on_adv_evt;
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    
    
    /**@brief Function for initializing the nrf log module.
     */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
       // ret_code_t err_code = NRF_LOG_INIT(app_timer_cnt_get); //..snehal
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    /**@brief Function for starting advertising. */
    void advertising_start(void * p_erase_bonds)
    {
        bool erase_bonds = *(bool*)p_erase_bonds;
        ret_code_t err_code;
    
        if (erase_bonds) {
            delete_bonds();
            // Advertising is started by PM_EVT_PEERS_DELETE_SUCCEEDED event.
        } else {
            err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
            APP_ERROR_CHECK(err_code);
        }
    
        NRF_LOG_INFO("ERROR CODE adv IS %d\r\n",err_code);
        if(err_code == 0)
        {
          adv_success  = 1;
        }
        else
        {
          adv_success  = 0;
        }
    }
    
    /* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
    implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
    used by the Idle task. */
    void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
                                        StackType_t **ppxIdleTaskStackBuffer,
                                        uint32_t *pulIdleTaskStackSize )
    {
        /* If the buffers to be provided to the Idle task are declared inside this
        function then they must be declared static - otherwise they will be allocated on
        the stack and so not exists after this function exits. */
        static StaticTask_t xIdleTaskTCB;
        static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
    
        /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
        state will be stored. */
        *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
    
        /* Pass out the array that will be used as the Idle task's stack. */
        *ppxIdleTaskStackBuffer = uxIdleTaskStack;
    
        /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
        Note that, as the array is necessarily of type StackType_t,
        configMINIMAL_STACK_SIZE is specified in words, not bytes. */
        *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
    }
    
    /* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
    application must provide an implementation of vApplicationGetTimerTaskMemory()
    to provide the memory that is used by the Timer service task. */
    void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
                                         StackType_t **ppxTimerTaskStackBuffer,
                                         uint32_t *pulTimerTaskStackSize )
    {
        /* If the buffers to be provided to the Timer task are declared inside this
        function then they must be declared static - otherwise they will be allocated on
        the stack and so not exists after this function exits. */
        static StaticTask_t xTimerTaskTCB;
        static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
    
        /* Pass out a pointer to the StaticTask_t structure in which the Timer
        task's state will be stored. */
        *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
    
        /* Pass out the array that will be used as the Timer task's stack. */
        *ppxTimerTaskStackBuffer = uxTimerTaskStack;
    
        /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
        Note that, as the array is necessarily of type StackType_t,
        configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
        *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
    }
    
    void vApplicationMallocFailedHook( void )
    {
        NRF_LOG_INFO("Malloc Failed");
    }
    
    void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char *pcTaskName )
    {
    
       for( ;; );
    }
    
    
    #if NRF_LOG_ENABLED
    /**@brief Thread for handling the logger.
     *
     * @details This thread is responsible for processing log entries if logs are deferred.
     *          Thread flushes all log entries and suspends. It is resumed by idle task hook.
     *
     * @param[in]   arg   Pointer used for passing some arbitrary information (context) from the
     *                    osThreadCreate() call to the thread.
     */
    static void logger_thread(void * arg)
    {
        UNUSED_PARAMETER(arg);
    
        while (1) {
            NRF_LOG_FLUSH();
    
            vTaskSuspend(NULL); // Suspend myself
        }
    }
    #endif //NRF_LOG_ENABLED
    
    /**@brief A function which is hooked to idle task.
     * @note Idle hook must be enabled in FreeRTOS configuration (configUSE_IDLE_HOOK).
     */
    void vApplicationIdleHook( void )
    {
    #if NRF_LOG_ENABLED
        vTaskResume(m_logger_thread);
    #endif
    }
    
    
    /**@brief Function for initializing the clock.
     */
    static void clock_init(void)
    {
        ret_code_t err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
    }
    
    #define LOGGER_TASK_STACK_SIZE 512
    #define LOGGER_TASK_PRIORITY   1
    /* Structure that will hold the TCB of the task being created. */
    StaticTask_t xLoggerTaskBuffer;
    
    /* Buffer that the task being created will use as its stack.  Note this is
    an array of StackType_t variables.  The size of StackType_t is dependent on
    the RTOS port. */
    StackType_t xLoggerStack[ LOGGER_TASK_STACK_SIZE ];
    
    
    /**@brief Function for application main entry.
     */
    /////////////////// USB MSC CODE /////////////////////////////////////
    
    bool g_test_open = false;
    uint32_t g_idle_s = 0;
    uint16_t rx_index;
    uint8_t m_rx = {0};
    uint8_t rx_buff[1024];
    
    #define CLOSE_FILE_BY_TIMER   0
    #define CLOSE_FILE_BY_STRING  1
    
    APP_TIMER_DEF(file_close_timer_id);
    #define USE_FATFS_SPI    1
    
    #ifndef USBD_POWER_DETECTION
    #define USBD_POWER_DETECTION true
    #endif
    
    static void msc_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                    app_usbd_msc_user_event_t     event);
    
    
    
    #define FR_FILE_OPENED 1
    #define FR_FILE_CLOSED 2
    
    const char my_filename[] = "test1.xls";
    
    
    NRF_BLOCK_DEV_SPI_DEFINE(
        m_block_dev_spi,
        NRF_BLOCK_DEV_SPI_CONFIG(
            512,
            NRF_BLOCK_DEV_SPI_FLAG_CACHE_WRITEBACK,
            NRF_DRV_SPI_DEFAULT_CONFIG
         ),
         NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SPI", "1.00")
    );
    
    #define BLOCKDEV_LIST() (                                   \
        NRF_BLOCKDEV_BASE_ADDR(m_block_dev_spi, block_dev)     \
    )
    
    /**
     * @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)
    
    /**
     * @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);
    
    static nrf_atomic_u32_t m_key_events;
    static bool m_usb_connected = false;
    
    
    
    static FATFS m_filesystem;
    
    void fatfs_mkfs(void)
    {
        FRESULT ff_result;
    
        if (m_usb_connected)
        {
            NRF_LOG_ERROR("Unable to operate on filesystem while USB is connected");
            return;
        }
    
        NRF_LOG_INFO("\r\nCreating filesystem...");
         uint8_t buf[4096] = {0};
      //  ff_result = f_mkfs("", FM_FAT, 1024, buf, sizeof(buf));
       // ff_result = f_mkfs("", FM_FAT, 4096, buf, sizeof(buf));
      ff_result = f_mkfs("", FM_FAT | FM_SFD, 4096, buf, sizeof(buf));
    
    
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("Mkfs failed with error %d",ff_result);
            return;
        }
    
        NRF_LOG_INFO("Mounting volume...");
        ff_result = f_mount(&m_filesystem, "", 1);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("Mount failed err %d",ff_result);
            return;
        }
    
        NRF_LOG_INFO("Done");
    }
    
    
    
    
    static bool fatfs_init(void)
    {
        FRESULT ff_result;
        DSTATUS disk_state = STA_NOINIT;
    
        memset(&m_filesystem, 0, sizeof(FATFS));
    
        // 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_spi, block_dev), NULL)
        };
    
        diskio_blockdev_register(drives, ARRAY_SIZE(drives));
    
        NRF_LOG_INFO("Initializing disk 0 (SPI)...");
        disk_state = disk_initialize(0);
        if (disk_state)
        {
            NRF_LOG_ERROR("Disk initialization failed.disk_state<%d>", disk_state);
            return false;
        }
        NRF_LOG_ERROR("disk_state <%d>", disk_state);
        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.");
                fatfs_mkfs();// flash is new, should execute this here once, and then it can be annotated 
            }
            else
            {
                NRF_LOG_ERROR("Mount failed: %u", ff_result);
            }
            return false;
        }
    
        return true;
    }
    
    
    
    static void fatfs_ls(void)
    {
        DIR dir;
        FRESULT ff_result;
        FILINFO fno;
    
        if (m_usb_connected)
        {
            NRF_LOG_ERROR("Unable to operate on filesystem while USB is connected");
            return;
        }
    
        NRF_LOG_INFO("\r\nListing directory: /");
        ff_result = f_opendir(&dir, "/");
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("Directory listing failed: %u", ff_result);
            return;
        }
    
        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;
            }
    
            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);
    }
    
    
    
    
    static void fatfs_file_create(void)
    {
        FRESULT ff_result;
        FIL file;
    
    
        if (m_usb_connected)
        {
            NRF_LOG_ERROR("Unable to operate on filesystem while USB is connected");
            return;
        }
    
        NRF_LOG_RAW_INFO("Creating random file: %s ...", (uint32_t)my_filename);
        NRF_LOG_FLUSH();
    
        ff_result = f_open(&file, my_filename, FA_CREATE_ALWAYS | FA_WRITE);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to open or create file: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
    
    //write a string
    
        static BYTE test_string[] = "christophe\t1995\t0707\r\nsid\t1997\t1234\r\n";
        UINT data_len_written = 0;
        ff_result = f_write(&file, test_string, (UINT)strlen(test_string), &data_len_written);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to write data: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
    
    
        ff_result = f_close(&file);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to close file: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
        NRF_LOG_RAW_INFO("done\r\n");
    
    }
    
    
    static FRESULT my_file_open(FIL* my_file)
    {
        FRESULT ff_result;
        ret_code_t err_code;
    
        if (g_test_open)
        {
            return FR_FILE_OPENED;
        }
    
        ff_result = f_open(my_file, my_filename, FA_OPEN_ALWAYS | FA_WRITE | FA_OPEN_APPEND);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to open or create file: %u", ff_result);
            NRF_LOG_FLUSH();
            return ff_result;
        }
    
    #if CLOSE_FILE_BY_TIMER
        err_code = app_timer_start(file_close_timer_id, CLOSE_INTERVAL, NULL);
        APP_ERROR_CHECK(err_code);
    #endif
    
        g_test_open = true;
    
          return ff_result;
    }
    
    #if 0
    static void my_file_write(void)
    {
        FRESULT ff_result;
        FIL file;
    
        ff_result = f_write(&file, test, (UINT)strlen(test), &written);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to write data: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
    
    }
    #endif
    
    static FRESULT my_file_close(FIL * my_file)
    {
        FRESULT ff_result;
    
        if (g_test_open == false)
        {
            return FR_FILE_CLOSED;
           
        }
    
        ff_result = f_close(my_file);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to close file: %u", ff_result);
            NRF_LOG_FLUSH();
            return ff_result;
        }
        NRF_LOG_RAW_INFO("done\r\n");
    
        g_test_open = false;
    #if CLOSE_FILE_BY_TIMER
        //app_timer_stop(file_close_timer_id);
    #endif
        NRF_LOG_RAW_INFO("file closed!\r\n"); 
        NRF_LOG_FLUSH();
    
         return ff_result;
    
    }
    
    
    static void my_write_data(void)
    {
    
        FRESULT ff_result;
        FIL file;
    
        ff_result = f_open(&file, my_filename, FA_CREATE_ALWAYS | FA_WRITE);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to open or create file: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
    
    //write a string
    
    #if 1
    //    ff_result = f_lseek(&file, file.obj->fs.fsize));
    //    if (ff_result != FR_OK)
    //    {
    //        NRF_LOG_ERROR("\r\nUnable to write data: %u", ff_result);
    //        NRF_LOG_FLUSH();
    //        return;
    //    }
    
    
        static BYTE test[] = "1111\t2222\t3333\r\n4444\t5555\t6666\r\n";
        UINT written = 0;
        ff_result = f_write(&file, test, (UINT)strlen(test), &written);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to write data: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
    
        ff_result = f_close(&file);
        if (ff_result != FR_OK)
        {
            NRF_LOG_ERROR("\r\nUnable to close file: %u", ff_result);
            NRF_LOG_FLUSH();
            return;
        }
        NRF_LOG_RAW_INFO("done\r\n");
    
    }
    
    static void fatfs_uninit(void)
    {
        NRF_LOG_INFO("Un-initializing disk 0 (SPI)...");
        UNUSED_RETURN_VALUE(disk_uninitialize(0));
    }
    
    
    /**
     * @brief Class specific event handler.
     *
     * @param p_inst    Class instance.
     * @param event     Class specific event.
     */
    static void msc_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                    app_usbd_msc_user_event_t     event)
    {
        UNUSED_PARAMETER(p_inst);
        UNUSED_PARAMETER(event);
    }
    
    
    /**
     * @brief USBD library specific event handler.
     *
     * @param event     USBD library event.
     */
    static void usbd_user_ev_handler(app_usbd_event_type_t event)
    {
        switch (event)
        {
            case APP_USBD_EVT_DRV_SUSPEND:
                //bsp_board_led_off(LED_USB_RESUME);
                break;
            case APP_USBD_EVT_DRV_RESUME:
                //bsp_board_led_on(LED_USB_RESUME);
                break;
            case APP_USBD_EVT_STARTED:
                //bsp_board_led_on(LED_USB_START);
                break;
            case APP_USBD_EVT_STOPPED:
                UNUSED_RETURN_VALUE(fatfs_init());
                app_usbd_disable();
                //bsp_board_leds_off();
                break;
            case APP_USBD_EVT_POWER_DETECTED:
                NRF_LOG_INFO("USB power detected");
    
                if (!nrf_drv_usbd_is_enabled())
                {
                    fatfs_uninit();
                    app_usbd_enable();
                }
                break;
            case APP_USBD_EVT_POWER_REMOVED:
                NRF_LOG_INFO("USB power removed");
                app_usbd_stop();
                m_usb_connected = false;
                //memset(&m_rx, 0, sizeof(m_rx));
                break;
            case APP_USBD_EVT_POWER_READY:
                NRF_LOG_INFO("USB ready");
                app_usbd_start();
                m_usb_connected = true;
                break;
            default:
                break;
        }
    }
    
    
    #endif
    
    
    static void close_file_handler(void * p_context)
    {
        UNUSED_PARAMETER(p_context);
        g_idle_s++;
    
    }
    
    
    static void timers_init(void)
    {
        // Initialize timer module.
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
        err_code = app_timer_create(&file_close_timer_id,
                                    APP_TIMER_MODE_REPEATED,
                                    close_file_handler);
        APP_ERROR_CHECK(err_code);
    
        // Create timers.
        m_rtc_timer = xTimerCreateStatic("RTC",
                                         RTC_INTERVAL,
                                         pdTRUE,
                                         NULL,
                                         rtc_timeout_handler,
                                         &xRTCTimer);
    
        /* Error checking */
        if (NULL == m_rtc_timer) {
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
    }
    
    
    //////////////////////////////////////////////////////////////////////
    
    int main(void)
    {
        FRESULT ff_result;
        FIL file;
    
        ret_code_t ret;
        static const app_usbd_config_t usbd_config = {
            .ev_state_proc = usbd_user_ev_handler
        };
    
        // Initialize modules.
        log_init();
        clock_init();
        nrf_drv_clock_lfclk_request(NULL);
        
        ret = NRF_LOG_INIT(app_timer_cnt_get);
        APP_ERROR_CHECK(ret);
        NRF_LOG_INFO("TESTING NEW FIRMWARE");
       
        ret = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(ret);
        
        gpio_init();
        timers_init();    
        application_timers_start();
    
        NRF_LOG_INFO("Firmware Starting");
        NRF_LOG_INFO("FW Version: %s", app_fw_version);
        
        nrf_gpio_pin_set(EN_SUPPLY);
     
        start_charging();
        // stop_charging();
        nrf_delay_ms(1000);
        spi_init();
        nrf_delay_ms(2000);
    
        if (fatfs_init())
        {
              fatfs_ls();
              fatfs_file_create();
    
        }
              fatfs_ls();
              fatfs_file_create();
              fatfs_ls();
                  
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(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);
    
        NRF_LOG_FLUSH();
    
        NRF_LOG_INFO("USBD MSC example started.");
    
        if (true)
        {
            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;
        }
        
        uint8_t write_cnt = 0;       
    
        while (true)
        {
    
            while (app_usbd_event_queue_process())
            {
                /* Nothing to do */
            }
              NRF_LOG_FLUSH();
        }         
    
    }
    
    static void nrf_nvmc_write_word(uint32_t address, uint32_t value)
    {
        // Enable write.
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
        __ISB();
        __DSB();
    
        *(uint32_t*)address = value;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {;}
    
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
        __ISB();
        __DSB();
    }
    
    
    uint32_t app_timer_cnt_get(void)
    {
        return xTaskGetTickCount();
    }
    
    uint32_t app_timer_cnt_diff_compute(uint32_t   ticks_to,
                                        uint32_t   ticks_from)
    {
        return ((ticks_to - ticks_from) & RTC_COUNTER_COUNTER_Msk);
    }
    
    

    Thanks.

Children
No Data
Related