1 //*****************************************************************************
2 //
3 //! @file am_hal_flash.c
4 //!
5 //! @brief Functions for Performing Flash Operations.
6 //!
7 //! @note IMPORTANT: Interrupts are active during execution of all HAL flash
8 //! functions. If an interrupt occurs during execution of a flash function
9 //! that programs or erases flash or INFO space, errors will occur if the
10 //! interrupt service routine (ISR) is located in on-chip flash.
11 //! If interrupts are expected during execution of a flash function that
12 //! programs or erases either flash or INFO space:
13 //! - Interrupts must be disabled via a critical section handler prior to
14 //! calling the flash function.
15 //! - Alternatively, applicable ISRs must be located in non-flash address space
16 //! (i.e. SRAM, off-chip ROM, etc.).
17 //!
18 //! @addtogroup flash3 Flash - Flash Functionality
19 //! @ingroup apollo3_hal
20 //! @{
21 //
22 //*****************************************************************************
23
24 //*****************************************************************************
25 //
26 // Copyright (c) 2024, Ambiq Micro, Inc.
27 // All rights reserved.
28 //
29 // Redistribution and use in source and binary forms, with or without
30 // modification, are permitted provided that the following conditions are met:
31 //
32 // 1. Redistributions of source code must retain the above copyright notice,
33 // this list of conditions and the following disclaimer.
34 //
35 // 2. Redistributions in binary form must reproduce the above copyright
36 // notice, this list of conditions and the following disclaimer in the
37 // documentation and/or other materials provided with the distribution.
38 //
39 // 3. Neither the name of the copyright holder nor the names of its
40 // contributors may be used to endorse or promote products derived from this
41 // software without specific prior written permission.
42 //
43 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
44 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
47 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
48 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
49 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
51 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
53 // POSSIBILITY OF SUCH DAMAGE.
54 //
55 // This is part of revision release_sdk_3_2_0-dd5f40c14b of the AmbiqSuite Development Package.
56 //
57 //*****************************************************************************
58
59 #include <stdint.h>
60 #include <stdbool.h>
61 #include "am_mcu_apollo.h"
62
63 //
64 // Look-up table
65 //
66 const g_am_hal_flash_t g_am_hal_flash =
67 {
68 ((int (*)(uint32_t, uint32_t)) 0x0800004d), // flash_mass_erase
69 ((int (*)(uint32_t, uint32_t, uint32_t)) 0x08000051), // flash_page_erase
70 ((int (*)(uint32_t, uint32_t *, uint32_t *, uint32_t)) 0x08000055), // flash_program_main
71 ((int (*)(uint32_t, uint32_t, uint32_t *, uint32_t, uint32_t))0x08000059), // flash_program_info_area
72 ((int (*)(uint32_t, uint32_t)) 0x0800006d), // flash_mass_erase_nb
73 ((int (*)(uint32_t, uint32_t, uint32_t)) 0x08000071), // flash_page_erase_nb
74 ((int (*)( uint32_t, uint32_t)) 0x08000095), // flash_page_erase2_nb
75 ((bool (*)(void)) 0x0800007d), // flash_nb_operation_complete
76 ((uint32_t (*)(uint32_t *)) 0x08000075), // flash_util_read_word
77 ((void (*)( uint32_t *, uint32_t)) 0x08000079), // flash_util_write_word
78 ((void (*)(uint32_t )) 0x0800009D), // bootrom_delay_cycles
79 ((int (*)( uint32_t, uint32_t)) 0x08000081), // flash_info_erase
80 ((int (*)( uint32_t, uint32_t)) 0x08000089), // flash_info_plus_main_erase
81 ((int (*)(uint32_t)) 0x08000091), // flash_info_plus_main_erase_both
82 ((int (*)( uint32_t )) 0x08000099), // flash_recovery
83 ((void (*)(void)) 0x0800005d), // flash_program_main_from_sram
84 ((void (*)(void)) 0x08000061), // flash_program_info_area_from_sram
85 ((void (*)(void)) 0x08000065), // flash_erase_main_pages_from_sram
86 ((void (*)(void)) 0x08000069), // flash_mass_erase_from_sram
87 ((void (*)(void)) 0x08000085), // flash_info_erase_from_sram
88 ((void (*)(void)) 0x0800008D), // flash_info_plus_main_erase_from_sram
89 ((void (*)(void)) 0x080000A1), // flash_nb_operation_complete_from_sram
90 ((void (*)(void)) 0x080000A5), // flash_page_erase2_nb_from_sram
91 ((void (*)(void)) 0x080000A9) // flash_recovery_from_sram
92 };
93
94 const uint32_t ui32SramMaxAddr = (AM_HAL_FLASH_SRAM_LARGEST_VALID_ADDR + 1);
95
96 #if (defined (__ARMCC_VERSION)) && (__ARMCC_VERSION < 6000000)
97 __align(16)
98 #define WA_ATTRIB
99 #elif (defined (__ARMCC_VERSION)) && (__ARMCC_VERSION >= 6000000)
100 #define WA_ATTRIB __attribute__ ((aligned (16)))
101 #elif defined(__GNUC_STDC_INLINE__)
102 #define WA_ATTRIB __attribute__ ((aligned (16)))
103 #elif defined(__IAR_SYSTEMS_ICC__)
104 #pragma data_alignment = 16
105 #define WA_ATTRIB
106 #else
107 #error Unknown compiler.
108 #endif
109
110 //
111 //! Opcodes for the workaround function.
112 //
113 static const uint16_t WakeWorkaround[] WA_ATTRIB =
114 {
115 0x20c3, 0xf244, 0x0114, 0xf2c4, 0x0101, 0x6008, 0xF244, 0x0034,
116 0xF2C4, 0x0000, 0x6800, 0xF04F, 0x02A0, 0xF010, 0x0F04, 0xD000,
117 0x0052, 0x4610, 0xF240, 0x019D, 0xF6C0, 0x0100, 0x4708, 0xBF00,
118 };
119
120 //
121 //! Prototype for the workaround function.
122 //
123 typedef void (*WakeWAfunc_t)(void);
124 WakeWAfunc_t WakeWAfunc = (WakeWAfunc_t)((uint8_t*)WakeWorkaround + 1);
125
126
127 //*****************************************************************************
128 //
129 // @brief This function performs a mass erase on a flash instance.
130 //
131 // @param ui32ProgramKey - The flash program key.
132 // @param ui32FlashInst - The flash instance to erase.
133 //
134 // This function will erase the desired instance of flash.
135 //
136 // @note For Apollo3, each flash instance contains a maximum of 512KB.
137 // @par
138 // @note Interrupts are active during execution of this function. Any interrupt
139 // taken could cause execution errors. Please see the IMPORTANT note under
140 // Detailed Description above for more details.
141 //
142 // @return 0 for success, non-zero for failure.
143 // Failing return code indicates:
144 // 1 ui32ProgramKey is invalid.
145 // 2 ui32FlashInst is invalid.
146 // 3 Flash controller hardware timeout.
147 //
148 //*****************************************************************************
149 int
am_hal_flash_mass_erase(uint32_t ui32ProgramKey,uint32_t ui32FlashInst)150 am_hal_flash_mass_erase(uint32_t ui32ProgramKey, uint32_t ui32FlashInst)
151 {
152 return g_am_hal_flash.flash_mass_erase(ui32ProgramKey, ui32FlashInst);
153 } // am_hal_flash_mass_erase()
154
155 //*****************************************************************************
156 //
157 // @brief This function performs a page erase on a flash instance.
158 //
159 // @param ui32ProgramKey - The flash program key.
160 // @param ui32FlashInst - The flash instance to reference the page number with.
161 // @param ui32PageNum - The flash page relative to the specified instance.
162 //
163 // This function will erase the desired flash page in the desired instance of
164 // flash.
165 //
166 // @note For Apollo3, each flash page is 8KB (or AM_HAL_FLASH_PAGE_SIZE).
167 // Each flash instance contains a maximum of 64 pages (or
168 // AM_HAL_FLASH_INSTANCE_PAGES).
169 // @par
170 // @note When given an absolute flash address, a couple of helpful macros can
171 // be utilized when calling this function.
172 // For example:
173 // am_hal_flash_page_erase(AM_HAL_FLASH_PROGRAM_KEY,
174 // AM_HAL_FLASH_ADDR2INST(ui32Addr),
175 // AM_HAL_FLASH_ADDR2PAGE(ui32Addr) );
176 // @par
177 // @note Interrupts are active during execution of this function. Any interrupt
178 // taken could cause execution errors. Please see the IMPORTANT note under
179 // Detailed Description above for more details.
180 //
181 // @return 0 for success, non-zero for failure.
182 // Failing return code indicates:
183 // 1 ui32ProgramKey is invalid.
184 // 2 ui32FlashInst is invalid.
185 // 3 ui32PageNum is invalid.
186 // 4 Flash controller hardware timeout.
187 //
188 //*****************************************************************************
189 int
am_hal_flash_page_erase(uint32_t ui32ProgramKey,uint32_t ui32FlashInst,uint32_t ui32PageNum)190 am_hal_flash_page_erase(uint32_t ui32ProgramKey, uint32_t ui32FlashInst,
191 uint32_t ui32PageNum)
192 {
193
194 //
195 // Call the function to perform the Wake Workaround
196 //
197 WakeWAfunc();
198
199 return g_am_hal_flash.flash_page_erase(ui32ProgramKey,
200 ui32FlashInst,
201 ui32PageNum);
202 } // am_hal_flash_page_erase()
203
204 //*****************************************************************************
205 //
206 // @brief This programs up to N words of the Main array on one flash instance.
207 //
208 // @param ui32ProgramKey - The programming key, AM_HAL_FLASH_PROGRAM_KEY.
209 // @param pui32Src - Pointer to word aligned array of data to program into
210 // the flash instance.
211 // @param pui32Dst - Pointer to the word aligned flash location where
212 // programming of the flash instance is to begin.
213 // @param ui32NumWords - The number of words to be programmed.
214 //
215 // This function will program multiple words in main flash.
216 //
217 // @note Interrupts are active during execution of this function. Any interrupt
218 // taken could cause execution errors. Please see the IMPORTANT note under
219 // Detailed Description above for more details.
220 //
221 // @return 0 for success, non-zero for failure.
222 // Failing return code indicates:
223 // 1 ui32ProgramKey is invalid.
224 // 2 pui32Dst is invalid.
225 // 3 Flash addressing range would be exceeded. That is, (pui32Dst +
226 // (ui32NumWords * 4)) is greater than the last valid address.
227 // 4 pui32Src is invalid.
228 // 5 Unused - will never be returned.
229 // 6 Flash controller hardware timeout.
230 //
231 //*****************************************************************************
232 int
am_hal_flash_program_main(uint32_t ui32ProgramKey,uint32_t * pui32Src,uint32_t * pui32Dst,uint32_t ui32NumWords)233 am_hal_flash_program_main(uint32_t ui32ProgramKey, uint32_t *pui32Src,
234 uint32_t *pui32Dst, uint32_t ui32NumWords)
235 {
236 uint32_t ui32MaxSrcAddr = (uint32_t)pui32Src + (ui32NumWords << 2);
237
238 //
239 // Call the function to perform the Wake Workaround
240 //
241 WakeWAfunc();
242
243 //
244 // Workaround, the last word of SRAM cannot be the source
245 // of programming by BootRom, check to see if it is the last
246 //
247 if ( ui32MaxSrcAddr == ui32SramMaxAddr )
248 {
249 uint32_t ui32Temp;
250 int iRetVal;
251
252 //
253 // program the other words using the boot-rom function
254 //
255 if ( ui32NumWords > 1 )
256 {
257 iRetVal = g_am_hal_flash.flash_program_main(
258 ui32ProgramKey,
259 pui32Src,
260 pui32Dst,
261 ui32NumWords - 1);
262
263 //
264 // return if anything wrong
265 //
266 if ( iRetVal != 0 )
267 {
268 return iRetVal;
269 }
270 }
271
272 //
273 // program the last word of the pSrc from a local
274 // variable if it is the last word of SRAM
275 //
276 ui32Temp = *(uint32_t *)(ui32MaxSrcAddr - 4);
277
278 return g_am_hal_flash.flash_program_main(
279 ui32ProgramKey,
280 &ui32Temp,
281 pui32Dst + ui32NumWords - 1,
282 1);
283 }
284
285 return g_am_hal_flash.flash_program_main(ui32ProgramKey, pui32Src,
286 pui32Dst, ui32NumWords);
287 } // am_hal_flash_program_main()
288
289 //*****************************************************************************
290 //
291 // @brief This clears the specified bits in the addressed flash word
292 //
293 // @param ui32ProgramKey - The programming key, AM_HAL_FLASH_PROGRAM_KEY.
294 // @param pui32Addr - Pointer to word aligned flash word to program into
295 // @param ui32BitMask - The bits to be cleared
296 //
297 // This function will clear one of more bits in a word in main flash.
298 // This function is mainly used when the same word is to be written multiple times
299 // few bits at a time, between erase cycle
300 //
301 // @note Interrupts are active during execution of this function. Any interrupt
302 // taken could cause execution errors. Please see the IMPORTANT note under
303 // Detailed Description above for more details.
304 //
305 // @note We can reprogram a bit in flash to 0 only once. This function takes
306 // care of not re-clearing bits if they are already programmed as 0
307 //
308 // @return 0 for success, non-zero for failure.
309 //
310 // Note: See am_hal_flash_program_main() for further details on return codes.
311 //
312 //*****************************************************************************
313 int
am_hal_flash_clear_bits(uint32_t ui32ProgramKey,uint32_t * pui32Addr,uint32_t ui32BitMask)314 am_hal_flash_clear_bits(uint32_t ui32ProgramKey, uint32_t *pui32Addr,
315 uint32_t ui32BitMask)
316 {
317 uint32_t ui32Val = ~ui32BitMask;
318
319 //
320 // CAUTION: We can reprogram a bit in flash to 0 only once...so make sure
321 // that we do not re-clear bits
322 //
323 ui32Val |= ~(*pui32Addr);
324
325 return g_am_hal_flash.flash_program_main(ui32ProgramKey, &ui32Val,
326 pui32Addr, 1);
327 } // am_hal_flash_clear_bits()
328
329 //*****************************************************************************
330 //
331 // @brief This function programs multiple words in the customer INFO space.
332 //
333 // @param ui32InfoKey - The customer INFO space key.
334 // @param ui32InfoInst - The INFO space instance, 0 or 1.
335 // @param *pui32Src - Pointer to word aligned array of data to program into
336 // the customer INFO space.
337 // @param ui32Offset - Word offset into customer INFO space (offset of 0 is
338 // the first word, 1 is second word, etc.).
339 // @param ui32NumWords - The number of words to be programmed, must not
340 // exceed AM_HAL_FLASH_INFO_SIZE/4.
341 //
342 // This function will program multiple words in the customer INFO space.
343 //
344 // @note Interrupts are active during execution of this function. Any interrupt
345 // taken could cause execution errors. Please see the IMPORTANT note under
346 // Detailed Description above for more details.
347 //
348 // @return 0 for success, non-zero for failure.
349 // Failing return code indicates:
350 // 1 ui32InfoKey is invalid.
351 // 2 ui32InfoInst is invalid.
352 // 3 ui32Offset is invalid.
353 // 4 INFO addressing range would be exceeded. That is, (ui32Offset +
354 // ui32NumWords) is greater than the last valid address.
355 // 5 pui32Src is invalid.
356 // 6 pui32Src is invalid.
357 // 7 Hardware error.
358 // 8 Flash controller hardware timeout.
359 //
360 //*****************************************************************************
361 int
am_hal_flash_program_info(uint32_t ui32InfoKey,uint32_t ui32InfoInst,uint32_t * pui32Src,uint32_t ui32Offset,uint32_t ui32NumWords)362 am_hal_flash_program_info(uint32_t ui32InfoKey, uint32_t ui32InfoInst,
363 uint32_t *pui32Src, uint32_t ui32Offset,
364 uint32_t ui32NumWords)
365 {
366 uint32_t ui32MaxSrcAddr = (uint32_t)pui32Src + (ui32NumWords << 2);
367
368 //
369 // workround, the last word of SRAM cannot be the source
370 // of programming by BootRom, check to see if it is the last
371 //
372 if ( ui32MaxSrcAddr == ui32SramMaxAddr )
373 {
374 uint32_t ui32Temp;
375 int iRetVal;
376
377 //
378 // program the other words using the boot-rom function
379 //
380 if ( ui32NumWords > 1 )
381 {
382 iRetVal = g_am_hal_flash.flash_program_info_area(
383 ui32InfoKey,
384 ui32InfoInst,
385 pui32Src,
386 ui32Offset,
387 ui32NumWords - 1);
388
389 //
390 // return if anything wrong
391 //
392 if ( iRetVal != 0 )
393 {
394 return iRetVal;
395 }
396 }
397
398 //
399 // program the last word of the pSrc from a local
400 // variable if it is the last word of SRAM
401 //
402 ui32Temp = *(uint32_t *)(ui32MaxSrcAddr - 4);
403 return g_am_hal_flash.flash_program_info_area(
404 ui32InfoKey,
405 ui32InfoInst,
406 &ui32Temp,
407 ui32Offset + ui32NumWords - 1,
408 1);
409 }
410
411 return g_am_hal_flash.flash_program_info_area(ui32InfoKey, ui32InfoInst, pui32Src,
412 ui32Offset, ui32NumWords);
413
414 } // am_hal_flash_program_info()
415
416 //*****************************************************************************
417 //
418 // @brief This function erases an instance of the customer INFO space.
419 //
420 // @param ui32InfoKey - The customer INFO space programming key
421 // (AM_HAL_FLASH_INFO_KEY).
422 // @param ui32Inst - The flash instance, either 0 or 1.
423 //
424 // This function will erase the the customer INFO space of the specified
425 // instance.
426 //
427 // @note Interrupts are active during execution of this function. Any interrupt
428 // taken could cause execution errors. Please see the IMPORTANT note under
429 // Detailed Description above for more details.
430 //
431 // @return 0 for success, non-zero for failure.
432 // Failing return code indicates:
433 // 1 ui32InfoKey is invalid.
434 // 2 ui32Inst is invalid.
435 // 3 Hardware error.
436 // 4 Flash controller hardware timeout.
437 //
438 //*****************************************************************************
439 int
am_hal_flash_erase_info(uint32_t ui32InfoKey,uint32_t ui32Inst)440 am_hal_flash_erase_info(uint32_t ui32InfoKey,
441 uint32_t ui32Inst)
442 {
443 return g_am_hal_flash.flash_info_erase(ui32InfoKey, ui32Inst);
444 } // am_hal_flash_erase_info()
445
446 //*****************************************************************************
447 //
448 // @brief This function erases the main instance + the customer INFO space.
449 //
450 // @param ui32InfoKey - The customer INFO space key.
451 // @param ui32Inst - The flash instance, either 0 or 1.
452 //
453 // This function will erase the main flash + the customer INFO space of the
454 // specified instance.
455 //
456 // @note Interrupts are active during execution of this function. Any interrupt
457 // taken could cause execution errors. Please see the IMPORTANT note under
458 // Detailed Description above for more details.
459 //
460 // @return 0 for success, non-zero for failure.
461 // Failing return code indicates:
462 // 1 ui32InfoKey is invalid.
463 // 2 ui32Inst is invalid.
464 // 3 Hardware error.
465 // 4 Flash controller hardware timeout.
466 // 11 Internal error.
467 // 12 Internal error.
468 // 13 Flash controller hardware timeout.
469 //
470 //*****************************************************************************
471 int
am_hal_flash_erase_main_plus_info(uint32_t ui32InfoKey,uint32_t ui32Inst)472 am_hal_flash_erase_main_plus_info(uint32_t ui32InfoKey,
473 uint32_t ui32Inst)
474 {
475 return g_am_hal_flash.flash_info_plus_main_erase(ui32InfoKey,
476 ui32Inst);
477 } // am_hal_flash_erase_main_plus_info()
478
479 //*****************************************************************************
480 //
481 // @brief This function erases the main flash + the customer INFO space.
482 //
483 // @param ui32InfoKey - The customer INFO space key.
484 //
485 // This function will erase both instances the main flash + the
486 // customer INFO space.
487 //
488 // @note Interrupts are active during execution of this function. Any interrupt
489 // taken could cause execution errors. Please see the IMPORTANT note under
490 // Detailed Description above for more details.
491 //
492 // @return 0 for success, non-zero for failure.
493 // Failing return code indicates:
494 // 1 ui32InfoKey is invalid, instance 0.
495 // 2 Internal error, instance 0.
496 // 3 Hardware error, instance 0.
497 // 4 Flash controller hardware timeout, instance 0.
498 // 11 Internal error.
499 // 12 Internal error.
500 // 13 Flash controller hardware timeout.
501 // 21 ui32InfoKey is invalid, instance 1.
502 // 22 Internal error, instance 1.
503 // 23 Hardware error, instance 1.
504 // 24 Flash controller hardware timeout, instance 1.
505 // 31 Internal error, instance 1.
506 // 32 Internal error, instance 1.
507 // 33 Flash controller hardware timeout, instance 1.
508 //
509 //*****************************************************************************
510 int
am_hal_flash_erase_main_plus_info_both_instances(uint32_t ui32InfoKey)511 am_hal_flash_erase_main_plus_info_both_instances(uint32_t ui32InfoKey)
512 {
513 return g_am_hal_flash.flash_info_plus_main_erase_both(ui32InfoKey);
514 } // am_hal_flash_erase_main_plus_info_both_instances()
515
516 //*****************************************************************************
517 //
518 // @brief This function erases both main flash instances + both customer INFO
519 // space instances.
520 //
521 // @param ui32RecoveryKey - The recovery key.
522 //
523 // This function erases both main instances and both customer INFOinstances
524 // even if the customer INFO space is programmed to not be erasable. This
525 // function completely erases the flash main and info instances and wipes the
526 // SRAM. Upon completion of the erasure operations, it does a POI (power on
527 // initialization) reset.
528 //
529 // @note The customer key lock is enforced by this function. Therefore, the
530 // customer key must be written prior to calling otherwise, the function will
531 // fail. Therefore, always check for a return code. If the function returns,
532 // a failure has occured.
533 // @par
534 // @note Interrupts are active during execution of this function. Any interrupt
535 // taken could cause execution errors. Please see the IMPORTANT note under
536 // Detailed Description above for more details.
537 //
538 // @return Does not return if successful. Returns failure code otherwise.
539 // Failing return code indicates:
540 // 0x00000001 ui32RecoveryKey is invalid.
541 // 0x00000002 Customer key lock not set.
542 // 0x00001001 Internal error.
543 // 0x00001002 Internal error.
544 // 0x00001003 Info erase, instance 0 - hardware error.
545 // 0x00001004 Info erase, instance 0 - flash controller hardware timeout.
546 // 0xi000ppee Error erasing page in instance, pp=page number, ee=error code.
547 // i=2|3, instance 0.
548 // i=4|5, instance 1.
549 // ee=1|2|3 Internal or hardware error.
550 // ee=4 Flash controller hardware timeout.
551 //
552 //*****************************************************************************
553 int
am_hal_flash_recovery(uint32_t ui32RecoveryKey)554 am_hal_flash_recovery(uint32_t ui32RecoveryKey)
555 {
556 int retVal;
557 MCUCTRL->SCRATCH0 |= 0x2;
558 retVal = g_am_hal_flash.flash_recovery(ui32RecoveryKey);
559 // Function does not return if successful
560 MCUCTRL->SCRATCH0 &= ~0x2;
561 return retVal;
562 } // am_hal_flash_recovery()
563
564 //*****************************************************************************
565 //
566 // @brief Use the bootrom to implement a spin loop.
567 //
568 // @param ui32Iterations - Number of iterations to delay.
569 //
570 // Use this function to implement a CPU busy waiting spin loop without cache
571 // or delay uncertainties.
572 //
573 // Notes for Apollo3:
574 // - The ROM-based function executes at 3 cycles per iteration plus the normal
575 // function call, entry, and exit overhead and latencies.
576 // - Cache settings affect call overhead. However, the cache does not affect
577 // the time while inside the BOOTROM function.
578 // - The function accounts for burst vs normal mode, along with some of the
579 // overhead encountered with executing the function itself (such as the
580 // check for burst mode).
581 // - Use of the FLASH_CYCLES_US() or FLASH_CYCLES_US_NOCACHE() macros for the
582 // ui32Iterations parameter will result in approximate microsecond timing.
583 // - The parameter ui32Iterations==0 is allowed but is still incurs a delay.
584 //
585 // Example:
586 // - MCU operating at 48MHz -> 20.83 ns / cycle
587 // - Therefore each iteration (once inside the bootrom function) will consume
588 // 62.5ns (non-burst-mode).
589 //
590 // @note Interrupts are not disabled during execution of this function.
591 // Therefore, any interrupt taken will affect the delay timing.
592 //
593 //*****************************************************************************
594 void
am_hal_flash_delay(uint32_t ui32Iterations)595 am_hal_flash_delay(uint32_t ui32Iterations)
596 {
597 //
598 // The read of the FREQCTRL register in order to check for burst mode
599 // could take up to 13 cycles, and almost double if in burst mode.
600 // There are also overhead delays encountered in this function, such
601 // as computing the cycle count adjustment itself.
602 // Let's account for these delays as much as possible.
603 //
604 register uint32_t ui32CycleCntAdj;
605
606 if ( am_hal_burst_mode_status() == AM_HAL_BURST_MODE )
607 {
608 ui32Iterations <<= 1;
609
610 //
611 // There's an additional shift to account for.
612 //
613 ui32CycleCntAdj = ((13 * 2) + 16) / 3;
614 }
615 else
616 {
617 ui32CycleCntAdj = ((13 * 1) + 20) / 3;
618 }
619
620 //
621 // Allow for the overhead of the burst-mode check and these comparisons
622 // by eliminating an appropriate number of iterations.
623 //
624 if ( ui32Iterations > ui32CycleCntAdj )
625 {
626 ui32Iterations -= ui32CycleCntAdj;
627
628 g_am_hal_flash.bootrom_delay_cycles(ui32Iterations);
629 }
630
631 } // am_hal_flash_delay()
632
633 //*****************************************************************************
634 //
635 // @brief Delays for a desired amount of cycles while also waiting for a
636 // status to change a value.
637 //
638 // @param ui32usMaxDelay - Maximum number of ~1uS delay loops.
639 // @param ui32Address - Address of the register for the status change.
640 // @param ui32Mask - Mask for the status change.
641 // @param ui32Value - Target value for the status change.
642 //
643 // This function will delay for approximately the given number of microseconds
644 // while checking for a status change, exiting when either the given time has
645 // expired or the status change is detected.
646 //
647 // @returns 0 = timeout.
648 // 1 = status change detected.
649 //
650 //*****************************************************************************
651 uint32_t
am_hal_flash_delay_status_change(uint32_t ui32usMaxDelay,uint32_t ui32Address,uint32_t ui32Mask,uint32_t ui32Value)652 am_hal_flash_delay_status_change(uint32_t ui32usMaxDelay, uint32_t ui32Address,
653 uint32_t ui32Mask, uint32_t ui32Value)
654 {
655 while ( 1 )
656 {
657 //
658 // Check the status
659 //
660 if ( ( AM_REGVAL(ui32Address) & ui32Mask ) == ui32Value )
661 {
662 return AM_HAL_STATUS_SUCCESS;
663 }
664
665 if ( ui32usMaxDelay-- )
666 {
667 //
668 // Call the BOOTROM cycle function to delay for about 1 microsecond.
669 //
670 am_hal_flash_delay( FLASH_CYCLES_US(1) );
671 }
672 else
673 {
674 break;
675 }
676 }
677
678 return AM_HAL_STATUS_TIMEOUT;
679
680 } // am_hal_flash_delay_status_change()
681
682 //*****************************************************************************
683 //
684 // @brief Delays for a desired amount of cycles while also waiting for a
685 // status to equal OR not-equal to a value.
686 //
687 // @param ui32usMaxDelay - Maximum number of ~1uS delay loops.
688 // @param ui32Address - Address of the register for the status change.
689 // @param ui32Mask - Mask for the status change.
690 // @param ui32Value - Target value for the status change.
691 // @param bIsEqual - Check for equal if true; not-equal if false.
692 //
693 // This function will delay for approximately the given number of microseconds
694 // while checking for a status change, exiting when either the given time has
695 // expired or the status change is detected.
696 //
697 // @returns 0 = timeout.
698 // 1 = status change detected.
699 //
700 //*****************************************************************************
701 uint32_t
am_hal_flash_delay_status_check(uint32_t ui32usMaxDelay,uint32_t ui32Address,uint32_t ui32Mask,uint32_t ui32Value,bool bIsEqual)702 am_hal_flash_delay_status_check(uint32_t ui32usMaxDelay, uint32_t ui32Address,
703 uint32_t ui32Mask, uint32_t ui32Value,
704 bool bIsEqual)
705 {
706 while ( 1 )
707 {
708 //
709 // Check the status
710 //
711 if ( bIsEqual )
712 {
713 if ( ( AM_REGVAL(ui32Address) & ui32Mask ) == ui32Value )
714 {
715 return AM_HAL_STATUS_SUCCESS;
716 }
717 }
718 else
719 {
720 if ( ( AM_REGVAL(ui32Address) & ui32Mask ) != ui32Value )
721 {
722 return AM_HAL_STATUS_SUCCESS;
723 }
724 }
725
726 if ( ui32usMaxDelay-- )
727 {
728 //
729 // Call the BOOTROM cycle function to delay for about 1 microsecond.
730 //
731 am_hal_flash_delay( FLASH_CYCLES_US(1) );
732 }
733 else
734 {
735 break;
736 }
737 }
738
739 return AM_HAL_STATUS_TIMEOUT;
740
741 } // am_hal_flash_delay_status_check()
742
743 //*****************************************************************************
744 //
745 //! @brief Static Helper Function to check customer info valid bits erasure.
746 //!
747 //! Use this function to test the state of the 128 valid bits at the beginning
748 //! of customer info space. If these are all erased then return true.
749 //!
750 //! @return true if the customer info bits are currently erased.
751 //
752 //*****************************************************************************
753 static bool
customer_info_signature_erased(void)754 customer_info_signature_erased(void)
755 {
756 uint32_t *pui32Signature = (uint32_t *) AM_HAL_FLASH_INFO_ADDR;
757
758 return ( (pui32Signature[3] == 0xFFFFFFFF) &&
759 (pui32Signature[2] == 0xFFFFFFFF) &&
760 (pui32Signature[1] == 0xFFFFFFFF) &&
761 (pui32Signature[0] == 0xFFFFFFFF) ) ? true : false;
762
763 } // customer_info_signature_erased()
764
765 //*****************************************************************************
766 //
767 //! @brief Static Helper Function to set customer info valid bits
768 //!
769 //! Use this function to set the state of the 128 valid bits at the beginning
770 //! of customer info space. If these bits are not set correctly then the
771 //! customer protection bits in the INFO space will not be honored by the
772 //! hardware.
773 //!
774 //! @return Zero for success. Non-Zero for errors.
775 //!
776 //! Note: See am_hal_flash_program_info() for further details on return codes.
777 //
778 //*****************************************************************************
779 static int
customer_info_signature_set(uint32_t ui32InfoKey)780 customer_info_signature_set(uint32_t ui32InfoKey)
781 {
782 uint32_t ui32Valid[4];
783 int iRC;
784
785 //
786 // If they are already set then we are done.
787 //
788 if ( am_hal_flash_customer_info_signature_check() )
789 {
790 return 0;
791 }
792
793 //
794 // If they are not erased at this point we have an error.
795 //
796 if ( !customer_info_signature_erased() )
797 {
798 return (2 << 16);
799 }
800
801 //
802 // OK they need to be set so do it.
803 //
804 ui32Valid[3] = AM_HAL_FLASH_INFO_SIGNATURE3;
805 ui32Valid[2] = AM_HAL_FLASH_INFO_SIGNATURE2;
806 ui32Valid[1] = AM_HAL_FLASH_INFO_SIGNATURE1;
807 ui32Valid[0] = AM_HAL_FLASH_INFO_SIGNATURE0;
808
809 iRC = g_am_hal_flash.flash_program_info_area(ui32InfoKey,
810 0, // instance
811 ui32Valid, // source data
812 0, // offset
813 4); // number of words
814
815 //
816 // See am_hal_flash_program_info() for further details on return codes.
817 //
818 return iRC | ((iRC) ? (1 << 16) : 0);
819
820 } // customer_info_signature_set()
821
822 //*****************************************************************************
823 //
824 // @brief Check that the customer info bits are valid.
825 //
826 // Use this function to test the state of the 128 valid bits at the beginning
827 // of customer info space. If these are not set correctly then the customer
828 // protection bits in the INFO space will not be honored by the hardware.
829 //
830 // @return true if valid.
831 //
832 //*****************************************************************************
833 bool
am_hal_flash_customer_info_signature_check(void)834 am_hal_flash_customer_info_signature_check(void)
835 {
836 uint32_t *pui32Signature = (uint32_t *)AM_HAL_FLASH_INFO_ADDR;
837
838 return ( (pui32Signature[3] == AM_HAL_FLASH_INFO_SIGNATURE3) &&
839 (pui32Signature[2] == AM_HAL_FLASH_INFO_SIGNATURE2) &&
840 (pui32Signature[1] == AM_HAL_FLASH_INFO_SIGNATURE1) &&
841 (pui32Signature[0] == AM_HAL_FLASH_INFO_SIGNATURE0) );
842
843 } // am_hal_flash_customer_info_signature_check()
844
845 //*****************************************************************************
846 //
847 // @brief INFO signature set.
848 //
849 // @param ui32InfoKey - The customer INFO space programming key
850 //
851 // Use this function to set the state of the 128 valid bits at the beginning
852 // of customer info space, if needed.
853 //
854 // @note Interrupts are active during execution of this function. Any interrupt
855 // taken could cause execution errors. Please see the IMPORTANT note under
856 // Detailed Description above for more details.
857 //
858 // @return Zero for success. Non-Zero for errors.
859 //
860 // Note: See am_hal_flash_program_info() for further details on return codes.
861 //
862 //*****************************************************************************
863 bool
am_hal_flash_info_signature_set(uint32_t ui32InfoKey)864 am_hal_flash_info_signature_set(uint32_t ui32InfoKey)
865 {
866 //
867 // Check and set signature.
868 //
869 return customer_info_signature_set(ui32InfoKey) ? false : true;
870
871 } // am_hal_flash_info_signature_set()
872
873 //*****************************************************************************
874 //
875 // @brief Disable FLASH INFO space.
876 //
877 // @param ui32InfoKey - The customer INFO space programming key
878 //
879 // Use this function to set the state of the 128 valid bits at the beginning
880 // of customer info space, if needed. Then disable FLASH erasure.
881 //
882 // @note Interrupts are active during execution of this function. Any interrupt
883 // taken could cause execution errors. Please see the IMPORTANT note under
884 // Detailed Description above for more details.
885 //
886 // @return Zero for success. Non-Zero for errors.
887 //
888 // Note: See am_hal_flash_program_info() for further details on return codes.
889 //
890 //*****************************************************************************
891 int32_t
am_hal_flash_info_erase_disable(uint32_t ui32InfoKey)892 am_hal_flash_info_erase_disable(uint32_t ui32InfoKey)
893 {
894 int iRC;
895 uint32_t ui32SecurityValue;
896
897 //
898 // Security protection only works if the signature data is correct.
899 //
900 iRC = customer_info_signature_set(ui32InfoKey);
901 if ( iRC )
902 {
903 return iRC;
904 }
905
906 //
907 // Clear bit in INFO space to disable erasure.
908 //
909 ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
910 ~AM_HAL_FLASH_INFO_SECURITY_ENINFOERASE_M;
911
912 //
913 // Now write the word to the flash INFO space.
914 //
915 return g_am_hal_flash.flash_program_info_area(
916 ui32InfoKey,
917 0, // instance
918 &ui32SecurityValue, // source data
919 AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
920 1 ); // number of words
921
922 } // am_hal_flash_info_erase_disable()
923
924 //*****************************************************************************
925 //
926 // @brief Check for Disabled FLASH INFO space.
927 //
928 // Use this function to determine whether FLASH INFO erasure is disabled.
929 //
930 // @return true if FLASH INFO erase is disabled, otherwise false.
931 //
932 //*****************************************************************************
933 bool
am_hal_flash_info_erase_disable_check(void)934 am_hal_flash_info_erase_disable_check(void)
935 {
936 //
937 // If they are erased at this point then SRAM wipe can't be enabled.
938 //
939 if ( customer_info_signature_erased() )
940 {
941 return false;
942 }
943
944 //
945 // If they are not valid at this point then SRAM wipe can't be enabled.
946 //
947 if ( !am_hal_flash_customer_info_signature_check() )
948 {
949 return false;
950 }
951
952 //
953 // Looking good so far, now check the SRAM WIPE bit.
954 //
955 return AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
956 AM_HAL_FLASH_INFO_SECURITY_ENINFOERASE_M ? false : true;
957
958 } // am_hal_flash_info_erase_disable_check()
959
960 //*****************************************************************************
961 //
962 // @brief Mask off 1 to 4 quadrants of FLASH INFO space for programming.
963 //
964 // Use this function to set the state of the 128 valid bits at the beginning
965 // of customer info space, if needed. Then and the mask bits with the INFO
966 // space programming disable bits.
967 //
968 // @param ui32InfoKey - The customer INFO space programming key
969 //
970 // @param ui32Mask - A mask of the 4 quadrants of info space where
971 // bit0 = First quadrant (first 2KB).
972 // bit1 = Second quadrant (second 2KB).
973 // bit2 = Third quadrant (third 2KB).
974 // bit3 = Fourth quadrant (fourth 2KB).
975 //
976 // @note This function disables only, any quadrant already disabled is not
977 // reenabled. That is, any ui32Mask bits specified as 0 are essentially nops.
978 // @par
979 // @note Interrupts are active during execution of this function. Any interrupt
980 // taken could cause execution errors. Please see the IMPORTANT note under
981 // Detailed Description above for more details.
982 //
983 // @return Zero for success. Non-Zero for errors.
984 //
985 // Note: See am_hal_flash_program_info() for further details on return codes.
986 //
987 //*****************************************************************************
988 int32_t
am_hal_flash_info_program_disable(uint32_t ui32InfoKey,uint32_t ui32Mask)989 am_hal_flash_info_program_disable(uint32_t ui32InfoKey, uint32_t ui32Mask)
990 {
991 int iRC;
992 uint32_t ui32SecurityValue;
993
994 //
995 // Security protection only works if the signature data is correct.
996 //
997 iRC = customer_info_signature_set(ui32InfoKey);
998 if ( iRC )
999 {
1000 return iRC;
1001 }
1002
1003 //
1004 // Make sure we have a valid mask and get the mask into the correct position.
1005 //
1006 ui32Mask <<= AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_S;
1007 ui32Mask &= AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_M;
1008
1009 //
1010 // The security bit set to 1 enables programming, 0 disables programming.
1011 //
1012 ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) & ~ui32Mask;
1013
1014 //
1015 // Now write the word to the flash INFO space.
1016 //
1017 return g_am_hal_flash.flash_program_info_area(
1018 ui32InfoKey,
1019 0, // instance
1020 &ui32SecurityValue, // source data
1021 AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
1022 1 ); // number of words
1023
1024 } // am_hal_flash_info_program_disable()
1025
1026 //*****************************************************************************
1027 //
1028 // @brief Return a mask specifying which quadrants of customer INFO space have
1029 // been disabled for programming.
1030 //
1031 // Use this function to determine whether programming of customer INFO space
1032 // has been disabled.
1033 //
1034 // @return A 4-bit mask of the disabled quadrants.
1035 // 0xFFFFFFFF indicates an error.
1036 // 0x0 indicates all customer INFO space programming is enabled.
1037 // 0xF indicates all customer INFO space programming is disabled.
1038 // bit0 indicates the first customer INFO space is disabled for programming.
1039 // bit1 indicates the second customer INFO space is disabled for programming.
1040 // bit2 indicates the third customer INFO space is disabled for programming.
1041 // bit3 indicates the fourth customer INFO space is disabled for programming.
1042 //
1043 //*****************************************************************************
1044 uint32_t
am_hal_flash_info_program_disable_get(void)1045 am_hal_flash_info_program_disable_get(void)
1046 {
1047 //
1048 // If they are erased at this point then SRAM wipe can't be enabled.
1049 //
1050 if ( customer_info_signature_erased() )
1051 {
1052 return 0xFFFFFFFF;
1053 }
1054
1055 //
1056 // If not valid at this point, then INFO programming can't be enabled.
1057 //
1058 if ( !am_hal_flash_customer_info_signature_check() )
1059 {
1060 return 0xFFFFFFFF;
1061 }
1062
1063 //
1064 // Looking good so far, now return a mask of the disabled bits.
1065 //
1066 return ((AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
1067 AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_M) ^
1068 AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_M) >>
1069 AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_S;
1070
1071 } // am_hal_flash_info_program_disable_get()
1072
1073 //*****************************************************************************
1074 //
1075 // @brief Enable FLASH debugger protection (FLASH gets wiped if a debugger is
1076 // connected).
1077 //
1078 // @param ui32InfoKey - The customer INFO space programming key
1079 //
1080 // Use this function to set the state of the 128 valid bits at the beginning
1081 // of customer info space, if needed. Then set the FLASH wipe bit to zero.
1082 //
1083 // @note Interrupts are active during execution of this function. Any interrupt
1084 // taken could cause execution errors. Please see the IMPORTANT note under
1085 // Detailed Description above for more details.
1086 //
1087 // @return Zero for success. Non-Zero for errors.
1088 //
1089 // Note: See am_hal_flash_program_info() for further details on return codes.
1090 //
1091 //*****************************************************************************
1092 int32_t
am_hal_flash_wipe_flash_enable(uint32_t ui32InfoKey)1093 am_hal_flash_wipe_flash_enable(uint32_t ui32InfoKey)
1094 {
1095 int iRC;
1096 uint32_t ui32SecurityValue;
1097
1098 //
1099 // Security protection only works if the signature data is correct.
1100 //
1101 iRC = customer_info_signature_set(ui32InfoKey);
1102 if ( iRC )
1103 {
1104 return iRC;
1105 }
1106
1107 //
1108 // Clear the FLASH Wipe bit.
1109 //
1110 ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
1111 ~AM_HAL_FLASH_INFO_SECURITY_FLASHWIPE_M;
1112
1113 //
1114 // Now write the word to the flash INFO space.
1115 //
1116 return g_am_hal_flash.flash_program_info_area(
1117 ui32InfoKey,
1118 0, // instance
1119 &ui32SecurityValue, // source data
1120 AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
1121 1 ); // number of words
1122
1123 } // am_hal_flash_wipe_flash_enable()
1124
1125 //*****************************************************************************
1126 //
1127 // @brief check for FLASH wipe protection enabled.
1128 //
1129 // Use this function to determine if FLASH wipe protection is enabled.
1130 //
1131 // @return true if FLASH wipe protection is enabled, otherwise false.
1132 //
1133 //*****************************************************************************
1134 bool
am_hal_flash_wipe_flash_enable_check(void)1135 am_hal_flash_wipe_flash_enable_check(void)
1136 {
1137 //
1138 // If they are erased at this point then flash wipe can't be enabled.
1139 //
1140 if ( customer_info_signature_erased() )
1141 {
1142 return false;
1143 }
1144
1145 //
1146 // If they are not valid at this point then flash wipe can't be enabled.
1147 //
1148 if ( !am_hal_flash_customer_info_signature_check() )
1149 {
1150 return false;
1151 }
1152
1153 //
1154 // Looking good so far, now check the Flash WIPE bit.
1155 //
1156 return AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
1157 AM_HAL_FLASH_INFO_SECURITY_FLASHWIPE_M ? false : true;
1158
1159 } // am_hal_flash_wipe_flash_enable_check()
1160
1161 //*****************************************************************************
1162 //
1163 // @brief Enable SRAM protection so SRAM gets wiped if a debgger is connected.
1164 //
1165 // @param ui32InfoKey - The customer INFO space programming key
1166 //
1167 // Use this function to set the state of the 128 valid bits at the beginning
1168 // of customer info space, if needed. Then set the SRAM wipe bit to zero.
1169 //
1170 // @note Interrupts are active during execution of this function. Any interrupt
1171 // taken could cause execution errors. Please see the IMPORTANT note under
1172 // Detailed Description above for more details.
1173 //
1174 // @return Zero for success. Non-Zero for errors.
1175 //
1176 // Note: See am_hal_flash_program_info() for further details on return codes.
1177 //
1178 //*****************************************************************************
1179 int32_t
am_hal_flash_wipe_sram_enable(uint32_t ui32InfoKey)1180 am_hal_flash_wipe_sram_enable(uint32_t ui32InfoKey)
1181 {
1182 int iRC;
1183 uint32_t ui32SecurityValue;
1184
1185 //
1186 // Security protection only works if the signature data is correct.
1187 //
1188 iRC = customer_info_signature_set(ui32InfoKey);
1189 if ( iRC )
1190 {
1191 return iRC;
1192 }
1193
1194 //
1195 // Clear the SRAM Wipe bit.
1196 //
1197 ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
1198 ~AM_HAL_FLASH_INFO_SECURITY_SRAMWIPE_M;
1199
1200 //
1201 // Now write the word to the flash INFO space.
1202 //
1203 return g_am_hal_flash.flash_program_info_area(
1204 ui32InfoKey,
1205 0, // instance
1206 &ui32SecurityValue, // source data
1207 AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
1208 1 ); // number of words
1209
1210 } // am_hal_flash_wipe_sram_enable()
1211
1212 //*****************************************************************************
1213 //
1214 // @brief check for SRAM protection enabled.
1215 //
1216 // Use this function to determine if SRAM protection is enabled.
1217 //
1218 // @return true if SRAM wipe protection is enabled, otherwise false.
1219 //
1220 //*****************************************************************************
1221 bool
am_hal_flash_wipe_sram_enable_check(void)1222 am_hal_flash_wipe_sram_enable_check(void)
1223 {
1224 //
1225 // If they are erased at this point then SRAM wipe can't be enabled.
1226 //
1227 if ( customer_info_signature_erased() )
1228 {
1229 return false;
1230 }
1231
1232 //
1233 // If they are not vale at this point then SRAM wipe can't be enabled.
1234 //
1235 if ( !am_hal_flash_customer_info_signature_check() )
1236 {
1237 return false;
1238 }
1239
1240 //
1241 // Looking good so far, now check the SRAM WIPE bit.
1242 //
1243 return AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
1244 AM_HAL_FLASH_INFO_SECURITY_SRAMWIPE_M ? false : true;
1245
1246 } // am_hal_flash_wipe_sram_enable_check()
1247
1248 //*****************************************************************************
1249 //
1250 // @brief Disable Output from ITM/SWO.
1251 //
1252 // @param ui32InfoKey - The customer INFO space programming key
1253 //
1254 // Use this function to set the state of the 128 valid bits at the beginning
1255 // of customer info space, if needed. Set the SWO disable bit to zero.
1256 //
1257 // @note Interrupts are active during execution of this function. Any interrupt
1258 // taken could cause execution errors. Please see the IMPORTANT note under
1259 // Detailed Description above for more details.
1260 //
1261 // @return Zero for success. Non-Zero for errors.
1262 //
1263 // Note: See am_hal_flash_program_info() for further details on return codes.
1264 //
1265 //*****************************************************************************
1266 int32_t
am_hal_flash_swo_disable(uint32_t ui32InfoKey)1267 am_hal_flash_swo_disable(uint32_t ui32InfoKey)
1268 {
1269 int iRC;
1270 uint32_t ui32SecurityValue;
1271
1272 //
1273 // Security protection only works if the signature data is correct.
1274 //
1275 iRC = customer_info_signature_set(ui32InfoKey);
1276 if ( iRC )
1277 {
1278 return iRC;
1279 }
1280
1281 //
1282 // Clear the SWO bit.
1283 //
1284 ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
1285 ~AM_HAL_FLASH_INFO_SECURITY_SWOCTRL_M;
1286
1287 //
1288 // Now write the word to the flash INFO space.
1289 //
1290 return g_am_hal_flash.flash_program_info_area(
1291 ui32InfoKey,
1292 0, // instance
1293 &ui32SecurityValue, // source data
1294 AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
1295 1 ); // number of words
1296
1297 } // am_hal_flash_swo_disable()
1298
1299 //*****************************************************************************
1300 //
1301 // @brief check for SWO disabled.
1302 //
1303 // Use this function to determine if the SWO is disabled.
1304 //
1305 // @return true if the ITM/SWO is disabled, otherwise false.
1306 //
1307 //*****************************************************************************
1308 bool
am_hal_flash_swo_disable_check(void)1309 am_hal_flash_swo_disable_check(void)
1310 {
1311 //
1312 // If they are erased at this point then SRAM wipe can't be enabled.
1313 //
1314 if ( customer_info_signature_erased() )
1315 {
1316 return false;
1317 }
1318
1319 //
1320 // If they are not vale at this point then SRAM wipe can't be enabled.
1321 //
1322 if ( !am_hal_flash_customer_info_signature_check() )
1323 {
1324 return false;
1325 }
1326
1327 //
1328 // Looking good so far, now check the SWO bit.
1329 //
1330 return AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
1331 AM_HAL_FLASH_INFO_SECURITY_SWOCTRL_M ? false : true;
1332
1333 } // am_hal_flash_swo_disable_check()
1334
1335 //*****************************************************************************
1336 //
1337 // @brief Disable Connections from a debugger on the SWD interface.
1338 //
1339 // @param ui32InfoKey - The customer INFO space programming key
1340 //
1341 // Use this function to set the state of the 128 valid bits at the beginning
1342 // of customer info space, if needed. Set the debugger disable bit to zero.
1343 //
1344 // @note Interrupts are active during execution of this function. Any interrupt
1345 // taken could cause execution errors. Please see the IMPORTANT note under
1346 // Detailed Description above for more details.
1347 //
1348 // @return Zero for success. Non-Zero for errors.
1349 //
1350 // Note: See am_hal_flash_program_info() for further details on return codes.
1351 //
1352 //*****************************************************************************
1353 int32_t
am_hal_flash_debugger_disable(uint32_t ui32InfoKey)1354 am_hal_flash_debugger_disable(uint32_t ui32InfoKey)
1355 {
1356 int iRC;
1357 uint32_t ui32SecurityValue;
1358
1359 //
1360 // Security protection only works if the signature data is correct.
1361 //
1362 iRC = customer_info_signature_set(ui32InfoKey);
1363 if ( iRC )
1364 {
1365 return iRC;
1366 }
1367
1368 //
1369 // Clear the DEBUGGER bit.
1370 //
1371 ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
1372 ~AM_HAL_FLASH_INFO_SECURITY_DEBUGGERPROT_M;
1373
1374 //
1375 // Now write the word to the flash INFO space.
1376 //
1377 return g_am_hal_flash.flash_program_info_area(
1378 ui32InfoKey,
1379 0, // instance
1380 &ui32SecurityValue, // source data
1381 AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
1382 1 ); // number of words
1383
1384 } // am_hal_flash_debugger_disable()
1385
1386 //*****************************************************************************
1387 //
1388 // @brief check for debugger disabled.
1389 //
1390 // Use this function to determine if the debugger is disabled.
1391 //
1392 // @return true if the debugger is disabled, otherwise false.
1393 //
1394 //*****************************************************************************
1395 bool
am_hal_flash_debugger_disable_check(void)1396 am_hal_flash_debugger_disable_check(void)
1397 {
1398 //
1399 // If they are erased at this point then SRAM wipe can't be enabled.
1400 //
1401 if ( customer_info_signature_erased() )
1402 {
1403 return false;
1404 }
1405
1406 //
1407 // If they are not vale at this point then SRAM wipe can't be enabled.
1408 //
1409 if ( !am_hal_flash_customer_info_signature_check() )
1410 {
1411 return false;
1412 }
1413
1414 //
1415 // Looking good so far, now check the debugger disable bit.
1416 //
1417 return AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
1418 AM_HAL_FLASH_INFO_SECURITY_DEBUGGERPROT_M ? false : true;
1419
1420 } // am_hal_flash_debugger_disable_check()
1421
1422 //*****************************************************************************
1423 //
1424 //! @brief This static helper function generates a 64-bit protection mask.
1425 //!
1426 //! @param pui32StartAddress - Starting address in flash to begin protection.
1427 //! @param pui32StopAddress - Ending address in flash to stop protection.
1428 //!
1429 //! This function computes a chunk map for the protection range.
1430 //!
1431 //! @return Inverse of the actual chunk mask. That is, chunks to be protected
1432 //! are represented as 0 in the returned mask, while chunks to be left alone
1433 //! are represented as 1. This value can therefore be directly ANDed with the
1434 //! existing bits in INFO space.
1435 //! Note that -1 is returned if input parameters are invalid - this return
1436 //! value would indicate that no chunks are to be protected.
1437 //
1438 //*****************************************************************************
1439 static uint64_t
generate_chunk_mask(uint32_t * pui32StartAddress,uint32_t * pui32StopAddress)1440 generate_chunk_mask(uint32_t *pui32StartAddress, uint32_t *pui32StopAddress)
1441 {
1442 uint32_t ui32ChunkStart, ui32ChunkStop;
1443 uint32_t ui32Width;
1444 uint64_t ui64Mask;
1445
1446 //
1447 // Validate the address input parameters
1448 //
1449 if ( (pui32StartAddress > pui32StopAddress) ||
1450 (pui32StopAddress > (uint32_t*)AM_HAL_FLASH_LARGEST_VALID_ADDR) )
1451 {
1452 //
1453 // Argument error, return value to leave all chunks unprotected.
1454 //
1455 return 0xFFFFFFFFFFFFFFFF;
1456 }
1457
1458 //
1459 // Extract chunk related information
1460 //
1461 ui32ChunkStart = AM_HAL_FLASH_INFO_ADDR2CHUNK((uint32_t)pui32StartAddress);
1462 ui32ChunkStop = AM_HAL_FLASH_INFO_ADDR2CHUNK((uint32_t)pui32StopAddress);
1463 ui32Width = ui32ChunkStop - ui32ChunkStart + 1;
1464
1465 if ( ui32Width == 64 )
1466 {
1467 ui64Mask = (uint64_t)0xFFFFFFFFFFFFFFFFLLU;
1468 }
1469 else
1470 {
1471 ui64Mask = ( ((uint64_t)0x0000000000000001) << ui32Width) - 1;
1472 ui64Mask <<= ui32ChunkStart;
1473 }
1474
1475 //
1476 // OK now return the chunk mask (inverted).
1477 //
1478 return ~ui64Mask;
1479
1480 } // generate_chunk_mask()
1481
1482 //*****************************************************************************
1483 //
1484 // @brief This function sets copy protection for a range of flash chunks.
1485 //
1486 // @param ui32InfoKey - The customer INFO space programming key
1487 // @param pui32StartAddress - Starting address in flash to begin protection.
1488 // @param pui32StopAddress - Ending address in flash to stop protection.
1489 //
1490 // This function will set copy protection bits for a range of flash chunks
1491 //
1492 // @note Each flash chunk contains 16KBytes and corresponds to one bit in
1493 // the protection register. Set the bit to zero to enable protection.
1494 //
1495 // @note Interrupts are active during execution of this function. Any interrupt
1496 // taken could cause execution errors. Please see the IMPORTANT note under
1497 // Detailed Description above for more details.
1498 //
1499 // @return
1500 // 0 for success.
1501 // 0x400000 if the protection bits were already programmed (mask the return
1502 // value with 0x3FFFFF to ignore this case and treat as success).
1503 // Otherwise, non-zero for failure.
1504 //
1505 // Note: See am_hal_flash_program_info() for further details on return codes.
1506 //
1507 //*****************************************************************************
1508 int32_t
am_hal_flash_copy_protect_set(uint32_t ui32InfoKey,uint32_t * pui32StartAddress,uint32_t * pui32StopAddress)1509 am_hal_flash_copy_protect_set(uint32_t ui32InfoKey,
1510 uint32_t *pui32StartAddress,
1511 uint32_t *pui32StopAddress)
1512 {
1513 int iRC;
1514 bool bModified = false;
1515 uint64_t ui64Mask;
1516 uint32_t ui32Work;
1517 uint32_t ui32Protection[2];
1518 uint32_t *pui32Protection = (uint32_t *)AM_HAL_FLASH_INFO_COPYPROT_ADDR;
1519
1520 //
1521 // Extract chunk mask from parameters.
1522 // Also checks parameter validity (returns -1 if bad parameters).
1523 //
1524 ui64Mask = generate_chunk_mask(pui32StartAddress, pui32StopAddress);
1525 if ( ~ui64Mask == 0x0 )
1526 {
1527 return 0x100000;
1528 }
1529
1530 //
1531 // Go get the current settings for copy protection.
1532 //
1533 ui32Protection[0] = pui32Protection[0];
1534 ui32Protection[1] = pui32Protection[1];
1535
1536 //
1537 // AND mask off the necessary protection bits in the lower word.
1538 //
1539 ui32Work = (uint32_t)ui64Mask;
1540 if ( ( ~ui32Work ) && ( ui32Work != ui32Protection[0] ) )
1541 {
1542 bModified = true;
1543 // Need to change only the bits changing - bits already set to 0 should not be rewritten to 0
1544 // Flash has limits on number of times a bit can be set to 0
1545 ui32Protection[0] = ui32Work | ~ui32Protection[0];
1546 iRC = g_am_hal_flash.flash_program_info_area(
1547 ui32InfoKey,
1548 0, // instance
1549 &ui32Protection[0], // source data
1550 (AM_HAL_FLASH_INFO_COPYPROT_O / 4) + 0, // word offset
1551 1 ); // number of words
1552
1553 if ( iRC )
1554 {
1555 return iRC | 0x10000;
1556 }
1557 }
1558
1559 //
1560 // AND mask off the necessary protection bits in the upper word.
1561 //
1562 ui32Work = (uint32_t)(ui64Mask >> 32);
1563 if ( ( ~ui32Work ) && ( ui32Work != ui32Protection[1] ) )
1564 {
1565 bModified = true;
1566 // Need to change only the bits changing - bits already set to 0 should not be rewritten to 0
1567 // Flash has limits on number of times a bit can be set to 0
1568 ui32Protection[1] = ui32Work | ~ui32Protection[1];
1569 iRC = g_am_hal_flash.flash_program_info_area(
1570 ui32InfoKey,
1571 0, // instance
1572 &ui32Protection[1], // source data
1573 (AM_HAL_FLASH_INFO_COPYPROT_O / 4) + 1, // word offset
1574 1 ); // number of words
1575
1576 if ( iRC )
1577 {
1578 return iRC | 0x20000;
1579 }
1580 }
1581
1582 if ( bModified )
1583 {
1584 return 0;
1585 }
1586 else
1587 {
1588 return 0x400000;
1589 }
1590
1591 } // am_hal_flash_copy_protect_set()
1592
1593 //*****************************************************************************
1594 //
1595 // @brief This function checks copy protection for a range of flash chunks.
1596 //
1597 // @param pui32StartAddress - Starting address in flash.
1598 // @param pui32StopAddress - Ending address in flash.
1599 //
1600 // This function will check copy protection bits for a range of flash chunks
1601 // it expects all chunks in the range to be protected.
1602 //
1603 // @note Each flash chunk contains 16KBytes and corresponds to one bit in
1604 // the protection register. Set the bit to zero to enable protection.
1605 //
1606 // @return false for at least one chunk in the covered range is not protected,
1607 // and true if all chunks in the covered range are protected.
1608 //
1609 //
1610 //*****************************************************************************
1611 bool
am_hal_flash_copy_protect_check(uint32_t * pui32StartAddress,uint32_t * pui32StopAddress)1612 am_hal_flash_copy_protect_check(uint32_t *pui32StartAddress,
1613 uint32_t *pui32StopAddress)
1614 {
1615 uint64_t ui64Mask;
1616 uint32_t ui32Work;
1617 uint32_t *pui32Protection = (uint32_t *)AM_HAL_FLASH_INFO_COPYPROT_ADDR;
1618
1619 //
1620 // Extract chunk mask from parameters.
1621 // Also checks parameter validity (returns -1 if bad parameters).
1622 //
1623 ui64Mask = generate_chunk_mask(pui32StartAddress, pui32StopAddress);
1624 if ( ~ui64Mask == 0x0 )
1625 {
1626 return false;
1627 }
1628
1629 //
1630 // Now check the lower word of protection bits.
1631 //
1632 ui32Work = (uint32_t)ui64Mask;
1633 if ( ~ui32Work & pui32Protection[0] )
1634 {
1635 return false;
1636 }
1637
1638 //
1639 // Now check the lower word of protection bits.
1640 //
1641 ui32Work = (uint32_t)(ui64Mask >> 32);
1642 if ( ~ui32Work & pui32Protection[1] )
1643 {
1644 return false;
1645 }
1646
1647 //
1648 // If we get here, there are no unprotected chunks within specified range.
1649 //
1650 return true;
1651
1652 } // am_hal_flash_copy_protect_check()
1653
1654 //*****************************************************************************
1655 //
1656 // @brief This function sets write protection for a range of flash chunks.
1657 //
1658 // @param ui32InfoKey - The customer INFO space programming key
1659 // @param pui32StartAddress - Starting address in flash to begin protection.
1660 // @param pui32StopAddress - Ending address in flash to stop protection.
1661 //
1662 // This function will set write protection bits for a range of flash chunks
1663 //
1664 // @note Each flash chunk contains 16KBytes and corresponds to one bit in
1665 // the protection register. Set the bit to zero to enable protection.
1666 // @par
1667 // @note Interrupts are active during execution of this function. Any interrupt
1668 // taken could cause execution errors. Please see the IMPORTANT note under
1669 // Detailed Description above for more details.
1670 //
1671 // @return
1672 // 0 for success.
1673 // 0x400000 if the protection bits were already programmed (mask the return
1674 // value with 0x3FFFFF to ignore this case and treat as success).
1675 // Otherwise, non-zero for failure.
1676 //
1677 // Note: See am_hal_flash_program_info() for further details on return codes.
1678 //
1679 //*****************************************************************************
1680 int32_t
am_hal_flash_write_protect_set(uint32_t ui32InfoKey,uint32_t * pui32StartAddress,uint32_t * pui32StopAddress)1681 am_hal_flash_write_protect_set(uint32_t ui32InfoKey,
1682 uint32_t *pui32StartAddress,
1683 uint32_t *pui32StopAddress)
1684 {
1685 int iRC;
1686 bool bModified = false;
1687 uint64_t ui64Mask;
1688 uint32_t ui32Work;
1689 uint32_t ui32Protection[2];
1690 uint32_t *pui32Protection = (uint32_t *)AM_HAL_FLASH_INFO_WRITPROT_ADDR;
1691
1692 //
1693 // Extract chunk mask from parameters.
1694 // Also checks parameter validity (returns -1 if bad parameters).
1695 //
1696 ui64Mask = generate_chunk_mask(pui32StartAddress, pui32StopAddress);
1697 if ( ~ui64Mask == 0x0 )
1698 {
1699 return 0x100000;
1700 }
1701
1702 //
1703 // Go get the current settings for copy protection.
1704 //
1705 ui32Protection[0] = pui32Protection[0];
1706 ui32Protection[1] = pui32Protection[1];
1707
1708 //
1709 // AND mask off the necessary protection bits in the lower word.
1710 //
1711 ui32Work = (uint32_t)ui64Mask;
1712 if ( ( ~ui32Work ) && ( ui32Work != ui32Protection[0] ) )
1713 {
1714 bModified = true;
1715 // Need to change only the bits changing - bits already set to 0 should not be rewritten to 0
1716 // Flash has limits on number of times a bit can be set to 0
1717 ui32Protection[0] = ui32Work | ~ui32Protection[0];
1718 iRC = g_am_hal_flash.flash_program_info_area(
1719 ui32InfoKey,
1720 0, // instance
1721 &ui32Protection[0], // source data
1722 (AM_HAL_FLASH_INFO_WRITPROT_O / 4) + 0, // word offset
1723 1 ); // number of words
1724
1725 if ( iRC )
1726 {
1727 return iRC | 0x10000;
1728 }
1729 }
1730
1731 //
1732 // AND mask off the necessary protection bits in the upper word.
1733 //
1734 ui32Work = (uint32_t)(ui64Mask >> 32);
1735 if ( ( ~ui32Work ) && ( ui32Work != ui32Protection[1] ) )
1736 {
1737 bModified = true;
1738 // Need to change only the bits changing - bits already set to 0 should not be rewritten to 0
1739 // Flash has limits on number of times a bit can be set to 0
1740 ui32Protection[1] = ui32Work | ~ui32Protection[1];
1741 iRC = g_am_hal_flash.flash_program_info_area(
1742 ui32InfoKey,
1743 0, // instance
1744 &ui32Protection[1], // source data
1745 (AM_HAL_FLASH_INFO_WRITPROT_O / 4) + 1, // word offset
1746 1 ); // number of words
1747
1748 if ( iRC )
1749 {
1750 return iRC | 0x20000;
1751 }
1752 }
1753
1754 if ( bModified )
1755 {
1756 return 0;
1757 }
1758 else
1759 {
1760 return 0x400000;
1761 }
1762
1763 } // am_hal_flash_write_protect_set()
1764
1765 //*****************************************************************************
1766 //
1767 // @brief This function checks write protection for a range of flash chunks.
1768 //
1769 // @param pui32StartAddress - Starting address in flash.
1770 // @param pui32StopAddress - Ending address in flash.
1771 //
1772 // This function will check write protection bits for a range of flash chunks
1773 // it expects all chunks in the range to be protected.
1774 //
1775 // @note Each flash chunk contains 16KBytes and corresponds to one bit in
1776 // the protection register. Set the bit to zero to enable protection.
1777 //
1778 // @return false for at least one chunk in the covered range is not protected,
1779 // and true if all chunks in the covered range are protected.
1780 //
1781 //
1782 //*****************************************************************************
1783 bool
am_hal_flash_write_protect_check(uint32_t * pui32StartAddress,uint32_t * pui32StopAddress)1784 am_hal_flash_write_protect_check(uint32_t *pui32StartAddress,
1785 uint32_t *pui32StopAddress)
1786 {
1787 uint64_t ui64Mask;
1788 uint32_t ui32Work;
1789 uint32_t *pui32Protection = (uint32_t *)AM_HAL_FLASH_INFO_WRITPROT_ADDR;
1790
1791 //
1792 // Extract chunk mask from parameters.
1793 // Also checks parameter validity (returns -1 if bad parameters).
1794 //
1795 ui64Mask = generate_chunk_mask(pui32StartAddress, pui32StopAddress);
1796 if ( ~ui64Mask == 0x0 )
1797 {
1798 return false;
1799 }
1800
1801 //
1802 // Now check the lower word of protection bits.
1803 //
1804 ui32Work = (uint32_t)ui64Mask;
1805 if ( ~ui32Work & pui32Protection[0] )
1806 {
1807 return false;
1808 }
1809
1810 //
1811 // Now check the lower word of protection bits.
1812 //
1813 ui32Work = (uint32_t)(ui64Mask >> 32);
1814 if ( ~ui32Work & pui32Protection[1] )
1815 {
1816 return false;
1817 }
1818
1819 //
1820 // If we get here, there are no unprotected chunks within specified range.
1821 //
1822 return true;
1823
1824 }// am_hal_flash_write_protect_check()
1825
1826 //*****************************************************************************
1827 //
1828 // @brief Read a uint32 value from a valid memory or peripheral location.
1829 //
1830 // @param pui32Address - The location to be read.
1831 //
1832 // Use this function to safely read a value from peripheral or memory locations.
1833 //
1834 // This function calls a function that resides BOOTROM or SRAM to do the actual
1835 // read, thus completely avoiding any conflict with flash or INFO space.
1836 //
1837 // @return The value read from the given address.
1838 //
1839 //*****************************************************************************
1840 uint32_t
am_hal_flash_load_ui32(uint32_t * pui32Address)1841 am_hal_flash_load_ui32(uint32_t *pui32Address)
1842 {
1843 return g_am_hal_flash.flash_util_read_word(pui32Address);
1844 } // am_hal_flash_load_ui32()
1845
1846 #if defined(__GNUC_STDC_INLINE__)
1847 uint32_t SRAM_write_ui32[12 / 4] =
1848 {
1849 //
1850 // A very simple, word-aligned function residing in SRAM (stack). This
1851 // function writes a given memory location while executing outside of
1852 // flash. It then does a read back to ensure that the write completed.
1853 // Prototype: uint32_t SRAM_write_ui32(ui32Addr, ui32Value);
1854 //
1855 0xBF006001, // 6001 str r1,[r0,#0]
1856 // BF00 nop
1857 0xBF006800, // 6800 ldr r0,[r0,#0]
1858 // BF00 nop
1859 0xBF004770 // 4770 bx lr
1860 // BF00 nop
1861 };
1862 #elif (defined (__ARMCC_VERSION) || defined(__IAR_SYSTEMS_ICC__))
1863 #else
1864 #error Compiler is unknown, please contact Ambiq support team
1865 #endif
1866
1867 //*****************************************************************************
1868 //
1869 // @brief Write a given uint32 value to a valid memory or peripheral location.
1870 //
1871 // @param pui32Address - The location to be written.
1872 // @param ui32Value - Value to be written
1873 //
1874 // Use this function to safely store a value to peripheral or memory locations.
1875 //
1876 // This function calls a function that resides in BOOTROM or SRAM to do the
1877 // actual write, thus completely avoiding any conflict with flash or INFO.
1878 //
1879 //*****************************************************************************
1880 void
am_hal_flash_store_ui32(uint32_t * pui32Address,uint32_t ui32Value)1881 am_hal_flash_store_ui32(uint32_t *pui32Address, uint32_t ui32Value)
1882 {
1883 #if (defined (__ARMCC_VERSION) || defined(__IAR_SYSTEMS_ICC__))
1884 uint32_t SRAM_write_ui32[12 / 4] =
1885 {
1886 //
1887 // A very simple, word-aligned function residing in SRAM (stack). This
1888 // function writes a given memory location while executing outside of
1889 // flash. It then does a read back to ensure that the write completed.
1890 // Prototype: uint32_t SRAM_write_ui32(ui32Addr, ui32Value);
1891 //
1892 0xBF006001, // 6001 str r1,[r0,#0]
1893 // BF00 nop
1894 0xBF006800, // 6800 ldr r0,[r0,#0]
1895 // BF00 nop
1896 0xBF004770 // 4770 bx lr
1897 // BF00 nop
1898 };
1899 #elif defined(__GNUC_STDC_INLINE__)
1900 #else
1901 #error Compiler is unknown, please contact Ambiq support team
1902 #endif
1903
1904 //
1905 // Call the simple routine that has been coded in SRAM.
1906 // First set up a function pointer to the array, being sure to set the
1907 // .T bit (Thumb bit, bit0) in the branch address, then use that
1908 // function ptr to call the SRAM function.
1909 //
1910 uint32_t SRAMCode = (uint32_t)SRAM_write_ui32 | 0x1;
1911 uint32_t (*pFunc)(uint32_t*, uint32_t) = (uint32_t (*)(uint32_t*, uint32_t))SRAMCode;
1912 (*pFunc)(pui32Address, ui32Value);
1913
1914 } // am_hal_flash_store_ui32()
1915
1916 //*****************************************************************************
1917 //
1918 // End Doxygen group.
1919 //! @}
1920 //
1921 //*****************************************************************************
1922