jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / contrib / loaders / flash / msp432 / main_msp432e4x.c
1 // SPDX-License-Identifier: BSD-3-Clause
2
3 /******************************************************************************
4 *
5 * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
6 *
7 ******************************************************************************/
8
9 #include <stdint.h>
10 #include <stdbool.h>
11 #include "driverlib.h"
12
13 #include "MSP432E4_FlashLibIf.h"
14
15 /* Local prototypes */
16 void msp432_flash_init(void);
17 void msp432_flash_mass_erase(void);
18 void msp432_flash_sector_erase(void);
19 void msp432_flash_write(void);
20 void msp432_flash_continous_write(void);
21 void msp432_flash_exit(void);
22
23 int main(void)
24 {
25 /* Disable interrupts */
26 __asm(" cpsid i");
27
28 /* Halt watchdog */
29 SYSCTL->RCGCWD &= ~(SYSCTL_RCGCWD_R1 + SYSCTL_RCGCWD_R0);
30
31 while (1) {
32 switch (FLASH_LOADER->FLASH_FUNCTION) {
33 case FLASH_INIT:
34 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
35 msp432_flash_init();
36 FLASH_LOADER->FLASH_FUNCTION = 0;
37 break;
38 case FLASH_MASS_ERASE:
39 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
40 msp432_flash_mass_erase();
41 FLASH_LOADER->FLASH_FUNCTION = 0;
42 break;
43 case FLASH_SECTOR_ERASE:
44 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
45 msp432_flash_sector_erase();
46 FLASH_LOADER->FLASH_FUNCTION = 0;
47 break;
48 case FLASH_PROGRAM:
49 case FLASH_CONTINUOUS_PROGRAM:
50 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
51 msp432_flash_continous_write();
52 FLASH_LOADER->FLASH_FUNCTION = 0;
53 break;
54 case FLASH_EXIT:
55 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
56 msp432_flash_exit();
57 FLASH_LOADER->FLASH_FUNCTION = 0;
58 break;
59 case FLASH_NO_COMMAND:
60 break;
61 default:
62 FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
63 break;
64 }
65 }
66 }
67
68 /* Initialize flash */
69 void msp432_flash_init(void)
70 {
71 SCB->VTOR = 0x20000000;
72 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
73 }
74
75 /* Erase entire flash */
76 void msp432_flash_mass_erase(void)
77 {
78 bool success = false;
79
80 /* Clear the flash access and error interrupts. */
81 FLASH_CTRL->FCMISC = (FLASH_FCMISC_AMISC | FLASH_FCMISC_VOLTMISC |
82 FLASH_FCMISC_ERMISC | FLASH_FCMISC_PMISC);
83
84 /* Trigger mass erase */
85 FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_MERASE;
86 while (FLASH_CTRL->FMC & FLASH_FMC_MERASE)
87 ;
88
89 /* Return an error if an access violation occurred. */
90 success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS | FLASH_FCRIS_VOLTRIS |
91 FLASH_FCRIS_ERRIS));
92 if (!success)
93 FLASH_LOADER->RETURN_CODE = FLASH_VERIFY_ERROR;
94 else
95 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
96 }
97
98 /* Erase one flash sector */
99 void msp432_flash_sector_erase(void)
100 {
101 bool success = false;
102
103 /* Clear the flash access and error interrupts. */
104 FLASH_CTRL->FCMISC = (FLASH_FCMISC_AMISC | FLASH_FCMISC_VOLTMISC |
105 FLASH_FCMISC_ERMISC | FLASH_FCMISC_PMISC);
106
107 /* Set 16kB aligned flash page address to be erased (16kB block) */
108 FLASH_CTRL->FMA = FLASH_LOADER->DST_ADDRESS;
109 /* Trigger sector erase (erase flash page) */
110 FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_ERASE;
111 while (FLASH_CTRL->FMC & FLASH_FMC_ERASE)
112 ;
113
114 /* Return an error if an access violation occurred. */
115 success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS | FLASH_FCRIS_VOLTRIS |
116 FLASH_FCRIS_ERRIS));
117
118 if (!success)
119 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
120 else
121 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
122 }
123
124 /* Write data to flash */
125 void msp432_flash_continous_write(void)
126 {
127 bool buffer1_in_use = false;
128 bool buffer2_in_use = false;
129 uint32_t *src_address = NULL;
130 bool success = true;
131 uint32_t i = 0;
132 uint32_t address = FLASH_LOADER->DST_ADDRESS;
133 uint32_t data_to_write = FLASH_LOADER->SRC_LENGTH;
134 int32_t write_package = 0;
135
136 /* Clear the flash access and error interrupts. */
137 FLASH_CTRL->FCMISC = (FLASH_FCMISC_AMISC | FLASH_FCMISC_VOLTMISC |
138 FLASH_FCMISC_INVDMISC | FLASH_FCMISC_PROGMISC | FLASH_FCMISC_PMISC);
139 do {
140 if (data_to_write > SRC_LENGTH_MAX) {
141 write_package = SRC_LENGTH_MAX;
142 data_to_write -= write_package;
143 } else {
144 write_package = data_to_write;
145 data_to_write -= write_package;
146 }
147 while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) &&
148 !(FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY))
149 ;
150
151 if (FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) {
152 FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE;
153 src_address = (uint32_t *) RAM_LOADER_BUFFER1;
154 buffer1_in_use = true;
155 } else if (FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY) {
156 FLASH_LOADER->BUFFER2_STATUS_REGISTER |= BUFFER_ACTIVE;
157 src_address = (uint32_t *) RAM_LOADER_BUFFER2;
158 buffer2_in_use = true;
159 }
160
161 /*
162 * The flash hardware can only write complete words to flash. If
163 * an unaligned address is passed in, we must do a read-modify-write
164 * on a word with enough bytes to align the rest of the buffer. And
165 * if less than a whole word remains at the end, we must also do a
166 * read-modify-write on a final word to finish up.
167 */
168 if (0 != (address & 0x3)) {
169 uint32_t head;
170 uint8_t *ui8head = (uint8_t *)&head;
171 uint8_t *buffer = (uint8_t *)src_address;
172
173 /* Get starting offset for data to write (will be 1 to 3) */
174 uint32_t head_offset = address & 0x03;
175
176 /* Get the aligned address to write this first word to */
177 uint32_t head_address = address & 0xfffffffc;
178
179 /* Retrieve what is already in flash at the head address */
180 head = *(uint32_t *)head_address;
181
182 /* Substitute in the new data to write */
183 while ((write_package > 0) && (head_offset < 4)) {
184 ui8head[head_offset] = *buffer;
185 head_offset++;
186 address++;
187 buffer++;
188 write_package--;
189 }
190 src_address = (uint32_t *)buffer;
191
192 FLASH_CTRL->FMD = head;
193 FLASH_CTRL->FMA = head_address;
194 FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_WRITE;
195
196 /* Wait until the word has been programmed. */
197 while (FLASH_CTRL->FMC & FLASH_FMC_WRITE)
198 ;
199
200 /* Return an error if an access violation occurred. */
201 success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS |
202 FLASH_FCRIS_ERIS | FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS));
203 }
204
205 /* Program a word at a time until aligned on 32-word boundary */
206 while ((write_package >= 4) && ((address & 0x7f) != 0) && success) {
207 FLASH_CTRL->FMD = *src_address++;
208 FLASH_CTRL->FMA = address;
209 FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_WRITE;
210
211 /* Wait until the word has been programmed. */
212 while (FLASH_CTRL->FMC & FLASH_FMC_WRITE)
213 ;
214
215 /* Prepare for next word to write */
216 write_package -= 4;
217 address += 4;
218
219 /* Return an error if an access violation occurred. */
220 success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS |
221 FLASH_FCRIS_ERIS | FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS));
222 }
223
224 /* Program data in 32-word blocks */
225 while ((write_package >= 32) && success) {
226 /* Loop over the words in this 32-word block. */
227 i = 0;
228 do {
229 FLASH_CTRL->FWBN[i] = *src_address++;
230 write_package -= 4;
231 i++;
232 } while ((write_package > 0) && (i < 32));
233 FLASH_CTRL->FMA = address;
234 FLASH_CTRL->FMC2 = FLASH_FMC_WRKEY | FLASH_FMC2_WRBUF;
235
236 /* Wait until the write buffer has been programmed. */
237 while (FLASH_CTRL->FMC2 & FLASH_FMC2_WRBUF)
238 ;
239
240 /* Increment destination address by words written */
241 address += 128;
242
243 /* Return an error if an access violation occurred. */
244 success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS |
245 FLASH_FCRIS_ERIS | FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS));
246 }
247
248 /* Program a word at a time on left over data */
249 while ((write_package >= 4) && success) {
250 FLASH_CTRL->FMD = *src_address++;
251 FLASH_CTRL->FMA = address;
252 FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_WRITE;
253
254 /* Wait until the word has been programmed. */
255 while (FLASH_CTRL->FMC & FLASH_FMC_WRITE)
256 ;
257
258 /* Prepare for next word to write */
259 write_package -= 4;
260 address += 4;
261
262 /* Return an error if an access violation occurred. */
263 success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS |
264 FLASH_FCRIS_ERIS | FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS));
265 }
266
267 if ((write_package > 0) && success) {
268 uint32_t tail;
269 uint8_t *ui8tail = (uint8_t *)&tail;
270 uint8_t *buffer = (uint8_t *)src_address;
271
272 /* Set starting offset for data to write */
273 uint32_t tail_offset = 0;
274
275 /* Get the address to write this last word to */
276 uint32_t tail_address = address;
277
278 /* Retrieve what is already in flash at the tail address */
279 tail = *(uint32_t *)address;
280
281 /* Substitute in the new data to write */
282 while (write_package > 0) {
283 ui8tail[tail_offset] = *buffer;
284 tail_offset++;
285 address++;
286 buffer++;
287 write_package--;
288 }
289
290 FLASH_CTRL->FMD = tail;
291 FLASH_CTRL->FMA = tail_address;
292 FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_WRITE;
293
294 /* Wait until the word has been programmed. */
295 while (FLASH_CTRL->FMC & FLASH_FMC_WRITE)
296 ;
297
298 /* Return an error if an access violation occurred. */
299 success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS |
300 FLASH_FCRIS_ERIS | FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS));
301 }
302
303 if (buffer1_in_use) {
304 FLASH_LOADER->BUFFER1_STATUS_REGISTER &=
305 ~(BUFFER_ACTIVE | BUFFER_DATA_READY);
306 buffer1_in_use = false;
307 } else if (buffer2_in_use) {
308 FLASH_LOADER->BUFFER2_STATUS_REGISTER &=
309 ~(BUFFER_ACTIVE | BUFFER_DATA_READY);
310 buffer2_in_use = false;
311 }
312 } while (success && data_to_write);
313
314 if (!success)
315 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
316 else
317 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
318 }
319
320 /* Exit flash programming */
321 void msp432_flash_exit(void)
322 {
323 SCB->VTOR = 0x00000000;
324 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
325 }

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)