diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 2da2c69fe..0c56ef6d9 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -287,7 +287,7 @@ struct stm32l4_wrp { }; /* human readable list of families this drivers supports (sorted alphabetically) */ -static const char *device_families = "STM32C0/G0/G4/L4/L4+/L5/U0/U5/WB/WL"; +static const char *device_families = "STM32C0/G0/G4/L4/L4+/L5/U0/U3/U5/WB/WL"; static const struct stm32l4_rev stm32l47_l48xx_revs[] = { { 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" } @@ -350,6 +350,10 @@ static const struct stm32l4_rev stm32u0xx_revs[] = { { 0x1000, "A" }, }; +static const struct stm32l4_rev stm32u37_u38xx_revs[] = { + { 0x1000, "A" }, { 0x1001, "Z" }, +}; + static const struct stm32l4_rev stm32g43_g44xx_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, { 0x2001, "Z" }, }; @@ -690,6 +694,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x1FFF6800, .otp_size = 1024, }, + { + .id = DEVID_STM32U37_U38XX, + .revs = stm32u37_u38xx_revs, + .num_revs = ARRAY_SIZE(stm32u37_u38xx_revs), + .device_str = "STM32U37/U38xx", + .max_flash_size_kb = 1024, + .flags = F_HAS_DUAL_BANK | F_HAS_TZ | F_HAS_L5_FLASH_REGS | F_WRP_HAS_LOCK, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x0BFA07A0, + .otp_base = 0x0BFA0000, + .otp_size = 512, + }, { .id = DEVID_STM32U59_U5AXX, .revs = stm32u59_u5axx_revs, @@ -1380,6 +1396,10 @@ static int stm32l4_erase(struct flash_bank *bank, unsigned int first, 4. Wait for the BSY bit to be cleared */ + retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); + if (retval != ERROR_OK) + goto err_lock; + for (unsigned int i = first; i <= last; i++) { uint32_t erase_flags; erase_flags = FLASH_PER | FLASH_STRT; @@ -1785,6 +1805,9 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, if (retval != ERROR_OK) goto err_lock; + retval = stm32l4_wait_status_busy(bank, FLASH_WRITE_TIMEOUT); + if (retval != ERROR_OK) + goto err_lock; /* For TrustZone enabled devices, when TZEN is set and RDP level is 0.5, * the debug is possible only in non-secure state. @@ -2151,6 +2174,15 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; + case DEVID_STM32U37_U38XX: + page_size_kb = 4; + num_pages = flash_size_kb / page_size_kb; + stm32l4_info->bank1_sectors = num_pages; + if (is_max_flash_size || (stm32l4_info->optr & FLASH_U5_DUALBANK)) { + stm32l4_info->dual_bank_mode = true; + stm32l4_info->bank1_sectors = num_pages / 2; + } + break; case DEVID_STM32U53_U54XX: case DEVID_STM32U57_U58XX: case DEVID_STM32U59_U5AXX: diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 1f4f2344f..8e6cb4309 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -94,6 +94,7 @@ #define DEVID_STM32C05XX 0x44C #define DEVID_STM32C09XX 0x44D #define DEVID_STM32C03XX 0x453 +#define DEVID_STM32U37_U38XX 0x454 #define DEVID_STM32U53_U54XX 0x455 #define DEVID_STM32G05_G06XX 0x456 #define DEVID_STM32U031XX 0x459 diff --git a/tcl/target/stm32u3x.cfg b/tcl/target/stm32u3x.cfg new file mode 100644 index 000000000..449c04217 --- /dev/null +++ b/tcl/target/stm32u3x.cfg @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# script for stm32u3x family +# stm32u3x devices support both JTAG and SWD transports. + +source [find target/swj-dp.tcl] +source [find mem_helper.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME stm32u3x +} + +source [find target/stm32x5x_common.cfg] + +# In order to allow the flash program and erase operations, +# we need to set the voltage scale to range 1 + +proc config_voltage_range {} { + set offset [expr {[stm32x5x_is_secure] ? 0x10000000 : 0}] + # PWR voltage scaling register + set PWR_VOSR [expr {0x4003080C + $offset}] + # PWR supply voltage monitoring control register + set PWR_SVMCR [expr {0x40030810 + $offset}] + # RCC AHB1 peripheral clock enable register 2 + # RCC_AHB1ENR2 = PWREN + mww [expr {0x40030C94 + $offset}] 0x4 + if {(([mrw $PWR_VOSR] & 0x10001) != 0x10001)} { + # PWR_SVMCR = IO2SV + mmw $PWR_SVMCR 0x20000000 0 + # PWR_VOSR : R1EN: Voltage scaling range 1 + mmw $PWR_VOSR 1 3 + # while !(PWR_VOSR & R1RDY) + while {([mrw $PWR_VOSR] & 0x10001) != 0x10001} {} + # Enable EPOD Booster + mmw $PWR_VOSR 0x00000100 0 + # while !(PWR_VOSR & BOOSTRDY) + while {([mrw $PWR_VOSR] & 0x1000000) != 0} {} + } +} + +$_TARGETNAME configure -event reset-init { + config_voltage_range +} diff --git a/tcl/target/stm32x5x_common.cfg b/tcl/target/stm32x5x_common.cfg index fb3aeb18c..b6370e493 100644 --- a/tcl/target/stm32x5x_common.cfg +++ b/tcl/target/stm32x5x_common.cfg @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-or-later -# common script for stm32l5x and stm32u5x families +# common script for stm32l5x, stm32u3x and stm32u5x families # Work-area is a space in RAM used for flash programming # By default use 64kB @@ -16,6 +16,7 @@ if { [info exists CPUTAPID] } { } else { if { [using_jtag] } { # STM32L5x: RM0438 Rev5, Section 52.2.8 JTAG debug port - Table 425. JTAG-DP data registers + # STM32U3x: RM0487 Rev1, Section 53.3.1 JTAG debug port - Table 569. JTAG-DP data registers # STM32U5x: RM0456 Rev1, Section 65.2.8 JTAG debug port - Table 661. JTAG-DP data registers # Corresponds to Cortex®-M33 JTAG debug port ID code set _CPUTAPID 0x0ba04477