From c5910f047a00e46a96cc6e5ba85cb34bee55e88a Mon Sep 17 00:00:00 2001 From: armink Date: Tue, 9 Jun 2015 17:29:45 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E5=AD=98=E5=82=A8=E8=87=B3Flash=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: armink --- easyflash/inc/flash.h | 24 +- easyflash/port/flash_port.c | 9 +- easyflash/src/flash.c | 31 ++- easyflash/src/flash_env.c | 1 - easyflash/src/flash_env_wl.c | 3 +- easyflash/src/flash_log.c | 441 +++++++++++++++++++++++++++++++++++ easyflash/src/flash_utils.c | 61 +++++ 7 files changed, 561 insertions(+), 9 deletions(-) create mode 100644 easyflash/src/flash_log.c diff --git a/easyflash/inc/flash.h b/easyflash/inc/flash.h index 85746fa..5a2b78d 100644 --- a/easyflash/inc/flash.h +++ b/easyflash/inc/flash.h @@ -36,6 +36,8 @@ extern "C" { #define FLASH_USING_ENV /* using IAP function */ #define FLASH_USING_IAP +/* using save log function */ +#define FLASH_USING_LOG /* using CRC32 check when load environment variable from Flash */ #define FLASH_ENV_USING_CRC_CHECK /* the user setting size of ENV, must be word alignment */ @@ -56,7 +58,7 @@ if (!(EXPR)) \ while (1); \ } /* EasyFlash software version number */ -#define FLASH_SW_VERSION "1.05.30" +#define FLASH_SW_VERSION "1.06.09" typedef struct _flash_env{ char *key; @@ -73,6 +75,13 @@ typedef enum { FLASH_ENV_FULL, } FlashErrCode; +/* the flash sector current status */ +typedef enum { + FLASH_SECTOR_EMPTY, + FLASH_SECTOR_USING, + FLASH_SECTOR_FULL, +}FlashSecrorStatus; + /* flash.c */ FlashErrCode flash_init(void); @@ -99,6 +108,19 @@ FlashErrCode flash_copy_app_from_bak(uint32_t user_app_addr, size_t app_size); FlashErrCode flash_copy_bl_from_bak(uint32_t bl_addr, size_t bl_size); #endif +#ifdef FLASH_USING_LOG +/* flash_log.c */ +FlashErrCode flash_log_read(size_t pos, uint32_t *log, size_t size); +FlashErrCode flash_log_write(const uint32_t *log, size_t size); +FlashErrCode flash_log_clean(void); +size_t flash_log_get_used_size(void); +#endif + +/* flash_utils.c */ +uint32_t calc_crc32(uint32_t crc, const void *buf, size_t size); +FlashSecrorStatus flash_get_sector_status(uint32_t addr, size_t sec_size); +uint32_t flash_find_sec_using_end_addr(uint32_t addr, size_t sec_size); + /* flash_port.c */ FlashErrCode flash_read(uint32_t addr, uint32_t *buf, size_t size); FlashErrCode flash_erase(uint32_t addr, size_t size); diff --git a/easyflash/port/flash_port.c b/easyflash/port/flash_port.c index 3572b24..28109f9 100644 --- a/easyflash/port/flash_port.c +++ b/easyflash/port/flash_port.c @@ -33,6 +33,8 @@ /* ENV section total bytes size in normal mode. It's equal with FLASH_USER_SETTING_ENV_SIZE */ #define FLASH_ENV_SECTION_SIZE (FLASH_USER_SETTING_ENV_SIZE) #endif +/* saved log section size */ +#define FLASH_LOG_AREA_SIZE /* @note you must define it for a value */ /* print debug information of flash */ #define FLASH_PRINT_DEBUG @@ -49,11 +51,12 @@ static const flash_env default_env_set[] = { * @param erase_min_size the minimum size of Flash erasure * @param default_env default ENV set for user * @param default_env_size default ENV size + * @param log_total_size saved log area size * * @return result */ FlashErrCode flash_port_init(uint32_t *env_addr, size_t *env_total_size, size_t *erase_min_size, - flash_env const **default_env, size_t *default_env_size) { + flash_env const **default_env, size_t *default_env_size, size_t *log_size) { FlashErrCode result = FLASH_NO_ERR; FLASH_ASSERT(FLASH_USER_SETTING_ENV_SIZE % 4 == 0); @@ -64,6 +67,7 @@ FlashErrCode flash_port_init(uint32_t *env_addr, size_t *env_total_size, size_t *erase_min_size = FLASH_ERASE_MIN_SIZE; *default_env = default_env_set; *default_env_size = sizeof(default_env_set)/sizeof(default_env_set[0]); + *log_size = FLASH_LOG_AREA_SIZE; return result; } @@ -81,7 +85,6 @@ FlashErrCode flash_port_init(uint32_t *env_addr, size_t *env_total_size, size_t FlashErrCode flash_read(uint32_t addr, uint32_t *buf, size_t size) { FlashErrCode result = FLASH_NO_ERR; - FLASH_ASSERT(size >= 4); FLASH_ASSERT(size % 4 == 0); /* You can add your code under here. */ @@ -123,6 +126,8 @@ FlashErrCode flash_erase(uint32_t addr, size_t size) { FlashErrCode flash_write(uint32_t addr, const uint32_t *buf, size_t size) { FlashErrCode result = FLASH_NO_ERR; + FLASH_ASSERT(size % 4 == 0); + /* You can add your code under here. */ return result; diff --git a/easyflash/src/flash.c b/easyflash/src/flash.c index 6fd4e47..006a243 100644 --- a/easyflash/src/flash.c +++ b/easyflash/src/flash.c @@ -27,6 +27,8 @@ * | 1.system section | FLASH_ENV_SYSTEM_SIZE * | 2:data section | FLASH_ENV_SECTION_SIZE - FLASH_ENV_SYSTEM_SIZE * |----------------------------| + * | Saved log area | Storage size: @see FLASH_LOG_AREA_SIZE + * |----------------------------| * |(IAP)Downloaded application | IAP already downloaded application size * |----------------------------| * | Remain flash | All remaining @@ -51,18 +53,20 @@ */ FlashErrCode flash_init(void) { extern FlashErrCode flash_port_init(uint32_t *env_addr, size_t *env_total_size, - size_t *erase_min_size, flash_env const **default_env, size_t *default_env_size); + size_t *erase_min_size, flash_env const **default_env, size_t *default_env_size, + size_t *log_size); extern FlashErrCode flash_env_init(uint32_t start_addr, size_t total_size, size_t erase_min_size, flash_env const *default_env, size_t default_env_size); extern FlashErrCode flash_iap_init(uint32_t start_addr); + extern FlashErrCode flash_log_init(uint32_t start_addr, size_t log_size, size_t erase_min_size); uint32_t env_start_addr; - size_t env_total_size, erase_min_size, default_env_set_size; + size_t env_total_size = 0, erase_min_size = 0, default_env_set_size = 0, log_size = 0; const flash_env *default_env_set; FlashErrCode result = FLASH_NO_ERR; result = flash_port_init(&env_start_addr, &env_total_size, &erase_min_size, &default_env_set, - &default_env_set_size); + &default_env_set_size, &log_size); #ifdef FLASH_USING_ENV if (result == FLASH_NO_ERR) { @@ -73,7 +77,26 @@ FlashErrCode flash_init(void) { #ifdef FLASH_USING_IAP if (result == FLASH_NO_ERR) { - result = flash_iap_init(env_start_addr + flash_get_env_total_size()); + if (flash_get_env_total_size() < erase_min_size) { + result = flash_iap_init(env_start_addr + erase_min_size + log_size); + } else if (flash_get_env_total_size() % erase_min_size == 0) { + result = flash_iap_init(env_start_addr + flash_get_env_total_size() + log_size); + } else { + result = flash_iap_init((flash_get_env_total_size() / erase_min_size + 1) * erase_min_size + log_size); + } + } +#endif + +#ifdef FLASH_USING_LOG + if (result == FLASH_NO_ERR) { + if (flash_get_env_total_size() < erase_min_size) { + result = flash_log_init(env_start_addr + erase_min_size, log_size, erase_min_size); + } else if (flash_get_env_total_size() % erase_min_size == 0) { + result = flash_log_init(env_start_addr + flash_get_env_total_size(), log_size, erase_min_size); + } else { + result = flash_log_init((flash_get_env_total_size() / erase_min_size + 1) * erase_min_size, + log_size, erase_min_size); + } } #endif diff --git a/easyflash/src/flash_env.c b/easyflash/src/flash_env.c index dfbd2c3..75ffdf0 100644 --- a/easyflash/src/flash_env.c +++ b/easyflash/src/flash_env.c @@ -557,7 +557,6 @@ FlashErrCode flash_save_env(void) { static uint32_t calc_env_crc(void) { uint32_t crc32 = 0; - extern uint32_t calc_crc32(uint32_t crc, const void *buf, size_t size); /* Calculate the ENV end address and all ENV data CRC32. * The 4 is ENV end address bytes size. */ crc32 = calc_crc32(crc32, &env_cache[ENV_PARAM_INDEX_END_ADDR], 4); diff --git a/easyflash/src/flash_env_wl.c b/easyflash/src/flash_env_wl.c index 53cb47e..f1c2d73 100644 --- a/easyflash/src/flash_env_wl.c +++ b/easyflash/src/flash_env_wl.c @@ -119,6 +119,8 @@ FlashErrCode flash_env_init(uint32_t start_addr, size_t total_size, size_t erase /* must be word alignment for ENV */ FLASH_ASSERT(FLASH_USER_SETTING_ENV_SIZE % 4 == 0); FLASH_ASSERT(total_size % 4 == 0); + /* the ENV total size should be an integral multiple of erase minimum size. */ + FLASH_ASSERT(total_size % erase_min_size == 0); env_start_addr = start_addr; env_total_size = total_size; @@ -668,7 +670,6 @@ FlashErrCode flash_save_env(void) { static uint32_t calc_env_crc(void) { uint32_t crc32 = 0; - extern uint32_t calc_crc32(uint32_t crc, const void *buf, size_t size); /* Calculate the ENV end address and all ENV data CRC32. * The 4 is ENV end address bytes size. */ crc32 = calc_crc32(crc32, &env_cache[ENV_PARAM_PART_INDEX_END_ADDR], 4); diff --git a/easyflash/src/flash_log.c b/easyflash/src/flash_log.c new file mode 100644 index 0000000..6639377 --- /dev/null +++ b/easyflash/src/flash_log.c @@ -0,0 +1,441 @@ +/* + * This file is part of the EasyFlash Library. + * + * Copyright (c) 2015, Armink, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Function: Save log to flash. + * Created on: 2015-06-04 + */ + +#include "flash.h" + +#ifdef FLASH_USING_LOG + +/* the stored log start address and end address. It's like a ring buffer which implement by flash. */ +static uint32_t log_start_addr = 0, log_end_addr = 0; +/* saved log area address for flash */ +static uint32_t log_area_start_addr = 0; +/* saved log area total size */ +static size_t flash_log_size = 0; +/* the minimum size of flash erasure */ +static size_t flash_erase_min_size = 0; +/* initialize OK flag */ +static bool init_ok = false; + +static void find_start_and_end_addr(void); +static uint32_t get_next_flash_sec_addr(uint32_t cur_addr); + +/** + * The flash save log function initialize. + * + * @param start_addr log area start address + * @param log_size log area total size + * @param erase_min_size the minimum size of flash erasure + * + * @return result + */ +FlashErrCode flash_log_init(uint32_t start_addr, size_t log_size, size_t erase_min_size) { + FlashErrCode result = FLASH_NO_ERR; + + FLASH_ASSERT(start_addr); + FLASH_ASSERT(log_size); + FLASH_ASSERT(erase_min_size); + /* the log section size must be an integral multiple of erase minimum size. */ + FLASH_ASSERT(log_size % erase_min_size == 0); + /* the log section size must be more than 2 multiple of erase minimum size */ + FLASH_ASSERT(log_size / erase_min_size >= 2); + + log_area_start_addr = start_addr; + flash_log_size = log_size; + flash_erase_min_size = erase_min_size; + + /* find the log store start address and end address */ + find_start_and_end_addr(); + /* initialize OK */ + init_ok = true; + + return result; +} + +/** + * Find the log store start address and end address. + * It's like a ring buffer which implement by flash. + * The flash log area has two state when find start address and end address. + * state 1 state 2 + * |============| |============| + * log area start--> |############| <-- start address |############| <-- end address + * |############| | empty | + * |------------| |------------| + * |############| |############| <-- start address + * |############| |############| + * |------------| |------------| + * | . | | . | + * | . | | . | + * | . | | . | + * |------------| |------------| + * |############| <-- end address |############| + * | empty | |############| + * log area end --> |============| |============| + * + * flash_log_size = log area end - log area star + * + */ +static void find_start_and_end_addr(void) { + size_t cur_size = 0; + FlashSecrorStatus cur_sec_status, last_sec_status; + uint32_t cur_using_sec_addr = 0; + /* all status sector counts */ + size_t empty_sec_counts = 0, using_sec_counts = 0, full_sector_counts = 0; + /* total sector number */ + size_t total_sec_num = flash_log_size / flash_erase_min_size; + /* see comment of find_start_and_end_addr function */ + uint8_t cur_log_sec_state = 0; + + /* get the first sector status */ + cur_sec_status = flash_get_sector_status(log_area_start_addr, flash_erase_min_size); + last_sec_status = cur_sec_status; + + for (cur_size = flash_erase_min_size; cur_size < flash_log_size; cur_size += flash_erase_min_size) { + /* get current sector status */ + cur_sec_status = flash_get_sector_status(log_area_start_addr + cur_size, flash_erase_min_size); + /* compare last and current status */ + switch (last_sec_status) { + case FLASH_SECTOR_EMPTY: { + switch (cur_sec_status) { + case FLASH_SECTOR_EMPTY: + break; + case FLASH_SECTOR_USING: + FLASH_DEBUG("Error: Log area error! Now will clean all log area.\n"); + flash_log_clean(); + return; + case FLASH_SECTOR_FULL: + FLASH_DEBUG("Error: Log area error! Now will clean all log area.\n"); + flash_log_clean(); + return; + } + empty_sec_counts++; + break; + } + case FLASH_SECTOR_USING: { + switch (cur_sec_status) { + case FLASH_SECTOR_EMPTY: + /* like state 1 */ + cur_log_sec_state = 1; + log_start_addr = log_area_start_addr; + cur_using_sec_addr = log_area_start_addr + cur_size - flash_erase_min_size; + break; + case FLASH_SECTOR_USING: + FLASH_DEBUG("Error: Log area error! Now will clean all log area.\n"); + flash_log_clean(); + return; + case FLASH_SECTOR_FULL: + /* like state 2 */ + cur_log_sec_state = 2; + log_start_addr = log_area_start_addr + cur_size; + cur_using_sec_addr = log_area_start_addr + cur_size - flash_erase_min_size; + break; + } + using_sec_counts++; + break; + } + case FLASH_SECTOR_FULL: { + switch (cur_sec_status) { + case FLASH_SECTOR_EMPTY: + /* like state 1 */ + if (cur_log_sec_state == 2) { + FLASH_DEBUG("Error: Log area error! Now will clean all log area.\n"); + flash_log_clean(); + return; + } else { + cur_log_sec_state = 1; + log_start_addr = log_area_start_addr; + /* word alignment */ + log_end_addr = log_area_start_addr + cur_size - 4; + cur_using_sec_addr = log_area_start_addr + cur_size - flash_erase_min_size; + } + break; + case FLASH_SECTOR_USING: + if(total_sec_num <= 2) { + /* like state 1 */ + cur_log_sec_state = 1; + log_start_addr = log_area_start_addr; + cur_using_sec_addr = log_area_start_addr + cur_size; + } else { + /* state 1 or 2*/ + } + break; + case FLASH_SECTOR_FULL: + break; + } + full_sector_counts++; + break; + } + } + last_sec_status = cur_sec_status; + } + + /* the last sector status counts */ + if (cur_sec_status == FLASH_SECTOR_EMPTY) { + empty_sec_counts++; + } else if (cur_sec_status == FLASH_SECTOR_USING) { + using_sec_counts++; + } else if (cur_sec_status == FLASH_SECTOR_FULL) { + full_sector_counts++; + } + + if (using_sec_counts > 1) { + FLASH_DEBUG("Error: Log area error! Now will clean all log area.\n"); + flash_log_clean(); + return; + } else if (empty_sec_counts == total_sec_num) { + log_start_addr = log_end_addr = log_area_start_addr; + } else if (full_sector_counts == total_sec_num) { + /* this state is almost impossible */ + FLASH_DEBUG("Error: Log area error! Now will clean all log area.\n"); + flash_log_clean(); + return; + } else if (((cur_log_sec_state == 1) && (cur_using_sec_addr != 0)) + || (cur_log_sec_state == 2)) { + /* find the end address */ + log_end_addr = flash_find_sec_using_end_addr(cur_using_sec_addr, flash_erase_min_size); + } +} + +/** + * Get log used flash total size. + * + * @return log used flash total size + */ +size_t flash_log_get_used_size(void) { + FLASH_ASSERT(log_start_addr); + FLASH_ASSERT(log_end_addr); + + /* must be call this function after initialize OK */ + FLASH_ASSERT(init_ok); + + if (log_start_addr < log_end_addr) { + return log_end_addr - log_start_addr + 4; + } else if (log_start_addr > log_end_addr) { + return flash_log_size - (log_start_addr - log_end_addr) + 4; + } else { + return 0; + } +} + +/** + * Read log from flash. + * + * @param pos position on saved log section. + * Minimum position is 0. + * Maximum position is saved log section total size + * @param log the log which will read from flash + * @param size read bytes size + * + * @return result + */ +FlashErrCode flash_log_read(size_t pos, uint32_t *log, size_t size) { + FlashErrCode result = FLASH_NO_ERR; + size_t cur_using_size = flash_log_get_used_size(); + size_t read_size_temp = 0; + + FLASH_ASSERT(size % 4 == 0); + FLASH_ASSERT(pos + size <= cur_using_size); + /* must be call this function after initialize OK */ + FLASH_ASSERT(init_ok); + + if (!size) { + return result; + } + + if (log_start_addr < log_end_addr) { + result = flash_read(log_area_start_addr + pos, log, size); + } else if (log_start_addr > log_end_addr) { + if (log_start_addr + pos + size <= log_area_start_addr + flash_log_size) { + /* Flash log area + * |--------------| + * log_area_start_addr --> |##############| + * |##############| + * |##############| + * |--------------| + * |##############| + * |##############| + * |##############| <-- log_end_addr + * |--------------| + * log_start_addr --> |##############| + * read start --> |**************| <-- read end + * |##############| + * |--------------| + * + * read from (log_start_addr + pos) to (log_start_addr + pos + size) + */ + result = flash_read(log_start_addr + pos, log, size); + } else if (log_start_addr + pos < log_area_start_addr + flash_log_size) { + /* Flash log area + * |--------------| + * log_area_start_addr --> |**************| <-- read end + * |##############| + * |##############| + * |--------------| + * |##############| + * |##############| + * |##############| <-- log_end_addr + * |--------------| + * log_start_addr --> |##############| + * read start --> |**************| + * |**************| + * |--------------| + * read will by 2 steps + * step1: read from (log_start_addr + pos) to flash log area end address + * step2: read from flash log area start address to read size's end address + */ + read_size_temp = (log_area_start_addr + flash_log_size) - (log_start_addr + pos); + result = flash_read(log_start_addr + pos, log, read_size_temp); + if (result == FLASH_NO_ERR) { + result = flash_read(log_area_start_addr, log + read_size_temp, + size - read_size_temp); + } + } else { + /* Flash log area + * |--------------| + * log_area_start_addr --> |##############| + * read start --> |**************| + * |**************| <-- read end + * |--------------| + * |##############| + * |##############| + * |##############| <-- log_end_addr + * |--------------| + * log_start_addr --> |##############| + * |##############| + * |##############| + * |--------------| + * read from (log_start_addr + pos - flash_log_size) to read size's end address + */ + result = flash_read(log_start_addr + pos - flash_log_size, log, size); + } + } + + return result; +} + +/** + * Write log to flash. + * + * @param log the log which will be write to flash + * @param size write bytes size + * + * @return result + */ +FlashErrCode flash_log_write(const uint32_t *log, size_t size) { + FlashErrCode result = FLASH_NO_ERR; + size_t cur_using_size = flash_log_get_used_size(), write_size = 0, writable_size = 0; + uint32_t write_addr, erase_addr; + + FLASH_ASSERT(size % 4 == 0); + /* must be call this function after initialize OK */ + FLASH_ASSERT(init_ok); + + /* write address is after log end address */ + write_addr = log_end_addr + 4; + /* write the already erased but not used area */ + writable_size = flash_erase_min_size - ((write_addr - log_area_start_addr) % flash_erase_min_size); + if (writable_size != flash_erase_min_size) { + if (size > writable_size) { + result = flash_write(write_addr, log, writable_size); + if (result != FLASH_NO_ERR) { + goto exit; + } + write_size += writable_size; + } else { + result = flash_write(write_addr, log, size); + log_end_addr = write_addr + size - 4; + goto exit; + } + } + /* erase and write remain log */ + while (true) { + /* calculate next available sector address */ + erase_addr = write_addr = get_next_flash_sec_addr(write_addr - 4); + /* move the flash log start address to next available sector address */ + if (log_start_addr == erase_addr) { + log_start_addr = get_next_flash_sec_addr(log_start_addr); + } + /* erase sector */ + result = flash_erase(erase_addr, flash_erase_min_size); + if (result == FLASH_NO_ERR) { + if (size - write_size > flash_erase_min_size) { + result = flash_write(write_addr, log + write_size / 4, flash_erase_min_size); + if (result != FLASH_NO_ERR) { + goto exit; + } + log_end_addr = write_addr + flash_erase_min_size - 4; + write_size += flash_erase_min_size; + write_addr += flash_erase_min_size; + } else { + result = flash_write(write_addr, log + write_size / 4, size - write_size); + if (result != FLASH_NO_ERR) { + goto exit; + } + log_end_addr = write_addr + (size - write_size) - 4; + break; + } + } else { + goto exit; + } + } + +exit: + return result; +} + +/** + * Get next flash sector address.The log total sector like ring buffer which implement by flash. + * + * @param cur_addr cur flash address + * + * @return next flash sector address + */ +static uint32_t get_next_flash_sec_addr(uint32_t cur_addr) { + size_t cur_sec_id = (cur_addr - log_area_start_addr) / flash_erase_min_size; + size_t sec_total_num = flash_log_size / flash_erase_min_size; + if (cur_sec_id + 1 >= sec_total_num) { + /* return to ring head */ + return log_area_start_addr; + } else { + return log_area_start_addr + (cur_sec_id + 1) * flash_erase_min_size; + } +} + +/** + * Clean all log which in flash. + * + * @return result + */ +FlashErrCode flash_log_clean(void) { + FlashErrCode result = FLASH_NO_ERR; + + FLASH_ASSERT(log_area_start_addr); + FLASH_ASSERT(flash_log_size); + + /* clean address */ + log_start_addr = log_end_addr = log_area_start_addr; + /* erase log flash area */ + result = flash_erase(log_area_start_addr, flash_log_size); + + return result; +} + +#endif diff --git a/easyflash/src/flash_utils.c b/easyflash/src/flash_utils.c index 445c8b7..996b25f 100644 --- a/easyflash/src/flash_utils.c +++ b/easyflash/src/flash_utils.c @@ -91,3 +91,64 @@ uint32_t calc_crc32(uint32_t crc, const void *buf, size_t size) return crc ^ ~0U; } + +/** + * Get this flash sector current status. + * + * @param addr sector address + * @param sec_size sector address + * + * @return the flash sector current status + */ +FlashSecrorStatus flash_get_sector_status(uint32_t addr, size_t sec_size) { + uint32_t cur_using_addr = flash_find_sec_using_end_addr(addr, sec_size); + /* get current status by current using address */ + if (cur_using_addr == addr) { + return FLASH_SECTOR_EMPTY; + } else if (cur_using_addr < addr + sec_size - 4) { + return FLASH_SECTOR_USING; + } else { + return FLASH_SECTOR_FULL; + } +} + +/** + * Find the current flash sector using end address by continuous 0xFF. + * + * @param addr sector address + * @param sec_size sector address + * + * @return current flash sector using end address + */ +uint32_t flash_find_sec_using_end_addr(uint32_t addr, size_t sec_size) { + size_t start, continue_ff; + /* counts continuous 0xFF */ + for (start = 0; start < sec_size; start++) { + if (*(uint8_t *) (addr + start) == 0xFF) { + /* make sure it is not the last byte */ + if (start < sec_size - 1) { + /* start counts */ + for (continue_ff = 1; continue_ff < sec_size - start; continue_ff++) { + if (*(uint8_t *) (addr + start + continue_ff) != 0xFF) { + start += continue_ff; + break; + } + } + /* all sector counts finish */ + if (continue_ff == sec_size - start) { + break; + } + } + } + } + if ((start == 0) && (continue_ff == sec_size)) { + /* from 0 to sec_size all sector is 0xFF, so the sector is empty */ + return addr; + } else if (start < sec_size) { + /* form start to sec_size all area is 0xFF, so it's used part of the sector */ + return addr + start; + } else { + /* all sector not has continuous 0xFF, alignment by word */ + return addr + sec_size - 4; + } +}