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 Reply Children
  • 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.

Related