#include "zeeprom_fs.h" #include "one_conduction_board.h" static zeeprom_header_t m_eeprom_header; static bool m_is_init = false; static filehandler_t m_filehandler[2]; static int m_fd_off; /******************************************************************************* * 函数声明 * *******************************************************************************/ static filehandler_t* filehandler_find(int fd); static filehandler_t* filehandler_alloc(); static void filehandler_rlease(int fd); static int32_t sector_mgr_find_earliest_file_created_index(); static int32_t sector_mgr_free_sector(int32_t fileuuid); static zeeprom_sector_info_t* sector_mgr_find_idle_sector(); static bool sector_mgr_sector_is_open(int32_t fileuuid); static zeeprom_sector_info_t* sector_mgr_force_find_idle_sector(); static void sector_mgr_open_sector(int32_t fileuuid); static void sector_mgr_close_sector(int32_t fileuuid); // static zeeprom_sector_info_t* sector_mgr_find_fileheader(int32_t fileuuid); static zeeprom_sector_info_t* sector_mgr_find_end_sector(int32_t fileuuid); static zeeprom_sector_info_t* sector_mgr_find_sector(int32_t fileuuid, int32_t sector_index_in_file); static int32_t sector_mgr_file_get_size(int32_t fileuuid); static zeeprom_sector_info_t* sector_mgr_find_fileheader_by_filename(uint8_t* fileid); static int32_t sector_mgr_get_sector_offset(zeeprom_sector_info_t* sector); static int32_t sector_mgr_get_sector_rom_add(zeeprom_sector_info_t* sector); static void zeeprom_read(int32_t add, uint8_t* data, uint16_t len); static void zeeprom_write(int32_t add, const uint8_t* data, uint16_t len); static int32_t compute_checksum(uint8_t* data, uint16_t len); /******************************************************************************* * CODE * *******************************************************************************/ static bool m_eeprom_header_inited = false; int zeeprom_fs_init() { // SingleLeadECG_eeprom_init(); if (!m_eeprom_header_inited) { zeeprom_read(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header)); int32_t checksum_val = compute_checksum((uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header) - sizeof(m_eeprom_header.checksum)); if (checksum_val != m_eeprom_header.checksum) { memset(&m_eeprom_header, 0, sizeof(m_eeprom_header)); } } m_is_init = true; m_eeprom_header_inited = true; return 0; } int zeeprom_fs_uinit() { // // zeeprom_write(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header)); SingleLeadECG_eeprom_uninit(); m_is_init = false; return 0; } zeeprom_header_t* zeeprom_fs_get_header() { return &m_eeprom_header; } int zeeprom_fs_open(uint8_t* filename, wrflag_t wrflag) { ZASSERT(m_is_init); /** * @brief * 1. 如果文件已经存在,则打开文件 * 2. 如果文件不存在, 则创建文件 * * 创建文件: * 1. 找到一个空闲扇区 * 2. 初始化文件头 */ filehandler_t* fileHander = filehandler_alloc(); if (!fileHander) { ZLOGI("fileHander_alloc fail"); return -1; } if (wrflag == kwrflag_write_only) { /******************************************************************************* * 写文件 * *******************************************************************************/ zeeprom_sector_info_t* sectorHeaderInfo = NULL; zeeprom_fs_delete_by_name(filename); sectorHeaderInfo = sector_mgr_force_find_idle_sector(); if (!sectorHeaderInfo) { ZLOGE("sector_mgr_force_find_idle_sector fail"); filehandler_rlease(fileHander->fd); return -1; } memset(sectorHeaderInfo, 0, sizeof(zeeprom_sector_info_t)); sectorHeaderInfo->usage = 1; sectorHeaderInfo->opened = 1; memcpy(sectorHeaderInfo->filename, filename, 8); sectorHeaderInfo->sector_index_in_file = 0; sectorHeaderInfo->datalen = 0; sectorHeaderInfo->fileuuid = m_eeprom_header.fileuuid++; fileHander->fileuuid = sectorHeaderInfo->fileuuid; fileHander->sector_header = sectorHeaderInfo; fileHander->file_offset = 0; fileHander->file_size = 0; return fileHander->fd; } else { /******************************************************************************* * 读文件 * *******************************************************************************/ zeeprom_sector_info_t* sectorHeaderInfo = sector_mgr_find_fileheader_by_filename(filename); if (sectorHeaderInfo) { fileHander->fileuuid = sectorHeaderInfo->fileuuid; fileHander->file_offset = 0; fileHander->fd = fileHander->fd; fileHander->sector_header = sectorHeaderInfo; fileHander->file_size = sector_mgr_file_get_size(fileHander->fileuuid); memcpy(fileHander->filename, filename, 8); memcpy(fileHander->usrdata, sectorHeaderInfo->usrdata, sizeof(sectorHeaderInfo->usrdata)); sector_mgr_open_sector(fileHander->fileuuid); return fileHander->fd; } else { filehandler_rlease(fileHander->fd); return -1; } } } int zeeprom_fs_write(int fileid, const uint8_t* data, int32_t size) { ZASSERT(m_is_init); filehandler_t* fileHander = NULL; zeeprom_sector_info_t* header_sinfo = NULL; zeeprom_sector_info_t* endsector = NULL; int32_t wadd = 0; ZASSERT(size == 256); fileHander = filehandler_find(fileid); if (!fileHander) { ZLOGE("fileHander_find fail"); return -1; } header_sinfo = fileHander->sector_header; if (!header_sinfo) { ZLOGE("header_sinfo fail"); return -1; } endsector = sector_mgr_find_end_sector(fileHander->fileuuid); if (!endsector) { ZLOGE("sector_mgr_find_end_sector fail"); return -1; } if (endsector->datalen + size > EEPROM_SECTOR_SIZE) { ZLOGE("endsector->datalen + size > EEPROM_SECTOR_SIZE"); return -1; } wadd = sector_mgr_get_sector_rom_add(endsector); if (wadd < 0) { ZLOGE("sector_mgr_get_sector_rom_add fail"); return -1; } ZASSERT(wadd % 256 == 0); ZASSERT(wadd >= EEPROM_SECTOR_SIZE); zeeprom_write(wadd + endsector->datalen, data, size); endsector->datalen = endsector->datalen + size; fileHander->file_offset += size; fileHander->file_size += size; if (endsector->datalen == EEPROM_SECTOR_SIZE) { zeeprom_sector_info_t* newsector = sector_mgr_force_find_idle_sector(); if (!newsector) { ZLOGE("sector_mgr_force_find_idle_sector fail"); return -1; } memset(newsector, 0, sizeof(zeeprom_sector_info_t)); newsector->usage = 1; newsector->opened = 1; memcpy(newsector->filename, header_sinfo->filename, 8); newsector->sector_index_in_file = endsector->sector_index_in_file + 1; newsector->datalen = 0; newsector->fileuuid = header_sinfo->fileuuid; } return size; } int zeeprom_fs_close(int fileid) { ZASSERT(m_is_init); filehandler_t* fileHander = filehandler_find(fileid); if (!fileHander) { ZLOGE("zeeprom_fs_close fileHander_find fail"); return -1; } sector_mgr_close_sector(fileHander->fileuuid); int32_t checksum_val = compute_checksum((uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header) - sizeof(m_eeprom_header.checksum)); m_eeprom_header.checksum = checksum_val; // zeeprom_write(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header)); filehandler_rlease(fileid); return 0; } int zeeprom_fs_get_filesize_by_fd(int fd) { ZASSERT(m_is_init); filehandler_t* fileHander = filehandler_find(fd); if (!fileHander) return 0; return fileHander->file_size; } int zeeprom_fs_read(int fileid, uint8_t* data, int32_t size) { ZASSERT(m_is_init); /** * @brief * 找到当前扇区 */ ZASSERT(size == 256); filehandler_t* fileHander = filehandler_find(fileid); if (!fileHander) return -1; zeeprom_sector_info_t* header_sinfo = fileHander->sector_header; if (!header_sinfo) { return -1; } int32_t sector_idx = fileHander->file_offset / EEPROM_SECTOR_SIZE; int32_t sector_off = fileHander->file_offset % EEPROM_SECTOR_SIZE; zeeprom_sector_info_t* sector = sector_mgr_find_sector(fileHander->fileuuid, sector_idx); if (!sector) { return -1; } int32_t radd = sector_mgr_get_sector_rom_add(sector); ZASSERT(radd % 256 == 0); radd += sector_off; zeeprom_read(radd, data, size); fileHander->file_offset += size; return size; } int zeeprom_fs_delete(int32_t fileuuid) { ZASSERT(m_is_init); sector_mgr_free_sector(fileuuid); return 0; } int zeeprom_fs_delete_by_name(uint8_t* filename) { ZASSERT(m_is_init); zeeprom_sector_info_t* sectorHeaderInfo = sector_mgr_find_fileheader_by_filename(filename); if (sectorHeaderInfo) { sector_mgr_free_sector(sectorHeaderInfo->fileuuid); } return 0; } int zeeprom_fs_get_file_num() { ZASSERT(m_is_init); int count = 0; for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1 && sinfo->sector_index_in_file == 0) { count++; } } return count; } int zeeprom_fs_delete_the_oldest_file() { ZASSERT(m_is_init); int32_t earliest_file_created_index = sector_mgr_find_earliest_file_created_index(); sector_mgr_free_sector(earliest_file_created_index); return 0; } int zeeprom_fs_get_filesize_by_fileuuid(int32_t fileuuid) { ZASSERT(m_is_init); return sector_mgr_file_get_size(fileuuid); } static void zeeprom_read(int32_t add, uint8_t* data, uint16_t len) { // int wrsize = EEPROM_SECTOR_MIN_WR_SIZE; int readTimes = len / wrsize; int readRemain = len % wrsize; for (int i = 0; i < readTimes; i++) { SingleLeadECG_eeprom_read(add + i * wrsize, data + i * wrsize, wrsize); } if (readRemain > 0) { SingleLeadECG_eeprom_read(add + readTimes * wrsize, data + readTimes * wrsize, readRemain); } } static void zeeprom_write(int32_t add, const uint8_t* data, uint16_t len) { int wrsize = EEPROM_SECTOR_MIN_WR_SIZE; int writeTimes = len / wrsize; int writeRemain = len % wrsize; for (int i = 0; i < writeTimes; i++) { // int pageoff = add / wrsize + i; int32_t writeadd = add + i * wrsize; SingleLeadECG_eeprom_write(writeadd, data + i * wrsize, wrsize); } if (writeRemain > 0) { int32_t writeadd = add + writeTimes * wrsize; SingleLeadECG_eeprom_write(writeadd, data + writeTimes * wrsize, writeRemain); } } static int32_t compute_checksum(uint8_t* data, uint16_t len) { int32_t sum = 0; for (int i = 0; i < len; i++) { sum += data[i]; } return sum; } /******************************************************************************* * filehandler * *******************************************************************************/ static filehandler_t* filehandler_find(int fd) { for (int i = 0; i < ZARRAY_SIZE(m_filehandler); i++) { if (m_filehandler[i].fd == fd) { return &m_filehandler[i]; } } return NULL; } static filehandler_t* filehandler_alloc() { for (int i = 0; i < ZARRAY_SIZE(m_filehandler); i++) { if (m_filehandler[i].fd == 0) { m_filehandler[i].fd = ++m_fd_off; return &m_filehandler[i]; } } return NULL; } static void filehandler_rlease(int fd) { for (int i = 0; i < ZARRAY_SIZE(m_filehandler); i++) { if (m_filehandler[i].fd == fd) { m_filehandler[i].fd = 0; return; } } } /******************************************************************************* * sector_mgr * *******************************************************************************/ // 查找最早创建的文件的file_created_index static int32_t sector_mgr_find_earliest_file_created_index() { int32_t earliest_file_created_index = INT32_MAX; for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1) { if (sinfo->fileuuid < earliest_file_created_index) { earliest_file_created_index = sinfo->fileuuid; } } } return earliest_file_created_index; } // 删除文件 static int32_t sector_mgr_free_sector(int32_t fileuuid) { for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { sinfo->usage = 0; } } return 0; } // static zeeprom_sector_info_t* sector_mgr_find_idle_sector() { for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 0) { return sinfo; } } return NULL; } static bool sector_mgr_sector_is_open(int32_t fileuuid) { for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { return sinfo->opened; } } return false; } static zeeprom_sector_info_t* sector_mgr_force_find_idle_sector() { /** * @brief 查找空闲扇区 */ zeeprom_sector_info_t* ret_sinfo = sector_mgr_find_idle_sector(); if (ret_sinfo) return ret_sinfo; /** * @brief 查找最早创建的文件 */ int32_t earliest_file_created_index = sector_mgr_find_earliest_file_created_index(); if (sector_mgr_sector_is_open(earliest_file_created_index)) { return NULL; } /** * @brief 删除最早创建的文件 */ sector_mgr_free_sector(earliest_file_created_index); /** * @brief 重新查找空闲扇区 */ ret_sinfo = sector_mgr_find_idle_sector(); if (ret_sinfo) return ret_sinfo; return NULL; } static void sector_mgr_open_sector(int32_t fileuuid) { for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { sinfo->opened = true; } } } static void sector_mgr_close_sector(int32_t fileuuid) { for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { sinfo->opened = false; } } } // static zeeprom_sector_info_t* sector_mgr_find_fileheader(int32_t fileuuid) { // for (int i = 0; i < MAX_SECTOR_NUM; i++) { // zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; // if (sinfo->usage == 1 && sinfo->sector_index_in_file == 0 && sinfo->fileuuid == fileuuid) { // return sinfo; // } // } // return NULL; // } static zeeprom_sector_info_t* sector_mgr_find_sector(int32_t fileuuid, int32_t sector_index_in_file) { for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1 && sinfo->sector_index_in_file == sector_index_in_file && sinfo->fileuuid == fileuuid) { return sinfo; } } return NULL; } static zeeprom_sector_info_t* sector_mgr_find_end_sector(int32_t fileuuid) { int32_t maxsectorindex = 0; for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { if (sinfo->sector_index_in_file >= maxsectorindex) { maxsectorindex = sinfo->sector_index_in_file; } } } return sector_mgr_find_sector(fileuuid, maxsectorindex); } static zeeprom_sector_info_t* sector_mgr_find_fileheader_by_filename(uint8_t* fileid) { for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1 && sinfo->sector_index_in_file == 0 && memcmp(sinfo->filename, fileid, 8) == 0) { return sinfo; } } return NULL; } static int32_t sector_mgr_get_sector_offset(zeeprom_sector_info_t* sector) { for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo == sector) { return i; } } return -1; } static int32_t sector_mgr_get_sector_rom_add(zeeprom_sector_info_t* sector) { int32_t offset = sector_mgr_get_sector_offset(sector); if (offset < 0) return -1; return (offset + 1) * EEPROM_SECTOR_SIZE; } static int32_t sector_mgr_file_get_size(int32_t fileuuid) { int32_t filesize = 0; for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { filesize += sinfo->datalen; } } return filesize; } static const char* filename2str(uint8_t* filename) { static char filename_str[32]; sprintf(filename_str, "%02x%02x%02x%02x%02x%02x%02x%02x", filename[0], filename[1], filename[2], filename[3], filename[4], filename[5], filename[6], filename[7]); return filename_str; } int zeeprom_fs_dump_sector_state() { ZLOGI_BLOCK("zeeprom_fs_dump_sector_state\n"); for (int i = 0; i < MAX_SECTOR_NUM; i++) { zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; if (sinfo->usage == 1) { ZLOGI_BLOCK("[%d]: usage=%d opened=%d", i, sinfo->usage, sinfo->opened); ZLOGI_BLOCK(" fname=%s, index_in_file=%d, datalen=%d, fileuuid=%d", filename2str(sinfo->filename), sinfo->sector_index_in_file, sinfo->datalen, sinfo->fileuuid); } else { ZLOGI_BLOCK("[%d]: usage=%d", i, sinfo->usage); } } return 0; }