flash/nor: add support for TI MSP432 devices
[fw/openocd] / 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 }