Hi,
I am trying to use fds file system to save some data in flash, when using the example code of sdk 14.0.1, it is not normally operated,
NRF_ERROR_INVALID_PARAM error is happened with fds_record_update function, I update the code as follows, please help to let me know what is wrong,
thankful for your support in advance, thanks.
/*
Copyright (c) 2010 - 2017, Nordic Semiconductor ASA
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form, except as embedded into a Nordic
Semiconductor ASA integrated circuit in a product or a software update for
such product, must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
3. Neither the name of Nordic Semiconductor ASA nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
4. This software, with or without modification, must only be used with a
Nordic Semiconductor ASA integrated circuit.
5. Any software provided in binary form under this license must not be reverse
engineered, decompiled, modified and/or disassembled.
THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdint.h>
#include <string.h>
#include "nrf.h"
#include "nordic_common.h"
#include "fds.h"
#include "hal_fds_module.h"
#define ALIGN_NUM(alignment, number) ((number - 1) + alignment - ((number - 1) % alignment))
/* Array to map FDS return values to strings. */
char const * fds_err_str[] =
{
"FDS_SUCCESS",
"FDS_ERR_OPERATION_TIMEOUT",
"FDS_ERR_NOT_INITIALIZED",
"FDS_ERR_UNALIGNED_ADDR",
"FDS_ERR_INVALID_ARG",
"FDS_ERR_NULL_ARG",
"FDS_ERR_NO_OPEN_RECORDS",
"FDS_ERR_NO_SPACE_IN_FLASH",
"FDS_ERR_NO_SPACE_IN_QUEUES",
"FDS_ERR_RECORD_TOO_LARGE",
"FDS_ERR_NOT_FOUND",
"FDS_ERR_NO_PAGES",
"FDS_ERR_USER_LIMIT_REACHED",
"FDS_ERR_CRC_CHECK_FAILED",
"FDS_ERR_BUSY",
"FDS_ERR_INTERNAL",
};
/* Array to map FDS events to strings. */
static char const * fds_evt_str[] =
{
"FDS_EVT_INIT",
"FDS_EVT_WRITE",
"FDS_EVT_UPDATE",
"FDS_EVT_DEL_RECORD",
"FDS_EVT_DEL_FILE",
"FDS_EVT_GC",
};
/* Dummy configuration data. */
static configuration_t m_dummy_cfg =
{
// .config1_on = false,
// .config2_on = true,
.boot_count = 0x0,
// .device_name = "dummy",
};
/* A record containing dummy configuration data. */
static fds_record_t const m_dummy_record =
{
.file_id = CONFIG_FILE,
.key = CONFIG_REC_KEY,
.data.p_data = &m_dummy_cfg,
/* The length of a record is always expressed in 4-byte units (words). */
.data.length_words = (sizeof(m_dummy_cfg) + 3) / sizeof(uint32_t),
};
/* Keep track of the progress of a delete_all operation. */
static struct
{
bool delete_next; //!< Delete next record.
bool pending; //!< Waiting for an fds FDS_EVT_DEL_RECORD event, to delete the next record.
} m_delete_all;
/* Flag to check fds initialization. */
static bool volatile m_fds_initialized;
/*
@brief Function for handling flash data storage events.
*/
static void fds_evt_handler(fds_evt_t const * p_evt)
{
printf("Event: %s received (%s)\r\n",
fds_evt_str[p_evt->id],
fds_err_str[p_evt->result]);
switch (p_evt->id)
{
case FDS_EVT_INIT:
if (p_evt->result == FDS_SUCCESS)
{
m_fds_initialized = true;
}
break;
case FDS_EVT_WRITE:
{
if (p_evt->result == FDS_SUCCESS)
{
// NRF_LOG_INFO("Record ID:\t0x%04x", p_evt->write.record_id);
// NRF_LOG_INFO("File ID:\t0x%04x", p_evt->write.file_id);
// NRF_LOG_INFO("Record key:\t0x%04x", p_evt->write.record_key);
}
} break;
case FDS_EVT_DEL_RECORD:
{
if (p_evt->result == FDS_SUCCESS)
{
// NRF_LOG_INFO("Record ID:\t0x%04x", p_evt->del.record_id);
// NRF_LOG_INFO("File ID:\t0x%04x", p_evt->del.file_id);
// NRF_LOG_INFO("Record key:\t0x%04x", p_evt->del.record_key);
}
m_delete_all.pending = false;
} break;
default:
break;
}
}
uint32_t m_flash_config_store(uint16_t file_id,
uint16_t record_key,
uint8_t *p_data)//love_0122 read function,
{
fds_record_desc_t desc = {0};
fds_find_token_t tok = {0};
ret_code_t rc;
rc = fds_record_find(file_id, record_key, &desc, &tok);
if (rc == FDS_SUCCESS)
{
/* A config file is in flash. Let's update it. */
fds_flash_record_t config = {0};
/* Open the record and read its contents. */
rc = fds_record_open(&desc, &config);
APP_ERROR_CHECK(rc);
/* Copy the configuration from flash into m_dummy_cfg. */
memcpy(&m_dummy_cfg, config.p_data, sizeof(configuration_t));
printf("Config file found, updating boot count to %d.\r\n", m_dummy_cfg.boot_count);
/* Update boot count. */
m_dummy_cfg.boot_count++;
/* Close the record when done reading. */
rc = fds_record_close(&desc);
APP_ERROR_CHECK(rc);
// fds_record_t record;
// memset(&record, 0, sizeof(record));
//
// record.file_id = CONFIG_FILE;
// record.key = CONFIG_REC_KEY;
// record.data.p_data = &m_dummy_cfg;
// record.data.length_words = ALIGN_NUM(4, sizeof(configuration_t))/sizeof(uint32_t);
//
// rc = fds_record_update(&desc, &record);
// APP_ERROR_CHECK(rc);
printf("Updating config file...\r\n");
/* Write the updated record to flash. */
rc = fds_record_update(&desc, &m_dummy_record);
APP_ERROR_CHECK(rc);
}
else
{
/* System config not found; write a new one. */
printf("Writing config file...\r\n");
rc = fds_record_write(&desc, &m_dummy_record);
APP_ERROR_CHECK(rc);
}
return NRF_SUCCESS;
}
uint32_t m_flash_config_load(uint16_t file_id,
uint16_t record_key,
uint8_t *p_data)//love_0122 read function,
{//refer to blog.naver.com/.../220973874671
fds_record_desc_t desc = {0};
fds_find_token_t tok = {0};
ret_code_t rc;
rc = fds_record_find(file_id, record_key, &desc, &tok);
if (rc == FDS_SUCCESS)
{
/* A config file is in flash. Let's update it. */
fds_flash_record_t config = {0};
/* Open the record and read its contents. */
rc = fds_record_open(&desc, &config);
APP_ERROR_CHECK(rc);
/* Copy the configuration from flash into m_dummy_cfg. */
memcpy(&p_data, config.p_data, sizeof(configuration_t));
// printf("love m_flash_config_load = %d \r\n", p_data);
/* Close the record when done reading. */
rc = fds_record_close(&desc);
APP_ERROR_CHECK(rc);
}
return NRF_SUCCESS;
}
bool record_delete_next(void)
{
fds_find_token_t tok = {0};
fds_record_desc_t desc = {0};
if (fds_record_iterate(&desc, &tok) == FDS_SUCCESS)
{
ret_code_t rc = fds_record_delete(&desc);
if (rc != FDS_SUCCESS)
{
return false;
}
return true;
}
else
{
/* No records left to delete. */
return false;
}
}
/**@brief Begin deleting all records, one by one. */
void delete_all_begin(void)
{
m_delete_all.delete_next = true;
}
/**@brief Process a delete all command.
*
* Delete records, one by one, until no records are left.
*/
void delete_all_process(void)
{
if ( m_delete_all.delete_next
& !m_delete_all.pending)
{
printf("Deleting next record.\r\n");
m_delete_all.delete_next = record_delete_next();
if (!m_delete_all.delete_next)
{
printf("No records left to delete.\r\n");
}
}
}
/**@brief Wait for fds to initialize. */
static void wait_for_fds_ready(void)
{
while (!m_fds_initialized)
{
// power_manage();
}
}
uint32_t m_flash_init(void)
{
ret_code_t rc;
/* Register first to receive an event when initialization is complete. */
(void) fds_register(fds_evt_handler);
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);
printf("Found %d valid records.\r\n", stat.valid_records);
printf("Found %d dirty records (ready to be garbage collected).\r\n", stat.dirty_records);
return NRF_SUCCESS;
}