flash/nor/stm32f2x: Support value line chips with trimmed flash 26/4926/12
authorKeir Fraser <keir.xen@gmail.com>
Tue, 3 Dec 2019 08:17:56 +0000 (08:17 +0000)
committerTomas Vanek <vanekt@fbl.cz>
Fri, 3 Jan 2020 10:28:45 +0000 (10:28 +0000)
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>
src/flash/nor/stm32f2x.c

index ea35fd05d691f196dce48c37ed740763e91b2c6e..c1283bb3f4dc382adf4bf896ea3267df6bdde8d5 100644 (file)
@@ -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;

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)