From 43d31a8fd507a7d15083b487cf06d3f934e25843 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Tue, 19 Jan 2021 13:26:48 +0100 Subject: [PATCH] flash/stm32l4x: add support of STM32G0Bx/G0Cx devices this device has a dual bank flash architecture up to 512 KB (page 2KB) reference: RM0444 Rev 5 notes: - 128k variant is always single bank - 256k variant flash is contiguous (no gap) in dual bank mode - BKER is bit 13 vs bit 11 for other devices > added cr_bker_mask in stm32l4_flash_bank struct - BSY2 for bank 2 operations > added sr_bsy_mask in stm32l4_flash_bank struct > proposed optimization: always wait for (BSY1 | BSY2) with STM32G0Bx/G0Cx devices only (for L4+ devices BSY2=PEMPTY) TODO: update flashloader to use the proper BSY bits temporarily don't use the loader in dual bank mode Change-Id: I54b0c93b494e7209da818791d15edd8cd42c2732 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6036 Reviewed-by: Oleksij Rempel Tested-by: jenkins --- src/flash/nor/stm32l4x.c | 54 +++++++++++++++++++++++++++++++++++++--- src/flash/nor/stm32l4x.h | 4 ++- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 32dff35e0..ff804bbaf 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -218,6 +218,8 @@ struct stm32l4_flash_bank { bool dual_bank_mode; int hole_sectors; uint32_t user_bank_size; + uint32_t cr_bker_mask; + uint32_t sr_bsy_mask; uint32_t wrpxxr_mask; const struct stm32l4_part_info *part_info; uint32_t flash_regs_base; @@ -275,6 +277,10 @@ static const struct stm32l4_rev stm32_466_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2000, "B" }, }; +static const struct stm32l4_rev stm32_467_revs[] = { + { 0x1000, "A" }, +}; + static const struct stm32l4_rev stm32_468_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, { 0x2001, "Z" }, }; @@ -396,6 +402,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x1FFF7000, .otp_size = 1024, }, + { + .id = 0x467, + .revs = stm32_467_revs, + .num_revs = ARRAY_SIZE(stm32_467_revs), + .device_str = "STM32G0Bx/G0Cx", + .max_flash_size_kb = 512, + .flags = F_HAS_DUAL_BANK, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75E0, + .otp_base = 0x1FFF7000, + .otp_size = 1024, + }, { .id = 0x468, .revs = stm32_468_revs, @@ -691,6 +709,7 @@ static inline int stm32l4_write_flash_reg_by_index(struct flash_bank *bank, static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout) { + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; uint32_t status; int retval = ERROR_OK; @@ -700,7 +719,7 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout) if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%" PRIx32 "", status); - if ((status & FLASH_BSY) == 0) + if ((status & stm32l4_info->sr_bsy_mask) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); @@ -1092,7 +1111,7 @@ static int stm32l4_erase(struct flash_bank *bank, unsigned int first, if (i >= stm32l4_info->bank1_sectors) { uint8_t snb; snb = i - stm32l4_info->bank1_sectors; - erase_flags |= snb << FLASH_PAGE_SHIFT | FLASH_CR_BKER; + erase_flags |= snb << FLASH_PAGE_SHIFT | stm32l4_info->cr_bker_mask; } else erase_flags |= i << FLASH_PAGE_SHIFT; retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, erase_flags); @@ -1463,7 +1482,18 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, if (retval != ERROR_OK) goto err_lock; - if (stm32l4_info->use_flashloader) { + /** + * FIXME update the flash loader to use a custom FLASH_SR_BSY mask + * Workaround for STM32G0Bx/G0Cx devices in dual bank mode, + * as the flash loader does not use the SR_BSY2 + */ + bool use_flashloader = stm32l4_info->use_flashloader; + if ((stm32l4_info->part_info->id == 0x467) && stm32l4_info->dual_bank_mode) { + LOG_INFO("Couldn't use the flash loader in dual-bank mode"); + use_flashloader = false; + } + + if (use_flashloader) { /* For TrustZone enabled devices, when TZEN is set and RDP level is 0.5, * the debug is possible only in non-secure state. * Thus means the flashloader will run in non-secure mode, @@ -1474,7 +1504,7 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, retval = stm32l4_write_block(bank, buffer, offset, count / 8); } - if (!stm32l4_info->use_flashloader || retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { + if (!use_flashloader || retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { LOG_INFO("falling back to single memory accesses"); retval = stm32l4_write_block_without_loader(bank, buffer, offset, count / 8); } @@ -1573,6 +1603,8 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->idcode, part_info->device_str, rev_str, rev_id); stm32l4_info->flash_regs_base = stm32l4_info->part_info->flash_regs_base; + stm32l4_info->cr_bker_mask = FLASH_BKER; + stm32l4_info->sr_bsy_mask = FLASH_BSY; /* initialise the flash registers layout */ if (part_info->flags & F_HAS_L5_FLASH_REGS) @@ -1696,6 +1728,20 @@ static int stm32l4_probe(struct flash_bank *bank) num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; break; + case 0x467: /* STM32G0B/G0Cxx */ + /* single/dual bank depending on bit(21) */ + page_size_kb = 2; + num_pages = flash_size_kb / page_size_kb; + stm32l4_info->bank1_sectors = num_pages; + stm32l4_info->cr_bker_mask = FLASH_BKER_G0; + + /* check DUAL_BANK bit */ + if (stm32l4_info->optr & BIT(21)) { + stm32l4_info->sr_bsy_mask = FLASH_BSY | FLASH_BSY2; + stm32l4_info->dual_bank_mode = true; + stm32l4_info->bank1_sectors = num_pages / 2; + } + break; case 0x469: /* STM32G47/G48xx */ /* STM32G47/8 can be single/dual bank: * if DUAL_BANK = 0 -> single bank diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index b8f3d8c5b..ba809ff40 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -24,7 +24,8 @@ #define FLASH_PER (1 << 1) #define FLASH_MER1 (1 << 2) #define FLASH_PAGE_SHIFT 3 -#define FLASH_CR_BKER (1 << 11) +#define FLASH_BKER (1 << 11) +#define FLASH_BKER_G0 (1 << 13) #define FLASH_MER2 (1 << 15) #define FLASH_STRT (1 << 16) #define FLASH_OPTSTRT (1 << 17) @@ -36,6 +37,7 @@ /* FLASH_SR register bits */ #define FLASH_BSY (1 << 16) +#define FLASH_BSY2 (1 << 17) /* Fast programming not used => related errors not used*/ #define FLASH_PGSERR (1 << 7) /* Programming sequence error */