fstorage write& Erase Interrupt not Triggered when BLE Init Called

I have written a word (32 bites) in 0xFF000 using nrf_fstorage_write(),  When BLEInit(), nrf_fstorage_evt() callback not trigged, 

BLE_Sleept()

nrf_storage_write()

BLE_wakeup()

  • Sorry for the delay, Thank you for your reply. I have changed the code as follows: 

    nrf_fstorage_api_t * p_fs_api;
    p_fs_api = &nrf_fstorage_nvmc;  -- I have changed to  p_fs_api = &nrf_fstorage_sd; 
    iDebug("fs Init started.");
    nrf_fstorage_init(&my_instance,/*fstorage instance,previously defined. */
    p_fs_api, /* Name of the backend. */
    NULL /* Optional parameter, backend-dependant. */
    );

    But I could not see any improvement.

    Can you share , if i have missed any point that you have given

  • I cannot tell what the program flow is based on the code snippet you posted. Can you upload a minimal version of your project so I can try to run it here?

    But I could not see any improvement.

    Have you performed any debugging to see if the program gets stuck or crashes?

  • Hello,

    This is my code as follows:

    #include "Infa.h"

    #define IMG_SIZE 16 //4096
    #define IMG_SIZE1 4 //4096

    __ALIGN(32) uint8_t img[4] = {12,13,14,15};
    __ALIGN(32) uint8_t img1[4] = {15,16,17,18};
    __ALIGN(32) uint8_t img_copy[IMG_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    #define FLASH_START_ADDR 0xFF000//0x30000 //0x10001000 //0x3F000 //0x30000
    #define FLASH_START_ADDR1 0xFF000 //0x10001000 //0x3F000 //0x30000
    #define FLASH_START_ADDR2 0xFF008
    bool write_finished = false, erase_finished = false;
    void callback(nrf_fstorage_evt_t *p_evt)
    {
    iDebug("======> flash result event");
    /*if (p_evt->id == FDS_EVT_INIT) {
    iDebug("======> flash write result event");
    write_finished = true;
    } */
    if (p_evt->id == NRF_FSTORAGE_EVT_WRITE_RESULT) {
    iDebug("======> flash write result event");
    write_finished = true;
    }
    if (p_evt->id == NRF_FSTORAGE_EVT_ERASE_RESULT) {
    iDebug("======> erase write result event");
    erase_finished = true;
    }
    }
    NRF_FSTORAGE_DEF(nrf_fstorage_t my_instance) = {
    .evt_handler = callback,
    .start_addr = FLASH_START_ADDR,
    .end_addr = 0xFFFFF , //FLASH_START_ADDR + 32, //0x3ffff-1, // 10,
    };


    bool write_to_flash(int SAddr)
    {
    ret_code_t rc=0;
    NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
    if(SAddr==1){
    rc = nrf_fstorage_write(&my_instance, /* The instance to use. */
    FLASH_START_ADDR1, /* The address in flash where to store the data. */
    img, /* A pointer to the data. */
    IMG_SIZE1, /* IMG_SIZE, Lenght of the data, in bytes. */
    NULL /* Optional parameter, backend-dependent. */
    );
    }
    else if(SAddr==2){
    rc = nrf_fstorage_write(&my_instance, /* The instance to use. */
    FLASH_START_ADDR2, /* The address in flash where to store the data. */
    img1, /* A pointer to the data. */
    IMG_SIZE1, /* IMG_SIZE, Lenght of the data, in bytes. */
    NULL /* Optional parameter, backend-dependent. */
    );
    }
    app_sched_execute();
    // nrf_delay_ms(1000);
    iDebug("\r\nflash write.... \r\n");
    while(nrf_fstorage_is_busy(&my_instance));

    if (rc == NRF_SUCCESS) {
    iDebug("\r\nflash write success");
    return true;
    } else {
    iDebug("\r\nflash write failure");
    return false;
    }
    }

    bool read_from_flash(int rType)
    {
    ret_code_t rc = 0;

    if(rType==1){
    rc = nrf_fstorage_read(&my_instance, /* The instance to use. */
    FLASH_START_ADDR1, /* The address in flash where to read data from. */
    img_copy, /* A buffer to copy the data into. */
    4 /* Lenght of the data, in bytes. */
    );
    }
    else if(rType==2){
    rc = nrf_fstorage_read(&my_instance, /* The instance to use. */
    FLASH_START_ADDR2, /* The address in flash where to read data from. */
    img_copy, /* A buffer to copy the data into. */
    4 /* Lenght of the data, in bytes. */
    );
    }
    if (rc == NRF_SUCCESS) {
    //iDebug("\r\nflash read success - Size %d",IMG_SIZE);
    for (int i = 0; i < 4; i++) {
    iDebug("\r\nflash read [%d] = %d", i,img_copy[i]);
    //if (img[i] != img_copy[i]) {
    // iDebug("\r\nflash read unequal at index %d", i);
    // return false;
    // }
    }
    return true;
    } else {
    iDebug("\r\nflash read Not success");
    return false;
    }
    }

    bool erase_from_flash()
    {
    iDebug("flash erase start..");
    ret_code_t rc = nrf_fstorage_erase(&my_instance,/* The instance to use. */
    FLASH_START_ADDR, /* The address of the flash pages to erase. */
    1, /* The number of pages to erase. */
    NULL /* Optional parameter, backend-dependent. */

    );
    app_sched_execute();
    while(nrf_fstorage_is_busy(&my_instance));
    NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
    if (rc == NRF_SUCCESS) {
    iDebug("flash erase success");
    return true;
    } else {
    iDebug("flash erase failure %u" + rc );
    return false;
    }
    }


    //======================= TWI - DIO ====================================

    /* TWI instance ID. */
    #if TWI0_ENABLED
    #define TWI_INSTANCE_ID 0
    #elif TWI1_ENABLED
    #define TWI_INSTANCE_ID 1
    #endif

    /* Number of possible TWI addresses. */
    #define TWI_ADDRESSES 127
    /* Common addresses definition for temperature sensor. */
    #define MAX5805_ADDR (0x18)

    #define MAX5805_REG_REF_CMD 0x50U
    #define MAX5805_REG_REF_HI 0x00U
    #define MAX5805_REG_REF_LO 0x38U

    #define MAX5805_REG_POW_CMD 0x40U
    #define MAX5805_REG_POW_HI 0x00U
    #define MAX5805_REG_POW_LO 0x00U

    #define MAX5805_REG_CODELODE_CMD 0xB0U //0xA0U //0xB0U
    #define MAX5805_REG_CODELODE_HI 0x00 //0x08//0xFFU
    #define MAX5805_REG_CODELODE_LO 0x00 //0x00//0xF0U


    #define MAX5805_REG_CONF 0x01U
    #define MAX5805_REG_POWER 0x02U


    /* Mode for LM75B. */
    #define NORMAL_MODE 0U

    #define SDA_PIN NRF_GPIO_PIN_MAP(0, 21)
    #define SCL_PIN NRF_GPIO_PIN_MAP(0, 23)

    /* Indicates if operation on TWI has ended. */
    static volatile bool m_xfer_done = false;

    /* Buffer for samples read from temperature sensor. */
    static uint8_t m_sample;

    /* TWI instance. */
    static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
    //static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(0);
    //=====================================================================
    /**Global variable declaration***/
    bool GetCurrentValue, PeriodicRead,GetModbusValue,SendMode;
    TransportMode_t IncomingTransportMode;
    uint16_t ModDataLen,ModStartAddr;
    uint16_t CalibValue4mA,CalibValue20mA,ProcessValue4mA,ProcessValue20mA;
    /*******************************/

    static void read_sensor_data()
    {
    m_xfer_done = false;

    /* Read 1 byte from the specified address - skip 3 bits dedicated for fractional part of temperature. */
    ret_code_t err_code = nrf_drv_twi_rx(&m_twi, MAX5805_ADDR, &m_sample, sizeof(m_sample));
    uint8_t lenData= sizeof(m_sample);
    iDebug("%d -- %d,%d", m_sample,lenData,err_code);
    //APP_ERROR_CHECK(err_code);
    }

    /**
    * @brief Function for setting active mode on MMA7660 accelerometer.
    */
    void MAX5805_set_mode(void)
    {
    ret_code_t err_code;

    /* Writing to LM75B_REG_CONF "0" set temperature sensor in NORMAL mode. */
    //uint8_t reg[2] = {LM75B_REG_CONF, NORMAL_MODE};
    uint8_t reg[3] = {MAX5805_REG_CODELODE_CMD,MAX5805_REG_CODELODE_HI,MAX5805_REG_CODELODE_LO};
    //iDebug("MAX5805_set_mode 1 " );
    err_code = nrf_drv_twi_tx(&m_twi, MAX5805_ADDR, reg, sizeof(reg), false);
    //iDebug("MAX5805_set_mode 1 %d" ,err_code);
    //APP_ERROR_CHECK(err_code);
    if(err_code) {}
    while (m_xfer_done == false);

    /* Writing to pointer byte. */
    /* reg[0] = LM75B_REG_TEMP;
    m_xfer_done = false;
    err_code = nrf_drv_twi_tx(&m_twi, MAX5805_ADDR, reg, 1, false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false); */
    iDebug("MAX5805_set_mode Write Success");
    //uint8_t i=0;
    //if(i)
    read_sensor_data();
    }
    /**
    * @brief Function for handling data from temperature sensor.
    *
    * @param[in] temp Temperature in Celsius degrees read from sensor.
    */
    __STATIC_INLINE void data_handler(uint8_t temp)
    {
    //NRF_LOG_INFO("Temperature: %d Celsius degrees.", temp);
    iDebug("TWI device Read Value 0x%d.", temp);
    }

    /**
    * @brief TWI events handler.
    */
    void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {
    //iDebug("TWI handler 0x%d.", p_event->type);
    switch (p_event->type)
    {
    case NRF_DRV_TWI_EVT_DONE:
    if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
    {
    data_handler(m_sample);
    }
    m_xfer_done = true;
    break;
    default:
    break;
    }
    }

    /**
    * @brief TWI initialization.
    */
    void twi_init (void)
    {
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_config = {
    .scl = SCL_PIN,
    .sda = SDA_PIN,
    .frequency = NRF_DRV_TWI_FREQ_100K,
    .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
    .clear_bus_init = false
    };

    err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
    }
    /**
    * @brief Function for reading data from temperature sensor.
    */

    void ScanTWI(){
    twi_init();
    }

    void DataFilter(uint8_t *data, uint16_t len)
    {
    SendMode=0;
    GetModbusValue = 0;
    //iDebug("DataFilter \n");
    if(!strncmp((char *)data, "getcurrent", 10))
    {
    PeriodicRead = 0;
    GetCurrentValue = 1;
    }
    else if(!strncmp((char *)data, "getperiodic", 11))
    {
    PeriodicRead = 1;
    }
    else if(!strncmp((char *)data, "stop", 4))
    {
    PeriodicRead = 0;
    }
    else if(data[0] == 0x01) //Slave ID
    {
    //iDebug("DataFilter 1 \n");
    if(data[1] == 0x03) //Read Holding Reg.
    {
    //Start Address data[2] & data[3]
    ModStartAddr = data[3] |(data[2] << 8);
    //iDebug("ModStartAddr : %d, data[2] : %d, data[3] : %d \n", ModStartAddr, data[2], data[3]);
    //Length data[4] & data[5]
    ModDataLen = data[5] | (data[4] << 8);
    //iDebug("ModDataLen : %d, data[4] : %d, data[5] : %d \n",ModDataLen,data[4], data[5]);
    //CRC data[6] & data[7]

    PeriodicRead = 0;
    GetCurrentValue = 0;
    GetModbusValue = 1;
    SendMode=1;

    }
    else if(data[1] == 0x06) //Write Holding Reg.
    {
    //BLEdeInit();
    //bluetooth_sleep();
    //nrf_delay_ms(500);
    iDebug("Write Start :");

    img[0] = data[2] ;
    img[1] = data[3] ;
    img[2] = data[4] ;
    img[3] = data[5] ;
    img1[0] = data[6] ;
    img1[1] = data[7] ;
    img1[2] = data[8] ;
    img1[3] = data[9] ;
    for (int i = 0; i < 4; i++){
    iDebug(" %d, ",img[i]);
    }
    for (int i = 0; i < 4; i++){
    iDebug(" %d, ",img1[i]);
    }
    CalibValue4mA = data[3] |(data[2] << 8);
    CalibValue20mA = data[5] |(data[4] << 8);
    ProcessValue4mA = data[7] |(data[6] << 8);
    ProcessValue20mA = data[9] |(data[8] << 8);
    iDebug("CalibValue4mA %d, ",CalibValue4mA);
    iDebug("CalibValue20mA %d, ",CalibValue20mA);
    iDebug("ProcessValue4mA %d, ",ProcessValue4mA);
    iDebug("ProcessValue20mA %d, ",ProcessValue20mA);

    iDebug("\r\nfs erase started.");
    erase_from_flash();
    nrf_delay_ms(500);
    write_to_flash(1);
    nrf_delay_ms(500);
    iDebug("Write 1 ");
    write_to_flash(2);
    nrf_delay_ms(500);
    iDebug("Write Finished ");
    read_from_flash(1);
    nrf_delay_ms(500);
    read_from_flash(2);
    }
    }
    }


    uint8_t Bit_test(uint32_t var, uint8_t var_bit)
    {
    if((var & ((uint32_t)1 << var_bit)))
    return 1;
    return 0;
    }

    uint16_t CalcCRC(uint8_t *Logbuffer, uint8_t MsgLen)
    {
    uint16_t CRC, i;
    uint8_t j, *Ptr8, Val, CRCLSB;

    i = 0;
    CRC = 0xffff;
    Ptr8 = Logbuffer; // Preload with ffff
    do{
    Val = *Ptr8;
    CRC = CRC ^ Val;
    Ptr8++;
    j = 0;
    do{
    if(Bit_test(CRC, 0))CRCLSB = 1;
    else CRCLSB = 0;
    CRC >>= 1; // Shift one bit to the right
    if(CRCLSB) CRC = CRC ^ 0xa001;
    }while(++j < 8);
    i++;
    }while(--MsgLen); // For all message bytes
    return CRC;
    }
    void SendValue(TransportMode_t Mode)
    {
    dist_meas_result_t dist_meas_result;
    ReadDetection(&dist_meas_result);
    if(Mode == Ble)
    {
    BLEPrintf("Distance = %u mm \n",(unsigned int)(dist_meas_result.distance * 1000));
    BLEPrintf("Signal Strength = %u\n",dist_meas_result.signal_strength);
    BLEPrintf("Data Saturated = %d \n",dist_meas_result.data_saturated);
    }
    else if(Mode == Serial)
    {
    if(SendMode==0){
    char temp[128] = {0};
    sprintf(temp, "Distance = %u mm \nSignal Strength = %lu\nData Saturated = %ld \n",(unsigned int)(dist_meas_result.distance * 1000), dist_meas_result.signal_strength, dist_meas_result.data_saturated);
    SendData(temp, strlen(temp));
    }
    else if(SendMode==1){
    uint8_t idx=0,SendData[64] = {0xff}, DataCRC[2] = {0xff};
    uint16_t DataDistance = 0,DataSaturated=0,DataSignalStrength=0;
    uint16_t CRCVal=0;
    //iDebug("Modbuas idx 0 : %d\n",idx);
    SendData[idx++] = 0x01; // Salve Address
    //iDebug("Modbuas idx 1 : %d\n",idx);
    SendData[idx++] = 0x03; // Function code - Read Holding Reg
    //iDebug("Modbuas idx 2 : %d\n",idx);
    SendData[idx++] = ModDataLen * 2; // Length
    //iDebug("Modbuas idx 3 : %d\n",idx);
    DataDistance = dist_meas_result.distance * 1000;
    DataSaturated = dist_meas_result.data_saturated;
    DataSignalStrength = dist_meas_result.signal_strength;
    if(ModDataLen ==1){
    SendData[idx++] = (DataDistance >> 8) & 0xFF; // Data
    SendData[idx++] = DataDistance & 0xFF; // Data
    //iDebug("Modbuas idx 4 : %d\n",idx);
    }
    if(ModDataLen ==2){
    SendData[idx++] = (DataDistance >> 8) & 0xFF; // Data
    SendData[idx++] = DataDistance & 0xFF; // Data
    SendData[idx++] = (DataSignalStrength >> 8) & 0xFF; //Signal Hi
    SendData[idx++] = (DataSignalStrength) & 0xFF;//SignalStrength Lo
    }
    if(ModDataLen ==3){
    SendData[idx++] = (DataDistance >> 8) & 0xFF; // Data
    SendData[idx++] = DataDistance & 0xFF; // Data
    SendData[idx++] = (DataSignalStrength >> 8) & 0xFF; //Signal Hi
    SendData[idx++] = (DataSignalStrength) & 0xFF;//SignalStrength Lo
    SendData[idx++] = (DataSaturated >> 8) & 0xFF;//Saturated Hi
    SendData[idx++] = (DataSaturated) & 0xFF; ; // SaturatedLo
    }
    else{
    SendData[idx++] = (DataDistance >> 8) & 0xFF; // Data
    SendData[idx++] = DataDistance & 0xFF; // Data
    SendData[idx++] = (DataSignalStrength >> 8) & 0xFF; //Signal Hi
    SendData[idx++] = (DataSignalStrength) & 0xFF;//SignalStrength Lo
    SendData[idx++] = (DataSaturated >> 8) & 0xFF;//Saturated Hi
    SendData[idx++] = (DataSaturated) & 0xFF; ; // SaturatedLo
    SendData[idx++] = (DataSaturated >> 8) & 0xFF;//Saturated Hi
    SendData[idx++] = (DataSaturated) & 0xFF; ; // SaturatedLo
    }
    //iDebug("Modbuas idx : %d\n",idx);
    CRCVal = CalcCRC(&SendData[0],idx );
    DataCRC[0] = (CRCVal >> 8) & 0xFF;
    DataCRC[1] = (CRCVal) & 0xFF;
    SendData[idx++] = DataCRC[1];// CRC Hi
    SendData[idx++] = DataCRC[0]; // CRC Lo
    //iDebug("Modbuas idx - 1 : %d\n",idx);
    SendModData(SendData,idx);
    }
    }
    }

    void StartRadarApp()
    {
    InitRadar();
    iDebug("Application started.");
    // Initialize
    nrf_fstorage_api_t * p_fs_api;
    p_fs_api = &nrf_fstorage_sd;
    iDebug("fs Init started.");
    nrf_fstorage_init(&my_instance,/*fstorage instance,previously defined. */
    p_fs_api, /* Name of the backend. */
    NULL /* Optional parameter, backend-dependant. */
    );

    nrf_delay_ms(500);
    iDebug(" BLE started. ");
    BLEInit();
    iDebug(" fs read started. ");
    uint32_t pgnum = NRF_FICR->CODESIZE-1;
    uint32_t pgsize = NRF_FICR->CODEPAGESIZE;
    iDebug(" fs pgnum %ul",pgnum);
    iDebug(" fs pgsize %ul ",pgsize); 
    read_from_flash(1);
    nrf_delay_ms(500);
    read_from_flash(2);

    nrf_delay_ms(100);
    for (;;)
    {
    uint8_t buff[128] = {0};
    uint16_t bufflen = 0;
    if(BleReceiveData(buff, &bufflen))
    {
    DataFilter(buff, bufflen);
    memset(buff, 0 ,sizeof(buff));
    bufflen = 0;
    IncomingTransportMode = Ble;
    }
    if(RecvData(buff, &bufflen))
    {
    //iDebug("Application started 1 ");
    //nrf_delay_ms(500);
    DataFilter(buff, bufflen);
    memset(buff, 0 ,sizeof(buff));
    bufflen = 0;
    IncomingTransportMode = Serial;
    }
    if(GetCurrentValue)
    {
    SendValue(IncomingTransportMode);
    GetCurrentValue = 0;
    }
    if(GetModbusValue){
    IncomingTransportMode = Serial;
    SendValue(IncomingTransportMode);
    GetModbusValue=0;
    }
    if(PeriodicRead)
    {
    SendValue(IncomingTransportMode);
    nrf_delay_ms(1000);
    }
    //Function for running power management. Should run in the main loop.
    nrf_pwr_mgmt_run();
    }
    }

    ==============================================

    #include "Infa.h"

    #define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */

    #define DEVICE_NAME "InfaRadar" /**< Name of device. Will be included in the advertising data. */
    #define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */

    #define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */

    #define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */

    #define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */

    #define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
    #define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
    #define SLAVE_LATENCY 0 /**< Slave latency. */
    #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
    #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(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 APP_TIMER_TICKS(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 DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */

    #define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */
    #define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */


    BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS 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. */

    static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */
    static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
    static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */
    {
    {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
    };

    bool IsDataAvail;
    uint8_t DataBuff[256] = {0};
    uint16_t Datalen = 0;

    /**@brief Function for assert macro callback.
    *
    * @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 analyse
    * 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] p_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);
    }

    /**@brief Function for initializing the timer module.
    */
    static void timers_init(void)
    {
    ret_code_t err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);
    }

    /**@brief Function for the GAP initialization.
    *
    * @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
    * the device. It also sets the permissions and appearance.
    */
    static void gap_params_init(void)
    {
    uint32_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);

    err_code = sd_ble_gap_device_name_set(&sec_mode,
    (const uint8_t *) DEVICE_NAME,
    strlen(DEVICE_NAME));
    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);
    }


    /**@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);
    }


    /**@brief Function for handling the data from the Nordic UART Service.
    *
    * @details This function will process the data received from the Nordic UART BLE Service and send
    * it to the UART module.
    *
    * @param[in] p_evt Nordic UART Service event.
    */
    /**@snippet [Handling the data received over BLE] */
    static void nus_data_handler(ble_nus_evt_t * p_evt)
    {
    if (p_evt->type == BLE_NUS_EVT_RX_DATA)
    {
    memcpy(DataBuff, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
    Datalen = p_evt->params.rx_data.length;
    //PrintData((char *)p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
    }
    }
    /**@snippet [Handling the data received over BLE] */


    /**@brief Function for initializing services that will be used by the application.
    */
    static void services_init(void)
    {
    uint32_t err_code;
    ble_nus_init_t nus_init;
    nrf_ble_qwr_init_t qwr_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 NUS.
    memset(&nus_init, 0, sizeof(nus_init));

    nus_init.data_handler = nus_data_handler;

    err_code = ble_nus_init(&m_nus, &nus_init);
    APP_ERROR_CHECK(err_code);
    }


    /**@brief Function for handling an event from 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)
    {
    uint32_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 errors from the Connection Parameters module.
    *
    * @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)
    {
    uint32_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.
    */
    static void sleep_mode_enter(void)
    {
    uint32_t 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();
    APP_ERROR_CHECK(err_code);
    }


    /**@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:
    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;
    }
    }


    /**@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;

    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);
    break;

    case BLE_GAP_EVT_DISCONNECTED:
    NRF_LOG_INFO("Disconnected");
    // LED indication will be changed when advertising starts.
    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_GAP_EVT_SEC_PARAMS_REQUEST:
    // Pairing not supported
    err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
    APP_ERROR_CHECK(err_code);
    break;

    case BLE_GATTS_EVT_SYS_ATTR_MISSING:
    // No system attributes have been stored.
    err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
    APP_ERROR_CHECK(err_code);
    break;

    case BLE_GATTC_EVT_TIMEOUT:
    // Disconnect on GATT Client timeout event.
    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.
    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;
    }
    }


    /**@brief Function for the SoftDevice initialization.
    *
    * @details This function 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);
    }
    /*
    #ifdef SOFTDEVICE_PRESENT
    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);
    }
    #else
    static void clock_init(void){
    // Initialize the clock.
    ret_code rc = nrf_drv_clock_init();
    APP_ERROR_CHECK(rc);
    nrf_drv_clock_lfclk_request(NULL);

    while(!nrf_clock_lf_is_running()) {;}
    }
    #endif*/
    /**@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 initializing the GATT library. */
    void gatt_init(void)
    {
    ret_code_t err_code;

    err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
    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 events from the BSP module.
    *
    * @param[in] event Event generated by button press.
    */
    void bsp_event_handler(bsp_event_t event)
    {
    uint32_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 initializing the Advertising functionality.
    */
    static void advertising_init(void)
    {
    uint32_t err_code;
    ble_advertising_init_t init;

    memset(&init, 0, sizeof(init));

    init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance = false;
    init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;

    init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    init.srdata.uuids_complete.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.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 buttons and leds.
    *
    * @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to wake the application up.
    */
    static void buttons_leds_init(bool * p_erase_bonds)
    {
    bsp_event_t startup_event;

    uint32_t err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
    APP_ERROR_CHECK(err_code);

    err_code = bsp_btn_ble_init(NULL, &startup_event);
    APP_ERROR_CHECK(err_code);

    *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
    }


    /**@brief Function for starting advertising.
    */
    static uint32_t advertising_start(void)
    {
    uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);
    return err_code;
    }

    uint32_t bluetooth_sleep(void)
    {
    uint32_t err_code;
    iDebug("sd_ble_gap_disconnect 1 \n");
    // If connected, disconnect
    if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
    {
    err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    if (err_code != NRF_SUCCESS) return err_code;
    }
    iDebug("sd_ble_gap_adv_stop 1 \n");
    // Stop advertising
    err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
    if (err_code != NRF_SUCCESS) return err_code;
    iDebug("TASKS_DISABLE 1 \n");
    // Disable the radio tasks as scytulip suggested
    // devzone.nordicsemi.com/.../
    //NRF_RADIO->TASKS_DISABLE =1;

    //NRF_RADIO->POWER=0;
    iDebug("NRF_SUCCESS 1 \n");
    return NRF_SUCCESS;
    }

    uint32_t bluetooth_wake(void)
    {
    uint32_t err_code;

    err_code = advertising_start();
    if (err_code != NRF_SUCCESS) return err_code;

    return NRF_SUCCESS;
    }

    void BLEInit()
    {
    bool erase_bonds;

    timers_init();
    buttons_leds_init(&erase_bonds);
    ////power_management_init();
    ble_stack_init();
    /*#ifdef SOFTDEVICE_PRESENT
    ble_stack_init();
    #else
    clock_init();
    #endif */
    iDebug("gap_params_init \n");
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();
    //Start execution.
    advertising_start();
    }


    uint16_t BLESend(uint8_t *data, uint16_t length)
    {
    if(m_conn_handle == BLE_CONN_HANDLE_INVALID)
    {
    return 0;
    }
    ble_nus_data_send(&m_nus, data, &length, m_conn_handle);
    nrf_delay_ms(50);
    return length;
    }

    void BLEPrintf(const char * format, ... )
    {
    char buffer[256];
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, 256, format, args);
    BLESend((uint8_t *)buffer, strlen(buffer));
    va_end(args);
    }

    bool BleReceiveData(uint8_t *data, uint16_t *length)
    {
    if(Datalen == 0)
    {
    return 0;
    }
    memcpy(data, DataBuff, Datalen);
    *length = Datalen;
    memset(DataBuff, '0', Datalen);
    Datalen = 0;
    return 1;
    }

  • Please upload your full project as a .zip file here.

    Here is how you upload attachments:

Related