flash/nor: add support for TI MSP432 devices
[openocd.git] / contrib / loaders / flash / msp432 / main_msp432p411x.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * Neither the name of Texas Instruments Incorporated nor the names of
18 * its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 ******************************************************************************/
34
35 #include <stdint.h>
36 #include <stdbool.h>
37 #include "driverlib.h"
38
39 #include "MSP432P4_FlashLibIf.h"
40
41 /* Number of erase repeats until timeout */
42 #define FLASH_MAX_REPEATS 5
43
44 /* Local prototypes */
45 void msp432_flash_init(void);
46 void msp432_flash_mass_erase(void);
47 void msp432_flash_sector_erase(void);
48 void msp432_flash_write(void);
49 void msp432_flash_continous_write(void);
50 void msp432_flash_exit(void);
51 void unlock_flash_sectors(void);
52 void unlock_all_flash_sectors(void);
53 void lock_all_flash_sectors(void);
54 void __cs_set_dco_frequency_range(uint32_t dco_freq);
55 static bool program_device(void *src, void *dest, uint32_t length);
56
57 struct backup_params {
58 uint32_t BANK0_WAIT_RESTORE;
59 uint32_t BANK1_WAIT_RESTORE;
60 uint32_t CS_DC0_FREQ_RESTORE;
61 uint8_t VCORE_LEVEL_RESTORE;
62 uint8_t PCM_VCORE_LEVEL_RESTORE;
63 };
64
65 #define BACKUP_PARAMS ((struct backup_params *) 0x20000180)
66 #define INFO_FLASH_START __INFO_FLASH_A_TECH_START__
67 #define INFO_FLASH_MIDDLE __INFO_FLASH_A_TECH_MIDDLE__
68 #define BSL_FLASH_START BSL_API_TABLE_ADDR
69
70 /* Main with trampoline */
71 int main(void)
72 {
73 /* Halt watchdog */
74 MAP_WDT_A_HOLD_TIMER();
75
76 /* Disable interrupts */
77 cpu_cpsid();
78
79 while (1) {
80 switch (FLASH_LOADER->FLASH_FUNCTION) {
81 case FLASH_INIT:
82 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
83 msp432_flash_init();
84 FLASH_LOADER->FLASH_FUNCTION = 0;
85 break;
86 case FLASH_MASS_ERASE:
87 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
88 msp432_flash_mass_erase();
89 FLASH_LOADER->FLASH_FUNCTION = 0;
90 break;
91 case FLASH_SECTOR_ERASE:
92 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
93 msp432_flash_sector_erase();
94 FLASH_LOADER->FLASH_FUNCTION = 0;
95 break;
96 case FLASH_PROGRAM:
97 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
98 msp432_flash_write();
99 FLASH_LOADER->FLASH_FUNCTION = 0;
100 break;
101 case FLASH_CONTINUOUS_PROGRAM:
102 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
103 msp432_flash_continous_write();
104 FLASH_LOADER->FLASH_FUNCTION = 0;
105 break;
106 case FLASH_EXIT:
107 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
108 msp432_flash_exit();
109 FLASH_LOADER->FLASH_FUNCTION = 0;
110 break;
111 case FLASH_NO_COMMAND:
112 break;
113 default:
114 FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
115 break;
116 }
117 }
118 }
119
120 /* Initialize flash */
121 void msp432_flash_init(void)
122 {
123 bool success = false;
124
125 /* Point to vector table in RAM */
126 SCB->VTOR = (uint32_t)0x01000000;
127
128 /* backup system parameters */
129 BACKUP_PARAMS->BANK0_WAIT_RESTORE =
130 MAP_FLASH_CTL_A_GET_WAIT_STATE(FLASH_A_BANK0);
131 BACKUP_PARAMS->BANK1_WAIT_RESTORE =
132 MAP_FLASH_CTL_A_GET_WAIT_STATE(FLASH_A_BANK1);
133 BACKUP_PARAMS->VCORE_LEVEL_RESTORE = MAP_PCM_GET_CORE_VOLTAGE_LEVEL();
134 BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE = MAP_PCM_GET_POWER_STATE();
135 BACKUP_PARAMS->CS_DC0_FREQ_RESTORE = CS->CTL0 & CS_CTL0_DCORSEL_MASK;
136
137 /* set parameters for flashing */
138 success = MAP_PCM_SET_POWER_STATE(PCM_AM_LDO_VCORE0);
139
140 /* Set Flash wait states to 2 */
141 MAP_FLASH_CTL_A_SET_WAIT_STATE(FLASH_A_BANK0, 2);
142 MAP_FLASH_CTL_A_SET_WAIT_STATE(FLASH_A_BANK1, 2);
143
144 /* Set CPU speed to 24MHz */
145 __cs_set_dco_frequency_range(CS_DCO_FREQUENCY_24);
146
147 if (!success) {
148 /* Indicate failed power switch */
149 FLASH_LOADER->RETURN_CODE = FLASH_POWER_ERROR;
150 } else
151 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
152 }
153
154 /* Erase entire flash */
155 void msp432_flash_mass_erase(void)
156 {
157 bool success = false;
158
159 /* Allow flash writes */
160 unlock_flash_sectors();
161
162 /* Allow some mass erase repeats before timeout with error */
163 int erase_repeats = FLASH_MAX_REPEATS;
164 while (!success && (erase_repeats > 0)) {
165 /* Mass erase with post-verify */
166 success = ROM_FLASH_CTL_A_PERFORM_MASS_ERASE();
167 erase_repeats--;
168 }
169
170 if (erase_repeats == 0)
171 FLASH_LOADER->RETURN_CODE = FLASH_VERIFY_ERROR;
172 else
173 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
174
175 /* Block flash writes */
176 lock_all_flash_sectors();
177 }
178
179 /* Erase one flash sector */
180 void msp432_flash_sector_erase(void)
181 {
182 bool success = false;
183
184 /* Allow flash writes */
185 unlock_all_flash_sectors();
186
187 /* Allow some sector erase repeats before timeout with error */
188 int erase_repeats = FLASH_MAX_REPEATS;
189 while (!success && (erase_repeats > 0)) {
190 /* Sector erase with post-verify */
191 success = MAP_FLASH_CTL_A_ERASE_SECTOR(FLASH_LOADER->DST_ADDRESS);
192 erase_repeats--;
193 }
194
195 if (erase_repeats == 0)
196 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
197 else
198 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
199
200 /* Block flash writes */
201 lock_all_flash_sectors();
202 }
203
204 /* Write data to flash with the help of DriverLib */
205 void msp432_flash_write(void)
206 {
207 bool success = false;
208
209 /* Allow flash writes */
210 unlock_all_flash_sectors();
211
212 while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY))
213 ;
214
215 FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE;
216
217 /* Program memory */
218 success = program_device((uint32_t *)RAM_LOADER_BUFFER1,
219 (void *)FLASH_LOADER->DST_ADDRESS, FLASH_LOADER->SRC_LENGTH);
220
221 FLASH_LOADER->BUFFER1_STATUS_REGISTER &=
222 ~(BUFFER_ACTIVE | BUFFER_DATA_READY);
223
224 /* Block flash writes */
225 lock_all_flash_sectors();
226
227 if (!success)
228 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
229 else
230 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
231 }
232
233 /* Write data to flash with the help of DriverLib with auto-increment */
234 void msp432_flash_continous_write(void)
235 {
236 bool buffer1_in_use = false;
237 bool buffer2_in_use = false;
238 uint32_t *src_address = NULL;
239 bool success = false;
240
241 uint32_t bytes_to_write = FLASH_LOADER->SRC_LENGTH;
242 uint32_t write_package = 0;
243 uint32_t start_addr = FLASH_LOADER->DST_ADDRESS;
244
245 while (bytes_to_write > 0) {
246 if (bytes_to_write > SRC_LENGTH_MAX) {
247 write_package = SRC_LENGTH_MAX;
248 bytes_to_write -= write_package;
249 } else {
250 write_package = bytes_to_write;
251 bytes_to_write -= write_package;
252 }
253 unlock_all_flash_sectors();
254 while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) &&
255 !(FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY))
256 ;
257
258 if (FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) {
259 FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE;
260 src_address = (uint32_t *) RAM_LOADER_BUFFER1;
261 buffer1_in_use = true;
262 } else if (FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY) {
263 FLASH_LOADER->BUFFER2_STATUS_REGISTER |= BUFFER_ACTIVE;
264 src_address = (uint32_t *) RAM_LOADER_BUFFER2;
265 buffer2_in_use = true;
266 }
267 if (buffer1_in_use || buffer2_in_use) {
268 success = program_device(src_address, (void *) start_addr, write_package);
269 start_addr += write_package;
270 }
271 if (buffer1_in_use) {
272 FLASH_LOADER->BUFFER1_STATUS_REGISTER &= ~(BUFFER_ACTIVE | BUFFER_DATA_READY);
273 buffer1_in_use = false;
274 } else if (buffer2_in_use) {
275 FLASH_LOADER->BUFFER2_STATUS_REGISTER &= ~(BUFFER_ACTIVE | BUFFER_DATA_READY);
276 buffer2_in_use = false;
277 }
278 /* Block flash writes */
279 lock_all_flash_sectors();
280
281 if (!success) {
282 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
283 break;
284 }
285 }
286 if (success)
287 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
288 }
289
290 /* Unlock Main/Info Flash sectors */
291 void unlock_flash_sectors(void)
292 {
293 if (FLASH_LOADER->ERASE_PARAM & ERASE_MAIN)
294 MAP_FLASH_CTL_A_UNPROTECT_MEMORY(FLASH_BASE, FLASH_BASE +
295 MAP_SYS_CTL_A_GET_FLASH_SIZE() - 1);
296
297 if (FLASH_LOADER->ERASE_PARAM & ERASE_INFO) {
298 MAP_FLASH_CTL_A_UNPROTECT_MEMORY(INFO_FLASH_START, TLV_BASE - 1);
299 if (FLASH_LOADER->UNLOCK_BSL == UNLOCK_BSL_KEY)
300 MAP_FLASH_CTL_A_UNPROTECT_MEMORY(BSL_FLASH_START,
301 INFO_FLASH_MIDDLE - 1);
302 MAP_FLASH_CTL_A_UNPROTECT_MEMORY(INFO_FLASH_MIDDLE, INFO_FLASH_MIDDLE +
303 MAP_SYS_CTL_A_GET_INFO_FLASH_SIZE() - 1);
304 }
305 }
306
307 /* Unlock All Flash sectors */
308 void unlock_all_flash_sectors(void)
309 {
310 MAP_FLASH_CTL_A_UNPROTECT_MEMORY(FLASH_BASE, FLASH_BASE +
311 MAP_SYS_CTL_A_GET_FLASH_SIZE() - 1);
312 MAP_FLASH_CTL_A_UNPROTECT_MEMORY(INFO_FLASH_START, TLV_BASE - 1);
313 if (FLASH_LOADER->UNLOCK_BSL == UNLOCK_BSL_KEY)
314 MAP_FLASH_CTL_A_UNPROTECT_MEMORY(BSL_FLASH_START,
315 INFO_FLASH_MIDDLE - 1);
316 MAP_FLASH_CTL_A_UNPROTECT_MEMORY(INFO_FLASH_MIDDLE, INFO_FLASH_MIDDLE +
317 MAP_SYS_CTL_A_GET_INFO_FLASH_SIZE() - 1);
318 }
319
320 /* Lock all Flash sectors */
321 void lock_all_flash_sectors(void)
322 {
323 MAP_FLASH_CTL_A_PROTECT_MEMORY(FLASH_BASE, FLASH_BASE +
324 MAP_SYS_CTL_A_GET_FLASH_SIZE() - 1);
325 MAP_FLASH_CTL_A_PROTECT_MEMORY(INFO_FLASH_START, INFO_FLASH_START +
326 MAP_SYS_CTL_A_GET_INFO_FLASH_SIZE() - 1);
327 }
328
329 /* Force DCO frequency range */
330 void __cs_set_dco_frequency_range(uint32_t dco_freq)
331 {
332 /* Unlocking the CS Module */
333 CS->KEY = CS_KEY_VAL;
334
335 /* Resetting Tuning Parameters and Setting the frequency */
336 CS->CTL0 = (CS->CTL0 & ~CS_CTL0_DCORSEL_MASK) | dco_freq;
337
338 /* Locking the CS Module */
339 CS->KEY = 0;
340 }
341
342 /* Exit flash programming */
343 void msp432_flash_exit(void)
344 {
345 bool success = false;
346
347 /* Restore modified registers, in reverse order */
348 __cs_set_dco_frequency_range(CS_DCO_FREQUENCY_3);
349
350 MAP_FLASH_CTL_A_SET_WAIT_STATE(FLASH_A_BANK0,
351 BACKUP_PARAMS->BANK0_WAIT_RESTORE);
352 MAP_FLASH_CTL_A_SET_WAIT_STATE(FLASH_A_BANK1,
353 BACKUP_PARAMS->BANK1_WAIT_RESTORE);
354
355 success = MAP_PCM_SET_POWER_STATE(BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE);
356
357 success &= MAP_PCM_SET_CORE_VOLTAGE_LEVEL(
358 BACKUP_PARAMS->VCORE_LEVEL_RESTORE);
359
360 __cs_set_dco_frequency_range(BACKUP_PARAMS->CS_DC0_FREQ_RESTORE);
361
362 /* Point to vector table in Flash */
363 SCB->VTOR = (uint32_t)0x00000000;
364
365 if (!success)
366 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
367 else
368 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
369 }
370
371 static bool program_device(void *src, void *dest, uint32_t length)
372 {
373 uint32_t dst_address = (uint32_t)dest;
374
375 /* Flash main memory first, then information memory */
376 if ((dst_address < INFO_FLASH_START) && ((dst_address + length) >
377 INFO_FLASH_START)) {
378 uint32_t block_length = INFO_FLASH_START - dst_address;
379 uint32_t src_address = (uint32_t)src;
380 /* Main memory block */
381 bool success = MAP_FLASH_CTL_A_PROGRAM_MEMORY(src, dest, block_length);
382
383 src_address = src_address + block_length;
384 block_length = length - block_length;
385 /* Information memory block */
386 success &= MAP_FLASH_CTL_A_PROGRAM_MEMORY((void *)src_address,
387 (void *)INFO_FLASH_START, block_length);
388 return success;
389 } else
390 return MAP_FLASH_CTL_A_PROGRAM_MEMORY(src, dest, length);
391 }

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)