openocd: fix SPDX tag format for files .c
[openocd.git] / contrib / loaders / flash / stm32 / stm32l4x.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /**
4 * Copyright (C) 2021 Tarek BOCHKATI
5 * tarek.bouchkati@st.com
6 */
7
8 #define OPENOCD_CONTRIB_LOADERS_FLASH_STM32_STM32L4X
9
10 #include <stdint.h>
11 #include "../../../../src/flash/nor/stm32l4x.h"
12
13 static inline __attribute__((always_inline))
14 void copy_buffer_u32(uint32_t *dst, uint32_t *src, int len)
15 {
16 for (int i = 0; i < len; i++)
17 dst[i] = src[i];
18 }
19
20 /* this function is assumes that fifo_size is multiple of flash_word_size
21 * this condition is ensured by target_run_flash_async_algorithm
22 */
23
24 void write(volatile struct stm32l4_work_area *work_area,
25 uint8_t *fifo_end,
26 uint8_t *target_address,
27 uint32_t count)
28 {
29 volatile uint32_t *flash_sr = (uint32_t *) work_area->params.flash_sr_addr;
30 volatile uint32_t *flash_cr = (uint32_t *) work_area->params.flash_cr_addr;
31
32 /* optimization to avoid reading from memory each time */
33 uint8_t *rp_cache = work_area->fifo.rp;
34
35 /* fifo_start is used to wrap when we reach fifo_end */
36 uint8_t *fifo_start = rp_cache;
37
38 /* enable flash programming */
39 *flash_cr = FLASH_PG;
40
41 while (count) {
42 /* optimization to avoid reading from memory each time */
43 uint8_t *wp_cache = work_area->fifo.wp;
44 if (wp_cache == 0)
45 break; /* aborted by target_run_flash_async_algorithm */
46
47 int32_t fifo_size = wp_cache - rp_cache;
48 if (fifo_size < 0) {
49 /* consider the linear fifo, we will wrap later */
50 fifo_size = fifo_end - rp_cache;
51 }
52
53 /* wait for at least a flash word */
54 while (fifo_size >= work_area->params.flash_word_size) {
55 copy_buffer_u32((uint32_t *)target_address,
56 (uint32_t *)rp_cache,
57 work_area->params.flash_word_size / 4);
58
59 /* update target_address and rp_cache */
60 target_address += work_area->params.flash_word_size;
61 rp_cache += work_area->params.flash_word_size;
62
63 /* wait for the busy flag */
64 while (*flash_sr & work_area->params.flash_sr_bsy_mask)
65 ;
66
67 if (*flash_sr & FLASH_ERROR) {
68 work_area->fifo.rp = 0; /* set rp to zero 0 on error */
69 goto write_end;
70 }
71
72 /* wrap if reach the fifo_end, and update rp in memory */
73 if (rp_cache >= fifo_end)
74 rp_cache = fifo_start;
75
76 /* flush the rp cache value,
77 * so target_run_flash_async_algorithm can fill the circular fifo */
78 work_area->fifo.rp = rp_cache;
79
80 /* update fifo_size and count */
81 fifo_size -= work_area->params.flash_word_size;
82 count--;
83 }
84 }
85
86 write_end:
87 /* disable flash programming */
88 *flash_cr = 0;
89
90 /* soft break the loader */
91 __asm("bkpt 0");
92 }
93
94 /* by enabling this define 'DEBUG':
95 * the main() function can help help debugging the loader algo
96 * note: the application should be linked into RAM */
97
98 /* #define DEBUG */
99
100 #ifdef DEBUG
101 /* device selector: STM32L5 | STM32U5 | STM32WB | STM32WL | STM32WL_CPU2 | STM32G0Bx | ... */
102 #define STM32U5
103
104 /* when using a secure device, and want to test the secure programming enable this define */
105 /* #define SECURE */
106
107 #if defined(STM32U5)
108 # define FLASH_WORD_SIZE 16
109 #else
110 # define FLASH_WORD_SIZE 8
111 #endif
112
113 #if defined(STM32WB) || defined(STM32WL)
114 # define FLASH_BASE 0x58004000
115 #else
116 # define FLASH_BASE 0x40022000
117 #endif
118
119 #if defined(STM32G0Bx)
120 # define FLASH_BSY_MASK (FLASH_BSY | FLASH_BSY2)
121 #else
122 # define FLASH_BSY_MASK FLASH_BSY
123 #endif
124
125 #if defined(STM32L5) || defined(STM32U5)
126 # ifdef SECURE
127 # define FLASH_KEYR_OFFSET 0x0c
128 # define FLASH_SR_OFFSET 0x24
129 # define FLASH_CR_OFFSET 0x2c
130 # else
131 # define FLASH_KEYR_OFFSET 0x08
132 # define FLASH_SR_OFFSET 0x20
133 # define FLASH_CR_OFFSET 0x28
134 # endif
135 #elif defined(STM32WL_CPU2)
136 # define FLASH_KEYR_OFFSET 0x08
137 # define FLASH_SR_OFFSET 0x60
138 # define FLASH_CR_OFFSET 0x64
139 #else
140 # define FLASH_KEYR_OFFSET 0x08
141 # define FLASH_SR_OFFSET 0x10
142 # define FLASH_CR_OFFSET 0x14
143 #endif
144
145 #define FLASH_KEYR (uint32_t *)((FLASH_BASE) + (FLASH_KEYR_OFFSET))
146 #define FLASH_SR (uint32_t *)((FLASH_BASE) + (FLASH_SR_OFFSET))
147 #define FLASH_CR (uint32_t *)((FLASH_BASE) + (FLASH_CR_OFFSET))
148
149 int main()
150 {
151 const uint32_t count = 2;
152 const uint32_t buf_size = count * FLASH_WORD_SIZE;
153 const uint32_t work_area_size = sizeof(struct stm32l4_work_area) + buf_size;
154
155 uint8_t work_area_buf[work_area_size];
156 struct stm32l4_work_area *workarea = (struct stm32l4_work_area *)work_area_buf;
157
158 /* fill the workarea struct */
159 workarea->params.flash_sr_addr = (uint32_t)(FLASH_SR);
160 workarea->params.flash_cr_addr = (uint32_t)(FLASH_CR);
161 workarea->params.flash_word_size = FLASH_WORD_SIZE;
162 workarea->params.flash_sr_bsy_mask = FLASH_BSY_MASK;
163 /* note: the workarea->stack is not used, in this configuration */
164
165 /* programming the existing memory raw content in workarea->fifo.buf */
166 /* feel free to fill the memory with magical values ... */
167
168 workarea->fifo.wp = (uint8_t *)(&workarea->fifo.buf + buf_size);
169 workarea->fifo.rp = (uint8_t *)&workarea->fifo.buf;
170
171 /* unlock the flash */
172 *FLASH_KEYR = KEY1;
173 *FLASH_KEYR = KEY2;
174
175 /* erase sector 0 */
176 *FLASH_CR = FLASH_PER | FLASH_STRT;
177 while (*FLASH_SR & FLASH_BSY)
178 ;
179
180 /* flash address, should be aligned to FLASH_WORD_SIZE */
181 uint8_t *target_address = (uint8_t *) 0x8000000;
182
183 write(workarea,
184 (uint8_t *)(workarea + work_area_size),
185 target_address,
186 count);
187
188 while (1)
189 ;
190 }
191 #endif /* DEBUG */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)