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

Write in flash + re-init problem

Hello,

I am currently running into an issue with nrf51822. I am trying to write in flash a flag which defines the device I use. Indeeed, the device on which the code will run can have 3 modes & a user can modify this mode with a command sent through UART. When the command has been run, the system should re-init to modify the UART, advertising or conn_params settings.

There is no particular problem with initialization but when the UART command is run, the system stops. Indeed, the write command is blocked in an infinite loop, waiting for the NRF_EVT_FLASH_OPERATION_SUCCESS event.

I join the code run at initialization & the function used to write in flash, the function run when the UART command has been received just calls the init function to re-init all settings with the new device mode.

void system_init(void)
{
    uint32_t err_code;
    
    softdevice_sys_evt_handler_set(sys_evt_handler);
    
    if (ble_device_type == DEFAULT)
    {
        ble_device_type = WBLE;
    }
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
    
    if (ble_device_type == WBLE)
    {
        db_discovery_init();
    }
    uart_init();
    ble_stack_init();
    //Function used to write the device type flag in flash memory
    wat_write_flash_type((uint8_t )ble_device_type);
    
    else if (ble_device_type == UART_MODULE || ble_device_type == WBEACON)
    {
        gap_params_init();
        services_init();
        if (ble_device_type == UART_MODULE)
        {
            advertising_init();
            conn_params_init();
            err_code = ble_advertising_start(BLE_ADV_MODE_SLOW);
        }
        else if (ble_device_type == WBEACON)
        {
            err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
            APP_ERROR_CHECK(err_code);
        }
        
    }
}

uint8_t wat_write_flash_type(uint8_t type)
{
    uint32_t status = NRF_ERROR_BUSY;
    uint8_t d_type[4];
    
    d_type[0] = type;
    d_type[1] = 0;
    d_type[2] = 0;
    d_type[3] = 0;
    
    do
    {
        status = sd_flash_write((uint32_t *)TYPE_LOCATION, (uint32_t*)d_type, 1);
    }
    while (status == NRF_ERROR_BUSY);
    
    flashBusy = true;
    
    while(flashBusy)
    {
        sd_app_evt_wait();
    }

    if(status != NRF_SUCCESS)
    {
        return 1; // Error
    }
    
    return 0;
}

I also join the callback used to trigger the event.

void sys_evt_handler(uint32_t evt)
{
    switch(evt)
    {
        case NRF_EVT_FLASH_OPERATION_SUCCESS:
            flashBusy = false;
        break;
        
        case NRF_EVT_FLASH_OPERATION_ERROR:
        break;
        
        default:
        break;
    }
}

It seems that when I try to re-init, the system is in INVALID_STATE (that is the error code returned by the function uart_init).

Do not hesitate to ask for further information if needed.

Parents Reply Children
  • I was at first trying to use it from interrupt context and figured out it was not working so I changed that and now  I trigger the Flash write in main context. I identified the problem I think, in my function which processes the UART command received, I sent again some debug information on same UART so I was trigerring a new interrupt which caused the write in flash to fail.

    Now I am able to write in flash & change the mode as I wanted, I just have another issue but I do not think it is related to this one, I guess it is due to bad behaviour in uart_event_handle function in different mode, I have to go check this out

  • Well in fact I am running into another issue which I do not understand at all, I managed to get the desired behaviour once, and now, nothing works at all, the program cannot write in flash at the specified address, I really do not know why.

    I tried to erase all in the device then re-flash the SoftDevice & application but it does not work anymore, I can write in flash the first time I run the program (I write at init the default mode) but after that, I cannot do it again it seems

  • You should be able to write the location in flash once after erasing the page. Did you run --eraseall command using nrfjprog? If you only erase the flash are used by softdevice and application, this will not erase the are where your application wrote to flash. If you need to update the information in flash, you need to change the location where it is stored, or erase the flash page where the address is located. If you are planning to write often/much data to flash, I would recommend looking into FDS.

  • I used nRFgo Studio to erase all and flasing again SoftDevice, then Keil for the application.

    When I try to write in flash, I start by erasing the corresponding page first

    flashBusy = true;
    sd_flash_page_erase(DEVICE_TYPE_PAGE);
        
    // Wait end erase flash page
    while(flashBusy)
    {
        sd_app_evt_wait();
    }

    I run this code before writing in flash, the flashBusy variable is reset by the sys_evt_handler callback on NRF_EVT_FLASH_OPERATION_SUCCESS .

    It is not planned to write oftenly to flash, but for now, I cannot change the default value, it is pretty weird because I had the behaviour I wanted once but since then I cannot reproduce it anymore, really do not know why

  • What happens when you try to write flash again? Do you get any error codes etc.? What address is the location you are trying to write?

Related