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

Flash read and write problems

Others have had similar problems with pointers for structures.  So, I've tried several different methods including one that was suggested in another help ticket. I am writing a block structure so I tried using (uint8_t *) &fstorage pointers to no effect.  

Here's my code:

/*****************************************************************************************
                     FStorage Flash EXAMPLE
******************************************************************************************/
static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);

NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
{
    /* Set a handler for fstorage events. */
    .evt_handler = fstorage_evt_handler,

    /* These below are the boundaries of the flash space assigned to this instance of fstorage.
     * You must set these manually, even at runtime, before nrf_fstorage_init() is called.
     * The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
     * last page of flash available to write data. */

    .start_addr = 0x3e000,
    .end_addr   = 0x3ffff,
};

/* Dummy data to write to flash. */

static uint32_t m_data          = 0xBADC0FFE;
static char     m_hello_world[] = "hello world";
#define FLASH_ADDR  0x3e000

/**@brief   Helper function to obtain the last address on the last page of the on-chip flash that
 *          can be used to write user data. */

static uint32_t nrf5_flash_end_addr_get()
{
    uint32_t const bootloader_addr = NRF_UICR->NRFFW[0];
    uint32_t const page_sz         = NRF_FICR->CODEPAGESIZE;
    uint32_t const code_sz         = NRF_FICR->CODESIZE;

    return (bootloader_addr != 0xFFFFFFFF ?
            bootloader_addr : (code_sz * page_sz));
}

// *@brief   Sleep until an event is received. 
static void power_manage(void)
{
    (void) sd_app_evt_wait();
}


static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
{
    if (p_evt->result != NRF_SUCCESS)
    {
        NRF_LOG_INFO("--> Event received: ERROR while executing an fstorage operation.");
        return;
    }

    switch (p_evt->id)
    {
        case NRF_FSTORAGE_EVT_WRITE_RESULT:
        {
            NRF_LOG_INFO("--> Event received: wrote %d bytes at address 0x%x.",
                         p_evt->len, p_evt->addr);
        } break;

        case NRF_FSTORAGE_EVT_ERASE_RESULT:
        {
            NRF_LOG_INFO("--> Event received: erased %d page from address 0x%x.",
                         p_evt->len, p_evt->addr);
        } break;

        default:
            break;
    }
}

static void print_flash_info(nrf_fstorage_t * p_fstorage)
{
    NRF_LOG_INFO("========| flash info |========");
    NRF_LOG_INFO("erase unit: \t%d bytes",      p_fstorage->p_flash_info->erase_unit);
    NRF_LOG_INFO("program unit: \t%d bytes",    p_fstorage->p_flash_info->program_unit);
    NRF_LOG_INFO("==============================");
}

void wait_for_flash_ready(nrf_fstorage_t const * p_fstorage)
{
    // While fstorage is busy, sleep and wait for an event. 
    while (nrf_fstorage_is_busy(p_fstorage))
    {
        power_manage();
    }
}

/****************** Erase Flash ***************************/
/* This is the address in flash page to be erased.
   The address below is presented as an example to illustrate the API. */

void erase_flash_block(void)
{
  ret_code_t rc;
  static uint32_t pages_to_erase = 1;
  // #define FLASH_ADDR  0x3e000        // defined in global area. Shown here clarity

    rc = nrf_fstorage_erase(
    &fstorage,      // The instance to use. 
    FLASH_ADDR,     // The address of the flash pages to erase. 
    pages_to_erase, // The number of pages to erase. 
    NULL            // Optional parameter, backend-dependent. 
    );
  if (rc == NRF_SUCCESS)
  {
    // The operation was accepted.
    // Upon completion, the NRF_FSTORAGE_ERASE_RESULT event
    // is sent to the callback function registered by the instance. 
  }
  else
  {
    // Handle error.
  }
}

//int main(void)
int flash_init(void)
{
//typedef enum { FALSE = 0, TRUE = 1, } BOOL; // copy of global section shown here for clarity

/*
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;
} flashblock, readflashblock;
*/

//  Fill flash structure with known data to test flash writes and reads
    flashblock.desired_temp = 75;   // Last water temperature requested by user.
    flashblock.desired_flow = 2;    // same
    flashblock.user_max_temp = 103;
    flashblock.absolute_max_temp = 115;
    flashblock.startup_done = 0;
    flashblock.install_mode = 0;
    flashblock.initialization_done = 1;
    flashblock.clockwise_heat = 1;
    flashblock.shower_timer = 13;
    flashblock.temp_scale = 0;

    erase_flash_block();

    wait_for_flash_ready(&fstorage);
    NRF_LOG_INFO("Done Erasing.");

    ret_code_t rc;
    NRF_LOG_INFO("fstorage example started.");
    nrf_fstorage_api_t * p_fs_api;

    NRF_LOG_INFO("Initializing nrf_fstorage_sd implementation...");
    /* Initialize an fstorage instance using the nrf_fstorage_sd backend.
     * nrf_fstorage_sd uses the SoftDevice to write to flash. This implementation can safely be
     * used whenever there is a SoftDevice, regardless of its status (enabled/disabled). */

    p_fs_api = &nrf_fstorage_sd;

    rc = nrf_fstorage_init(&fstorage, p_fs_api, NULL);
    APP_ERROR_CHECK(rc);

    // Print out the flash structure to the debug window 
    print_flash_info(&fstorage);

    /* It is possible to set the start and end addresses of an fstorage instance at runtime.
     * They can be set multiple times, should it be needed. The helper function below can
     * be used to determine the last address on the last page of flash memory available to
     * store data. */

    (void) nrf5_flash_end_addr_get();

    // Let's write to flash. 
//    NRF_LOG_INFO("Writing \"%x\" to flash.", m_data);
    NRF_LOG_INFO("Writing \"%d\" to flash.", flashblock.desired_temp);
    NRF_LOG_INFO("Writing \"%x\" to flash.", flashblock.desired_flow);
    NRF_LOG_INFO("Writing \"%d\" to flash.", flashblock.user_max_temp);
    NRF_LOG_INFO("Writing \"%d\" to flash.", flashblock.absolute_max_temp);
    NRF_LOG_INFO("Writing \"%h\" to flash.", flashblock.startup_done);
    NRF_LOG_INFO("Writing \"%h\" to flash.", flashblock.install_mode);
    NRF_LOG_INFO("Writing \"%h\" to flash.", flashblock.initialization_done);
    NRF_LOG_INFO("Writing \"%h\" to flash.", flashblock.clockwise_heat);
    NRF_LOG_INFO("Writing \"%d\" to flash.", flashblock.shower_timer);
    NRF_LOG_INFO("Writing \"%h\" to flash.", flashblock.temp_scale);
//    rc = nrf_fstorage_write(&fstorage, 0x3e000, &m_data, sizeof(m_data), NULL);
    rc = nrf_fstorage_write(&fstorage, 0x3e000, (uint8_t*) &flashblock, sizeof(flashblock), NULL);
//    rc = nrf_fstorage_write(&fstorage, 0x3e000, &flashblock, sizeof(flashblock), NULL);
    APP_ERROR_CHECK(rc);

    wait_for_flash_ready(&fstorage);
    NRF_LOG_INFO("Done Writing.");

// Read the information back and put into new structure
/****************** Read Flash ***************************/
/* This is the address in flash where data will be read.
   The address below is presented as an example to illustrate the API.
*/
//#define FLASH_ADDR  0x3e000   // defined in global area. Shown here for clarity

    rc = nrf_fstorage_read(
    &fstorage,              // The instance to use. 
    FLASH_ADDR,             // The address in flash where to read data from. 
    (uint8_t*) &readflashblock,        // A buffer to copy the data into. 
    sizeof(readflashblock)  // Lenght of the data, in bytes. 
    );
    if (rc == NRF_SUCCESS)
    {
    // The operation was accepted. 
    }
    else
    {
    // Handle error.
    }

    wait_for_flash_ready(&fstorage);
    NRF_LOG_INFO("Done Reading.");

// Now read back the data
    NRF_LOG_INFO("Read back data \"%d\" from flash.", readflashblock.desired_temp);
    NRF_LOG_INFO("Read back data \"%x\" from flash.", readflashblock.desired_flow);
    NRF_LOG_INFO("Read back data \"%d\" from flash.", readflashblock.user_max_temp);
    NRF_LOG_INFO("Read back data \"%d\" from flash.", readflashblock.absolute_max_temp);
    NRF_LOG_INFO("Read back data \"%h\" from flash.", readflashblock.startup_done);
    NRF_LOG_INFO("Read back data \"%h\" from flash.", readflashblock.install_mode);
    NRF_LOG_INFO("Read back data \"%h\" from flash.", readflashblock.initialization_done);
    NRF_LOG_INFO("Read back data \"%h\" from flash.", readflashblock.clockwise_heat);
    NRF_LOG_INFO("Read back data \"%d\" from flash.", readflashblock.shower_timer);
    NRF_LOG_INFO("Read back data \"%h\" from flash.", readflashblock.temp_scale);

    m_data = 0xDEADBEEF;

    NRF_LOG_INFO("Writing \"%x\" to flash.", m_data);
    rc = nrf_fstorage_write(&fstorage, 0x3e100, &m_data, sizeof(m_data), NULL);
    APP_ERROR_CHECK(rc);

    wait_for_flash_ready(&fstorage);
    NRF_LOG_INFO("Done.");

    NRF_LOG_INFO("Writing \"%s\" to flash.", m_hello_world);
    rc = nrf_fstorage_write(&fstorage, 0x3f000, m_hello_world, sizeof(m_hello_world), NULL);
    APP_ERROR_CHECK(rc);

    wait_for_flash_ready(&fstorage);
    NRF_LOG_INFO("Done.");
}

I copied the block structures from the global area into this flash routine for clarity so you can see what I am trying to write. Here's my debug info:

Parents Reply Children
No Data
Related