/** * EasyFlash system initialize. * * @return result */ EfErrCode easyflash_init(void) { extern EfErrCode ef_port_init(uint32_t *env_addr, size_t *env_total_size, size_t *erase_min_size, ef_env const **default_env, size_t *default_env_size, size_t *log_size); extern EfErrCode ef_env_init(uint32_t start_addr, size_t total_size, size_t erase_min_size, ef_env const *default_env, size_t default_env_size); extern EfErrCode ef_iap_init(uint32_t start_addr); extern EfErrCode ef_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 = 0, erase_min_size = 0, default_env_set_size = 0, log_size = 0; const ef_env *default_env_set; EfErrCode result = EF_NO_ERR; result = ef_port_init(&env_start_addr, &env_total_size, &erase_min_size, &default_env_set, &default_env_set_size, &log_size); #ifdef EF_USING_ENV if (result == EF_NO_ERR) { result = ef_env_init(env_start_addr, env_total_size, erase_min_size, default_env_set, default_env_set_size); } #endif #ifdef EF_USING_IAP if (result == EF_NO_ERR) { result = ef_iap_init(env_start_addr + env_total_size + log_size); } #endif #ifdef EF_USING_LOG if (result == EF_NO_ERR) { result = ef_log_init(env_start_addr + env_total_size, log_size, erase_min_size); } #endif if (result == EF_NO_ERR) { EF_DEBUG("EasyFlash V%s is initialize success.\n", EF_SW_VERSION); } else { EF_DEBUG("EasyFlash V%s is initialize fail.\n", EF_SW_VERSION); } 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 --> |============| |============| * * LOG_AREA_SIZE = log area end - log area star * */ static void find_start_and_end_addr(void) { size_t cur_size = 0; EfSecrorStatus 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 = LOG_AREA_SIZE / EF_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 = ef_get_sector_status(log_area_start_addr, EF_ERASE_MIN_SIZE); last_sec_status = cur_sec_status; for (cur_size = EF_ERASE_MIN_SIZE; cur_size < LOG_AREA_SIZE; cur_size += EF_ERASE_MIN_SIZE) { /* get current sector status */ cur_sec_status = ef_get_sector_status(log_area_start_addr + cur_size, EF_ERASE_MIN_SIZE); /* compare last and current status */ switch (last_sec_status) { case EF_SECTOR_EMPTY: { switch (cur_sec_status) { case EF_SECTOR_EMPTY: break; case EF_SECTOR_USING: EF_DEBUG("Error: Log area error! Now will clean all log area.\n"); ef_log_clean(); return; case EF_SECTOR_FULL: EF_DEBUG("Error: Log area error! Now will clean all log area.\n"); ef_log_clean(); return; } empty_sec_counts++; break; } case EF_SECTOR_USING: { switch (cur_sec_status) { case EF_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 - EF_ERASE_MIN_SIZE; break; case EF_SECTOR_USING: EF_DEBUG("Error: Log area error! Now will clean all log area.\n"); ef_log_clean(); return; case EF_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 - EF_ERASE_MIN_SIZE; break; } using_sec_counts++; break; } case EF_SECTOR_FULL: { switch (cur_sec_status) { case EF_SECTOR_EMPTY: /* like state 1 */ if (cur_log_sec_state == 2) { EF_DEBUG("Error: Log area error! Now will clean all log area.\n"); ef_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 - EF_ERASE_MIN_SIZE; } break; case EF_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 { /* like state 2 when the sector is the last one */ if (cur_size + EF_ERASE_MIN_SIZE >= LOG_AREA_SIZE) { cur_log_sec_state = 2; log_start_addr = log_area_start_addr + cur_size; cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE; } } break; case EF_SECTOR_FULL: break; } full_sector_counts++; break; } } last_sec_status = cur_sec_status; } /* the last sector status counts */ if (cur_sec_status == EF_SECTOR_EMPTY) { empty_sec_counts++; } else if (cur_sec_status == EF_SECTOR_USING) { using_sec_counts++; } else if (cur_sec_status == EF_SECTOR_FULL) { full_sector_counts++; } if (using_sec_counts > 1) { EF_DEBUG("Error: Log area error! Now will clean all log area.\n"); ef_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 */ EF_DEBUG("Error: Log area error! Now will clean all log area.\n"); ef_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 = ef_find_sec_using_end_addr(cur_using_sec_addr, EF_ERASE_MIN_SIZE); } }