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

Flash FDS initialization failure until 4 reset with nRF5 SDK for Thread and Zigbee v4.1.0

Hi everyone.

I have an application using BLE and OpenThread dynamicaly.
I am working with nRF52840 chip with nRF5 SDK for Thread and Zigbee v4.1.0 (Release Date: Week 18, 2020)

In order to store the advertising data and some mesh parameters, I need to use the flash.
I first try to implement a solution with nrf_fstorage module, but I had a lot of issues with it so I changed for FDS module.

I manage to implement a working solution exept that the first time the chip is programmed (after a full erase), I need to do 3 to 4 resets befor the program starts.

I have been investigating in debug mode. It seems I am stuck somewhere into sd_app_evt_wait();
Here is my code to init the flash :

static bool volatile fdsInitialized;
static bool writeTerminated;

/************************************* fds_evt_handler ***************************************/
/** 
* @Brief Simple event handler to handle errors during initialization. 
*/
static void fds_evt_handler(fds_evt_t const * p_evt)
{
		switch (p_evt->id){
			case FDS_EVT_INIT:
					if (p_evt->result == FDS_SUCCESS){
						 fdsInitialized = true;
					}
					break;
			case FDS_EVT_WRITE:
					if (p_evt->result == FDS_SUCCESS){
						 writeTerminated = true;
					}
					break;
			case FDS_EVT_UPDATE:
					if (p_evt->result == FDS_SUCCESS){
						 writeTerminated = true;
						 if(netStr2Save.netReset == 1){
								//Restar tne Mesh Network with the new name		
								NVIC_SystemReset();
						 }
					}
					break;
			case FDS_EVT_DEL_RECORD:
					if (p_evt->result == FDS_SUCCESS){    
					}
				break;
			
			 case FDS_EVT_GC:
					if (p_evt->result == FDS_SUCCESS){
						 flash_save_config(&netStr2Save);
					}
					break;
			default:
					break;
    }
}

void flash_init(void){

	ret_code_t ret = fds_register(fds_evt_handler);
	if (ret != FDS_SUCCESS)
	{
    	return ret;
	}

	ret = fds_init();	
	if (ret != FDS_SUCCESS)
	{
		return ret;
	}
    
    while (!fdsInitialized){
        sd_app_evt_wait();
    }
	writeTerminated = true;
}


The flash init function is called after ble_stack_init in the main.

Here is the SDK config I  have got :
/ <e> FDS_ENABLED - fds - Flash data storage module
//==========================================================
#ifndef FDS_ENABLED
#define FDS_ENABLED 1
#endif
// <h> Pages - Virtual page settings

// <i> Configure the number of virtual pages to use and their size.
//==========================================================
// <o> FDS_VIRTUAL_PAGES - Number of virtual flash pages to use. 
// <i> One of the virtual pages is reserved by the system for garbage collection.
// <i> Therefore, the minimum is two virtual pages: one page to store data and one page to be used by the system for garbage collection.
// <i> The total amount of flash memory that is used by FDS amounts to @ref FDS_VIRTUAL_PAGES * @ref FDS_VIRTUAL_PAGE_SIZE * 4 bytes.

#ifndef FDS_VIRTUAL_PAGES
#define FDS_VIRTUAL_PAGES 3
#endif

// <o> FDS_VIRTUAL_PAGE_SIZE  - The size of a virtual flash page.
 

// <i> Expressed in number of 4-byte words.
// <i> By default, a virtual page is the same size as a physical page.
// <i> The size of a virtual page must be a multiple of the size of a physical page.
// <1024=> 1024 
// <2048=> 2048 

#ifndef FDS_VIRTUAL_PAGE_SIZE
#define FDS_VIRTUAL_PAGE_SIZE 1024
#endif

// <o> FDS_VIRTUAL_PAGES_RESERVED - The number of virtual flash pages that are used by other modules. 
// <i> FDS module stores its data in the last pages of the flash memory.
// <i> By setting this value, you can move flash end address used by the FDS.
// <i> As a result the reserved space can be used by other modules.

#ifndef FDS_VIRTUAL_PAGES_RESERVED
#define FDS_VIRTUAL_PAGES_RESERVED 4
#endif

// </h> 
//==========================================================

// <h> Backend - Backend configuration

// <i> Configure which nrf_fstorage backend is used by FDS to write to flash.
//==========================================================
// <o> FDS_BACKEND  - FDS flash backend.
 

// <i> NRF_FSTORAGE_SD uses the nrf_fstorage_sd backend implementation using the SoftDevice API. Use this if you have a SoftDevice present.
// <i> NRF_FSTORAGE_NVMC uses the nrf_fstorage_nvmc implementation. Use this setting if you don't use the SoftDevice.
// <1=> NRF_FSTORAGE_NVMC 
// <2=> NRF_FSTORAGE_SD 

#ifndef FDS_BACKEND
#define FDS_BACKEND 2
#endif


I found a few posts on the forum about similar issues, but none of them solved mine.
Would you have any ideas where it could come from ?

Best regards.

Parents
  • Hello,

    I just had a quick glance in the ble_zigbee_fynamic_door_lock_nus example, and I see that FDS_VIRTUAL_PAGES_RESERVED is set to:

    #define FDS_VIRTUAL_PAGES_RESERVED ((ZIGBEE_NVRAM_PAGE_SIZE * ZIGBEE_NVRAM_PAGE_COUNT + ZIGBEE_NVRAM_CONFIG_PAGE_SIZE * ZIGBEE_NVRAM_CONFIG_PAGE_COUNT)/(FDS_VIRTUAL_PAGE_SIZE * 4))

    Which in this case gives FDS_VIRTUAL_PAGES_RESERVED = 9

    While in your sdk_config.h it is set to 4. 

    Can you please try to use the macro from the ble_zigbee_dynamic_door_lock_nus example? If you can use the macros, then it will automatically adjust to your project, rather than just assuming it is 9 in your case as well.

    Based on your description above, you are stuck in flash_init() -> sd_app_evt_wait(), right?

    Where do you call flash_init() from? From your main() function, or an interrupt?

    I am also not sure about your implementation. What happens if you check fdsInitialized, which is false, and then you get the interrupt setting it to true right before you call sd_app_evt_wait()? You would have to wait for another interrupt then. Just for debugging purposes, try to comment out sd_app_evt_wait() in flash_init(). Does it behave the same?

    Also, could it be that you receive the FDS_EVT_INIT event, but the result != NRF_SUCCESS? Try to ignore the p_evt->result and see if it still behaves the same. 

    Do you have any logging from the FDS module? If so, does it say anything?

    BR,

    Edvin

Reply
  • Hello,

    I just had a quick glance in the ble_zigbee_fynamic_door_lock_nus example, and I see that FDS_VIRTUAL_PAGES_RESERVED is set to:

    #define FDS_VIRTUAL_PAGES_RESERVED ((ZIGBEE_NVRAM_PAGE_SIZE * ZIGBEE_NVRAM_PAGE_COUNT + ZIGBEE_NVRAM_CONFIG_PAGE_SIZE * ZIGBEE_NVRAM_CONFIG_PAGE_COUNT)/(FDS_VIRTUAL_PAGE_SIZE * 4))

    Which in this case gives FDS_VIRTUAL_PAGES_RESERVED = 9

    While in your sdk_config.h it is set to 4. 

    Can you please try to use the macro from the ble_zigbee_dynamic_door_lock_nus example? If you can use the macros, then it will automatically adjust to your project, rather than just assuming it is 9 in your case as well.

    Based on your description above, you are stuck in flash_init() -> sd_app_evt_wait(), right?

    Where do you call flash_init() from? From your main() function, or an interrupt?

    I am also not sure about your implementation. What happens if you check fdsInitialized, which is false, and then you get the interrupt setting it to true right before you call sd_app_evt_wait()? You would have to wait for another interrupt then. Just for debugging purposes, try to comment out sd_app_evt_wait() in flash_init(). Does it behave the same?

    Also, could it be that you receive the FDS_EVT_INIT event, but the result != NRF_SUCCESS? Try to ignore the p_evt->result and see if it still behaves the same. 

    Do you have any logging from the FDS module? If so, does it say anything?

    BR,

    Edvin

Children
  • Hi Edvin,

    Thank for your quick answer.

    I tried the macro you wrote but most of the ZIGBEE macro are not defined in my case. I tried with 9 instead of 4 but it did not solve the issue.

    My program seems indeed stuck into sd_app_evt_wait(). I do not know where exactly since it is a precompiled function. I just know when I stop the program, it does not show me where I am. (I am using keil uVision 5).

    flash_init() is called in the main, juste after ble_stack_init(). fdsInitialized is set to true, but I all the example I read wrote it that way.


    I do not know about the sd_app_evt_wait() called after fdsInitialized is set to true. It was impliemented like this in the example I have. And since it works all the time exept at the very first start of the device, I guess it is not the problem cause.
    I did try to comment sd_app_evt_wait(), and I still have the same issue.

    However, you were right about FDS_EVT_INIT event --> result != NRF_SUCCESS
    So i just added this :

    case FDS_EVT_INIT:
    					if (p_evt->result == FDS_SUCCESS){
    							 fdsInitialized = true;
    								#if defined(BOARD_PCA10056) || defined(BOARD_PCA10059)
    									m_light_changed(LIGHT_TOGGLE);
    								#endif
    					}
    					else{
    						fds_init();
    					}
    					break;

    and the issue seems corrected.
    I might change a bit my code not to call fds_init in fds_evt_handler() but I think we have a solution.

    Thanks a lot.
    Best regards

  • False alarm.

    In fact it does not work. I guess I was in the 4th try.

    It looks like no event is ever generated by the softdevice once the fds_init() has been called.

  • This means that every ~4 times you reset the device, it works, and the FDS event handler is called with FDS_INIT status OK?

    Is there any way for me to reproduce this on a DK? Is it possible to zip the project and send it here? 

    I see that FDS is used in the example:

    SDK4.1.0\examples\multiprotocol\ble_zigbee\ble_zigbee_dynamic_door_lock_nus without modifications. 

    Can you please try one thing for me in the meantime:

    If you erase the chip completely (nrfjprog --eraseall), and then program the softdevice. Modify your application to not call storage_init(). Then run the application and read out the flash. You can use the command "nrfjprog --readcode my_flash_dump.hex", or the nRF Connect for Desktop --> Programmer application to get a visual representation. What I want to know is what kind of data, and mainly where it is stored. 

    E.g. if I comment out storage_init() in the ble_zigbee_dynamic_door_lock_nus example, it looks like this:

    While if I include storage_init(), it looks like this:

    As you can see, the last page of the FDS pages is from 0x000F6000->0x000F6FFF. The reason it is not starting at the top of the flash is that in this case 9 pages of 0x1000 (4096) bytes is reserved.

    So can you check without storage_init() what the flash looks like? Where is the bottom green line near the top of the flash starting?

    BR,
    Edvin

  • And in case you haven't tried, erase the chip completely before you program anything on it. Perhaps there is some old flash content in the flash area

  • This means that every ~4 times you reset the device, it works, and the FDS event handler is called with FDS_INIT status OK?

    Yes, after erasing all the chip I need to do 4 reset until it works.
    After that it works well.
    I can compile and program a new .hex without issues exept if I do a full erase.

    I 've prepared a zip keil project with only the FDS part of my project, event with it and my custom board it does not work. I tried with the nRF52840 dongle, same issue, I guess you can also try with the nRF52840 DK.
    You can download the archive here https://we.tl/t-gHRwu5GXTW

Related