/** * Read and output recent log which saved in flash. * * @param size recent log size */ void elog_flash_outout_recent(size_t size) { size_t max_size = ef_log_get_used_size(); if (size > max_size) { log_i("The output size is out of bound. The max size is %d.", max_size); } else { elog_flash_outout(max_size - size, size); } }
/** * Read and output log which saved in flash. * * @param index index for saved log. * Minimum index is 0. * Maximum index is log used flash total size - 1. * @param size */ void elog_flash_outout(size_t index, size_t size) { /* 128 bytes buffer */ uint32_t buf[32] = { 0 }; size_t log_total_size = ef_log_get_used_size(); size_t buf_szie = sizeof(buf); size_t read_size = 0, read_overage_size = 0; if (index + size > log_total_size) { log_i("The output position and size is out of bound. The max size is %d.", log_total_size); return; } /* must be call this function after initialize OK */ ELOG_ASSERT(init_ok); /* lock flash log buffer */ log_buf_lock(); /* Output all flash saved log. It will use filter */ while (true) { if (index + read_size + buf_szie < log_total_size) { ef_log_read(index + read_size, buf, buf_szie); elog_flash_port_output((const char*)buf, buf_szie); read_size += buf_szie; } else { /* flash read is word alignment */ if ((log_total_size - index - read_size) % 4 == 0) { read_overage_size = 0; } else { read_overage_size = 4 - ((log_total_size - index - read_size) % 4); } ef_log_read(index + read_size - read_overage_size, buf, log_total_size - index - read_size + read_overage_size); elog_flash_port_output((const char*) buf + read_overage_size, log_total_size - index - read_size); /* output newline sign */ elog_flash_port_output(ELOG_NEWLINE_SIGN, strlen(ELOG_NEWLINE_SIGN)); break; } } /* unlock flash log buffer */ log_buf_unlock(); }
/** * Write log to flash. * * @param log the log which will be write to flash * @param size write bytes size * * @return result */ EfErrCode ef_log_write(const uint32_t *log, size_t size) { EfErrCode result = EF_NO_ERR; size_t cur_using_size = ef_log_get_used_size(), write_size = 0, writable_size = 0; uint32_t write_addr, erase_addr; EF_ASSERT(size % 4 == 0); /* must be call this function after initialize OK */ EF_ASSERT(init_ok); /* write address is after log end address when LOG AREA isn't empty */ if (log_start_addr != log_end_addr) { write_addr = log_end_addr + 4; } else { write_addr = log_start_addr; } /* write the already erased but not used area */ writable_size = EF_ERASE_MIN_SIZE - ((write_addr - log_area_start_addr) % EF_ERASE_MIN_SIZE); if ((writable_size != EF_ERASE_MIN_SIZE) || (log_start_addr == log_end_addr)) { if (size > writable_size) { result = ef_port_write(write_addr, log, writable_size); if (result != EF_NO_ERR) { goto exit; } write_size += writable_size; } else { result = ef_port_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 = ef_port_erase(erase_addr, EF_ERASE_MIN_SIZE); if (result == EF_NO_ERR) { if (size - write_size > EF_ERASE_MIN_SIZE) { result = ef_port_write(write_addr, log + write_size / 4, EF_ERASE_MIN_SIZE); if (result != EF_NO_ERR) { goto exit; } log_end_addr = write_addr + EF_ERASE_MIN_SIZE - 4; write_size += EF_ERASE_MIN_SIZE; write_addr += EF_ERASE_MIN_SIZE; } else { result = ef_port_write(write_addr, log + write_size / 4, size - write_size); if (result != EF_NO_ERR) { goto exit; } log_end_addr = write_addr + (size - write_size) - 4; break; } } else { goto exit; } } exit: return result; }
/** * Read log from flash. * * @param index index for saved log. * Minimum index is 0. * Maximum index is log used flash total size - 1. * @param log the log which will read from flash * @param size read bytes size * * @return result */ EfErrCode ef_log_read(size_t index, uint32_t *log, size_t size) { EfErrCode result = EF_NO_ERR; size_t cur_using_size = ef_log_get_used_size(); size_t read_size_temp = 0; EF_ASSERT(size % 4 == 0); EF_ASSERT(index + size <= cur_using_size); /* must be call this function after initialize OK */ EF_ASSERT(init_ok); if (!size) { return result; } if (log_start_addr < log_end_addr) { result = ef_port_read(log_area_start_addr + index, log, size); } else if (log_start_addr > log_end_addr) { if (log_start_addr + index + size <= log_area_start_addr + LOG_AREA_SIZE) { /* Flash log area * |--------------| * log_area_start_addr --> |##############| * |##############| * |##############| * |--------------| * |##############| * |##############| * |##############| <-- log_end_addr * |--------------| * log_start_addr --> |##############| * read start --> |**************| <-- read end * |##############| * |--------------| * * read from (log_start_addr + index) to (log_start_addr + index + size) */ result = ef_port_read(log_start_addr + index, log, size); } else if (log_start_addr + index < log_area_start_addr + LOG_AREA_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 + index) 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 + LOG_AREA_SIZE) - (log_start_addr + index); result = ef_port_read(log_start_addr + index, log, read_size_temp); if (result == EF_NO_ERR) { result = ef_port_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 + index - LOG_AREA_SIZE) to read size's end address */ result = ef_port_read(log_start_addr + index - LOG_AREA_SIZE, log, size); } } return result; }
/** * Read and output all log which saved in flash. */ void elog_flash_outout_all(void) { elog_flash_outout(0, ef_log_get_used_size()); }