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

As to fds_record_update error of sdk 14.0.1 (NRF 52832)

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;
}
Related