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

Problem with fstorage and ble init

Hi:

I am having a problem with the fstorage and ble_stack_init. When fstorage is used before the ble_stack_init it works fine. If used after ble_stack_init, the fstorage handler is not called. I tried several combinations among test() and ble_stack_init and even replace the erase by the write and read operations, but the problem is always the same. Apparently, after the ble_stack_init, the handler of the fstorage module is not longer called and the program crashes (app_error_fault_handler is called). I am using the ble_app_hids_mouse as base project.

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

uint32_t fs_callback_flag=0;

void fs_evt_handler(nrf_fstorage_evt_t * evt){
if(evt->result == NRF_SUCCESS){
fs_callback_flag= 0;
}
}

NRF_FSTORAGE_DEF(nrf_fstorage_t my_instance) = {
.evt_handler = fs_evt_handler,
.start_addr = 0x00078000,
.end_addr = 0x0007FFFF,
};

void wait_for_flash_ready(){
/* While fstorage is busy, sleep and wait for an event. */
while (nrf_fstorage_is_busy(&my_instance)){
#ifdef SOFTDEVICE_PRESENT
(void) sd_app_evt_wait();
#else
__WFE();
#endif
}
}

void test(void){
ret_code_t ret = nrf_fstorage_init(&my_instance, &nrf_fstorage_sd, NULL);
uint8_t msg = 0;
wait_for_flash_ready();
fs_callback_flag = 1; 
ret = nrf_fstorage_erase(&my_instance, my_instance.start_addr, 1, &msg);
if (ret == NRF_SUCCESS) while(fs_callback_flag) nrf_delay_ms(25);
}

int main(void){
// Initialize.
log_init();
test();
ble_stack_init();
test();

...

for (;;){idle_state_handle();}

}

I would appreciate any help that you can supply to me.

Thanks,

Paulo Matos

Parents
  • Hi,

    Which SDK version are you using? I will assume SDK 15.2 for now.

    Which of the fstorage implementations are you using? I ask because there are several implementation files:

    • nrf_fstorage_nvmc.c works without the SoftDevice (which is the situation before you call ble_stack_init ())
    • nrf_fstorage_sd.c works with the SoftDevice (which is the situation after you call ble_stack_init ())

    When you use the SoftDevice you should initialize it first, then initialize fstorage after, using the SoftDevice compatible implementation.

  • Dear Einar:

    I am using the SDK15.2, with the NRF_FSTORAGE_SD, and even when i initialized the fstorage after the ble, the problem is the same.

    I tested using a "clean" copy of the ble_app_hids_mouse adding the code to deal with the fstorage:

    #include "nrf_fstorage.h"
    #include "nrf_fstorage_sd.h"
    #include "nrf_delay.h"
    uint32_t fs_callback_flag=0;
    
    void fs_evt_handler(nrf_fstorage_evt_t * evt){
      if(evt->result == NRF_SUCCESS){     
          fs_callback_flag=0;
      }
    }
    
    NRF_FSTORAGE_DEF(nrf_fstorage_t my_instance) = {
        .evt_handler    = fs_evt_handler, // Function for event callbacks.
        .start_addr     = 0x00078000,  // Corresponde a 0x7FFFF - 4096 (tamanho de cada página) * 8 páginas
        .end_addr       = 0x0007FFFF,  // Topo da memória Flash - ATENÇÃO - Deve ser alterado caso se utilize bootloader
    };
    
    void wait_for_flash_ready(){
        /* While fstorage is busy, sleep and wait for an event. */
        while (nrf_fstorage_is_busy(&my_instance)){
          (void) sd_app_evt_wait();
        }
    }
    void test(void){
        ret_code_t ret = nrf_fstorage_init(&my_instance, &nrf_fstorage_sd, NULL);
        uint8_t msg = 0;
        wait_for_flash_ready();
        fs_callback_flag = 1;    
        ret = nrf_fstorage_erase(&my_instance, my_instance.start_addr, 1, &msg);
        if (ret == NRF_SUCCESS) while(fs_callback_flag) nrf_delay_ms(25);         
    }
    
    int main(void)
    {
        bool erase_bonds;
        ret_code_t rc;
        // Initialize.
        log_init();
        timers_init();
        buttons_leds_init(&erase_bonds);
        power_management_init();
        test(); // Here, it works
        ble_stack_init();
        //test(); // Here, it does not work
        scheduler_init();
        gap_params_init();
        gatt_init();
        advertising_init();
        services_init();
        sensor_simulator_init();
        conn_params_init();    
        peer_manager_init();
    
        // Start execution.
        NRF_LOG_INFO("HID Mouse example started.");
        timers_start();
        advertising_start(erase_bonds);
    
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
        }
    }
    

    The test() function works fine when used before ble_stack_init(). After it, it does not work.

    I am testing it on the PCA10040 board.

    Thanks,

    Paulo Matos

  • Hi Paulo,

    OK, now I see. The ble_app_hids_mouse example use the app_scheduler, which means that the SoftDevice events are handled in the main context when the application calls app_sched_execute(). This does not happen in your code, as you only call nrf_delay_ms(). You can fix it by moving the call to test() after the call to scheduler_init() and modifying your test function like this so that you process the scheduler queue while waiting:

    void test(void){
        ret_code_t ret = nrf_fstorage_init(&my_instance, &nrf_fstorage_sd, NULL);
        uint8_t msg = 0;
        wait_for_flash_ready();
        fs_callback_flag = 1;    
        ret = nrf_fstorage_erase(&my_instance, my_instance.start_addr, 1, &msg);
        if (ret == NRF_SUCCESS)
        {
            while(fs_callback_flag)
            {
                app_sched_execute();
                nrf_delay_ms(25);
            }
        }
    }

    Alternatively you can stop using the scheduler by setting NRF_SDH_DISPATCH_MODEL to 0 (NRF_SDH_DISPATCH_MODEL_INTERRUPT) in sdk_config.h and commenting out the call to scheduler_init() in main() and app_sched_execute() in idle_state_handle().

    (As a side note I want to mention something which might be obvious, and that is that you should only use nrf_delay_ms() like this for proof of concept. It will prevent the CPU from sleeping or processing other tasks, so it is not suitable in a low power application.)

    Einar

  • Dear Einar:

    Thanks very much for your reply. It solves the problem, allowing us to continue.
    Allow me one more question related with your last comment. Is it possible to replace

    while(fs_callback_flag){
    app_sched_execute();
    nrf_delay_ms(25);
    }


    by:

    wait_for_flash_ready();

    I tried, but it is not working ... the program does not wakeup ... what am i missing here? Is it not a feasible solution?

    Once more thanks for your help,

    Paulo Matos

  • Hi Paulo,

    You can call wait_for_flash_ready() instead, but then you have to call app_sched_execute() from there as well, for the same reason as described in the previous post. Then it would be something like this:

    void wait_for_flash_ready(){
        /* While fstorage is busy, sleep and wait for an event. */
        while (nrf_fstorage_is_busy(&my_instance)){
            sd_app_evt_wait();
            app_sched_execute();
        }
    }

Reply
  • Hi Paulo,

    You can call wait_for_flash_ready() instead, but then you have to call app_sched_execute() from there as well, for the same reason as described in the previous post. Then it would be something like this:

    void wait_for_flash_ready(){
        /* While fstorage is busy, sleep and wait for an event. */
        while (nrf_fstorage_is_busy(&my_instance)){
            sd_app_evt_wait();
            app_sched_execute();
        }
    }

Children
Related