#include "flash_common.h" #include "flash.h" secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data); secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data); const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size); static uint32_t flash_subarea_get_size(const flash_subarea_t *subarea) { uint32_t size = 0; for (int s = 0; s < subarea->num_sectors; s++) { size += flash_sector_size(subarea->first_sector + s); } return size; } static secbool subarea_get_sector_and_offset(const flash_subarea_t *subarea, uint32_t offset, uint16_t *sector_out, uint32_t *offset_out) { uint32_t tmp_offset = offset; uint16_t sector = subarea->first_sector; // in correct subarea for (int s = 0; s < subarea->num_sectors; s++) { const uint32_t sector_size = flash_sector_size(sector); if (tmp_offset < sector_size) { *sector_out = sector; *offset_out = tmp_offset; return sectrue; } tmp_offset -= sector_size; sector++; } return secfalse; } uint32_t flash_area_get_size(const flash_area_t *area) { uint32_t size = 0; for (int i = 0; i < area->num_subareas; i++) { size += flash_subarea_get_size(&area->subarea[i]); } return size; } uint16_t flash_total_sectors(const flash_area_t *area) { uint16_t total = 0; for (int i = 0; i < area->num_subareas; i++) { total += area->subarea[i].num_sectors; } return total; } int32_t flash_get_sector_num(const flash_area_t *area, uint32_t sector_inner_num) { uint16_t sector = 0; uint16_t remaining = sector_inner_num; for (int i = 0; i < area->num_subareas; i++) { if (remaining < area->subarea[i].num_sectors) { sector = area->subarea[i].first_sector + remaining; return sector; } else { remaining -= area->subarea[i].num_sectors; } } return -1; } static secbool get_sector_and_offset(const flash_area_t *area, uint32_t offset, uint16_t *sector_out, uint32_t *offset_out) { uint32_t tmp_offset = offset; for (int i = 0; i < area->num_subareas; i++) { uint32_t sub_size = flash_subarea_get_size(&area->subarea[i]); if (tmp_offset >= sub_size) { tmp_offset -= sub_size; continue; } return subarea_get_sector_and_offset(&area->subarea[i], tmp_offset, sector_out, offset_out); } return secfalse; } const void *flash_area_get_address(const flash_area_t *area, uint32_t offset, uint32_t size) { uint16_t sector; uint32_t sector_offset; if (!get_sector_and_offset(area, offset, §or, §or_offset)) { return NULL; } return flash_get_address(sector, sector_offset, size); } secbool flash_area_erase(const flash_area_t *area, void (*progress)(int pos, int len)) { return flash_area_erase_bulk(area, 1, progress); } secbool flash_area_write_byte(const flash_area_t *area, uint32_t offset, uint8_t data) { uint16_t sector; uint32_t sector_offset; if (get_sector_and_offset(area, offset, §or, §or_offset) != sectrue) { return secfalse; } return flash_write_byte(sector, sector_offset, data); } secbool flash_area_write_word(const flash_area_t *area, uint32_t offset, uint32_t data) { uint16_t sector; uint32_t sector_offset; if (get_sector_and_offset(area, offset, §or, §or_offset) != sectrue) { return secfalse; } return flash_write_word(sector, sector_offset, data); } secbool flash_area_write_block(const flash_area_t *area, uint32_t offset, const flash_block_t block) { if (!FLASH_IS_ALIGNED(offset)) { return secfalse; } uint16_t sector; uint32_t sector_offset; if (sectrue != get_sector_and_offset(area, offset, §or, §or_offset)) { return secfalse; } #if FLASH_BLOCK_WORDS == 1 return flash_write_word(sector, sector_offset, block); #else for (int i = 0; i < FLASH_BLOCK_WORDS; i++) { if (sectrue != flash_write_word(sector, sector_offset + i * sizeof(uint32_t), block[i])) { return secfalse; } } return sectrue; #endif }