aboutsummaryrefslogtreecommitdiff
path: root/src/flash/nor
diff options
context:
space:
mode:
Diffstat (limited to 'src/flash/nor')
-rw-r--r--src/flash/nor/stm32f2x.c75
1 files changed, 56 insertions, 19 deletions
diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c
index ea35fd05..c1283bb3 100644
--- a/src/flash/nor/stm32f2x.c
+++ b/src/flash/nor/stm32f2x.c
@@ -894,31 +894,68 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
return target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK);
}
-static int setup_sector(struct flash_bank *bank, int start, int num, int size)
+static void setup_sector(struct flash_bank *bank, int i, int size)
{
+ assert(i < bank->num_sectors);
+ bank->sectors[i].offset = bank->size;
+ bank->sectors[i].size = size;
+ bank->size += bank->sectors[i].size;
+ LOG_DEBUG("sector %d: %dkBytes", i, size >> 10);
+}
+
+static uint16_t sector_size_in_kb(int i, uint16_t max_sector_size_in_kb)
+{
+ assert(i >= 0);
+ if (i < 4)
+ return max_sector_size_in_kb / 8;
+ if (i == 4)
+ return max_sector_size_in_kb / 2;
+ return max_sector_size_in_kb;
+}
+
+static int calculate_number_of_sectors(struct flash_bank *bank,
+ uint16_t flash_size_in_kb,
+ uint16_t max_sector_size_in_kb)
+{
+ struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
+ uint16_t remaining_flash_size_in_kb = flash_size_in_kb;
+ int nr_sectors;
- for (int i = start; i < (start + num) ; i++) {
- assert(i < bank->num_sectors);
- bank->sectors[i].offset = bank->size;
- bank->sectors[i].size = size;
- bank->size += bank->sectors[i].size;
- LOG_DEBUG("sector %d: %d kBytes", i, size >> 10);
+ /* Dual Bank Flash has two identically-arranged banks of sectors. */
+ if (stm32x_info->has_large_mem)
+ remaining_flash_size_in_kb /= 2;
+
+ for (nr_sectors = 0; remaining_flash_size_in_kb > 0; nr_sectors++) {
+ uint16_t size_in_kb = sector_size_in_kb(nr_sectors, max_sector_size_in_kb);
+ if (size_in_kb > remaining_flash_size_in_kb) {
+ LOG_INFO("%s Bank %" PRIu16 " kiB final sector clipped to %" PRIu16 " kiB",
+ stm32x_info->has_large_mem ? "Dual" : "Single",
+ flash_size_in_kb, remaining_flash_size_in_kb);
+ remaining_flash_size_in_kb = 0;
+ } else {
+ remaining_flash_size_in_kb -= size_in_kb;
+ }
}
- return start + num;
+ return stm32x_info->has_large_mem ? nr_sectors*2 : nr_sectors;
}
static void setup_bank(struct flash_bank *bank, int start,
uint16_t flash_size_in_kb, uint16_t max_sector_size_in_kb)
{
- int remain;
-
- start = setup_sector(bank, start, 4, (max_sector_size_in_kb / 8) * 1024);
- start = setup_sector(bank, start, 1, (max_sector_size_in_kb / 2) * 1024);
-
- /* remaining sectors all of size max_sector_size_in_kb */
- remain = (flash_size_in_kb / max_sector_size_in_kb) - 1;
- start = setup_sector(bank, start, remain, max_sector_size_in_kb * 1024);
+ uint16_t remaining_flash_size_in_kb = flash_size_in_kb;
+ int sector_index = 0;
+ while (remaining_flash_size_in_kb > 0) {
+ uint16_t size_in_kb = sector_size_in_kb(sector_index, max_sector_size_in_kb);
+ if (size_in_kb > remaining_flash_size_in_kb) {
+ /* Clip last sector. Already warned in
+ * calculate_number_of_sectors. */
+ size_in_kb = remaining_flash_size_in_kb;
+ }
+ setup_sector(bank, start + sector_index, size_in_kb * 1024);
+ remaining_flash_size_in_kb -= size_in_kb;
+ sector_index++;
+ }
}
static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
@@ -1150,12 +1187,12 @@ static int stm32x_probe(struct flash_bank *bank)
}
/* calculate numbers of pages */
- int num_pages = flash_size_in_kb / max_sector_size_in_kb
- + (stm32x_info->has_large_mem ? 8 : 4);
+ int num_pages = calculate_number_of_sectors(
+ bank, flash_size_in_kb, max_sector_size_in_kb);
bank->base = base_address;
bank->num_sectors = num_pages;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
+ bank->sectors = calloc(num_pages, sizeof(struct flash_sector));
for (i = 0; i < num_pages; i++) {
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 0;