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

erasing/writing to NVRAM not working

Howdy,

I am having difficulties writing to NVRAM (reading appears to be fine and is reporting 0xFF's everwhere). I am using a rather old SDK and SoftDevice 110 (version 8) on an NRF51822 because I was modifying code in production.

I am trying to save some calibration to NVRAM (my old code worked fine, but it no longer is and I can't find where the problem is). Unfortunately the erasing and saving does not appear to work. All of the Nordic SDK functions are returning NRF_SUCCESS; however I never get a call back after doing a write or erase. I also tried waiting (250 ms) in case it was just a problem in receiving the callback message, but every time the data remains unwritten and is read as all 0xFF. Normally the save code is run when the system powers down (way after all system initialization is complete), but I moved some test code (indicated in nvram_init() below) to the beginning in order to more easily debug the problem. No luck. I have attached the relevant code below and was hoping that something jumps out as obviously wrong.

Thanks,

-F

PS- hardware_configure() just sets some GPIOs.

int main(void)
{
  system_init();
          
  while(1)
  {
    app_sched_execute();  
    nrf_drv_wdt_feed();
    power_manage();
  }
}
        
void system_init(void)
{
  static app_button_cfg_t button[] = { BUTTON_PIN, APP_BUTTON_ACTIVE_LOW, NRF_GPIO_PIN_NOPULL, system_button_handler };
            
  uint32_t error;
         
  sys.shutdown       = false;
  sys.buttonShutdown = false;
  sys.buttonReleased = false;
  sys.forceSave      = false;
  sys.forceReseed    = false;
  sys.connected      = false;
  sys.newNFC         = false;
  sys.reset          = false;
          
  hardware_configure();
          
  timers_init();
          
  error = pstorage_init();
  APP_ERROR_CHECK(error);
          
  ble_stack_init();
          
  nvram_init();
  device_manager_init(false);
              
  gap_params_init();
  advertising_init();
  ble_services_init();
         
  i2c_init();
  leds_init();
  spi_init();
        
  sensors_init();
        
//  wdt_init();
  conn_params_init();
  error              = app_button_init(button, NUMBER_OF_BUTTONS, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER));
  APP_ERROR_CHECK(error);
  error              = app_button_enable();
  APP_ERROR_CHECK(error);

  app_timer_start(timers.logo, TIMER_LOGO_TICKS, NULL);
  app_timer_start(timers.led, TIMER_LED_EVENT_TICKS, NULL);
        
  error = ble_advertising_start(BLE_ADV_MODE_FAST);
  APP_ERROR_CHECK(error);
}
        
void timers_init(void)
{
  uint32_t error;
        
  APP_TIMER_APPSH_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, true);
        
  error = app_timer_create(&timers.bt, APP_TIMER_MODE_REPEATED, bt_timer_handler);
  APP_ERROR_CHECK(error);
  error = app_timer_create(&timers.led, APP_TIMER_MODE_REPEATED, led_timer_handler);
  APP_ERROR_CHECK(error);
  error = app_timer_create(&timers.sample, APP_TIMER_MODE_REPEATED, sample_timer_handler);
  APP_ERROR_CHECK(error);
  error = app_timer_create(&timers.button, APP_TIMER_MODE_SINGLE_SHOT, button_timer_handler);
  APP_ERROR_CHECK(error);
  error = app_timer_create(&timers.nfc, APP_TIMER_MODE_REPEATED, nfc_timer_handler);
  APP_ERROR_CHECK(error);
  error = app_timer_create(&timers.logo, APP_TIMER_MODE_SINGLE_SHOT, system_logo_timer_handler);
        
  APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
}
        
void ble_stack_init(void)
{
  ble_enable_params_t bleEnableParams;
  uint32_t            error;

  SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_TEMP_4000MS_CALIBRATION, NULL);

  memset(&bleEnableParams, 0, sizeof(bleEnableParams));
  bleEnableParams.gatts_enable_params.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT;
  error                                               = sd_ble_enable(&bleEnableParams);
  APP_ERROR_CHECK(error);
        
  // Register with the SoftDevice handler module for BLE events.
  error = softdevice_ble_evt_handler_set(_ble_evt_dispatch);
  APP_ERROR_CHECK(error);

  // Register with the SoftDevice handler module for BLE events.
  error = softdevice_sys_evt_handler_set(_sys_evt_dispatch);
  APP_ERROR_CHECK(error);
}
        
void nvram_init(void)
{
  uint32_t                error;
  pstorage_module_param_t psParams;
        
  memset(&nvram, 0, sizeof(nvram));
        
  psParams.block_size  = NVRAM_BLOCK_SIZE;
  psParams.block_count = NVRAM_BLOCKS;
  psParams.cb          = nvram_callback_handler;

  error = pstorage_register(&psParams, &nvram.blockBase);
  APP_ERROR_CHECK(error);

// TEST CODE
sys.forceSave = true;
for(error=0;error<8;error++)
{
  uint8_t i;
  for(i=0;i<18;i++)
  {
    references[error][i] = error*8 + i;
  }
}  
nvram_save();

// END TEST CODE
  
  sys.forceSave = false;
  _recover_data();
}
    
uint8_t nvram_save(void)
{
  uint8_t  *bufferPtr;
  uint16_t  i;
  uint16_t  crc;
  int16_t  *rData = (int16_t *)references;
  uint32_t  error;
    
  if((sys.forceSave == true) || sensor_check_references())
  {
    for(i=0;i<NVRAM_NAME_LENGTH;i++)
    {
      buffer[i] = nvram.name[i];
    }
    bufferPtr = buffer + NVRAM_NAME_LENGTH;
    for(i=0;i<SENSOR_ELEMENTS;i++)
    {
      bufferPtr[i << 1]       = (uint8_t)((rData[i] >> 8) & 0x00FF);
      bufferPtr[(i << 1) + 1] = (uint8_t)rData[i];
    }
        
    for(i = (NVRAM_NAME_LENGTH + (SENSOR_ELEMENTS * 2));i<NVRAM_DATA_LENGTH;i++)
    {
      buffer[i] = 0;
    }
    
    _erase();
     
    crc = crc16_compute((const uint8_t *)buffer, NVRAM_DATA_LENGTH, NULL);
    buffer[i++] = (uint8_t)(crc >> 8);
    buffer[i]   = (uint8_t)crc;
  }
      
  error = _write(0);
  APP_ERROR_CHECK(error);
  return false;
}
    
static inline uint8_t _write(uint8_t block)
{
  uint32_t error;
      
  error = pstorage_block_identifier_get(&nvram.blockBase, 0, &nvram.cBlock);
  APP_ERROR_CHECK(error);
 
  error = pstorage_store(&nvram.cBlock, buffer, NVRAM_BLOCK_SIZE, 0);
  APP_ERROR_CHECK(error);
      
  nrf_delay_ms(250);

  // IF WE GET A CRC MISMATCH DURING READBACK THEN SOMETHING WENT WRONG...
  if(_read(block) == NVRAM_CRC_MISMATCH)
  {
    return NVRAM_CRC_MISMATCH;
  }

  return NVRAM_SUCCESS;
}
    
static inline void _erase(void)
{
  uint32_t error;
      
  pstorage_block_identifier_get(&nvram.blockBase, 0, &nvram.cBlock);
  error      = pstorage_clear(&nvram.cBlock, NVRAM_BLOCK_SIZE * NVRAM_BLOCKS);
  APP_ERROR_CHECK(error);
  nrf_delay_ms(250);
}
Related