From e8591132d4885f603f32918f6f51c3ef91b57b33 Mon Sep 17 00:00:00 2001 From: Ryan <> Date: Fri, 26 Sep 2025 18:42:39 -0500 Subject: [PATCH] Add autoerase to digdude --- .../nexys2_host_controller/host/digdude.c | 121 ++++++++++++++++-- 1 file changed, 108 insertions(+), 13 deletions(-) diff --git a/projects/nexys2_host_controller/host/digdude.c b/projects/nexys2_host_controller/host/digdude.c index 135d73b..6a979d4 100644 --- a/projects/nexys2_host_controller/host/digdude.c +++ b/projects/nexys2_host_controller/host/digdude.c @@ -26,6 +26,112 @@ enum exitspec { X_RESET, X_NORESET }; // ----------------------------------------------------------------------------- +typedef struct +{ + uint32_t block_size; + uint32_t block_count; + uint8_t block_is_erased[0x10000]; +} erase_region_t; + + +typedef struct +{ + uint8_t region_count; + erase_region_t regions[256]; +} erase_info_t; + + +static erase_info_t erase_info; + + +bool get_erase_info(HIF hif) +{ + assert(hif != hifInvalid); + + uint8_t cfi_buf[0x100]; + + // Read and verify CFI query information + EC_FALSE(flash_cfi(hif, 0, cfi_buf, sizeof(cfi_buf))); + EC_FALSE(cfi_buf[0x10] == 'Q'); + EC_FALSE(cfi_buf[0x11] == 'R'); + EC_FALSE(cfi_buf[0x12] == 'Y'); + + // Flash chips can contain multiple "erase regions," each of which + // contains some number of equal-sized eraseable blocks + + // Read the number of regions from the CFI query and loop for each + erase_info.region_count = cfi_buf[0x2c]; + + for (size_t i = 0; i < erase_info.region_count; i++) + { + size_t block_info_idx = 0x2d + (4 * i); + assert(block_info_idx < 0x100); // Just in case + + // Read the geometry of this region's blocks from the CFI query + uint32_t block_count = ((cfi_buf[block_info_idx + 1] << 8) | + cfi_buf[block_info_idx + 0]) + 1; + uint32_t block_size = ((cfi_buf[block_info_idx + 3] << 8) | + cfi_buf[block_info_idx + 2]) * 256; + if (block_size == 0) block_size = 128; + + erase_info.regions[i].block_size = block_size; + erase_info.regions[i].block_count = block_count; + } + + return true; + +EC_CLEANUP_BEGIN + return false; +EC_CLEANUP_END +} + + +bool ensure_erased(HIF hif, uint32_t addr, size_t data_len) +{ + assert(hif != hifInvalid); + + uint32_t scan_addr = 0; + + uint32_t region_count = erase_info.region_count; + for (uint32_t i = 0; i < region_count; i++) + { + uint32_t block_count = erase_info.regions[i].block_count; + for (uint32_t j = 0; j < block_count; j++) + { + uint32_t block_size = erase_info.regions[i].block_size; + uint32_t block_start = scan_addr; + uint32_t block_end = scan_addr + block_size; + + uint32_t data_start = addr; + uint32_t data_end = data_start + data_len; + + if (data_start < block_end && data_end > block_start) + { + if (!erase_info.regions[i].block_is_erased[j]) + { + printf("Erase region:%u of %u, block:%u of %u, addr:%08x size:%08x\n", + i+1, region_count, + j+1, block_count, + block_start, block_size); + EC_FALSE(flash_erase(hif, scan_addr)); + erase_info.regions[i].block_is_erased[j] = 1; + } + } + scan_addr = block_end; + } + } + + return true; + +EC_CLEANUP_BEGIN + return false; +EC_CLEANUP_END +} + + +// ----------------------------------------------------------------------------- + + bool update_ram_read(HIF hif, struct iter *iter, uint32_t addr, size_t data_len) { assert(hif != hifInvalid); @@ -178,25 +284,14 @@ bool update_flash_write(HIF hif, struct iter *iter, bool erase, bool verify) assert(hif != hifInvalid); assert(iter != NULL); - uint32_t unerased_watermark = 0; - uint8_t cfi_buf[0x100]; - uint8_t num_erase_regions; - - // Read and verify CFI query information - EC_FALSE(flash_cfi(hif, 0, cfi_buf, sizeof(cfi_buf))); - EC_FALSE(cfi_buf[0x10] == 'Q'); - EC_FALSE(cfi_buf[0x11] == 'R'); - EC_FALSE(cfi_buf[0x12] == 'Y'); - - // Read the number of regions from the CFI query and loop for each - num_erase_regions = cfi_buf[0x2c]; + if (erase) EC_FALSE(get_erase_info(hif)); while (!iter_done(iter)) { EC_FALSE(iter_next(iter)); if (erase) { - // TODO + EC_FALSE(ensure_erased(hif, iter->address, iter->data_len)); } EC_FALSE(flash_write(hif, iter->address, iter->data, iter->data_len)); -- 2.43.0