Browse Source

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>
master
Keir Fraser 4 years ago
committed by Tomas Vanek
parent
commit
9f1529da4f
1 changed files with 56 additions and 19 deletions
  1. +56
    -19
      src/flash/nor/stm32f2x.c

+ 56
- 19
src/flash/nor/stm32f2x.c View 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;


Loading…
Cancel
Save