]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M4F_MSP432_LaunchPad_IAR_CCS_Keil/driverlib/flash.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M4F_MSP432_LaunchPad_IAR_CCS_Keil / driverlib / flash.c
1 /*
2  * -------------------------------------------
3  *    MSP432 DriverLib - v01_04_00_18 
4  * -------------------------------------------
5  *
6  * --COPYRIGHT--,BSD,BSD
7  * Copyright (c) 2015, Texas Instruments Incorporated
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * *  Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  * *  Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * *  Neither the name of Texas Instruments Incorporated nor the names of
22  *    its contributors may be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
32  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  * --/COPYRIGHT--*/
37 /* Standard Includes */
38 #include <stdint.h>
39
40 /* DriverLib Includes */
41 #include <flash.h>
42 #include <debug.h>
43 #include <interrupt.h>
44 #include <msp.h>
45 #include <cpu.h>
46 #include <rom.h>
47 #include <sysctl.h>
48
49 /* Statics */
50 static const uint32_t MAX_PROGRAM_TRIES = 5;
51 static const uint32_t MAX_ERASE_TRIES = 50;
52
53 static uint32_t getUserFlashSector(uint32_t addr)
54 {
55     if (addr > 0x1ffff)
56     {
57         addr = addr - 0x20000;
58     }
59
60     switch (addr)
61     {
62     case 0:
63         return FLASH_SECTOR0;
64     case 0x1000:
65         return FLASH_SECTOR1;
66     case 0x2000:
67         return FLASH_SECTOR2;
68     case 0x3000:
69         return FLASH_SECTOR3;
70     case 0x4000:
71         return FLASH_SECTOR4;
72     case 0x5000:
73         return FLASH_SECTOR5;
74     case 0x6000:
75         return FLASH_SECTOR6;
76     case 0x7000:
77         return FLASH_SECTOR7;
78     case 0x8000:
79         return FLASH_SECTOR8;
80     case 0x9000:
81         return FLASH_SECTOR9;
82     case 0xA000:
83         return FLASH_SECTOR10;
84     case 0xB000:
85         return FLASH_SECTOR11;
86     case 0xC000:
87         return FLASH_SECTOR12;
88     case 0xD000:
89         return FLASH_SECTOR13;
90     case 0xE000:
91         return FLASH_SECTOR14;
92     case 0xF000:
93         return FLASH_SECTOR15;
94     case 0x10000:
95         return FLASH_SECTOR16;
96     case 0x11000:
97         return FLASH_SECTOR17;
98     case 0x12000:
99         return FLASH_SECTOR18;
100     case 0x13000:
101         return FLASH_SECTOR19;
102     case 0x14000:
103         return FLASH_SECTOR20;
104     case 0x15000:
105         return FLASH_SECTOR21;
106     case 0x16000:
107         return FLASH_SECTOR22;
108     case 0x17000:
109         return FLASH_SECTOR23;
110     case 0x18000:
111         return FLASH_SECTOR24;
112     case 0x19000:
113         return FLASH_SECTOR25;
114     case 0x1A000:
115         return FLASH_SECTOR26;
116     case 0x1B000:
117         return FLASH_SECTOR27;
118     case 0x1C000:
119         return FLASH_SECTOR28;
120     case 0x1D000:
121         return FLASH_SECTOR29;
122     case 0x1E000:
123         return FLASH_SECTOR30;
124     case 0x1F000:
125         return FLASH_SECTOR31;
126     default:
127         ASSERT(false);
128         return 0;
129     }
130 }
131
132 static bool _FlashCtl_Program8(uint32_t src, uint32_t dest)
133 {
134     uint32_t ii;
135
136     /* Enabling the correct verification settings  */
137     FlashCtl_setProgramVerification(FLASH_REGPRE | FLASH_REGPOST);
138     FlashCtl_clearProgramVerification(FLASH_BURSTPOST | FLASH_BURSTPRE);
139
140     for(ii=0;ii<MAX_PROGRAM_TRIES;ii++)
141     {
142         /* Clearing flags */
143         FLCTL->rCLRIFG.r |= (FLASH_PROGRAM_ERROR | FLASH_POSTVERIFY_FAILED
144                 | FLASH_PREVERIFY_FAILED | FLASH_WRDPRGM_COMPLETE);
145
146         HWREG8(dest) = HWREG8(src);
147
148         while (!(FlashCtl_getInterruptStatus() & FLASH_WRDPRGM_COMPLETE))
149         {
150             __no_operation();
151         }
152
153         if ((BITBAND_PERI(FLCTL->rIFG.r, FLCTL_IFG_PRG_ERR_OFS))
154                 || (BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r,
155                         FLCTL_PRG_CTLSTAT_VER_PRE_OFS)
156                         && BITBAND_PERI(FLCTL->rIFG.r,
157                                 FLCTL_IFG_AVPRE_OFS))
158                 || (BITBAND_PERI(FLCTL->rIFG.r, FLCTL_IFG_AVPST_OFS)))
159         {
160             if(BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_VER_PRE_OFS))
161             {
162                 FlashCtl_clearProgramVerification(FLASH_REGPRE);
163             }
164         }
165         else
166         {
167             return true;
168         }
169     }
170
171     return false;
172
173 }
174
175 static bool _FlashCtl_Program32(uint32_t src, uint32_t dest)
176 {
177     uint32_t ii;
178
179     /* Enabling the correct verification settings  */
180     FlashCtl_setProgramVerification(FLASH_REGPRE | FLASH_REGPOST);
181     FlashCtl_clearProgramVerification(FLASH_BURSTPOST | FLASH_BURSTPRE);
182
183     for(ii=0;ii<MAX_PROGRAM_TRIES;ii++)
184     {
185         /* Clearing flags */
186         FLCTL->rCLRIFG.r |= (FLASH_PROGRAM_ERROR | FLASH_POSTVERIFY_FAILED
187                 | FLASH_PREVERIFY_FAILED | FLASH_WRDPRGM_COMPLETE);
188
189         HWREG32(dest) = HWREG32(src);
190
191         while (!(FlashCtl_getInterruptStatus() & FLASH_WRDPRGM_COMPLETE))
192         {
193             __no_operation();
194         }
195
196         if ((BITBAND_PERI(FLCTL->rIFG.r, FLCTL_IFG_PRG_ERR_OFS))
197                 || (BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r,
198                         FLCTL_PRG_CTLSTAT_VER_PRE_OFS)
199                         && BITBAND_PERI(FLCTL->rIFG.r,
200                                 FLCTL_IFG_AVPRE_OFS))
201                 || (BITBAND_PERI(FLCTL->rIFG.r, FLCTL_IFG_AVPST_OFS)))
202         {
203             if(BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_VER_PRE_OFS))
204             {
205                 FlashCtl_clearProgramVerification(FLASH_REGPRE);
206             }
207         }
208         else
209         {
210             return true;
211         }
212     }
213
214     return false;
215
216 }
217
218 void FlashCtl_enableReadBuffering(uint_fast8_t memoryBank,
219         uint_fast8_t accessMethod)
220 {
221     if (memoryBank == FLASH_BANK0 && accessMethod == FLASH_DATA_READ)
222         BITBAND_PERI(FLCTL->rBANK0_RDCTL.r, FLCTL_BANK0_RDCTL_BUFD_OFS) = 1;
223     else if (memoryBank == FLASH_BANK1 && accessMethod == FLASH_DATA_READ)
224         BITBAND_PERI(FLCTL->rBANK1_RDCTL.r, FLCTL_BANK1_RDCTL_BUFD_OFS) = 1;
225     else if (memoryBank == FLASH_BANK0
226             && accessMethod == FLASH_INSTRUCTION_FETCH)
227         BITBAND_PERI(FLCTL->rBANK0_RDCTL.r, FLCTL_BANK0_RDCTL_BUFI_OFS) = 1;
228     else if (memoryBank == FLASH_BANK1
229             && accessMethod == FLASH_INSTRUCTION_FETCH)
230         BITBAND_PERI(FLCTL->rBANK1_RDCTL.r, FLCTL_BANK1_RDCTL_BUFI_OFS) = 1;
231     else
232         ASSERT(false);
233 }
234
235 void FlashCtl_disableReadBuffering(uint_fast8_t memoryBank,
236         uint_fast8_t accessMethod)
237 {
238     if (memoryBank == FLASH_BANK0 && accessMethod == FLASH_DATA_READ)
239         BITBAND_PERI(FLCTL->rBANK0_RDCTL.r, FLCTL_BANK0_RDCTL_BUFD_OFS) = 0;
240     else if (memoryBank == FLASH_BANK1 && accessMethod == FLASH_DATA_READ)
241         BITBAND_PERI(FLCTL->rBANK1_RDCTL.r, FLCTL_BANK1_RDCTL_BUFD_OFS) = 0;
242     else if (memoryBank == FLASH_BANK0
243             && accessMethod == FLASH_INSTRUCTION_FETCH)
244         BITBAND_PERI(FLCTL->rBANK0_RDCTL.r, FLCTL_BANK0_RDCTL_BUFI_OFS) = 0;
245     else if (memoryBank == FLASH_BANK1
246             && accessMethod == FLASH_INSTRUCTION_FETCH)
247         BITBAND_PERI(FLCTL->rBANK1_RDCTL.r, FLCTL_BANK1_RDCTL_BUFI_OFS) = 0;
248     else
249         ASSERT(false);
250 }
251
252 bool FlashCtl_unprotectSector(uint_fast8_t memorySpace, uint32_t sectorMask)
253 {
254     switch (memorySpace)
255     {
256     case FLASH_MAIN_MEMORY_SPACE_BANK0:
257         FLCTL->rBANK0_MAIN_WEPROT.r &= ~sectorMask;
258         break;
259     case FLASH_MAIN_MEMORY_SPACE_BANK1:
260         FLCTL->rBANK1_MAIN_WEPROT.r &= ~sectorMask;
261         break;
262     case FLASH_INFO_MEMORY_SPACE_BANK0:
263         ASSERT(sectorMask <= 0x04);
264         FLCTL->rBANK0_INFO_WEPROT.r &= ~sectorMask;
265         break;
266     case FLASH_INFO_MEMORY_SPACE_BANK1:
267         ASSERT(sectorMask <= 0x04);
268         FLCTL->rBANK1_INFO_WEPROT.r &= ~sectorMask;
269         break;
270
271     default:
272         ASSERT(false);
273
274     }
275
276     return !FlashCtl_isSectorProtected(memorySpace, sectorMask);
277 }
278
279 bool FlashCtl_protectSector(uint_fast8_t memorySpace, uint32_t sectorMask)
280 {
281     switch (memorySpace)
282     {
283     case FLASH_MAIN_MEMORY_SPACE_BANK0:
284         FLCTL->rBANK0_MAIN_WEPROT.r |= sectorMask;
285         break;
286     case FLASH_MAIN_MEMORY_SPACE_BANK1:
287         FLCTL->rBANK1_MAIN_WEPROT.r |= sectorMask;
288         break;
289     case FLASH_INFO_MEMORY_SPACE_BANK0:
290         ASSERT(sectorMask <= 0x04);
291         FLCTL->rBANK0_INFO_WEPROT.r |= sectorMask;
292         break;
293     case FLASH_INFO_MEMORY_SPACE_BANK1:
294         ASSERT(sectorMask <= 0x04);
295         FLCTL->rBANK1_INFO_WEPROT.r |= sectorMask;
296         break;
297
298     default:
299         ASSERT(false);
300
301     }
302
303     return FlashCtl_isSectorProtected(memorySpace, sectorMask);
304 }
305
306 bool FlashCtl_isSectorProtected(uint_fast8_t memorySpace, uint32_t sector)
307 {
308     switch (memorySpace)
309     {
310     case FLASH_MAIN_MEMORY_SPACE_BANK0:
311         return FLCTL->rBANK0_MAIN_WEPROT.r & sector;
312     case FLASH_MAIN_MEMORY_SPACE_BANK1:
313         return FLCTL->rBANK1_MAIN_WEPROT.r & sector;
314     case FLASH_INFO_MEMORY_SPACE_BANK0:
315         ASSERT(sector <= 0x04);
316         return FLCTL->rBANK0_INFO_WEPROT.r & sector;
317     case FLASH_INFO_MEMORY_SPACE_BANK1:
318         ASSERT(sector <= 0x04);
319         return FLCTL->rBANK1_INFO_WEPROT.r & sector;
320     default:
321         return false;
322     }
323 }
324
325 bool FlashCtl_verifyMemory(void* verifyAddr, uint32_t length,
326         uint_fast8_t pattern)
327 {
328     uint32_t memoryPattern, addr, otpOffset;
329     uint_fast8_t memoryType;
330
331     ASSERT(pattern == FLASH_0_PATTERN || pattern == FLASH_1_PATTERN);
332
333     addr = (uint32_t) verifyAddr;
334     memoryPattern = (pattern == FLASH_1_PATTERN) ? 0xFFFFFFFF : 0;
335     memoryType = (addr > __MAIN_MEMORY_END__) ? FLASH_INFO_SPACE : FLASH_MAIN_SPACE;
336
337     /* Taking care of byte accesses */
338     while ((addr & 0x03) && (length > 0))
339     {
340         if (HWREG8(addr++) != ((uint8_t) memoryPattern))
341             return false;
342         length--;
343     }
344
345     /* Making sure we are aligned by 128-bit address */
346     while (((addr & 0x0F)) && (length > 3))
347     {
348         if (HWREG32(addr) != memoryPattern)
349             return false;
350
351         addr = addr + 4;
352         length = length - 4;
353     }
354
355     /* Burst Verify */
356     if (length > 63)
357     {
358
359         /* Setting/clearing INFO flash flags as appropriate */
360         if (addr > __MAIN_MEMORY_END__)
361         {
362             FLCTL->rRDBRST_CTLSTAT.r = (FLCTL->rRDBRST_CTLSTAT.r
363                     & ~FLCTL_RDBRST_CTLSTAT_MEM_TYPE_M)
364                     | FLCTL_RDBRST_CTLSTAT_MEM_TYPE_1;
365             otpOffset = 0x00200000;
366         } else
367         {
368             FLCTL->rRDBRST_CTLSTAT.r = (FLCTL->rRDBRST_CTLSTAT.r
369                     & ~FLCTL_RDBRST_CTLSTAT_MEM_TYPE_M)
370                     | FLCTL_RDBRST_CTLSTAT_MEM_TYPE_0;
371             otpOffset = __MAIN_MEMORY_START__;
372         }
373
374         /* Clearing any lingering fault flags  and preparing burst verify*/
375         BITBAND_PERI(FLCTL->rRDBRST_CTLSTAT.r, FLCTL_RDBRST_CTLSTAT_CLR_STAT_OFS) =
376                 1;
377         FLCTL->rRDBRST_FAILCNT.r = 0;
378         FLCTL->rRDBRST_STARTADDR.r = addr - otpOffset;
379         FLCTL->rRDBRST_LEN.r = (length & 0xFFFFFFF0);
380         addr += FLCTL->rRDBRST_LEN.r;
381         length = length & 0xF;
382
383         /* Starting Burst Verify */
384         FLCTL->rRDBRST_CTLSTAT.r = (FLCTL_RDBRST_CTLSTAT_STOP_FAIL | pattern
385                 | memoryType | FLCTL_RDBRST_CTLSTAT_START);
386
387         /* While the burst read hasn't finished */
388         while ((FLCTL->rRDBRST_CTLSTAT.r & FLCTL_RDBRST_CTLSTAT_BRST_STAT_M)
389                 != FLCTL_RDBRST_CTLSTAT_BRST_STAT_3)
390         {
391             __no_operation();
392         }
393
394         /* Checking  for a verification/access error/failure */
395         if (BITBAND_PERI(FLCTL->rRDBRST_CTLSTAT.r,
396                 FLCTL_RDBRST_CTLSTAT_CMP_ERR_OFS)
397                 || BITBAND_PERI(FLCTL->rRDBRST_CTLSTAT.r,
398                         FLCTL_RDBRST_CTLSTAT_ADDR_ERR_OFS)
399                 || FLCTL->rRDBRST_FAILCNT.r)
400         {
401             /* Clearing the Read Burst flag and returning */
402             BITBAND_PERI(FLCTL->rRDBRST_CTLSTAT.r, FLCTL_RDBRST_CTLSTAT_CLR_STAT_OFS) =
403                     1;
404             return false;
405         }
406
407         /* Clearing the Read Burst flag */
408         BITBAND_PERI(FLCTL->rRDBRST_CTLSTAT.r, FLCTL_RDBRST_CTLSTAT_CLR_STAT_OFS) =
409                 1;
410
411     }
412
413     /* Remaining Words */
414     while (length > 3)
415     {
416         if (HWREG32(addr) != memoryPattern)
417             return false;
418
419         addr = addr + 4;
420         length = length - 4;
421     }
422
423     /* Remaining Bytes */
424     while (length > 0)
425     {
426         if (HWREG8(addr++) != ((uint8_t) memoryPattern))
427             return false;
428         length--;
429     }
430
431     return true;
432 }
433
434 bool FlashCtl_setReadMode(uint32_t flashBank, uint32_t readMode)
435 {
436
437     if (FLCTL->rPOWER_STAT.r & FLCTL_POWER_STAT_RD_2T)
438         return false;
439
440     if (flashBank == FLASH_BANK0)
441     {
442         FLCTL->rBANK0_RDCTL.r = (FLCTL->rBANK0_RDCTL.r
443                 & ~FLCTL_BANK0_RDCTL_RD_MODE_M) | readMode;
444         while (FLCTL->rBANK0_RDCTL.b.bRD_MODE != readMode)
445             ;
446     } else if (flashBank == FLASH_BANK1)
447     {
448         FLCTL->rBANK1_RDCTL.r = (FLCTL->rBANK1_RDCTL.r
449                 & ~FLCTL_BANK1_RDCTL_RD_MODE_M) | readMode;
450         while (FLCTL->rBANK1_RDCTL.b.bRD_MODE != readMode)
451             ;
452     } else
453     {
454         ASSERT(false);
455         return false;
456     }
457
458     return true;
459 }
460
461 uint32_t FlashCtl_getReadMode(uint32_t flashBank)
462 {
463     if (flashBank == FLASH_BANK0)
464     {
465         return FLCTL->rBANK0_RDCTL.b.bRD_MODE;
466     } else if (flashBank == FLASH_BANK1)
467     {
468         return FLCTL->rBANK1_RDCTL.b.bRD_MODE;
469     } else
470     {
471         ASSERT(false);
472         return 0;
473     }
474 }
475
476 bool FlashCtl_performMassErase(void)
477 {
478     uint32_t userFlash, ii, jj, sector;
479
480     /* Trying a mass erase in ROM first. If it fails (should be rare), going
481      * through and erasing each sector one-by-one
482      */
483     if (!FlashInternal_performMassErase(true))
484     {
485         userFlash = SysCtl_getFlashSize() / 2;
486
487         for (ii = __MAIN_MEMORY_START__; ii < userFlash; ii += 4096)
488         {
489             sector = getUserFlashSector(ii);
490
491             if (!((FLCTL->rBANK0_MAIN_WEPROT.r) & sector))
492             {
493                 for (jj = 1; jj < MAX_ERASE_TRIES; jj++)
494                 {
495                     if (FlashInternal_eraseSector(ii, true))
496                     {
497                         break;
498                     }
499                 }
500
501                 if (jj == MAX_ERASE_TRIES)
502                     return false;
503             }
504
505             if (!(FLCTL->rBANK1_MAIN_WEPROT.r & sector))
506             {
507                 for (jj = 1; jj < MAX_ERASE_TRIES; jj++)
508                 {
509                     if (FlashInternal_eraseSector(ii + userFlash, true))
510                     {
511                         break;
512                     }
513                 }
514
515                 if (jj == MAX_ERASE_TRIES)
516                     return false;
517             }
518
519             if (sector < FLCTL_BANK0_MAIN_WEPROT_PROT2)
520             {
521                 if (!(FLCTL->rBANK0_INFO_WEPROT.r & sector))
522                 {
523                     for (jj = 1; jj < MAX_ERASE_TRIES; jj++)
524                     {
525                         if (FlashInternal_eraseSector(ii + __BSL_MEMORY_START__,
526                         true))
527                         {
528                             break;
529                         }
530                     }
531
532                     if (jj == MAX_ERASE_TRIES)
533                         return false;
534                 }
535
536                 if (!(FLCTL->rBANK1_INFO_WEPROT.r & sector))
537                 {
538
539                     for (jj = 1; jj < MAX_ERASE_TRIES; jj++)
540                     {
541
542                         if (FlashInternal_eraseSector(
543                                 ii + __BSL_MEMORY_START__ + 0x2000, true))
544                         {
545                             break;
546                         }
547                     }
548
549                     if (jj == MAX_ERASE_TRIES)
550                         return false;
551                 }
552
553             }
554         }
555     }
556
557     return true;
558 }
559
560 bool FlashCtl_eraseSector(uint32_t addr)
561 {
562     uint32_t ii;
563
564     for(ii=0;ii<MAX_ERASE_TRIES;ii++)
565     {
566         if(FlashInternal_eraseSector(addr, true))
567         {
568             return true;
569         }
570     }
571
572     return false;
573 }
574
575 bool FlashCtl_programMemory(void* src, void* dest, uint32_t length)
576 {
577     uint32_t destAddr, srcAddr;
578     bool res;
579
580     /* Casting to integers */
581     srcAddr = (uint32_t)src;
582     destAddr = (uint32_t)dest;
583
584     /* Enabling word programming */
585     FlashCtl_enableWordProgramming(FLASH_IMMEDIATE_WRITE_MODE);
586
587     /* Assume failure */
588     res = false;
589
590     /* Taking care of byte accesses */
591     while ((destAddr & 0x03) && length > 0)
592     {
593         if(!_FlashCtl_Program8(srcAddr,destAddr))
594         {
595             goto FlashProgramCleanUp;
596         }
597         else
598         {
599             srcAddr++;
600             destAddr++;
601             length--;
602         }
603     }
604
605     /* Taking care of word accesses */
606     while ((destAddr & 0x0F) && (length > 3))
607     {
608         if (!_FlashCtl_Program32(srcAddr, destAddr))
609         {
610             goto FlashProgramCleanUp;
611         }
612         else
613         {
614             srcAddr += 4;
615             destAddr += 4;
616             length -= 4;
617         }
618     }
619
620     /* Remaining byte accesses */
621     while (length > 0)
622     {
623         if(!_FlashCtl_Program8(srcAddr,destAddr))
624         {
625             goto FlashProgramCleanUp;
626         }
627         else
628         {
629             srcAddr++;
630             destAddr++;
631             length--;
632         }
633     }
634
635     /* If we got this far that means that we succeeded  */
636     res = true;
637
638 FlashProgramCleanUp:
639     FlashCtl_disableWordProgramming();
640     return res;
641
642 }
643
644 void FlashCtl_setProgramVerification(uint32_t verificationSetting)
645 {
646     if ((verificationSetting & FLASH_BURSTPOST))
647         BITBAND_PERI(FLCTL->rPRGBRST_CTLSTAT.r, FLCTL_PRGBRST_CTLSTAT_AUTO_PST_OFS) =
648                 1;
649
650     if ((verificationSetting & FLASH_BURSTPRE))
651         BITBAND_PERI(FLCTL->rPRGBRST_CTLSTAT.r, FLCTL_PRGBRST_CTLSTAT_AUTO_PRE_OFS) =
652                 1;
653
654     if ((verificationSetting & FLASH_REGPRE))
655         BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_VER_PRE_OFS) = 1;
656
657     if ((verificationSetting & FLASH_REGPOST))
658         BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_VER_PST_OFS) = 1;
659 }
660
661 void FlashCtl_clearProgramVerification(uint32_t verificationSetting)
662 {
663     if ((verificationSetting & FLASH_BURSTPOST))
664         BITBAND_PERI(FLCTL->rPRGBRST_CTLSTAT.r, FLCTL_PRGBRST_CTLSTAT_AUTO_PST_OFS) =
665                 0;
666
667     if ((verificationSetting & FLASH_BURSTPRE))
668         BITBAND_PERI(FLCTL->rPRGBRST_CTLSTAT.r, FLCTL_PRGBRST_CTLSTAT_AUTO_PRE_OFS) =
669                 0;
670
671     if ((verificationSetting & FLASH_REGPRE))
672         BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_VER_PRE_OFS) = 0;
673
674     if ((verificationSetting & FLASH_REGPOST))
675         BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_VER_PST_OFS) = 0;
676
677 }
678
679 void FlashCtl_enableWordProgramming(uint32_t mode)
680 {
681     if (mode == FLASH_IMMEDIATE_WRITE_MODE)
682     {
683         BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_ENABLE_OFS) = 1;
684         BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_MODE_OFS) = 0;
685
686     } else if (mode == FLASH_COLLATED_WRITE_MODE)
687     {
688         BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_ENABLE_OFS) = 1;
689         BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_MODE_OFS) = 1;
690     }
691 }
692
693 void FlashCtl_disableWordProgramming(void)
694 {
695     BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_ENABLE_OFS) = 0;
696 }
697
698 uint32_t FlashCtl_isWordProgrammingEnabled(void)
699 {
700     if (!BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_ENABLE_OFS))
701     {
702         return 0;
703     } else if (BITBAND_PERI(FLCTL->rPRG_CTLSTAT.r, FLCTL_PRG_CTLSTAT_MODE_OFS))
704         return FLASH_COLLATED_WRITE_MODE;
705     else
706         return FLASH_IMMEDIATE_WRITE_MODE;
707 }
708
709 void FlashCtl_setWaitState(uint32_t flashBank, uint32_t waitState)
710 {
711     if (flashBank == FLASH_BANK0)
712     {
713         FLCTL->rBANK0_RDCTL.r =
714                 (FLCTL->rBANK0_RDCTL.r & ~FLCTL_BANK0_RDCTL_WAIT_M)
715                         | (waitState << 12);
716     } else if (flashBank == FLASH_BANK1)
717     {
718         FLCTL->rBANK1_RDCTL.r =
719                 (FLCTL->rBANK1_RDCTL.r & ~FLCTL_BANK1_RDCTL_WAIT_M)
720                         | (waitState << 12);
721     } else
722     {
723         ASSERT(false);
724     }
725 }
726
727 uint32_t FlashCtl_getWaitState(uint32_t flashBank)
728 {
729     if (flashBank == FLASH_BANK0)
730     {
731         return FLCTL->rBANK0_RDCTL.b.bWAIT;
732     } else if (flashBank == FLASH_BANK1)
733     {
734         return FLCTL->rBANK1_RDCTL.b.bWAIT;
735     } else
736     {
737         ASSERT(false);
738         return 0;
739     }
740 }
741
742 void FlashCtl_enableInterrupt(uint32_t flags)
743 {
744     FLCTL->rIE.r |= flags;
745 }
746
747 void FlashCtl_disableInterrupt(uint32_t flags)
748 {
749     FLCTL->rIE.r &= ~flags;
750 }
751
752 uint32_t FlashCtl_getInterruptStatus(void)
753 {
754     return FLCTL->rIFG.r;
755 }
756
757 uint32_t FlashCtl_getEnabledInterruptStatus(void)
758 {
759     return FlashCtl_getInterruptStatus() & FLCTL->rIE.r;
760 }
761
762 void FlashCtl_clearInterruptFlag(uint32_t flags)
763 {
764     FLCTL->rCLRIFG.r |= flags;
765 }
766
767 void FlashCtl_registerInterrupt(void (*intHandler)(void))
768 {
769     //
770     // Register the interrupt handler, returning an error if an error occurs.
771     //
772     Interrupt_registerInterrupt(INT_FLCTL, intHandler);
773
774     //
775     // Enable the system control interrupt.
776     //
777     Interrupt_enableInterrupt(INT_FLCTL);
778 }
779
780 void FlashCtl_unregisterInterrupt(void)
781 {
782     //
783     // Disable the interrupt.
784     //
785     Interrupt_disableInterrupt(INT_FLCTL);
786
787     //
788     // Unregister the interrupt handler.
789     //
790     Interrupt_unregisterInterrupt(INT_FLCTL);
791 }
792