1 /* SPDX-License-Identifier: BSD-3-Clause */
3 /******************************************************************************
5 * Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/
7 ******************************************************************************/
11 #include "driverlib.h"
13 #include "MSP432P4_FlashLibIf.h"
15 /* Number of erase repeats until timeout */
16 #define FLASH_MAX_REPEATS 5
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);
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;
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
44 /* Main with trampoline */
48 MAP_WDT_A_HOLD_TIMER();
50 /* Disable interrupts */
54 switch (FLASH_LOADER->FLASH_FUNCTION) {
56 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
58 FLASH_LOADER->FLASH_FUNCTION = 0;
60 case FLASH_MASS_ERASE:
61 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
62 msp432_flash_mass_erase();
63 FLASH_LOADER->FLASH_FUNCTION = 0;
65 case FLASH_SECTOR_ERASE:
66 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
67 msp432_flash_sector_erase();
68 FLASH_LOADER->FLASH_FUNCTION = 0;
71 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
73 FLASH_LOADER->FLASH_FUNCTION = 0;
75 case FLASH_CONTINUOUS_PROGRAM:
76 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
77 msp432_flash_continous_write();
78 FLASH_LOADER->FLASH_FUNCTION = 0;
81 FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
83 FLASH_LOADER->FLASH_FUNCTION = 0;
85 case FLASH_NO_COMMAND:
88 FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
94 /* Initialize flash */
95 void msp432_flash_init(void)
99 /* Point to vector table in RAM */
100 SCB->VTOR = (uint32_t)0x01000000;
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;
111 /* set parameters for flashing */
112 success = MAP_PCM_SET_POWER_STATE(PCM_AM_LDO_VCORE0);
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);
118 /* Set CPU speed to 24MHz */
119 __cs_set_dco_frequency_range(CS_DCO_FREQUENCY_24);
122 /* Indicate failed power switch */
123 FLASH_LOADER->RETURN_CODE = FLASH_POWER_ERROR;
125 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
128 /* Erase entire flash */
129 void msp432_flash_mass_erase(void)
131 bool success = false;
133 /* Allow flash writes */
134 unlock_flash_sectors();
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();
144 if (erase_repeats == 0)
145 FLASH_LOADER->RETURN_CODE = FLASH_VERIFY_ERROR;
147 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
149 /* Block flash writes */
150 lock_all_flash_sectors();
153 /* Erase one flash sector */
154 void msp432_flash_sector_erase(void)
156 bool success = false;
158 /* Allow flash writes */
159 unlock_all_flash_sectors();
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);
169 if (erase_repeats == 0)
170 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
172 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
174 /* Block flash writes */
175 lock_all_flash_sectors();
178 /* Write data to flash with the help of DriverLib */
179 void msp432_flash_write(void)
181 bool success = false;
183 /* Allow flash writes */
184 unlock_all_flash_sectors();
186 while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY))
189 FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE;
192 success = program_device((uint32_t *)RAM_LOADER_BUFFER1,
193 (void *)FLASH_LOADER->DST_ADDRESS, FLASH_LOADER->SRC_LENGTH);
195 FLASH_LOADER->BUFFER1_STATUS_REGISTER &=
196 ~(BUFFER_ACTIVE | BUFFER_DATA_READY);
198 /* Block flash writes */
199 lock_all_flash_sectors();
202 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
204 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
207 /* Write data to flash with the help of DriverLib with auto-increment */
208 void msp432_flash_continous_write(void)
210 bool buffer1_in_use = false;
211 bool buffer2_in_use = false;
212 uint32_t *src_address = NULL;
213 bool success = false;
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;
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;
224 write_package = bytes_to_write;
225 bytes_to_write -= write_package;
227 unlock_all_flash_sectors();
228 while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) &&
229 !(FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY))
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;
241 if (buffer1_in_use || buffer2_in_use) {
242 success = program_device(src_address, (void *) start_addr, write_package);
243 start_addr += write_package;
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;
252 /* Block flash writes */
253 lock_all_flash_sectors();
256 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
261 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
264 /* Unlock Main/Info Flash sectors */
265 void unlock_flash_sectors(void)
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);
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);
281 /* Unlock All Flash sectors */
282 void unlock_all_flash_sectors(void)
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);
294 /* Lock all Flash sectors */
295 void lock_all_flash_sectors(void)
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);
303 /* Force DCO frequency range */
304 void __cs_set_dco_frequency_range(uint32_t dco_freq)
306 /* Unlocking the CS Module */
307 CS->KEY = CS_KEY_VAL;
309 /* Resetting Tuning Parameters and Setting the frequency */
310 CS->CTL0 = (CS->CTL0 & ~CS_CTL0_DCORSEL_MASK) | dco_freq;
312 /* Locking the CS Module */
316 /* Exit flash programming */
317 void msp432_flash_exit(void)
319 bool success = false;
321 /* Restore modified registers, in reverse order */
322 __cs_set_dco_frequency_range(CS_DCO_FREQUENCY_3);
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);
329 success = MAP_PCM_SET_POWER_STATE(BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE);
331 success &= MAP_PCM_SET_CORE_VOLTAGE_LEVEL(
332 BACKUP_PARAMS->VCORE_LEVEL_RESTORE);
334 __cs_set_dco_frequency_range(BACKUP_PARAMS->CS_DC0_FREQ_RESTORE);
336 /* Point to vector table in Flash */
337 SCB->VTOR = (uint32_t)0x00000000;
340 FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
342 FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
345 static bool program_device(void *src, void *dest, uint32_t length)
347 uint32_t dst_address = (uint32_t)dest;
349 /* Flash main memory first, then information memory */
350 if ((dst_address < INFO_FLASH_START) && ((dst_address + length) >
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);
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);
364 return MAP_FLASH_CTL_A_PROGRAM_MEMORY(src, dest, length);