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

Errors writing to flash memory multiple times in flash_fds example

I'm trying to modify the flash_fds example to write a start time when a button is pressed, then an end time when the button is released.  I get the time over TWI from an RTC and I've verified my functions to get the time and to write the time are both working.  So basically the flow of the program goes: 

1.) initialize FDS

2.)Enter the function buttonPress() which waits for a button to be pressed then calls the writeStartTime() function when pressed

3.)Write the time to flash memory when a button is pressed

(What I want to add) 4.)Write the end time to flash memory when the button is released

The program runs as I have it currently, but adding a second function, writeEndTime() (commented out in line 95)  within the button press function breaks the program.  When I run the program with writeEndTime() included the call to writeStartTime() works and the first time is written to memory, but then I get "fatal error" and "system reset" afterwards.  Below are the important areas of code.

void writeEndTime()
{
   #define FILE_ID         0x0005  /* The ID of the file to write the records into. */
   #define RECORD_KEY_1    0x5555  /* A key for the first record. */

   ret_code_t rc = NULL;

   uint8_t* rx_data = clockTime(); //get the pointer to the array that holds the clockTime

   static char intermediate[20] = {0}; //writing to the aligned variable breaks the alignment but memcpy doesn't.  So add data to an intermediate var then memcpy it to the aligned variable and write it to memory.
  __ALIGN(4) static char m_timeStart[20] = {0};
   
    
  //generate a string that holds the start time from the array
  
  snprintf(intermediate, sizeof(intermediate), "E: %x:%x:%x %x/%x/%x", rx_data[2], rx_data[1], rx_data[0], rx_data[5], rx_data[4], rx_data[6]);
  memcpy(m_timeStart, intermediate, sizeof(intermediate));

  //add this line to see what was written to timeStart.  After first run can also check what was written through getTime fn.
  //NRF_LOG_INFO("time: %c%c%c%c written to memory!", m_timeStart[0],m_timeStart[1],m_timeStart[2],m_timeStart[3]); 


   fds_record_t        record;
   fds_record_desc_t   record_desc;


   // Set up record.

   record.file_id           = FILE_ID;
   record.key               = RECORD_KEY_1;
   record.data.p_data       = &m_timeStart;
   /* The following calculation takes into account any eventual remainder of the division. */
   record.data.length_words = (sizeof(m_timeStart) + 3) / 4;
   rc = fds_record_write(&record_desc, &record);
}


void writeStartTime()
{
   #define FILE_ID         0x0005  /* The ID of the file to write the records into. */
   #define RECORD_KEY_1    0x5555  /* A key for the first record. */

   ret_code_t rc = NULL;

   uint8_t* rx_data = clockTime(); //get the pointer to the array that holds the clockTime

   static char intermediate[20] = {0}; //writing to the aligned variable breaks the alignment but memcpy doesn't.  So add data to an intermediate var then memcpy it to the aligned variable and write it to memory.
  __ALIGN(4) static char m_timeStart[20] = {0};
   
    
  //generate a string that holds the start time from the array
  
  snprintf(intermediate, sizeof(intermediate), "S: %x:%x:%x %x/%x/%x", rx_data[2], rx_data[1], rx_data[0], rx_data[5], rx_data[4], rx_data[6]);
  memcpy(m_timeStart, intermediate, sizeof(intermediate));

 
   fds_record_t        record;
   fds_record_desc_t   record_desc;


   // Set up record.

   record.file_id           = FILE_ID;
   record.key               = RECORD_KEY_1;
   record.data.p_data       = &m_timeStart;
   /* The following calculation takes into account any eventual remainder of the division. */
   record.data.length_words = (sizeof(m_timeStart) + 3) / 4;
   rc = fds_record_write(&record_desc, &record);

}

void buttonPress()
{

  nrf_gpio_cfg_output(LED); 
  nrf_gpio_cfg_input(Button, NRF_GPIO_PIN_PULLUP); 
                                                   
  

   nrf_gpio_pin_set(LED); 


   while (true) //general run loop
   {
      
      if(nrf_gpio_pin_read(Button) == 0) //when the button is pressed 
      {
        
        nrf_gpio_pin_clear(LED); //turn on the LED 
        writeStartTime(); //write the string with starting time then enter the while loop 
        
        while(nrf_gpio_pin_read(Button) == 0) 
        {};
        
        //writeEndTime();
        nrf_gpio_pin_set(LED);
        break;
      }
   } 
}


int main(void) //when clock time is called it can cause an error if placed after log_init
{
    ret_code_t rc;


#ifdef SOFTDEVICE_PRESENT
    ble_stack_init();
#else
    clock_init();
#endif

    timer_init();
    log_init();
    cli_init();

    
    NRF_LOG_INFO("FDS example started.")


    /* Register first to receive an event when initialization is complete. */
    (void) fds_register(fds_evt_handler);

    NRF_LOG_INFO("Initializing fds...");

    rc = fds_init();
    APP_ERROR_CHECK(rc);

    /* Wait for fds to initialize. */
    wait_for_fds_ready();

    fds_stat_t stat = {0};

    rc = fds_stat(&stat);
    APP_ERROR_CHECK(rc);
    
    buttonPress(); 
    cli_start();

    /* Enter main loop. */
    for (;;)
    {
        if (!NRF_LOG_PROCESS())
        {
            power_manage();
        }
        cli_process();
        delete_all_process();
    }
}

I think I'm not understanding something in the flow of events for writing to flash memory through the flash_fds example since I know I can write once, but the second write breaks it.  Is there something that I need to do or reset between calls for functions that write to flash memory to allow the program to write to memory twice?

I also think there might be an issue with the cli interface.  I'm not sure what exactly it does in the flash fds example other than provide the cli to give the program commands, but commenting it out gives a variety of errors, so if anyone could explain what it is doing to setup the flash_fds that would be very helpful as well, thanks!

Parents
  • Update:  I solved this issue by adding a 100ms delay after the write functions.  Basically the next command was being executed before the write event had finished, which led to an interruption that was causing the error.  I found it when I noticed only the beginning of what I wanted to write was successfully written to memory.

    The code I used was nrf_delay_ms(100).  Hope this is helpful!

Reply
  • Update:  I solved this issue by adding a 100ms delay after the write functions.  Basically the next command was being executed before the write event had finished, which led to an interruption that was causing the error.  I found it when I noticed only the beginning of what I wanted to write was successfully written to memory.

    The code I used was nrf_delay_ms(100).  Hope this is helpful!

Children
  • Thanks for letting us know. Note that a better approach, which is to wait for the FDS_EVT_WRITE or FDS_EVT_UPDATE event before scheduling a new write. That way you will not wait longer than necessary (also busy waiting with nrf_delay_ms() is fine in some situations, but you do typically not want to do that often for long times in areal product as it is jus ta busy wait, spending CPU time and power).

Related