This is an automated email from Gerrit.

Michael Jung ([email protected]) just uploaded a new patch set to Gerrit, which 
you can find at http://openocd.zylin.com/5386

-- gerrit

commit 936a2151a3334d133b6650fc588c7192b800fabb
Author: Michael Jung <[email protected]>
Date:   Fri Nov 15 19:33:25 2019 +0100

    flash/nor/stm32l4x.c: Support for STM32L5 devices
    
    The STM32L5 family of MCUs is very similar to the L4 one, with regard to
    flash programming.  However, some register offsets have changed in the FLASH
    macro.  This has been taken care of by a register address table that maps
    register names to the respective addresses depenend on the MCU family.
    
    A stm32l5x.cfg has also been added, basically as a copy of stm32l4.cfg with
    the following addition:  Prior to any write access to flash the MCU has to
    be put into Voltage Scaling Range 1.  This is done in the reset-init event
    script.
    
    Please note that I do not have a STM32L4 device available and thus was not
    able to do any transparency tests.
    
    Tested with:
     - NUCLEO-L552ZE-Q
    
    Signed-off-by: Michael Jung <[email protected]>
    Change-Id: I09db36f6260ee99e5d3d559ba2b83df157c9f87b

diff --git a/contrib/loaders/flash/stm32/Makefile 
b/contrib/loaders/flash/stm32/Makefile
index b58b412..46d265a 100644
--- a/contrib/loaders/flash/stm32/Makefile
+++ b/contrib/loaders/flash/stm32/Makefile
@@ -8,7 +8,7 @@ OBJDUMP=$(CROSS_COMPILE)objdump
 
 CFLAGS = -static -nostartfiles -mlittle-endian -Wa,-EL
 
-all: stm32f1x.inc stm32f2x.inc stm32h7x.inc stm32l4x.inc stm32lx.inc
+all: stm32f1x.inc stm32f2x.inc stm32h7x.inc stm32l4x.inc stm32l5x.inc 
stm32lx.inc
 
 .PHONY: clean
 
diff --git a/contrib/loaders/flash/stm32/stm32l5x.S 
b/contrib/loaders/flash/stm32/stm32l5x.S
new file mode 100644
index 0000000..d0c2f9d
--- /dev/null
+++ b/contrib/loaders/flash/stm32/stm32l5x.S
@@ -0,0 +1,94 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Spencer Oliver                                  *
+ *   [email protected]                                                  *
+ *                                                                         *
+ *   Copyright (C) 2011 Øyvind Harboe                                      *
+ *   [email protected]                                               *
+ *                                                                         *
+ *   Copyright (C) 2015 Uwe Bonnes                                         *
+ *   [email protected]                               *
+ *                                                                         *
+ *   Copyright (C) 2019 Michael Jung                                       *
+ *   [email protected]                                                        *
+ *                                                                         *
+ *   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, write to the                         *
+ *   Free Software Foundation, Inc.                                        *
+ ***************************************************************************/
+
+       .text
+       .syntax unified
+       .cpu cortex-m33
+       .thumb
+
+/*
+ * Params :
+ * r0 = workarea start, status (out)
+ * r1 = workarea end
+ * r2 = target address
+ * r3 = count (64bit words)
+ * r4 = flash base
+ *
+ * Clobbered:
+ * r5   - rp
+ * r6/7 - temp (64-bit)
+ * r8   - wp, tmp
+ */
+
+#define STM32_FLASH_NSCR_OFFSET        0x28    /* offset of NSCR register in 
FLASH struct */
+#define STM32_FLASH_NSSR_OFFSET        0x20    /* offset of NSSR register in 
FLASH struct */
+
+#define STM32_PROG      0x1    /* PG */
+
+       .thumb_func
+       .global _start
+_start:
+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, =STM32_PROG
+       str     r6, [r4, #STM32_FLASH_NSCR_OFFSET]
+       ldrd    r6, [r5], #0x08 /* read one word from src, increment ptr */
+       strd    r6, [r2], #0x08 /* write one word to dst, increment ptr */
+       dsb
+busy:
+       ldr     r6, [r4, #STM32_FLASH_NSSR_OFFSET]
+       tst     r6, #0x10000    /* BSY (bit16) == 1 => operation in progress */
+       bne     busy            /* wait more... */
+       tst     r6, #0xfa       /* PGSERR | PGPERR | PGAERR | WRPERR | PROGERR*/
+       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
+
+       .pool
diff --git a/contrib/loaders/flash/stm32/stm32l5x.inc 
b/contrib/loaders/flash/stm32/stm32l5x.inc
new file mode 100644
index 0000000..a200565
--- /dev/null
+++ b/contrib/loaders/flash/stm32/stm32l5x.inc
@@ -0,0 +1,7 @@
+/* Autogenerated with ../../../../src/helper/bin2char.sh */
+0xd0,0xf8,0x00,0x80,0xb8,0xf1,0x00,0x0f,0x21,0xd0,0x45,0x68,0xb8,0xeb,0x05,0x06,
+0x44,0xbf,0x76,0x18,0x36,0x1a,0x08,0x2e,0xf2,0xd3,0x4f,0xf0,0x01,0x06,0xa6,0x62,
+0xf5,0xe8,0x02,0x67,0xe2,0xe8,0x02,0x67,0xbf,0xf3,0x4f,0x8f,0x26,0x6a,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,0xda,0xe7,0x00,0x21,0x41,0x60,0x30,0x46,
+0x00,0xbe,
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 551f389..35a3f15 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -72,6 +72,7 @@ extern const struct flash_driver stm32f1x_flash;
 extern const struct flash_driver stm32f2x_flash;
 extern const struct flash_driver stm32lx_flash;
 extern const struct flash_driver stm32l4x_flash;
+extern const struct flash_driver stm32l5x_flash;
 extern const struct flash_driver stm32h7x_flash;
 extern const struct flash_driver stmsmi_flash;
 extern const struct flash_driver str7x_flash;
@@ -142,6 +143,7 @@ static const struct flash_driver * const flash_drivers[] = {
        &stm32f2x_flash,
        &stm32lx_flash,
        &stm32l4x_flash,
+       &stm32l5x_flash,
        &stm32h7x_flash,
        &stmsmi_flash,
        &str7x_flash,
diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
index f680542..1075355 100644
--- a/src/flash/nor/stm32l4x.c
+++ b/src/flash/nor/stm32l4x.c
@@ -1,7 +1,10 @@
 /***************************************************************************
  *   Copyright (C) 2015 by Uwe Bonnes                                      *
  *   [email protected]                               *
- *
+ *                                                                         *
+ *   Copyright (C) 2019 by Michael Jung                                    *
+ *   [email protected]                                                        *
+ *                                                                         *
  *   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     *
@@ -56,21 +59,64 @@
  *
  */
 
+/* STM32L562 series for reference.
+ *
+ * RM0428 (STM32L552xx/STM32L562xx)
+ * http://www.st.com/resource/en/reference_manual/dm00346336.pdf
+ */
+
 /* Erase time can be as high as 25ms, 10x this and assume it's toast... */
 
 #define FLASH_ERASE_TIMEOUT 250
 
-#define STM32_FLASH_BASE    0x40022000
-#define STM32_FLASH_ACR     0x40022000
-#define STM32_FLASH_KEYR    0x40022008
-#define STM32_FLASH_OPTKEYR 0x4002200c
-#define STM32_FLASH_SR      0x40022010
-#define STM32_FLASH_CR      0x40022014
-#define STM32_FLASH_OPTR    0x40022020
-#define STM32_FLASH_WRP1AR  0x4002202c
-#define STM32_FLASH_WRP1BR  0x40022030
-#define STM32_FLASH_WRP2AR  0x4002204c
-#define STM32_FLASH_WRP2BR  0x40022050
+const uint32_t regaddr[2][13] = {
+       {       /* STM32L4xx register offsets */
+               0x40022000, /* STM32_FLASH_BASE     */
+               0x40022000, /* STM32_FLASH_ACR      */
+               0x40022008, /* STM32_FLASH_KEYR     */
+               0x4002200c, /* STM32_FLASH_OPTKEYR  */
+               0x40022010, /* STM32_FLASH_SR       */
+               0x40022014, /* STM32_FLASH_CR       */
+               0x40022020, /* STM32_FLASH_OPTR     */
+               0x4002202c, /* STM32_FLASH_WRP1AR   */
+               0x40022030, /* STM32_FLASH_WRP1BR   */
+               0x4002204c, /* STM32_FLASH_WRP2AR   */
+               0x40022050, /* STM32_FLASH_WRP2BR   */
+               0xE0042000, /* STM32_DBGMCU_IDCODE  */
+               0x1FFF75E0, /* STM32_FLASH_SIZE_REG */
+       },
+       {       /* STM32L5xx register offsets */
+               0x40022000, /* STM32_FLASH_BASE     */
+               0x40022000, /* STM32_FLASH_ACR      */
+               0x40022008, /* STM32_FLASH_KEYR     */
+               0x40022010, /* STM32_FLASH_OPTKEYR  */
+               0x40022020, /* STM32_FLASH_SR       */
+               0x40022028, /* STM32_FLASH_CR       */
+               0x40022040, /* STM32_FLASH_OPTR     */
+               0x40022058, /* STM32_FLASH_WRP1AR   */
+               0x4002205c, /* STM32_FLASH_WRP1BR   */
+               0x40022068, /* STM32_FLASH_WRP2AR   */
+               0x4002206c, /* STM32_FLASH_WRP2BR   */
+               0xE0044000, /* STM32_DBGMCU_IDCODE  */
+               0x0BFA05E0, /* STM32_FLASH_SIZE_REG */
+       }
+};
+
+/* Indices into the regaddr table */
+
+#define STM32_FLASH_BASE               0
+#define STM32_FLASH_ACR                        1
+#define STM32_FLASH_KEYR               2
+#define STM32_FLASH_OPTKEYR            3
+#define STM32_FLASH_SR                 4
+#define STM32_FLASH_CR                 5
+#define STM32_FLASH_OPTR               6
+#define STM32_FLASH_WRP1AR             7
+#define STM32_FLASH_WRP1BR             8
+#define STM32_FLASH_WRP2AR             9
+#define STM32_FLASH_WRP2BR             10
+#define STM32_DBGMCU_IDCODE            11
+#define STM32_FLASH_SIZE_REG   12
 
 /* FLASH_CR register bits */
 
@@ -100,10 +146,12 @@
 #define FLASH_OPERR    (1 << 1) /* Operation error */
 #define FLASH_EOP      (1 << 0) /* End of operation */
 
-#define FLASH_ERROR (FLASH_PGSERR | FLASH_PGSERR | FLASH_PGAERR | FLASH_WRPERR 
| FLASH_OPERR)
+#define FLASH_ERROR (FLASH_PGSERR | FLASH_SIZERR | FLASH_PGAERR | FLASH_WRPERR 
| FLASH_OPERR)
 
 /* STM32_FLASH_OBR bit definitions (reading) */
 
+#define OPT_DBANK_C_256K (1 << 21)     /* dual bank for devices with 256 KiB 
flash */
+#define OPT_DBANK_E_512K (1 << 22)     /* dual bank for devices with 512 KiB 
flash */
 #define OPT_DBANK_LE_1M (1 << 21)      /* dual bank for devices up to 1M flash 
*/
 #define OPT_DBANK_GE_2M (1 << 22)      /* dual bank for devices with 2M flash 
*/
 
@@ -120,18 +168,18 @@
 #define RDP_LEVEL_1       0xBB
 #define RDP_LEVEL_2       0xCC
 
-
-/* other registers */
-#define DBGMCU_IDCODE  0xE0042000
-#define FLASH_SIZE_REG 0x1FFF75E0
+#define STM32_FAMILY_L4 0
+#define STM32_FAMILY_L5 1
 
 struct stm32l4_flash_bank {
        uint16_t bank2_start;
        int probed;
+       int family;
 };
 
 /* flash bank stm32l4x <base> <size> 0 0 <target#>
  */
+
 FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command)
 {
        struct stm32l4_flash_bank *stm32l4_info;
@@ -145,13 +193,33 @@ FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command)
        bank->driver_priv = stm32l4_info;
 
        stm32l4_info->probed = 0;
+       stm32l4_info->family = STM32_FAMILY_L4;
+
+       return ERROR_OK;
+}
+
+FLASH_BANK_COMMAND_HANDLER(stm32l5_flash_bank_command)
+{
+       struct stm32l4_flash_bank *stm32l4_info;
+
+       if (CMD_ARGC < 6)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       stm32l4_info = malloc(sizeof(struct stm32l4_flash_bank));
+       if (!stm32l4_info)
+               return ERROR_FAIL; /* Checkme: What better error to use?*/
+       bank->driver_priv = stm32l4_info;
+
+       stm32l4_info->probed = 0;
+       stm32l4_info->family = STM32_FAMILY_L5;
 
        return ERROR_OK;
 }
 
 static inline int stm32l4_get_flash_reg(struct flash_bank *bank, uint32_t reg)
 {
-       return reg;
+       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+       return regaddr[stm32l4_info->family][reg];
 }
 
 static inline int stm32l4_get_flash_status(struct flash_bank *bank, uint32_t 
*status)
@@ -201,14 +269,15 @@ static int stm32l4_wait_status_busy(struct flash_bank 
*bank, int timeout)
        return retval;
 }
 
-static int stm32l4_unlock_reg(struct target *target)
+static int stm32l4_unlock_reg(struct flash_bank *bank)
 {
+       struct target *target = bank->target;
        uint32_t ctrl;
 
        /* first check if not already unlocked
         * otherwise writing on STM32_FLASH_KEYR will fail
         */
-       int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
+       int retval = target_read_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_CR), &ctrl);
        if (retval != ERROR_OK)
                return retval;
 
@@ -216,15 +285,15 @@ static int stm32l4_unlock_reg(struct target *target)
                return ERROR_OK;
 
        /* unlock flash registers */
-       retval = target_write_u32(target, STM32_FLASH_KEYR, KEY1);
+       retval = target_write_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_KEYR), KEY1);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = target_write_u32(target, STM32_FLASH_KEYR, KEY2);
+       retval = target_write_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_KEYR), KEY2);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
+       retval = target_read_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_CR), &ctrl);
        if (retval != ERROR_OK)
                return retval;
 
@@ -236,11 +305,12 @@ static int stm32l4_unlock_reg(struct target *target)
        return ERROR_OK;
 }
 
-static int stm32l4_unlock_option_reg(struct target *target)
+static int stm32l4_unlock_option_reg(struct flash_bank *bank)
 {
+       struct target *target = bank->target;
        uint32_t ctrl;
 
-       int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
+       int retval = target_read_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_CR), &ctrl);
        if (retval != ERROR_OK)
                return retval;
 
@@ -248,15 +318,15 @@ static int stm32l4_unlock_option_reg(struct target 
*target)
                return ERROR_OK;
 
        /* unlock option registers */
-       retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY1);
+       retval = target_write_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_OPTKEYR), OPTKEY1);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY2);
+       retval = target_write_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_OPTKEYR), OPTKEY2);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
+       retval = target_read_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_CR), &ctrl);
        if (retval != ERROR_OK)
                return retval;
 
@@ -271,7 +341,7 @@ static int stm32l4_unlock_option_reg(struct target *target)
 static int stm32l4_read_option(struct flash_bank *bank, uint32_t address, 
uint32_t* value)
 {
        struct target *target = bank->target;
-       return target_read_u32(target, address, value);
+       return target_read_u32(target, stm32l4_get_flash_reg(bank, address), 
value);
 }
 
 static int stm32l4_write_option(struct flash_bank *bank, uint32_t address, 
uint32_t value, uint32_t mask)
@@ -279,21 +349,21 @@ static int stm32l4_write_option(struct flash_bank *bank, 
uint32_t address, uint3
        struct target *target = bank->target;
        uint32_t optiondata;
 
-       int retval = target_read_u32(target, address, &optiondata);
+       int retval = target_read_u32(target, stm32l4_get_flash_reg(bank, 
address), &optiondata);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = stm32l4_unlock_reg(target);
+       retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = stm32l4_unlock_option_reg(target);
+       retval = stm32l4_unlock_option_reg(bank);
        if (retval != ERROR_OK)
                return retval;
 
        optiondata = (optiondata & ~mask) | (value & mask);
 
-       retval = target_write_u32(target, address, optiondata);
+       retval = target_write_u32(target, stm32l4_get_flash_reg(bank, address), 
optiondata);
        if (retval != ERROR_OK)
                return retval;
 
@@ -364,7 +434,7 @@ static int stm32l4_erase(struct flash_bank *bank, int 
first, int last)
        }
 
        int retval;
-       retval = stm32l4_unlock_reg(target);
+       retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
                return retval;
 
@@ -449,6 +519,7 @@ static int stm32l4_protect(struct flash_bank *bank, int 
set, int first, int last
 static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
                uint32_t offset, uint32_t count)
 {
+       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
        struct target *target = bank->target;
        uint32_t buffer_size = 16384;
        struct working_area *write_algorithm;
@@ -458,22 +529,48 @@ static int stm32l4_write_block(struct flash_bank *bank, 
const uint8_t *buffer,
        struct armv7m_algorithm armv7m_info;
        int retval = ERROR_OK;
 
-       static const uint8_t stm32l4_flash_write_code[] = {
+       if (stm32l4_info->family == STM32_FAMILY_L4) {
+               static const uint8_t stm32l4_flash_write_code[] = {
 #include "../../../contrib/loaders/flash/stm32/stm32l4x.inc"
-       };
+               };
 
-       if (target_alloc_working_area(target, sizeof(stm32l4_flash_write_code),
-                       &write_algorithm) != ERROR_OK) {
-               LOG_WARNING("no working area available, can't do block memory 
writes");
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-       }
+               if (target_alloc_working_area(target, 
sizeof(stm32l4_flash_write_code),
+                               &write_algorithm) != ERROR_OK) {
+                       LOG_WARNING("no working area available, can't do block 
memory writes");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
 
-       retval = target_write_buffer(target, write_algorithm->address,
-                       sizeof(stm32l4_flash_write_code),
-                       stm32l4_flash_write_code);
-       if (retval != ERROR_OK) {
-               target_free_working_area(target, write_algorithm);
-               return retval;
+               retval = target_write_buffer(target, write_algorithm->address,
+                               sizeof(stm32l4_flash_write_code),
+                               stm32l4_flash_write_code);
+               if (retval != ERROR_OK) {
+                       target_free_working_area(target, write_algorithm);
+                       return retval;
+               }
+
+       } else if (stm32l4_info->family == STM32_FAMILY_L5) {
+               static const uint8_t stm32l5_flash_write_code[] = {
+#include "../../../contrib/loaders/flash/stm32/stm32l5x.inc"
+               };
+
+               if (target_alloc_working_area(target, 
sizeof(stm32l5_flash_write_code),
+                               &write_algorithm) != ERROR_OK) {
+                       LOG_WARNING("no working area available, can't do block 
memory writes");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+
+               retval = target_write_buffer(target, write_algorithm->address,
+                               sizeof(stm32l5_flash_write_code),
+                               stm32l5_flash_write_code);
+               if (retval != ERROR_OK) {
+                       target_free_working_area(target, write_algorithm);
+                       return retval;
+               }
+
+       } else {
+
+               LOG_ERROR("unknown STM32 family.");
+               return ERROR_TARGET_INVALID;
        }
 
        /* memory buffer */
@@ -503,7 +600,7 @@ static int stm32l4_write_block(struct flash_bank *bank, 
const uint8_t *buffer,
        buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
        buf_set_u32(reg_params[2].value, 0, 32, address);
        buf_set_u32(reg_params[3].value, 0, 32, count / 4);
-       buf_set_u32(reg_params[4].value, 0, 32, STM32_FLASH_BASE);
+       buf_set_u32(reg_params[4].value, 0, 32, stm32l4_get_flash_reg(bank, 
STM32_FLASH_BASE));
 
        retval = target_run_flash_async_algorithm(target, buffer, count, 2,
                        0, NULL,
@@ -523,7 +620,7 @@ static int stm32l4_write_block(struct flash_bank *bank, 
const uint8_t *buffer,
                if (error != 0) {
                        LOG_ERROR("flash write failed = %08" PRIx32, error);
                        /* Clear but report errors */
-                       target_write_u32(target, STM32_FLASH_SR, error);
+                       target_write_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_SR), error);
                        retval = ERROR_FAIL;
                }
        }
@@ -570,7 +667,7 @@ static int stm32l4_write(struct flash_bank *bank, const 
uint8_t *buffer,
                 */
        }
 
-       retval = stm32l4_unlock_reg(target);
+       retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
                return retval;
 
@@ -582,7 +679,7 @@ static int stm32l4_write(struct flash_bank *bank, const 
uint8_t *buffer,
                }
 
        LOG_WARNING("block write succeeded");
-       return target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK);
+       return target_write_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_CR), FLASH_LOCK);
 }
 
 static int stm32l4_probe(struct flash_bank *bank)
@@ -599,7 +696,7 @@ static int stm32l4_probe(struct flash_bank *bank)
        stm32l4_info->probed = 0;
 
        /* read stm32 device id register */
-       int retval = target_read_u32(target, DBGMCU_IDCODE, &device_id);
+       int retval = target_read_u32(target, stm32l4_get_flash_reg(bank, 
STM32_DBGMCU_IDCODE), &device_id);
        if (retval != ERROR_OK)
                return retval;
        LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
@@ -619,13 +716,16 @@ static int stm32l4_probe(struct flash_bank *bank)
        case 0x435:
                max_flash_size_in_kb = 256;
                break;
+       case 0x472:
+               max_flash_size_in_kb = 512;
+               break;
        default:
                LOG_WARNING("Cannot identify target as an STM32L4 family 
device.");
                return ERROR_FAIL;
        }
 
        /* get flash size from target. */
-       retval = target_read_u16(target, FLASH_SIZE_REG, &flash_size_in_kb);
+       retval = target_read_u16(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_SIZE_REG), &flash_size_in_kb);
 
        /* failed reading flash size or flash size invalid (early silicon),
         * default to max target family */
@@ -641,7 +741,7 @@ static int stm32l4_probe(struct flash_bank *bank)
        assert((flash_size_in_kb != 0xffff) && flash_size_in_kb);
 
        /* get options for DUAL BANK. */
-       retval = target_read_u32(target, STM32_FLASH_OPTR, &options);
+       retval = target_read_u32(target, stm32l4_get_flash_reg(bank, 
STM32_FLASH_OPTR), &options);
 
        if (retval != ERROR_OK)
                return retval;
@@ -650,6 +750,23 @@ static int stm32l4_probe(struct flash_bank *bank)
        int page_size = 0;
 
        switch (device_id & 0xfff) {
+               case 0x472:
+                       /* L552/L562 have 512 KiB FLASH and dual/single bank 
mode.
+                        * Page size is 2K or 4K.*/
+                       if (flash_size_in_kb == 512) {
+                               stm32l4_info->bank2_start = 128;
+                               if (options & OPT_DBANK_E_512K) {
+                                       page_size = 2048;
+                                       num_pages = 256;
+                               } else {
+                                       page_size = 4096;
+                                       num_pages = 128;
+                               }
+                               break;
+                       }
+                       /* Invalid FLASH size for this device. */
+                       LOG_WARNING("Invalid flash size for STM32L5 family 
device.");
+                       return ERROR_FAIL;
                case 0x470:
                        /* L4R/S have 1M or 2M FLASH and dual/single bank mode.
                         * Page size is 4K or 8K.*/
@@ -742,7 +859,7 @@ static int get_stm32l4_info(struct flash_bank *bank, char 
*buf, int buf_size)
        uint32_t dbgmcu_idcode;
 
        /* read stm32 device id register */
-       int retval = target_read_u32(target, DBGMCU_IDCODE, &dbgmcu_idcode);
+       int retval = target_read_u32(target, stm32l4_get_flash_reg(bank, 
STM32_DBGMCU_IDCODE), &dbgmcu_idcode);
        if (retval != ERROR_OK)
                return retval;
 
@@ -781,6 +898,10 @@ static int get_stm32l4_info(struct flash_bank *bank, char 
*buf, int buf_size)
                device_str = "STM32L43x/44x";
                break;
 
+       case 0x472:
+               device_str = "STM32L552/562";
+               break;
+
        default:
                snprintf(buf, buf_size, "Cannot identify target as a 
STM32L4\n");
                return ERROR_FAIL;
@@ -802,7 +923,7 @@ static int stm32l4_mass_erase(struct flash_bank *bank, 
uint32_t action)
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       retval = stm32l4_unlock_reg(target);
+       retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
                return retval;
 
@@ -926,11 +1047,11 @@ COMMAND_HANDLER(stm32l4_handle_option_load_command)
 
        struct target *target = bank->target;
 
-       retval = stm32l4_unlock_reg(target);
+       retval = stm32l4_unlock_reg(bank);
        if (ERROR_OK != retval)
                return retval;
 
-       retval = stm32l4_unlock_option_reg(target);
+       retval = stm32l4_unlock_option_reg(bank);
        if (ERROR_OK != retval)
                return retval;
 
@@ -1068,3 +1189,30 @@ const struct flash_driver stm32l4x_flash = {
        .info = get_stm32l4_info,
        .free_driver_priv = default_flash_free_driver_priv,
 };
+
+static const struct command_registration stm32l5_command_handlers[] = {
+       {
+               .name = "stm32l5x",
+               .mode = COMMAND_ANY,
+               .help = "stm32l5x flash command group",
+               .usage = "",
+               .chain = stm32l4_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+const struct flash_driver stm32l5x_flash = {
+       .name = "stm32l5x",
+       .commands = stm32l5_command_handlers,
+       .flash_bank_command = stm32l5_flash_bank_command,
+       .erase = stm32l4_erase,
+       .protect = stm32l4_protect,
+       .write = stm32l4_write,
+       .read = default_flash_read,
+       .probe = stm32l4_probe,
+       .auto_probe = stm32l4_auto_probe,
+       .erase_check = default_flash_blank_check,
+       .protect_check = stm32l4_protect_check,
+       .info = get_stm32l4_info,
+       .free_driver_priv = default_flash_free_driver_priv,
+};
diff --git a/tcl/target/stm32l5x.cfg b/tcl/target/stm32l5x.cfg
new file mode 100644
index 0000000..4a9df0e
--- /dev/null
+++ b/tcl/target/stm32l5x.cfg
@@ -0,0 +1,107 @@
+# script for stm32l5x family
+
+#
+# stm32l5 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 stm32l5x
+}
+
+set _ENDIAN little
+
+# Work-area is a space in RAM used for flash programming
+# Smallest current target has 256kB ram, use 32kB by default to avoid surprises
+if { [info exists WORKAREASIZE] } {
+   set _WORKAREASIZE $WORKAREASIZE
+} else {
+   set _WORKAREASIZE 0x8000
+}
+
+#jtag scan chain
+if { [info exists CPUTAPID] } {
+   set _CPUTAPID $CPUTAPID
+} else {
+   if { [using_jtag] } {
+      # See STM Document RM0438
+      # Section 51.2.10 Debug port registers - corresponds to Cortex-M33 r0p0
+      set _CPUTAPID 0x0be11477
+   } {
+      set _CPUTAPID 0x0be12477
+   }
+}
+
+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 stm32l5x 0 0 0 0 $_TARGETNAME
+
+# Common knowledges tells JTAG speed should be <= F_CPU/6.
+# F_CPU after reset is MSI 4MHz, so use F_JTAG = 500 kHz to stay on
+# the safe side.
+#
+# Note that there is a pretty wide band where things are
+# more or less stable, see http://openocd.zylin.com/#/c/3366/
+adapter_khz 500
+
+adapter_nsrst_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 MSI_ON | MSI_RDY | MSI Range 6 (4 MHz).
+       # Use MSI 24 MHz clock, compliant even with VOS == 2.
+       # 3 WS compliant with VOS == 2 and 24 MHz.
+       mww 0x40022000 0x00000103   ;# FLASH_ACR = PRFTBE | 3(Latency)
+       mww 0x40021000 0x00000099   ;# RCC_CR = MSI_ON | MSIRGSEL | MSI Range 9
+       # Enable Voltage Scaling Range 1 (req. for flash write)
+       mww 0x40021058 0x10000000   ;# RCC_APB1ENR1 = PWREN
+       mww 0x40007000 0x00000200   ;# PWR_CR1 = VOS Range 1
+       sleep 10                    ;# Wait for Voltage Regulator
+       # Boost JTAG frequency
+       adapter_khz 4000
+}
+
+$_TARGETNAME configure -event reset-start {
+       # Reset clock is MSI (4 MHz)
+       adapter_khz 480
+}
+
+$_TARGETNAME configure -event examine-end {
+       # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP
+       mmw 0xE0042004 0x00000007 0
+
+       # Stop watchdog counters during halt
+       # DBGMCU_APB1_FZ |= 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
+}

-- 


_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to