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