flash/nor: add support for TI MSP432 devices
[openocd.git] / contrib / loaders / flash / msp432 / main_msp432p401x.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
67 /* Main with trampoline */
68 int main(void)
69 {
70 /* Halt watchdog */
71 MAP_WDT_A_HOLD_TIMER();
72
73 /* Disable interrupts */
74 cpu_cpsid();
75
76 while (1) {
77 switch (FLASH_LOADER->FLASH_FUNCTION) {
78 case FLASH_INIT:
79 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
80 msp432_flash_init();
81 FLASH_LOADER->FLASH_FUNCTION = 0;
82 break;
83 case FLASH_MASS_ERASE:
84 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
85 msp432_flash_mass_erase();
86 FLASH_LOADER->FLASH_FUNCTION = 0;
87 break;
88 case FLASH_SECTOR_ERASE:
89 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
90 msp432_flash_sector_erase();
91 FLASH_LOADER->FLASH_FUNCTION = 0;
92 break;
93 case FLASH_PROGRAM:
94 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
95 msp432_flash_write();
96 FLASH_LOADER->FLASH_FUNCTION = 0;
97 break;
98 case FLASH_CONTINUOUS_PROGRAM:
99 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
100 msp432_flash_continous_write();
101 FLASH_LOADER->FLASH_FUNCTION = 0;
102 break;
103 case FLASH_EXIT:
104 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
105 msp432_flash_exit();
106 FLASH_LOADER->FLASH_FUNCTION = 0;
107 break;
108 case FLASH_NO_COMMAND:
109 break;
110 default:
111 FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
112 break;
113 }
114 }
115 }
116
117 /* Initialize flash */
118 void msp432_flash_init(void)
119 {
120 bool success = false;
121
122 /* Point to vector table in RAM */
123 SCB->VTOR = (uint32_t)0x01000000;
124
125 /* backup system parameters */
126 BACKUP_PARAMS->BANK0_WAIT_RESTORE =
127 MAP_FLASH_CTL_GET_WAIT_STATE(FLASH_BANK0);
128 BACKUP_PARAMS->BANK1_WAIT_RESTORE =
129 MAP_FLASH_CTL_GET_WAIT_STATE(FLASH_BANK1);
130 BACKUP_PARAMS->VCORE_LEVEL_RESTORE = MAP_PCM_GET_CORE_VOLTAGE_LEVEL();
131 BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE = MAP_PCM_GET_POWER_STATE();
132 BACKUP_PARAMS->CS_DC0_FREQ_RESTORE = CS->CTL0 & CS_CTL0_DCORSEL_MASK;
133
134 /* set parameters for flashing */
135 success = MAP_PCM_SET_POWER_STATE(PCM_AM_LDO_VCORE0);
136
137 /* Set Flash wait states to 2 */
138 MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK0, 2);
139 MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK1, 2);
140
141 /* Set CPU speed to 24MHz */
142 __cs_set_dco_frequency_range(CS_DCO_FREQUENCY_24);
143
144 if (!success) {
145 /* Indicate failed power switch */
146 FLASH_LOADER->RETURN_CODE = FLASH_POWER_ERROR;
147 } else
148 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
149 }
150
151 /* Erase entire flash */
152 void msp432_flash_mass_erase(void)
153 {
154 bool success = false;
155
156 /* Allow flash writes */
157 unlock_flash_sectors();
158
159 /* Allow some mass erase repeats before timeout with error */
160 int erase_repeats = FLASH_MAX_REPEATS;
161 while (!success && (erase_repeats > 0)) {
162 /* Mass erase with post-verify */
163 success = MAP_FLASH_CTL_PERFORM_MASS_ERASE();
164 erase_repeats--;
165 }
166
167 if (erase_repeats == 0)
168 FLASH_LOADER->RETURN_CODE = FLASH_VERIFY_ERROR;
169 else
170 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
171
172 /* Block flash writes */
173 lock_all_flash_sectors();
174 }
175
176 /* Erase one flash sector */
177 void msp432_flash_sector_erase(void)
178 {
179 bool success = false;
180
181 /* Allow flash writes */
182 unlock_all_flash_sectors();
183
184 /* Allow some sector erase repeats before timeout with error */
185 int erase_repeats = FLASH_MAX_REPEATS;
186 while (!success && (erase_repeats > 0)) {
187 /* Sector erase with post-verify */
188 success = MAP_FLASH_CTL_ERASE_SECTOR(FLASH_LOADER->DST_ADDRESS);
189 erase_repeats--;
190 }
191
192 if (erase_repeats == 0)
193 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
194 else
195 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
196
197 /* Block flash writes */
198 lock_all_flash_sectors();
199 }
200
201 /* Write data to flash with the help of DriverLib */
202 void msp432_flash_write(void)
203 {
204 bool success = false;
205
206 /* Allow flash writes */
207 unlock_all_flash_sectors();
208
209 while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY))
210 ;
211
212 FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE;
213
214 /* Program memory */
215 success = program_device((uint32_t *)RAM_LOADER_BUFFER1,
216 (void *)FLASH_LOADER->DST_ADDRESS, FLASH_LOADER->SRC_LENGTH);
217
218 FLASH_LOADER->BUFFER1_STATUS_REGISTER &=
219 ~(BUFFER_ACTIVE | BUFFER_DATA_READY);
220
221 /* Block flash writes */
222 lock_all_flash_sectors();
223
224 if (!success)
225 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
226 else
227 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
228 }
229
230 /* Write data to flash with the help of DriverLib with auto-increment */
231 void msp432_flash_continous_write(void)
232 {
233 bool buffer1_in_use = false;
234 bool buffer2_in_use = false;
235 uint32_t *src_address = NULL;
236 bool success = false;
237
238 uint32_t bytes_to_write = FLASH_LOADER->SRC_LENGTH;
239 uint32_t write_package = 0;
240 uint32_t start_addr = FLASH_LOADER->DST_ADDRESS;
241
242 while (bytes_to_write > 0) {
243 if (bytes_to_write > SRC_LENGTH_MAX) {
244 write_package = SRC_LENGTH_MAX;
245 bytes_to_write -= write_package;
246 } else {
247 write_package = bytes_to_write;
248 bytes_to_write -= write_package;
249 }
250 unlock_all_flash_sectors();
251
252 while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) &&
253 !(FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY))
254 ;
255
256 if (FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) {
257 FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE;
258 src_address = (uint32_t *)RAM_LOADER_BUFFER1;
259 buffer1_in_use = true;
260 } else if (FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY) {
261 FLASH_LOADER->BUFFER2_STATUS_REGISTER |= BUFFER_ACTIVE;
262 src_address = (uint32_t *)RAM_LOADER_BUFFER2;
263 buffer2_in_use = true;
264 }
265 if (buffer1_in_use || buffer2_in_use) {
266 success = program_device(src_address,
267 (void *)start_addr, write_package);
268
269 if (buffer1_in_use)
270 P6->OUT &= ~BIT4; /* Program from B1 */
271 else if (buffer2_in_use)
272 P3->OUT &= ~BIT6; /* Program from B1 */
273
274 start_addr += write_package;
275 }
276 if (buffer1_in_use) {
277 FLASH_LOADER->BUFFER1_STATUS_REGISTER &=
278 ~(BUFFER_ACTIVE | BUFFER_DATA_READY);
279 buffer1_in_use = false;
280 } else if (buffer2_in_use) {
281 FLASH_LOADER->BUFFER2_STATUS_REGISTER &=
282 ~(BUFFER_ACTIVE | BUFFER_DATA_READY);
283 buffer2_in_use = false;
284 }
285 /* Block flash writes */
286 lock_all_flash_sectors();
287
288 if (!success) {
289 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
290 break;
291 }
292 }
293 if (success)
294 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
295 }
296
297 /* Unlock Main/Info Flash sectors */
298 void unlock_flash_sectors(void)
299 {
300 if (FLASH_LOADER->ERASE_PARAM & ERASE_MAIN) {
301 MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK0,
302 0xFFFFFFFF);
303 MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK1,
304 0xFFFFFFFF);
305 }
306 if (FLASH_LOADER->ERASE_PARAM & ERASE_INFO) {
307 MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK0,
308 FLASH_SECTOR0 | FLASH_SECTOR1);
309 if (FLASH_LOADER->UNLOCK_BSL == UNLOCK_BSL_KEY)
310 MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK1,
311 FLASH_SECTOR0 | FLASH_SECTOR1);
312 }
313 }
314
315 /* Unlock All Flash sectors */
316 void unlock_all_flash_sectors(void)
317 {
318 MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK0, 0xFFFFFFFF);
319 MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK1, 0xFFFFFFFF);
320 MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK0,
321 FLASH_SECTOR0 | FLASH_SECTOR1);
322 if (FLASH_LOADER->UNLOCK_BSL == UNLOCK_BSL_KEY)
323 MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK1,
324 FLASH_SECTOR0 | FLASH_SECTOR1);
325 }
326
327
328 /* Lock all Flash sectors */
329 void lock_all_flash_sectors(void)
330 {
331 MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK0, 0xFFFFFFFF);
332 MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK1, 0xFFFFFFFF);
333 MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK0,
334 FLASH_SECTOR0 | FLASH_SECTOR1);
335 MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK1,
336 FLASH_SECTOR0 | FLASH_SECTOR1);
337 }
338
339
340 /* Force DCO frequency range */
341 void __cs_set_dco_frequency_range(uint32_t dco_freq)
342 {
343 /* Unlocking the CS Module */
344 CS->KEY = CS_KEY_VAL;
345
346 /* Resetting Tuning Parameters and Setting the frequency */
347 CS->CTL0 = (CS->CTL0 & ~CS_CTL0_DCORSEL_MASK) | dco_freq;
348
349 /* Locking the CS Module */
350 CS->KEY = 0;
351 }
352
353 /* Exit flash programming */
354 void msp432_flash_exit(void)
355 {
356 bool success = false;
357
358 /* Restore modified registers, in reverse order */
359 __cs_set_dco_frequency_range(CS_DCO_FREQUENCY_3);
360
361 MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK0,
362 BACKUP_PARAMS->BANK0_WAIT_RESTORE);
363 MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK1,
364 BACKUP_PARAMS->BANK1_WAIT_RESTORE);
365
366 success = MAP_PCM_SET_POWER_STATE(BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE);
367
368 success &= MAP_PCM_SET_CORE_VOLTAGE_LEVEL(
369 BACKUP_PARAMS->VCORE_LEVEL_RESTORE);
370
371 __cs_set_dco_frequency_range(BACKUP_PARAMS->CS_DC0_FREQ_RESTORE);
372
373 /* Point to vector table in Flash */
374 SCB->VTOR = (uint32_t)0x00000000;
375
376 if (!success)
377 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
378 else
379 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
380 }
381
382 static bool program_device(void *src, void *dest, uint32_t length)
383 {
384 return MAP_FLASH_CTL_PROGRAM_MEMORY(src, dest, length);
385 }

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)