flash/stm32h7x: fix bank sizes for devices with trimmed flash

STM32H7yxxI: dual independent 1 MByte banks
STM32H7yxxG: dual independent 512 Kbyte banks
STM32H7yxxB: single 128 Kbyte bank

where y = [4/5] or [A/B]

references: (documents are available in www.st.com)
 - STM32H7[4/5]x[G/I] : DS12110 Rev 7
    >> 3.3.1 Embedded Flash memory
 - STM32H750xB : RM0433 Rev 6
    >> Table 11. Flash memory organization on STM32H750xB devices
 - STM32H7[A/B]x[B/G/I] : RM0455 Rev 3
    >> 4.3.4 Flash memory architecture and usage


Change-Id: Ic9346964ef2554abf47f5832e25adfdc77bd323e
Signed-off-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
Reviewed-on: http://openocd.zylin.com/5442
Tested-by: jenkins
Reviewed-by: Christopher Head <chead@zaber.com>
This commit is contained in:
Tarek BOCHKATI 2020-02-07 12:52:14 +01:00 committed by Tomas Vanek
parent b304971f38
commit 123e10288d
1 changed files with 49 additions and 28 deletions

View File

@ -117,7 +117,7 @@ struct stm32h7x_part_info {
unsigned int block_size; /* flash write word size in bytes */ unsigned int block_size; /* flash write word size in bytes */
uint16_t max_flash_size_kb; uint16_t max_flash_size_kb;
uint8_t has_dual_bank; uint8_t has_dual_bank;
uint16_t first_bank_size_kb; /* Used when has_dual_bank is true */ uint16_t max_bank_size_kb; /* Used when has_dual_bank is true */
uint32_t flash_regs_base; /* Flash controller registers location */ uint32_t flash_regs_base; /* Flash controller registers location */
uint32_t fsize_addr; /* Location of FSIZE register */ uint32_t fsize_addr; /* Location of FSIZE register */
uint32_t wps_group_size; /* write protection group sectors' count */ uint32_t wps_group_size; /* write protection group sectors' count */
@ -173,7 +173,7 @@ static const struct stm32h7x_part_info stm32h7x_parts[] = {
.page_size_kb = 128, .page_size_kb = 128,
.block_size = 32, .block_size = 32,
.max_flash_size_kb = 2048, .max_flash_size_kb = 2048,
.first_bank_size_kb = 1024, .max_bank_size_kb = 1024,
.has_dual_bank = 1, .has_dual_bank = 1,
.flash_regs_base = FLASH_REG_BASE_B0, .flash_regs_base = FLASH_REG_BASE_B0,
.fsize_addr = 0x1FF1E880, .fsize_addr = 0x1FF1E880,
@ -189,7 +189,7 @@ static const struct stm32h7x_part_info stm32h7x_parts[] = {
.page_size_kb = 8, .page_size_kb = 8,
.block_size = 16, .block_size = 16,
.max_flash_size_kb = 2048, .max_flash_size_kb = 2048,
.first_bank_size_kb = 1024, .max_bank_size_kb = 1024,
.has_dual_bank = 1, .has_dual_bank = 1,
.flash_regs_base = FLASH_REG_BASE_B0, .flash_regs_base = FLASH_REG_BASE_B0,
.fsize_addr = 0x08FFF80C, .fsize_addr = 0x08FFF80C,
@ -740,8 +740,6 @@ static int stm32x_probe(struct flash_bank *bank)
struct stm32h7x_flash_bank *stm32x_info = bank->driver_priv; struct stm32h7x_flash_bank *stm32x_info = bank->driver_priv;
uint16_t flash_size_in_kb; uint16_t flash_size_in_kb;
uint32_t device_id; uint32_t device_id;
uint32_t base_address = FLASH_BANK0_ADDRESS;
uint32_t second_bank_base;
stm32x_info->probed = false; stm32x_info->probed = false;
stm32x_info->part_info = NULL; stm32x_info->part_info = NULL;
@ -776,33 +774,58 @@ static int stm32x_probe(struct flash_bank *bank)
} else } else
LOG_INFO("flash size probed value %d", flash_size_in_kb); LOG_INFO("flash size probed value %d", flash_size_in_kb);
/* Lower flash size devices are single bank */
if (stm32x_info->part_info->has_dual_bank && (flash_size_in_kb > stm32x_info->part_info->first_bank_size_kb)) {
/* Use the configured base address to determine if this is the first or second flash bank.
* Verify that the base address is reasonably correct and determine the flash bank size /* setup bank size */
const uint32_t bank1_base = FLASH_BANK0_ADDRESS;
const uint32_t bank2_base = bank1_base + stm32x_info->part_info->max_bank_size_kb * 1024;
bool has_dual_bank = stm32x_info->part_info->has_dual_bank;
switch (device_id) {
case 0x450:
case 0x480:
/* For STM32H74x/75x and STM32H7Ax/Bx
* - STM32H7xxxI devices contains dual bank, 1 Mbyte each
* - STM32H7xxxG devices contains dual bank, 512 Kbyte each
* - STM32H7xxxB devices contains single bank, 128 Kbyte
* - the second bank starts always from 0x08100000
*/ */
second_bank_base = base_address + stm32x_info->part_info->first_bank_size_kb * 1024; if (flash_size_in_kb == 128)
if (bank->base == second_bank_base) { has_dual_bank = false;
/* This is the second bank */ else
base_address = second_bank_base; /* flash size is 2M or 1M */
flash_size_in_kb = flash_size_in_kb - stm32x_info->part_info->first_bank_size_kb; flash_size_in_kb /= 2;
/* bank1 also uses a register offset */ break;
stm32x_info->flash_regs_base = FLASH_REG_BASE_B1; default:
} else if (bank->base == base_address) { LOG_ERROR("unsupported device");
/* This is the first bank */ return ERROR_FAIL;
flash_size_in_kb = stm32x_info->part_info->first_bank_size_kb; }
} else {
LOG_WARNING("STM32H flash bank base address config is incorrect. " if (has_dual_bank) {
TARGET_ADDR_FMT " but should rather be 0x%" PRIx32 " or 0x%" PRIx32, LOG_INFO("STM32H7 flash has dual banks");
bank->base, base_address, second_bank_base); if (bank->base != bank1_base && bank->base != bank2_base) {
LOG_ERROR("STM32H7 flash bank base address config is incorrect. "
TARGET_ADDR_FMT " but should rather be 0x%" PRIx32 " or 0x%" PRIx32,
bank->base, bank1_base, bank2_base);
return ERROR_FAIL; return ERROR_FAIL;
} }
LOG_INFO("STM32H flash has dual banks. Bank (%d) size is %dkb, base address is 0x%" PRIx32,
bank->bank_number, flash_size_in_kb, base_address);
} else { } else {
LOG_INFO("STM32H flash size is %dkb, base address is 0x%" PRIx32, flash_size_in_kb, base_address); LOG_INFO("STM32H7 flash has a single bank");
if (bank->base == bank2_base) {
LOG_ERROR("this device has a single bank only");
return ERROR_FAIL;
} else if (bank->base != bank1_base) {
LOG_ERROR("STM32H7 flash bank base address config is incorrect. "
TARGET_ADDR_FMT " but should be 0x%" PRIx32,
bank->base, bank1_base);
return ERROR_FAIL;
}
} }
LOG_INFO("Bank (%d) size is %d kb, base address is 0x%" PRIx32,
bank->bank_number, flash_size_in_kb, (uint32_t) bank->base);
/* if the user sets the size manually then ignore the probed value /* if the user sets the size manually then ignore the probed value
* this allows us to work around devices that have an invalid flash size register value */ * this allows us to work around devices that have an invalid flash size register value */
if (stm32x_info->user_bank_size) { if (stm32x_info->user_bank_size) {
@ -815,8 +838,6 @@ static int stm32x_probe(struct flash_bank *bank)
/* did we assign flash size? */ /* did we assign flash size? */
assert(flash_size_in_kb != 0xffff); assert(flash_size_in_kb != 0xffff);
bank->base = base_address;
bank->size = flash_size_in_kb * 1024; bank->size = flash_size_in_kb * 1024;
bank->write_start_alignment = stm32x_info->part_info->block_size; bank->write_start_alignment = stm32x_info->part_info->block_size;
bank->write_end_alignment = stm32x_info->part_info->block_size; bank->write_end_alignment = stm32x_info->part_info->block_size;