This is an automated email from Gerrit.

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

-- gerrit

commit 4b06e534356314ad2fd998d4321cc0616660894a
Author: Tarek BOCHKATI <[email protected]>
Date:   Sat Mar 6 22:46:35 2021 +0100

    flash/stm32l4x: switch to to c loader instead of assembly loader
    
    add loader argument for flash_word_size, to permit using the loader
    with STM32U5.
    
    Change-Id: I24cafc2ba637a065593a0506eae787b21080a0ba
    Signed-off-by: Tarek BOCHKATI <[email protected]>
    Reviewed-on: https://gerrit.st.com/c/stm32ide/official/openocd/+/197040
    Tested-by: CITOOLS <[email protected]>
    Reviewed-by: Tarek BOUCHKATI <[email protected]>

diff --git a/contrib/loaders/flash/stm32/Makefile 
b/contrib/loaders/flash/stm32/Makefile
index b58b412..3c90a87 100644
--- a/contrib/loaders/flash/stm32/Makefile
+++ b/contrib/loaders/flash/stm32/Makefile
@@ -6,14 +6,19 @@ CC=$(CROSS_COMPILE)gcc
 OBJCOPY=$(CROSS_COMPILE)objcopy
 OBJDUMP=$(CROSS_COMPILE)objdump
 
-CFLAGS = -static -nostartfiles -mlittle-endian -Wa,-EL
+
+AFLAGS = -static -nostartfiles -mlittle-endian -Wa,-EL
+CFLAGS = -c -mthumb -nostdlib -nostartfiles -Os -g -fPIC
 
 all: stm32f1x.inc stm32f2x.inc stm32h7x.inc stm32l4x.inc stm32lx.inc
 
 .PHONY: clean
 
 %.elf: %.S
-       $(CC) $(CFLAGS) $< -o $@
+       $(CC) $(AFLAGS) $< -o $@
+
+stm32l4x.elf: stm32l4x.c
+       $(CC) $(CFLAGS) -mcpu=cortex-m0plus -Wa,-adhln=$(<:.c=.lst) $< -o $@
 
 %.lst: %.elf
        $(OBJDUMP) -S $< > $@
diff --git a/contrib/loaders/flash/stm32/stm32l4x.S 
b/contrib/loaders/flash/stm32/stm32l4x.S
deleted file mode 100644
index 9923ce7..0000000
--- a/contrib/loaders/flash/stm32/stm32l4x.S
+++ /dev/null
@@ -1,105 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2010 by Spencer Oliver                                  *
- *   [email protected]                                                  *
- *                                                                         *
- *   Copyright (C) 2011 Øyvind Harboe                                      *
- *   [email protected]                                               *
- *                                                                         *
- *   Copyright (C) 2015 Uwe Bonnes                                         *
- *   [email protected]                               *
- *                                                                         *
- *   Copyright (C) 2018 Andreas Bolsch                                     *
- *   [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-m0
-       .thumb
-
-/*
- * Params :
- * r0 = workarea start, status (out)
- * r1 = workarea end + 1
- * r2 = target address
- * r3 = count (64bit words)
- * r4 = flash status register
- * r5 = flash control register
- *
- * Clobbered:
- * r6/7 - temp (64-bit)
- */
-
-#include "../../../../src/flash/nor/stm32l4x.h"
-
-       .thumb_func
-       .global _start
-
-_start:
-       mov             r8, r3                                          /* copy 
dword count */
-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
-
-       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]                                        /* 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             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
diff --git a/contrib/loaders/flash/stm32/stm32l4x.c 
b/contrib/loaders/flash/stm32/stm32l4x.c
new file mode 100644
index 0000000..069760f
--- /dev/null
+++ b/contrib/loaders/flash/stm32/stm32l4x.c
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/**
+ * Copyright (C) 2021 Tarek BOCHKATI
+ *   [email protected]
+ */
+
+#include <stdint.h>
+#include "../../../../src/flash/nor/stm32l4x.h"
+
+struct work_area {
+       uint8_t *wp;
+       uint8_t *rp;
+};
+
+static inline __attribute__((always_inline)) void copy_buffer_u32(uint32_t 
*dst, uint32_t *src, int len)
+{
+       for (int i = 0; i < len; i++)
+               dst[i] = src[i];
+}
+
+
+/* this function is assumes that fifo_size is multiple of flash_word_size
+ * this condition is ensured by target_run_flash_async_algorithm
+ *
+ * IMPORTANT:
+ * when updating this loader and re-compiling it, the stack arguments could be 
placed
+ * at a different offset from sp register.
+ * according the AAPCS, only the 4 32-bit first arguments are passed in the 
registers r0 to r4
+ * the arguments starting from number 5 is passed in the stack.
+ * to make it work, you need to:
+ *   - check the generated listing 'stm32l4x.lst
+ *   - get the highest offset used with sp:
+ *     example: ldr    r3, [sp, #48]
+ *   - change the size of 'write_algorithm_sp' working_area to this value + 4
+ */
+
+#ifndef DEBUG
+__attribute__((naked))
+#endif
+void write(volatile struct work_area *work_area,
+                  uint8_t *fifo_end,
+                  uint8_t *target_address,
+                  uint32_t count,
+                  volatile uint32_t *flash_sr,
+                  volatile uint32_t *flash_cr,
+                  uint32_t flash_word_size)
+{
+       uint8_t *rp_cache  = work_area->rp; /* optimization to avoid reading 
from memory each time */
+       uint8_t *fifo_start = rp_cache; /* used to wrap when we reach fifo_end 
*/
+
+       /* enable flash programming */
+       *flash_cr = FLASH_PG;
+
+       while (count) {
+               uint8_t *wp_cache  = work_area->wp; /* optimization to avoid 
reading from memory each time */
+               if (wp_cache == 0)
+                       break; /* aborted by target_run_flash_async_algorithm */
+
+               int32_t fifo_size = wp_cache - rp_cache;
+               if (fifo_size < 0) {
+                       /* consider the linear fifo, we will wrap later */
+                       fifo_size = fifo_end - rp_cache;
+               }
+
+               /* wait for at least a flash word */
+               while (fifo_size >= flash_word_size) { /* same as checking for 
non-zero size */
+                       copy_buffer_u32((uint32_t *)target_address, (uint32_t 
*)rp_cache, flash_word_size / 4);
+
+                       /* update target_address and rp_cache */
+                       target_address += flash_word_size;
+                       rp_cache += flash_word_size;
+
+                       /* wait for the busy flag */
+                       while (*flash_sr & FLASH_BSY)
+                               ;
+
+                       if (*flash_sr & FLASH_ERROR) {
+                               work_area->rp = 0; /* set rp to zero 0 on error 
*/
+                               break;
+                       }
+
+                       /* wrap if reach the fifo_end, and update rp in memory 
*/
+                       if (rp_cache >= fifo_end)
+                               rp_cache = fifo_start;
+
+                       /* flush the rp cache value,
+                        * so target_run_flash_async_algorithm can fill the 
circular fifo */
+                       work_area->rp = rp_cache;
+
+                       /* update fifo_size and count */
+                       fifo_size -= flash_word_size;
+                       count--;
+               }
+       }
+
+       /* disable flash programming */
+       *flash_cr = 0;
+
+       /* soft break the loader */
+       __asm("bkpt 0");
+}
+
+/* by enabling this define 'DEBUG':
+ * the main() function can help help debugging the loader algo
+ * note: the application should be linked into RAM */
+
+/* #define DEBUG */
+
+#ifdef DEBUG
+#define STM32U5
+/* #define SECURE */
+
+#if defined(STM32U5)
+#define FLASH_WORD_SIZE   16
+#else
+#define FLASH_WORD_SIZE   8
+#endif
+
+#if defined(STM32WB) || defined(STM32WL)
+#define FLASH_BASE        0x58004000
+#else
+#define FLASH_BASE        0x40022000
+#endif
+
+#if defined(STM32L5) || defined(STM32U5)
+#ifdef SECURE
+#define FLASH_KEYR_OFFSET 0x0c
+#define FLASH_SR_OFFSET   0x24
+#define FLASH_CR_OFFSET   0x2c
+#else
+#define FLASH_KEYR_OFFSET 0x08
+#define FLASH_SR_OFFSET   0x20
+#define FLASH_CR_OFFSET   0x28
+#endif
+#elif defined(STM32WL_CPU2)
+#define FLASH_KEYR_OFFSET 0x08
+#define FLASH_SR_OFFSET   0x60
+#define FLASH_CR_OFFSET   0x64
+#else
+#define FLASH_KEYR_OFFSET 0x08
+#define FLASH_SR_OFFSET   0x10
+#define FLASH_CR_OFFSET   0x14
+#endif
+
+#define FLASH_KEYR        (uint32_t *)((FLASH_BASE) + (FLASH_KEYR_OFFSET))
+#define FLASH_SR          (uint32_t *)((FLASH_BASE) + (FLASH_SR_OFFSET))
+#define FLASH_CR          (uint32_t *)((FLASH_BASE) + (FLASH_CR_OFFSET))
+
+int main()
+{
+       const int count = 2;
+       uint8_t *target_address = (uint8_t *) 0x8000000; /* flash address, 
should be aligned to FLASH_WORD_SIZE */
+
+       uint32_t work_area[(8 + count * FLASH_WORD_SIZE) / 4]; /* wp, rp, and 
buffer */
+       work_area[0] = (uint32_t) &work_area[2] + count * FLASH_WORD_SIZE; /* 
wp */
+       work_area[1] = (uint32_t) &work_area[2]; /* rp */
+
+       /* unlock the flash */
+       *FLASH_KEYR = KEY1;
+       *FLASH_KEYR = KEY2;
+
+       /* erase sector 0 */
+       *FLASH_CR = FLASH_PER | FLASH_STRT;
+       while (*FLASH_SR & FLASH_BSY)
+               ;
+
+       write((struct work_area *)work_area,
+                 (uint8_t *)(work_area + 0x22),
+                 target_address,
+                 count,
+                 FLASH_SR,
+                 FLASH_CR,
+                 FLASH_WORD_SIZE);
+
+       while (1)
+               ;
+}
+#endif /* DEBUG */
diff --git a/contrib/loaders/flash/stm32/stm32l4x.inc 
b/contrib/loaders/flash/stm32/stm32l4x.inc
index df5c7ed..0d69c05 100644
--- a/contrib/loaders/flash/stm32/stm32l4x.inc
+++ b/contrib/loaders/flash/stm32/stm32l4x.inc
@@ -1,7 +1,9 @@
 /* Autogenerated with ../../../../src/helper/bin2char.sh */
-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,
+0x02,0x91,0x41,0x68,0x0c,0x9d,0x01,0x91,0x01,0x21,0x0b,0x9c,0x00,0x93,0x21,0x60,
+0xa9,0x08,0x03,0x91,0x01,0x99,0x00,0x9b,0x00,0x2b,0x03,0xd1,0x00,0x23,0x0b,0x9a,
+0x13,0x60,0x00,0xbe,0x04,0x68,0x00,0x2c,0xf8,0xd0,0x64,0x1a,0x01,0xd5,0x02,0x9c,
+0x64,0x1a,0xa5,0x42,0xef,0xd8,0x00,0x26,0x03,0xe0,0xb7,0x00,0xcb,0x59,0x01,0x36,
+0xd3,0x51,0x03,0x9b,0xb3,0x42,0xf8,0xdc,0x52,0x19,0x49,0x19,0x0a,0x9b,0x1e,0x68,
+0x80,0x23,0x37,0x00,0x5b,0x02,0x1f,0x40,0x1e,0x42,0xf7,0xd1,0x0a,0x9b,0x1e,0x68,
+0xfa,0x23,0x1e,0x42,0x01,0xd0,0x47,0x60,0xd5,0xe7,0x02,0x9b,0x8b,0x42,0x00,0xd8,
+0x01,0x99,0x00,0x9b,0x41,0x60,0x01,0x3b,0x64,0x1b,0x00,0x93,0xd9,0xe7,
diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
index 01b512b..656282b 100644
--- a/src/flash/nor/stm32l4x.c
+++ b/src/flash/nor/stm32l4x.c
@@ -1311,9 +1311,11 @@ static int stm32l4_write_block(struct flash_bank *bank, 
const uint8_t *buffer,
        struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
        uint32_t buffer_size;
        struct working_area *write_algorithm;
+       struct working_area *write_algorithm_sp;
        struct working_area *source;
        uint32_t address = bank->base + offset;
-       struct reg_param reg_params[6];
+       struct reg_param reg_params[5];
+       struct mem_param mem_params[3];
        struct armv7m_algorithm armv7m_info;
        int retval = ERROR_OK;
 
@@ -1335,16 +1337,27 @@ static int stm32l4_write_block(struct flash_bank *bank, 
const uint8_t *buffer,
                return retval;
        }
 
+       /* write algorithm stack area */
+       if (target_alloc_working_area(target, 48 + 4,  &write_algorithm_sp) != 
ERROR_OK) {
+               LOG_WARNING("no working area for write code stack pointer");
+               target_free_working_area(target, write_algorithm);
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
        /* memory buffer, size *must* be multiple of stm32l4_info->data_width
-        * plus one dword for rp and one for wp */ /* FIXME */
-       buffer_size = target_get_working_area_avail(target) & ~(2 * 
sizeof(uint32_t) - 1);
+        * plus one dword for rp and one for wp */
+       assert(stm32l4_info->data_width % 8 == 0); /* data_width should be 
multiple of dword */
+       buffer_size = target_get_working_area_avail(target) & 
~(stm32l4_info->data_width - 1);
+       buffer_size = buffer_size - stm32l4_info->data_width + 8;
+
        if (buffer_size < 256) {
                LOG_WARNING("large enough working area not available, can't do 
block memory writes");
                target_free_working_area(target, write_algorithm);
+               target_free_working_area(target, write_algorithm_sp);
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-       } else if (buffer_size > 16384) {
-               /* probably won't benefit from more than 16k ... */
-               buffer_size = 16384;
+       } else if (buffer_size > 16392) {
+               /* probably won't benefit from more than 16k + 8 ... */
+               buffer_size = 16392;
        }
 
        if (target_alloc_working_area_try(target, buffer_size, &source) != 
ERROR_OK) {
@@ -1358,19 +1371,35 @@ static int stm32l4_write_block(struct flash_bank *bank, 
const uint8_t *buffer,
        init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* buffer 
start, status (out) */
        init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);    /* buffer end */
        init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);    /* target 
address */
-       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);    /* count 
(double word-64bit) */
-       init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);    /* flash status 
register */
-       init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);    /* flash 
control register */
+       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);    /* count (of 
stm32l4_info->data_width) */
+       init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);    /* write algo 
stack pointer */
+
+       /* check the loader generated assembly to get where the first stack 
argument is stored */
+       uint32_t mem_param_addr = write_algorithm_sp->address + 
write_algorithm_sp->size;
+
+       /* important: loader exceeding arguments in the reversed order */
+       /* flash word_len */
+       mem_param_addr -= 4;
+       init_mem_param(&mem_params[2], mem_param_addr, 4, PARAM_OUT);
+       /* flash control register */
+       mem_param_addr -= 4;
+       init_mem_param(&mem_params[1], mem_param_addr, 4, PARAM_OUT);
+       /* flash status register */
+       mem_param_addr -= 4;
+       init_mem_param(&mem_params[0], mem_param_addr, 4, PARAM_OUT);
 
        buf_set_u32(reg_params[0].value, 0, 32, source->address);
        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);
-       buf_set_u32(reg_params[4].value, 0, 32, 
stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX));
-       buf_set_u32(reg_params[5].value, 0, 32, 
stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX));
+       buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_sp->address);
+
+       buf_set_u32(mem_params[0].value, 0, 32, 
stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX));
+       buf_set_u32(mem_params[1].value, 0, 32, 
stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX));
+       buf_set_u32(mem_params[2].value, 0, 32, stm32l4_info->data_width);
 
        retval = target_run_flash_async_algorithm(target, buffer, count, 
stm32l4_info->data_width,
-                       0, NULL,
+                       ARRAY_SIZE(mem_params), mem_params,
                        ARRAY_SIZE(reg_params), reg_params,
                        source->address, source->size,
                        write_algorithm->address, 0,
@@ -1379,7 +1408,9 @@ static int stm32l4_write_block(struct flash_bank *bank, 
const uint8_t *buffer,
        if (retval == ERROR_FLASH_OPERATION_FAILED) {
                LOG_ERROR("error executing stm32l4 flash write algorithm");
 
-               uint32_t error = buf_get_u32(reg_params[0].value, 0, 32) & 
FLASH_ERROR;
+               uint32_t error;
+               stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX, 
&error);
+               error &= FLASH_ERROR;
 
                if (error & FLASH_WRPERR)
                        LOG_ERROR("flash memory write protected");
@@ -1393,6 +1424,7 @@ static int stm32l4_write_block(struct flash_bank *bank, 
const uint8_t *buffer,
        }
 
        target_free_working_area(target, source);
+       target_free_working_area(target, write_algorithm_sp);
        target_free_working_area(target, write_algorithm);
 
        destroy_reg_param(&reg_params[0]);
@@ -1400,7 +1432,10 @@ static int stm32l4_write_block(struct flash_bank *bank, 
const uint8_t *buffer,
        destroy_reg_param(&reg_params[2]);
        destroy_reg_param(&reg_params[3]);
        destroy_reg_param(&reg_params[4]);
-       destroy_reg_param(&reg_params[5]);
+
+       destroy_mem_param(&mem_params[0]);
+       destroy_mem_param(&mem_params[1]);
+       destroy_mem_param(&mem_params[2]);
 
        return retval;
 }
@@ -1537,12 +1572,6 @@ static int stm32l4_write(struct flash_bank *bank, const 
uint8_t *buffer,
                 */
                LOG_INFO("Couldn't use the flash loader in dual-bank mode");
                use_loader = false;
-       } else if (stm32l4_info->part_info->id == 0x482) {
-               /**
-                * FIXME for STM32U5 device we get this error and random pointer
-                * Error: corrupted fifo read pointer 0x200006ec
-                */
-               use_loader = false;
        }
 
        if (use_loader)

-- 


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

Reply via email to