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