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: