aboutsummaryrefslogtreecommitdiff
path: root/src/flash
diff options
context:
space:
mode:
authorKeir Fraser <keir.xen@gmail.com>2019-12-03 08:17:56 +0000
committerTomas Vanek <vanekt@fbl.cz>2020-01-03 10:28:45 +0000
commit9f1529da4fcc7d1e508ab9ea4dc915800d68e730 (patch)
tree5a485b7484b6d50b18dddf34ef4609f50db7f21a /src/flash
parentbe2d25efcc0132e02c76c304487a8759ca587b0c (diff)
flash/nor/stm32f2x: Support value line chips with trimmed flash
The current code assumes an STM32's flash bank is laid-out in either of two configurations: - 4 x 16kB + 1 x 64kB + n x 128kB - 4 x 32kB + 1 x 128kB + n x 256kB This is quite ad-hoc but works fine in practice, as long as there are at least 5 sectors (if n=0). Unfortunately, some newer STM32s are shipping with only 64 kB of flash (4 x 16kB sectors). This patch still assumes the same sector layout, but only keeps adding sectors to the bank if the bank's capacity has not been reached. This prevents openocd from crashing on some newer STM32s. Change-Id: If00e5d7a328d11b399babc0bb2111e3ad8a3217e Signed-off-by: Romain Goyet <romain.goyet@numworks.com> Signed-off-by: Keir Fraser <keir.xen@gmail.com> Reviewed-on: http://openocd.zylin.com/4926 Tested-by: jenkins Reviewed-by: Andreas Bolsch <hyphen0break@gmail.com> Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Diffstat (limited to 'src/flash')
-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;