be1f709760bca03043497587516f9b802d05a4cf
[fw/openocd] / 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 }