fds_record_write stops prematurely.

Hello.

It is under development using nrf52832 (S132 v7.0.1, SDK v17.0.0) as a peripheral device.

I'm currently considering Flash Data Storage (FDS).

As settings, "FDS_VIRTUAL_PAGES" is set to 4, "FDS_VIRTUAL_PAGE_SIZE" is set to 1024, and the writable area is 12kB.
In order to check how many times 64Byte can be written to 12kB, I created a process that repeats fds_record_write and made it work, but it is not an error and the operation stops halfway. I checked the number of times I wrote when I stopped, but the number of times was different each time.

#include "app_error.h"
#include "fds.h"

/* Definition of sdk_config.h */
#define FDS_ENABLED 1
#define FDS_VIRTUAL_PAGES 4
#define FDS_VIRTUAL_PAGE_SIZE 1024
#define FDS_VIRTUAL_PAGES_RESERVED 0
#define FDS_BACKEND 2
#define FDS_OP_QUEUE_SIZE 4
#define FDS_CRC_CHECK_ON_READ 0
#define FDS_CRC_CHECK_ON_WRITE 0
#define FDS_MAX_USERS 4

#define FILE_ID      0x1000 /* The ID of the file to write the records into. */
#define RECORD_KEY   0x1100 /* A key for the first record. */

typedef struct {
    uint8_t test_data_a;
    uint8_t test_data_b[6];
    uint8_t test_data_c[16];
    uint8_t test_data_d[16];
    uint8_t test_data_e[16];
    uint8_t test_data_f[8];
    uint8_t test_data_g;
} T_FDS_LOG_DATA;

static T_FDS_LOG_DATA v_fds_log_data_write;

static fds_record_t m_record =
{
    .file_id           = FILE_ID,
    .key               = RECORD_KEY,
    .data.p_data       = &v_fds_log_data_write,
    /* The length of a record is always expressed in 4-byte units (words). */
    .data.length_words = (sizeof(v_fds_log_data_write) / sizeof(uint32_t)),
};

static fds_record_desc_t  record_desc;
static uint32_t cb_write_cnt = 0;

static void fds_evt_handler(fds_evt_t const * p_fds_evt);

/* FDS related initialization function */
void fds_evt_init(void)
{
    ret_code_t err_code;

    memset(&v_fds_log_data_write, 0xAA, sizeof(v_fds_log_data_write));

    err_code = fds_register(fds_evt_handler);
    APP_ERROR_CHECK(err_code);

    err_code = fds_init();
    APP_ERROR_CHECK(err_code);    

    return;
}

/* FDS event handler */
static void fds_evt_handler(fds_evt_t const * p_fds_evt)
{
    switch (p_fds_evt->id)
    {
        // Initialization completion event.
        case FDS_EVT_INIT:
            if (p_fds_evt->result != NRF_SUCCESS) {
                // Initialization failed.
            }
            else {
                fds_data_write();
            }
            break;

        // Write complete event.
        case FDS_EVT_WRITE:
            cb_write_cnt++;
            m_record.key = (uint16_t)cb_write_cnt;
            v_fds_log_data_write.test_data_a = (uint8_t)cb_write_cnt;
            fds_data_write();
            break;

        default:
            break;
    }

    return;
}

/* FDS write process*/
void fds_data_write(void)
{
    ret_code_t err_code;

    // Write a record to Flash.
    err_code = fds_record_write(&record_desc, &m_record);
    APP_ERROR_CHECK(err_code);

    return;
}

Why does it stop working? Is there a countermeasure?

Best regards.

Parents
  • Hi Kei, 

    When you mention the operation stopped half way, could you describe what exactly you observed ? 
    If you stop the MCU where would it be ? 

    Could you provide a simple application to reproduce the issue that I can test here ? 

  • Hello.

    I decided to stop the operation because I checked the memory with IDE (IAR Embedded Workbench) and confirmed that the value was not written. At this time, when I stopped the debugger, it was in the HardFault Handler.

    Regarding applications that can be tested, they cannot be published. The mechanism is to call fds_evt_init before the advertisement output. Subsequent processing is as described in the callback. I think that it can work by making the same mechanism with the sample code of SDK.

    Best regards.

  • Hi Kei, 

    I tried your code here and don't see the same problem. I attached the code here. The write worked for 159 records and the it stops. 159x64 = 10176 bytes matching with the roughly 12kB you reserved for the fds (there is some headers on each of the record).


    Note that you should do a flash eraseall before you test so that the previous database will be cleaned. 

    In addition when you declare your data to be written to fds they should be word aligned. I added __ALIGN(4) into: 

    __ALIGN(4) static T_FDS_LOG_DATA v_fds_log_data_write;

    Here is the log I get : 

    ble_app_hrs_fds.zip

  • Hello.

    After investigating, you may have found the cause.

    In my program, UART communication was performed, and UART communication was also performed while writing FDS. Therefore, the UART reception interrupt may occur and the FDS interrupt (callback) may not operate normally, so I think that a problem has occurred.
    When I stopped the UART communication for a trial, I found that the FDS was written until FDS_ERR_NO_SPACE_IN_FLASH occurred.

    I would like to change the interrupt priority to solve this problem. Is it possible to change it? Do you have sample code or documentation?

    Best regards.

Reply
  • Hello.

    After investigating, you may have found the cause.

    In my program, UART communication was performed, and UART communication was also performed while writing FDS. Therefore, the UART reception interrupt may occur and the FDS interrupt (callback) may not operate normally, so I think that a problem has occurred.
    When I stopped the UART communication for a trial, I found that the FDS was written until FDS_ERR_NO_SPACE_IN_FLASH occurred.

    I would like to change the interrupt priority to solve this problem. Is it possible to change it? Do you have sample code or documentation?

    Best regards.

Children
  • Hi Kei, 
    I don't think using UART would cause a hardfault. Unless you are calling a softdevice API in a APP_HIGH priority interrupt handler. 

    As you can see the log I had was also from UART. 

    Please check which interrupt level you are doing your UART on. 

    I would suggest to define DEBUG in the project's preprocessor symbols so that you have more logging data. 
    Please try to check which function causing hardfault. Have a look here.

Related