Hi,
Here is some background information:
Using Flash Translation Layer (FTL) to store configuration data including SSID, pwd, firmware parameters. The size of the data structure is about 500 bytes.
FLT is initialized as such:
ftl_init(ftl_phy_page_start_addr, ftl_phy_page_num);
//where ftl_phy_page_start_addr is USER_DATA_START_ADDR
#define USER_DATA_START_ADDR 0x00100000
//and ftl_phy_page_num = 3
Flash structure has 2 bytes to start with “flash_magic” to signify that flash data is valid:
// Structure that contains all user data, note the maximum size is 8K (or maybe 4K, untested)
typedef struct af_flash__user_data_t {
// Flash Parameters
uint16_t flash_magic; // used to determine if flash is "good" or "bad"
//more parameters go here...
} af_flash__user_data_t;
Application logic is:
- read flash
- if error then “write defaults” in flash (flash_magic = 0xABCD)
- if flash_magic != 0xABCD then “write defaults”
- Firmware business logic starts here using values from af_flash__user_data_t structure
Problem:
Above code/logic runs fine. We have run tests on several tags without any issues. However, when we increased the sample size and duration of tests, we are seeing cases where flash had reset to default values which under normal circumstances should not happen. We had 7 tags out of 200 that after about 2 days, the 7 tags lost their configuration. without re flashing the tags, we have a process of de-activation and activation, during activation configuration is pushed the tags - once we did that (after re-activated), the tags are working fine.
Seems an intermittent problem, and because of it I am not sure how to troubleshoot and fix.
To provide more info, flash is read after every startup, flash is only written to during activation and when AP switch occurs - when tag is connecting to a new AP, the idea is to write to flash only when values change. Duty cycle for the test of 200 was to report 1 minute, main MCU (not the RTL8722 chip) powers on RTL8722 - read flash, connect, send a packet, write to flash if needed, respond to main MCU, then RTL8722 is powered off.
Code to read FTL:
// initialize FTL subsystem
ftl_init(ftl_phy_page_start_addr, ftl_phy_page_num);
// Read what's currently stored in flash
ret = af_flash__read_user_data();
// Check if the "magic" value is valid, if not let's write defaults
if (__global_flash_user_data.flash_magic != AF_FLASH_DEFAULT_FLASH_MAGIC)
{ /* default write forced by configuration */
// Write defaults stored in `airista_flash.h`
ret = af_flash__write_defaults(&__global_flash_user_data);
}
// Read user data into global buffer, returns pdPASS or pdFAIL
int af_flash__read_user_data(void) {
// read from storage
int err = ftl_load_from_storage(&__global_flash_user_data, 0x0000, sizeof(af_flash__user_data_t));
// check for errors (for debug print purposes)
if (err == FTL_WRITE_ERROR_INVALID_ADDR) {
AF_DEBUG(AF_CONFIG_DEBUG_FLASH, "[Warning]: found uninitialized FTL layer"); // this return code is not necessarily an error, just means FTL has never been initialized before
}
else if ((!err) != pdPASS) {
AF_DEBUG(AF_CONFIG_DEBUG_FLASH, "[Error]: failed to read user data from flash! err=%d", err); // everything here is an actual error
}
return ((!err) == pdPASS); // return failure (pdFAIL) or success (pdPASS)
}
// Write user data buffer into flash, and afterward read flash into global buffer, returns pdPASS or pdFAIL
int af_flash__write_user_data(af_flash__user_data_t* data) {
// write data to storage
int err = ftl_save_to_storage((void*) data, 0x0000, sizeof(af_flash__user_data_t));
AF_DEBUG(AF_CONFIG_DEBUG_FLASH || AF_CONFIG_DEBUG_WLAN_FAST_CONNECT | AF_CONFIG_DEBUG_WIFI, "af_flash__write_user_data, err=%d",err);
AF_ASSERT(err,"af_flash__write_user_data failed");
// check for error (for debug print purposes)
if ((!err) != pdPASS) {
AF_DEBUG(AF_CONFIG_DEBUG_FLASH, "[Error]: failed to write user data to flash! err=%d", err);
}
return ((!err) == pdPASS); // return failure (pdFAIL) or success (pdPASS)
}