Flash driver for STM32G0xx and STM32G4xx

Flash module of STM32G0/G4 family is quite similar to the one of
STM32L4, so only minor changes are required, in particular
adaption of flash loader to Cortex-M0. Register addresses
passed to flash loader to simplify integration of L5.
Added re-probe after option byte load.
Added flash size override via cfg file.
WRPxxR mask now based on max. number of pages instead of fixed 0xFF,
as G4 devices fill up unused bits with '1'.
Sizes in stm32l4_probe changed to multiples of 1kB.

Tested with Nucleo-G071RB, G030J6, Nucleo-G431RB and Nucleo-G474RE.
Gap handling in G4 Cat. 3 dual bank mode tested with STM32G473RB.
This handling isn't optimal as the bank size includes the
size of the gap. WB not tested.

Change-Id: I24df7c065afeb71c11c7e96de4aa9fdb91845593
Signed-off-by: Andreas Bolsch <hyphen0break@gmail.com>
Reviewed-on: http://openocd.zylin.com/4807
Tested-by: jenkins
Reviewed-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
This commit is contained in:
Andreas Bolsch
2018-12-16 17:30:41 +01:00
committed by Tomas Vanek
parent e03de33c41
commit ba131f30a0
8 changed files with 641 additions and 195 deletions

View File

@@ -8,6 +8,9 @@
* Copyright (C) 2015 Uwe Bonnes *
* bon@elektron.ikp.physik.tu-darmstadt.de *
* *
* Copyright (C) 2018 Andreas Bolsch *
* andreas.bolsch@mni.thm.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
@@ -25,68 +28,79 @@
.text
.syntax unified
.cpu cortex-m4
.cpu cortex-m0
.thumb
/*
* Params :
* r0 = workarea start, status (out)
* r1 = workarea end
* r1 = workarea end + 1
* r2 = target address
* r3 = count (64bit words)
* r4 = flash base
* r4 = flash status register
* r5 = flash control register
*
* Clobbered:
* r5 - rp
* r6/7 - temp (64-bit)
* r8 - wp, tmp
*/
#define STM32_FLASH_CR_OFFSET 0x14 /* offset of CR register in FLASH struct */
#define STM32_FLASH_SR_OFFSET 0x10 /* offset of SR register in FLASH struct */
#define STM32_PROG 0x1 /* PG */
#include "../../../../src/flash/nor/stm32l4x.h"
.thumb_func
.global _start
_start:
mov r8, r3 /* copy dword count */
wait_fifo:
ldr r8, [r0, #0] /* read wp */
cmp r8, #0 /* abort if wp == 0 */
beq exit
ldr r5, [r0, #4] /* read rp */
subs r6, r8, r5 /* number of bytes available for read in r6*/
itt mi /* if wrapped around*/
addmi r6, r1 /* add size of buffer */
submi r6, r0
cmp r6, #8 /* wait until 8 bytes are available */
bcc wait_fifo
ldr r6, [r0, #0] /* read wp */
cmp r6, #0 /* if wp == 0, */
beq exit /* then abort */
ldr r3, [r0, #4] /* read rp */
subs r6, r6, r3 /* number of bytes available for read in r6 */
bpl fifo_stat /* if not wrapped around, skip */
adds r6, r6, r1 /* add end of buffer */
subs r6, r6, r0 /* sub start of buffer */
fifo_stat:
cmp r6, #8 /* wait until at least one dword available */
bcc wait_fifo
ldr r6, =STM32_PROG
str r6, [r4, #STM32_FLASH_CR_OFFSET]
ldrd r6, [r5], #0x08 /* read one word from src, increment ptr */
strd r6, [r2], #0x08 /* write one word to dst, increment ptr */
movs r6, #FLASH_PG /* flash program enable */
str r6, [r5] /* write to FLASH_CR, start operation */
ldmia r3!, {r6, r7} /* read one dword from src, increment ptr */
stmia r2!, {r6, r7} /* write one dword to dst, increment ptr */
dsb
ldr r7, =FLASH_BSY /* FLASH_BSY mask */
busy:
ldr r6, [r4, #STM32_FLASH_SR_OFFSET]
tst r6, #0x10000 /* BSY (bit16) == 1 => operation in progress */
bne busy /* wait more... */
tst r6, #0xfa /* PGSERR | SIZERR | PGAERR | WRPERR | PROGERR | OPERR */
bne error /* fail... */
ldr r6, [r4] /* get FLASH_SR register */
tst r6, r7 /* BSY == 1 => operation in progress */
bne busy /* if still set, wait more ... */
movs r7, #FLASH_ERROR /* all error bits */
tst r6, r7 /* check for any error bit */
bne error /* fail ... */
cmp r5, r1 /* wrap rp at end of buffer */
it cs
addcs r5, r0, #8 /* skip loader args */
str r5, [r0, #4] /* store rp */
subs r3, r3, #1 /* decrement dword count */
cbz r3, exit /* loop if not done */
b wait_fifo
error:
movs r1, #0
str r1, [r0, #4] /* set rp = 0 on error */
exit:
mov r0, r6 /* return status in r0 */
bkpt #0x00
cmp r3, r1 /* rp at end of buffer? */
bcc upd_rp /* if no, then skip */
subs r3, r3, r1 /* sub end of buffer */
adds r3, r3, r0 /* add start of buffer */
adds r3, r3, #8 /* skip wp and rp */
upd_rp:
str r3, [r0, #4] /* store rp */
mov r7, r8 /* get dword count */
subs r7, r7, #1 /* decrement dword count */
mov r8, r7 /* save dword count */
beq exit /* exit if done */
b wait_fifo
.pool
error:
movs r3, #0
str r3, [r0, #4] /* set rp = 0 on error */
exit:
mov r0, r6 /* return status in r0 */
movs r6, #0 /* flash program disable */
str r6, [r5] /* write to FLASH_CR */
movs r6, #FLASH_ERROR /* all error bits */
str r6, [r4] /* write to FLASH_CR to clear errors */
bkpt #0x00

View File

@@ -1,7 +1,7 @@
/* Autogenerated with ../../../../src/helper/bin2char.sh */
0xd0,0xf8,0x00,0x80,0xb8,0xf1,0x00,0x0f,0x20,0xd0,0x45,0x68,0xb8,0xeb,0x05,0x06,
0x44,0xbf,0x76,0x18,0x36,0x1a,0x08,0x2e,0xf2,0xd3,0x0d,0x4e,0x66,0x61,0xf5,0xe8,
0x02,0x67,0xe2,0xe8,0x02,0x67,0xbf,0xf3,0x4f,0x8f,0x26,0x69,0x16,0xf4,0x80,0x3f,
0xfb,0xd1,0x16,0xf0,0xfa,0x0f,0x07,0xd1,0x8d,0x42,0x28,0xbf,0x00,0xf1,0x08,0x05,
0x45,0x60,0x01,0x3b,0x13,0xb1,0xdb,0xe7,0x00,0x21,0x41,0x60,0x30,0x46,0x00,0xbe,
0x01,0x00,0x00,0x00,
0x98,0x46,0x06,0x68,0x00,0x2e,0x23,0xd0,0x43,0x68,0xf6,0x1a,0x01,0xd5,0x76,0x18,
0x36,0x1a,0x08,0x2e,0xf5,0xd3,0x01,0x26,0x2e,0x60,0xc0,0xcb,0xc0,0xc2,0xbf,0xf3,
0x4f,0x8f,0x09,0x4f,0x26,0x68,0x3e,0x42,0xfc,0xd1,0xfa,0x27,0x3e,0x42,0x0d,0xd1,
0x8b,0x42,0x02,0xd3,0x5b,0x1a,0x1b,0x18,0x08,0x33,0x43,0x60,0x47,0x46,0x01,0x3f,
0xb8,0x46,0x05,0xd0,0xdd,0xe7,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x23,0x43,0x60,
0x30,0x46,0x00,0x26,0x2e,0x60,0xfa,0x26,0x26,0x60,0x00,0xbe,

View File

@@ -6892,8 +6892,10 @@ The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@deffn {Flash Driver} stm32l4x
All members of the STM32L4 and STM32WB microcontroller families from STMicroelectronics
include internal flash and use ARM Cortex-M4 cores.
All members of the STM32L4, STM32L4+, STM32WB and STM32G4
microcontroller families from STMicroelectronics include internal flash
and use ARM Cortex-M4 cores.
Additionally this driver supports STM32G0 family with ARM Cortex-M0+ core.
The driver automatically recognizes a number of these chips using
the chip identification register, and autoconfigures itself.
@@ -6903,7 +6905,8 @@ flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
Note that some devices have been found that have a flash size register that contains
an invalid value, to workaround this issue you can override the probed value used by
the flash driver.
the flash driver. However, specifying a wrong value might lead to a completely
wrong flash layout, so this feature must be used carefully.
@example
flash bank $_FLASHNAME stm32l4x 0x08000000 0x40000 0 0 $_TARGETNAME
@@ -6960,7 +6963,7 @@ This will effectively write protect all sectors in flash bank 1.
@end deffn
@deffn Command {stm32l4x option_load} num
Forces a re-load of the option byte registers. Will cause a reset of the device.
Forces a re-load of the option byte registers. Will cause a system reset of the device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@end deffn

View File

@@ -84,4 +84,5 @@ NORHEADERS = \
%D%/non_cfi.h \
%D%/ocl.h \
%D%/spi.h \
%D%/stm32l4x.h \
%D%/msp432.h

File diff suppressed because it is too large Load Diff

82
src/flash/nor/stm32l4x.h Normal file
View File

@@ -0,0 +1,82 @@
/***************************************************************************
* Copyright (C) 2015 by Uwe Bonnes *
* bon@elektron.ikp.physik.tu-darmstadt.de *
*
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_FLASH_NOR_STM32L4X
#define OPENOCD_FLASH_NOR_STM32L4X
/* Flash registers offsets */
#define STM32_FLASH_ACR 0x00
#define STM32_FLASH_KEYR 0x08
#define STM32_FLASH_OPTKEYR 0x0c
#define STM32_FLASH_SR 0x10
#define STM32_FLASH_CR 0x14
#define STM32_FLASH_OPTR 0x20
#define STM32_FLASH_WRP1AR 0x2c
#define STM32_FLASH_WRP1BR 0x30
#define STM32_FLASH_WRP2AR 0x4c
#define STM32_FLASH_WRP2BR 0x50
/* FLASH_CR register bits */
#define FLASH_PG (1 << 0)
#define FLASH_PER (1 << 1)
#define FLASH_MER1 (1 << 2)
#define FLASH_PAGE_SHIFT 3
#define FLASH_CR_BKER (1 << 11)
#define FLASH_MER2 (1 << 15)
#define FLASH_STRT (1 << 16)
#define FLASH_OPTSTRT (1 << 17)
#define FLASH_EOPIE (1 << 24)
#define FLASH_ERRIE (1 << 25)
#define FLASH_OBL_LAUNCH (1 << 27)
#define FLASH_OPTLOCK (1 << 30)
#define FLASH_LOCK (1 << 31)
/* FLASH_SR register bits */
#define FLASH_BSY (1 << 16)
/* Fast programming not used => related errors not used*/
#define FLASH_PGSERR (1 << 7) /* Programming sequence error */
#define FLASH_SIZERR (1 << 6) /* Size error */
#define FLASH_PGAERR (1 << 5) /* Programming alignment error */
#define FLASH_WRPERR (1 << 4) /* Write protection error */
#define FLASH_PROGERR (1 << 3) /* Programming error */
#define FLASH_OPERR (1 << 1) /* Operation error */
#define FLASH_EOP (1 << 0) /* End of operation */
#define FLASH_ERROR (FLASH_PGSERR | FLASH_SIZERR | FLASH_PGAERR | \
FLASH_WRPERR | FLASH_PROGERR | FLASH_OPERR)
/* register unlock keys */
#define KEY1 0x45670123
#define KEY2 0xCDEF89AB
/* option register unlock key */
#define OPTKEY1 0x08192A3B
#define OPTKEY2 0x4C5D6E7F
#define RDP_LEVEL_0 0xAA
#define RDP_LEVEL_1 0xBB
#define RDP_LEVEL_2 0xCC
/* other registers */
#define DBGMCU_IDCODE_G0 0x40015800
#define DBGMCU_IDCODE_L4_G4 0xE0042000
#define DBGMCU_IDCODE_L5 0xE0044000
#define STM32_FLASH_BANK_BASE 0x08000000
#endif

88
tcl/target/stm32g0x.cfg Normal file
View File

@@ -0,0 +1,88 @@
# script for stm32g0x family
#
# stm32g0 devices support SWD transports only.
#
source [find target/swj-dp.tcl]
source [find mem_helper.tcl]
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME stm32g0x
}
set _ENDIAN little
# Work-area is a space in RAM used for flash programming
# Smallest proposed target has 8kB ram, use 4kB by default to avoid surprises
if { [info exists WORKAREASIZE] } {
set _WORKAREASIZE $WORKAREASIZE
} else {
set _WORKAREASIZE 0x1000
}
#jtag scan chain
if { [info exists CPUTAPID] } {
set _CPUTAPID $CPUTAPID
} else {
# Section 37.5.5 - corresponds to Cortex-M0+
set _CPUTAPID 0x0bc11477
}
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
# reasonable default
adapter speed 2000
adapter srst delay 100
if {[using_jtag]} {
jtag_ntrst_delay 100
}
reset_config srst_nogate
if {![using_hla]} {
# if srst is not fitted use SYSRESETREQ to
# perform a soft reset
cortex_m reset_config sysresetreq
}
proc stm32g0x_default_reset_start {} {
# Reset clock is HSI16 (16 MHz)
adapter speed 2000
}
proc stm32g0x_default_examine_end {} {
# DBGMCU_CR |= DBG_STANDBY | DBG_STOP
mmw 0x40015804 0x00000006 0
# Stop watchdog counters during halt
# DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP
mmw 0x40015808 0x00001800 0
}
proc stm32g0x_default_reset_init {} {
# Increase clock to 64 Mhz
mmw 0x40022000 0x00000002 0x00000005 ;# FLASH_ACR: Latency = 2
mww 0x4002100C 0x30000802 ;# RCC_PLLCFGR = PLLR=/2, PLLN=8, PLLM=/1, PLLSRC=0x2
mmw 0x40021000 0x01000000 0x00000000 ;# RCC_CR |= PLLON
mmw 0x40021008 0x00000002 0x00000005 ;# RCC_CFGR: SW=PLLRCLK
# Boost JTAG frequency
adapter speed 4000
}
# Default hooks
$_TARGETNAME configure -event examine-end { stm32g0x_default_examine_end }
$_TARGETNAME configure -event reset-start { stm32g0x_default_reset_start }
$_TARGETNAME configure -event reset-init { stm32g0x_default_reset_init }

103
tcl/target/stm32g4x.cfg Normal file
View File

@@ -0,0 +1,103 @@
# script for stm32g4x family
#
# stm32g4 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 stm32g4x
}
set _ENDIAN little
# Work-area is a space in RAM used for flash programming
# Smallest current target has 32kB ram, use 16kB by default to avoid surprises
if { [info exists WORKAREASIZE] } {
set _WORKAREASIZE $WORKAREASIZE
} else {
set _WORKAREASIZE 0x4000
}
#jtag scan chain
if { [info exists CPUTAPID] } {
set _CPUTAPID $CPUTAPID
} else {
if { [using_jtag] } {
# See STM Document RM0440
# Section 46.6.3 - corresponds to Cortex-M4 r0p1
set _CPUTAPID 0x4ba00477
} {
set _CPUTAPID 0x2ba01477
}
}
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
if {[using_jtag]} {
jtag newtap $_CHIPNAME bs -irlen 5
}
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
if { [info exists QUADSPI] && $QUADSPI } {
set a [llength [flash list]]
set _QSPINAME $_CHIPNAME.qspi
flash bank $_QSPINAME stmqspi 0x90000000 0 0 0 $_TARGETNAME 0xA0001000
}
# reasonable default
adapter speed 2000
adapter srst delay 100
if {[using_jtag]} {
jtag_ntrst_delay 100
}
reset_config srst_nogate
if {![using_hla]} {
# if srst is not fitted use SYSRESETREQ to
# perform a soft reset
cortex_m reset_config sysresetreq
}
$_TARGETNAME configure -event reset-init {
# CPU comes out of reset with HSION | HSIRDY.
# Use HSI 16 MHz clock, compliant even with VOS == 2.
# 1 WS compliant with VOS == 2 and 16 MHz.
mmw 0x40022000 0x00000001 0x0000000E ;# FLASH_ACR: Latency = 1
mmw 0x40021000 0x00000100 0x00000000 ;# RCC_CR |= HSION
mmw 0x40021008 0x00000001 0x00000002 ;# RCC_CFGR: SW=HSI16
}
$_TARGETNAME configure -event reset-start {
# Reset clock is HSI (16 MHz)
adapter speed 2000
}
$_TARGETNAME configure -event examine-end {
# DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP
mmw 0xE0042004 0x00000007 0
# Stop watchdog counters during halt
# DBGMCU_APB1_FZR1 |= DBG_IWDG_STOP | DBG_WWDG_STOP
mmw 0xE0042008 0x00001800 0
}
$_TARGETNAME configure -event trace-config {
# Set TRACE_IOEN; TRACE_MODE is set to async; when using sync
# change this value accordingly to configure trace pins
# assignment
mmw 0xE0042004 0x00000020 0
}