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