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

pstorage_update calback question.

Hello everyone, i need some help and suggestions in understanding what is exactly happening. I have read a lot about bugs and workarounds in pstorage and now i actually don't know what to try, so i need some ideas :) Im using S110 v.8.0, SDK v9 and no, i am not using device manager. Im still debugging the code so you might see some strange flag names and etc. (sorry for kinda bad code formatting)

  • Before starting to see a code, i will try to explain my problem. I have registered two different pieces of flash with pstorage module. One is holding sensor configuration data, and the other should hold sensor measurements. While i am writing sensor data for the first time in flash, there are no problems. But when i try to update these sectors, the callback function is never called. The strange thing is for me that i am ussing the same callback for another block of flash which holds sensor configuration data and the handler is called for that and update operation happens successfully.So the question is, why i am able to update one segment of the flash and app_data_flash_manager_cb_handler() calback is called, but this callback is not called when i am updating another part of the flash.

  • I have created two modules to hold parameters in flash. One is to hold sensor configurations and the other one two hold sensor data (right now i made a small simulator to put "sensor" data in that place. Code for this:

      static void flash_area_for_pstorage_init(void)
      {
         /* Initialize pstorage module  */
         pstorage_retval = pstorage_init();
         if(pstorage_retval == NRF_SUCCESS)
         {
      	// Module initialization successful.
      	pstorage_dead = 0;
         }
         else
         {
      	 // Initialization failed, take corrective action.
      	pstorage_dead = 1;
         }
      
         
         param1.block_size = 32; // Block size is 32bytes
         param1.block_count = 1; // Get 1 block for data. 
         param1.cb = app_data_flash_manager_cb_handler;
    
         pstorage_retval = pstorage_register(&param1, &handle1);
         if (pstorage_retval == NRF_SUCCESS)
         {
      	// Registration successful.
      	pstorage_dead = 0;
         }
         else
         {
      	// Failed to register, take corrective action.
      	pstorage_dead = 1;
         }
      
         
         param.block_size = 128; 
         param.block_count = 3;
         param.cb = app_data_flash_manager_cb_handler;
    
         pstorage_retval = pstorage_register(&param, &handle);
      
         if (pstorage_retval == NRF_SUCCESS)
         {
      	// Registration successful.
      	pstorage_dead = 0;
         }
         else
         {
      	// Failed to register, take corrective action.
      	pstorage_dead = 1;
         }
      }
    
  • As you can see from the code above, i registered the same callback handler for both modules of pstorage. The code for handler is just to change flag value:

         static void app_data_flash_manager_cb_handler(pstorage_handle_t * handle, uint8_t op_code, uint32_t result, uint8_t * p_data, uint32_t data_len)
         { 
            switch(op_code)
            {
               case PSTORAGE_STORE_OP_CODE:
                  if (result == NRF_SUCCESS)
                  {
                     flash_manager_status_flag = 1;
                     // Store operation successful.
                  }
                  else
                  {
                      flash_manager_status_flag = 2;
                  }
               case PSTORAGE_LOAD_OP_CODE:
                  if (result == NRF_SUCCESS)
                  {
                      flash_manager_status_flag = 3;
                  }
                  else
                  {
                      flash_manager_status_flag = 4;
                  }
               // Source memory can now be reused or freed.
                break;
                case PSTORAGE_UPDATE_OP_CODE:
                   if (result == NRF_SUCCESS)
                      {
     			         flash_manager_status_flag = 5;
                      }
                      else
                      {
     			         flash_manager_status_flag = 6;
                      }
                 break;
                 case PSTORAGE_CLEAR_OP_CODE:
                     if (result == NRF_SUCCESS)
                     {
                          flash_manager_status_flag = 7;
                     }
                     else
                     {
                          flash_manager_status_flag = 8;
                     }
                  break;
                  default:
     		         flash_manager_status_flag = 0xAA;
                  break;
             }
         }
    
  • Thats pretty much it, now i am modifying the flash space which should hold the values for sensor configuration. I am doing this when i connect to the device and write to the characteristic (this is my own made custom service, code for this)

      static void gld_write_handler(ble_gld_t * p_gld, uint8_t *characteristic_data, uint8_t length)
      {
    
        for(myvar1 = 0; myvar1 < length; myvar1++)
        {
            write_data[myvar1] = characteristic_data[myvar1];
        }
    
        characteristic_write_flag = 1;
    
        /* Write parameters to the flash */
        err_code = pstorage_block_identifier_get(&handle1, 0, &p_block_id1); // Get 1 block
        APP_ERROR_CHECK(err_code);
      
        // Update data hold in this flash area where params are 
        err_code = pstorage_update(&p_block_id1, write_data, param1.block_size, 0);
        APP_ERROR_CHECK(err_code);
      }
    
  • The above piece of code is working without problems. I can modify this flash space as i want. The problem shows up when i am trying to work with another flash space. The problem is that while it using pstorage_store() to just store the data to flash everything works fine, but when all three blocks of data are full, i am starting to use pstorage_update(), but that does not even call my callback handler. Here is exactly how i am doing this(this handler is called every 500ms by a timer,

RAM_BLOCK_SIZE = 128

    static void fill_data_simulator_handler(void * p_context)
    {
       UNUSED_PARAMETER(p_context);
       sensor_data[ram_index] = cnt_nu;
       ram_index++;

       if(ram_index == (RAM_BLOCK_SIZE-1))
       {
 	 	  store_data_flag = 1;
	 
		  if(flash_overwrite_flag==1)
		  {
			 app_timer_stop(m_simulator_timer_id);
			 APP_ERROR_CHECK(err_code);
		  }
	   }
    }
  • The main function code,

RAM_BLOCK_COUNT=3

      int main(void)
      {
        // Initialize.
        timers_init();
        ble_stack_init();
        gap_params_init();
    services_init();
        advertising_init();
        conn_params_init();
        flash_area_for_pstorage_init();

	/* Store sensor configuration in flash */
	err_code = pstorage_block_identifier_get(&handle1, 0, &p_block_id1); // Get 1 block
	APP_ERROR_CHECK(err_code);
	
	err_code = pstorage_store(&p_block_id1, write_data, param1.block_size, 0);
	APP_ERROR_CHECK(err_code);
		
	nrf_dongle_led_init(); // Led pins init.

    application_timers_start();
	advertising_start();

       // Enter main loop.
       for (;;)
      {
        power_manage();
		
		if(store_data_flag == 1)
		{
			store_data_flag = 0;
			ram_index = 0;
			
			err_code = pstorage_block_identifier_get(&handle, block_id, &p_block_id); // Get 1 block
			APP_ERROR_CHECK(err_code);
			
			 if(flash_overwrite_flag == 1)
			 {
					err_code = pstorage_update(&p_block_id, sensor_data, param.block_size, 0);
					APP_ERROR_CHECK(err_code);
				 
					err_code = app_timer_start(m_simulator_timer_id, SIMULATOR_INTERVAL, NULL);
					APP_ERROR_CHECK(err_code);

			 }
			 else
			 {
					err_code = pstorage_store(&p_block_id, sensor_data, param.block_size, 0);
					APP_ERROR_CHECK(err_code);

			 }
			 
			 block_id++;
			 counter++;
			 cnt_nu++;
			 
			 if(block_id == RAM_BLOCK_COUNT)
			 {
				 flash_overwrite_flag = 1;
				 block_id = 0;
			 }
		}
        }
    }
  • And yes, i have registered for the system events:

      static void sys_evt_dispatch(uint32_t sys_evt)
      {
           if ((sys_evt == NRF_EVT_FLASH_OPERATION_SUCCESS) || (sys_evt ==   NRF_EVT_FLASH_OPERATION_ERROR))
           {
      	   pstorage_sys_event_handler(sys_evt);
           }
      
             ble_advertising_on_sys_evt(sys_evt);
      }
    
  • I did a further investagion and it seems that pstorage module is working correctly until i call update operation one time on the bigger block. I was doing these test with disabled advertising, just to make sure that i have enough time to write and update flash memory. After that, i can see that operations are posted on the queue, in pstorage.c, cmd_queue_enqueue() function m_cmd_queue.count variable gets incremented as it should but function pstorage_sys_event_handler() is never called agan. Any ideas?

  • I don't quickly see anything wrong with your code, but perhaps you can try a few things in order to find out something more.

    Have you tried to put breakpoint in the sys_evt_dispatch, to see if there is no callback or if just the pstorage module somehow does not forward the callback to the application? pstorage_update is in fact several flash operations combined into one, so you might get several callbacks into the sys_evt_dispatch handler.

    What if you only register pstorage only once, and write just to different blocks of the same page. Does that make a difference?

    What are your pstorage_platform settings?

    Can you read out the flash page in order to see if data is written/updated in flash or not?

  • Thank you for your comments. They helped me to track down the problem. I tried almost everything what you said and nothing worked, until i got to pstorage_platform settings. For some reason ( i don't remember modifying this file ever in my life), SWAP page address was defined like this:

    #define PSTORAGE_DATA_END_ADDR      (PSTORAGE_FLASH_PAGE_END * PSTORAGE_FLASH_PAGE_SIZE)        /**< End address for persistent data, configurable according to system requirements. */
    #define PSTORAGE_SWAP_ADDR          PSTORAGE_DATA_END_ADDR
    

    So, i thought that it doesn't make any sence, because swap page address should be the start address of last flash page and not the end address, so i modified it to this:

    #define PSTORAGE_DATA_END_ADDR      (PSTORAGE_FLASH_PAGE_END * PSTORAGE_FLASH_PAGE_SIZE)        /**< End address for persistent data, configurable according to system requirements. */
    #define PSTORAGE_SWAP_ADDR          (PSTORAGE_DATA_END_ADDR - PSTORAGE_FLASH_PAGE_SIZE)
    

    And everything started to work. I still do not know why i was allowed to update one block of flash, but when i had the other block full, update op also stopped working on the smaller block. Is this a known bug in the older SDK? As i said, i am using sdk v9.

  • ok, good that you found the issue. The SDK 9.0.0 should have in the pstorage_platform

    #define PSTORAGE_DATA_END_ADDR      ((PSTORAGE_FLASH_PAGE_END - 1) * PSTORAGE_FLASH_PAGE_SIZE)  
    #define PSTORAGE_SWAP_ADDR          PSTORAGE_DATA_END_ADDR  
    

    With your former setting I can't understand how that could work for a single pstorage_update call. At least now you know how it should be.

  • Well i did not understand this either when i found it, since it does not make any sence and should not have worked at all, but thank you Stefan, now i know how it should be.

Related