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

Flash erase/write problems

I've spent several days reading all the support tickets regarding this issue but I cannot find a resolution.

I am running the ble_central_uart example with SD 132, SES 4.30, SDK 15.3 on an nRF52 DK dev board.  

I have been unable to erase flash consistently or to write flash at all.  It appears that I am having problems with both erasing and writing flash.  I implemented the sd_flash_page_erase() function as follows:

uint32_t static pg_size;
uint32_t static pg_num;
uint32_t static flash_addr;
uint32_t static p_flash_addr;

static uint32_t nrf5_flash_end_addr_get()
{
    pg_size = NRF_FICR->CODEPAGESIZE;
    pg_num = NRF_FICR->CODESIZE-2; // Use last page in flash
    flash_addr = (uint32_t *)(pg_size * pg_num);
    p_flash_addr = &flash_addr;
}

void erase_flash_page(void)
{

  flash_operation_completed = false;
  sd_flash_page_erase(pg_num);

  while(!flash_operation_completed)
  {
  sd_app_evt_wait();
  flash_operation_completed = true;
  }
}

This code executes but it does not check for the flash erase function to complete.  In debugging the problem, I found that the write function sd_flash_write() was erroring out on err_code == NRF_ERROR_BUSY.  So I figured the erase function required more time to complete.  I added a delay nrf_delay_ms(100) and tried a timer as well.  Neither did any good.  So I added an error check on the sd_flash_page_erase() function, like this:

void erase_flash_page(void)
{
uint32_t evt = 0;
retry_flash:
    flash_operation_completed = false;
    sd_flash_page_erase(pg_num);
   
    while(!flash_operation_completed)
    {
      sd_evt_get (&evt);
      if (evt == NRF_EVT_FLASH_OPERATION_SUCCESS || evt == NRF_EVT_FLASH_OPERATION_ERROR)
      {
        flash_operation_completed = true;
        goto resume_flash_operations;
      }
      else 
      {
        start_flash_timer();
        goto retry_flash;
      }
    }

//  nrf_delay_ms(10);     // give flash time to finish

  while(!flash_operation_completed)
  {
  sd_app_evt_wait();
  flash_operation_completed = true;
  }

resume_flash_operations:
return (12345);
}

Line 11 never evaluates as true.  So the code gets stuck in this loop.

The other problem I have is that even when I put a delay in the erase code and let it pass through the erase function to the write function, I get an NRF_BUSY_ERROR in the write flash function.  See code below:

void write_flash_page(void)
{
  ret_code_t err_code;
uint8_t block_size = sizeof(write_flash_block);

//  sd_flash_write((uint32_t*)flash_addr, (uint32_t*)&write_flash_block, sizeof(write_flash_block));
//  sd_flash_write((uint32_t*)&flash_addr, p_write_flash_block, sizeof(write_flash_block));
//  sd_flash_write(p_flash_addr, p_write_flash_block, sizeof(write_flash_block));

  flash_operation_completed = false;
  err_code = sd_flash_write((uint32_t*)flash_addr, p_write_flash_block, block_size);

  if (err_code != NRF_SUCCESS)
  {
     NRF_LOG_INFO("Error writing to flash, err_code = \"%x\" .", err_code);
      if (err_code == NRF_ERROR_INVALID_LENGTH) while (1);
      if (err_code == NRF_ERROR_INVALID_ADDR) while (1);
      if (err_code == NRF_ERROR_BUSY) while (1);
      if (err_code == NRF_ERROR_FORBIDDEN) while (1);
  }

  while(!flash_operation_completed)
  {
  sd_app_evt_wait();
  flash_operation_completed = true;
  }
}

The code always hangs on line 18 - if (err_code == NRF_ERROR_BUSY) while (1);

I make sure that my writes are word aligned as shown:

    struct blockstruct // block to write into flash.
    {
      int desired_temp;                       // Last water temperature requested by user.
      int desired_flow;                       // same
      int user_max_temp;
      int absolute_max_temp;
      bool startup_done;
      bool install_mode;
      bool initialization_done;
      bool clockwise_heat;
      int shower_timer;
      bool temp_scale;
      int user_last_preset;
      int user_last_temp;
    }__ALIGN(4)write_flash_block, __ALIGN(4)read_flash_block;

and my flash writes always begin at the start of the flash page which happens to be 7e000.  

Finally, I tried to supply my own event handler with this code:

static void sys_evt_dispatch(uint32_t sys_evt)
{
    app_sys_event_handler(sys_evt);
}

void app_sys_event_handler(uint32_t sys_evt)
{
//    flash_operation_completed = false;

	switch (sys_evt)
	{
		case NRF_EVT_FLASH_OPERATION_SUCCESS:
			flash_operation_completed = true;
                        NRF_LOG_INFO("--> Flash page operation sucessfull.");
			break;

		case NRF_EVT_FLASH_OPERATION_ERROR:
			// Handle error
                        NRF_LOG_INFO("--> Flash page operation FAILED!!!!!!!!!!!!!!.");
			break;
	}
}

    // Register with the SoftDevice handler module for BLE events.
ret_code_t err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
softdevice_sys_evt_handler_set(sys_evt_dispatch);
APP_ERROR_CHECK(err_code);

But it seems that this code isn't supported by SDK 15.3.  I get compile errors.

Where am I going wrong?

Parents Reply
  • I was previously told (by another Nordic tech support person) to use the sd_flash_page_erase() / write functions.  The problem is that I only need to store a single structure in flash and the FDS code carries a HUGE overhead.  Do you have a scaled down example that uses FDS but only deals with storing and reading a few system variables?  I don't need any kind of record processing support.

Children
No Data
Related