| /* |
| * ------------------------------------------- |
| * MSP432 DriverLib - v3_10_00_09 |
| * ------------------------------------------- |
| * |
| * --COPYRIGHT--,BSD,BSD |
| * Copyright (c) 2014, Texas Instruments Incorporated |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * * Neither the name of Texas Instruments Incorporated nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
| * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * --/COPYRIGHT--*/ |
| /* Standard Includes */ |
| #include <stdint.h> |
| |
| /* DriverLib Includes */ |
| #include <flash.h> |
| #include <debug.h> |
| #include <interrupt.h> |
| #include <msp.h> |
| #include <cpu.h> |
| #include <rom.h> |
| #include <sysctl.h> |
| #include <hw_memmap.h> |
| |
| static const uint32_t MAX_ERASE_NO_TLV = 50; |
| static const uint32_t MAX_PROGRAM_NO_TLV = 5; |
| |
| static volatile uint32_t* __getBurstProgramRegs[16] = |
| { &FLCTL->PRGBRST_DATA0_0, &FLCTL->PRGBRST_DATA0_1, |
| &FLCTL->PRGBRST_DATA0_2, &FLCTL->PRGBRST_DATA0_3, |
| &FLCTL->PRGBRST_DATA1_0, &FLCTL->PRGBRST_DATA1_1, |
| &FLCTL->PRGBRST_DATA1_2, &FLCTL->PRGBRST_DATA1_3, |
| &FLCTL->PRGBRST_DATA2_0, &FLCTL->PRGBRST_DATA2_1, |
| &FLCTL->PRGBRST_DATA2_2, &FLCTL->PRGBRST_DATA2_3, |
| &FLCTL->PRGBRST_DATA3_0, &FLCTL->PRGBRST_DATA3_1, |
| &FLCTL->PRGBRST_DATA3_2, &FLCTL->PRGBRST_DATA3_3 }; |
| |
| static uint32_t getUserFlashSector(uint32_t addr) |
| { |
| if (addr > 0x1ffff) |
| { |
| addr = addr - 0x20000; |
| } |
| |
| switch (addr) |
| { |
| case 0: |
| return FLASH_SECTOR0; |
| case 0x1000: |
| return FLASH_SECTOR1; |
| case 0x2000: |
| return FLASH_SECTOR2; |
| case 0x3000: |
| return FLASH_SECTOR3; |
| case 0x4000: |
| return FLASH_SECTOR4; |
| case 0x5000: |
| return FLASH_SECTOR5; |
| case 0x6000: |
| return FLASH_SECTOR6; |
| case 0x7000: |
| return FLASH_SECTOR7; |
| case 0x8000: |
| return FLASH_SECTOR8; |
| case 0x9000: |
| return FLASH_SECTOR9; |
| case 0xA000: |
| return FLASH_SECTOR10; |
| case 0xB000: |
| return FLASH_SECTOR11; |
| case 0xC000: |
| return FLASH_SECTOR12; |
| case 0xD000: |
| return FLASH_SECTOR13; |
| case 0xE000: |
| return FLASH_SECTOR14; |
| case 0xF000: |
| return FLASH_SECTOR15; |
| case 0x10000: |
| return FLASH_SECTOR16; |
| case 0x11000: |
| return FLASH_SECTOR17; |
| case 0x12000: |
| return FLASH_SECTOR18; |
| case 0x13000: |
| return FLASH_SECTOR19; |
| case 0x14000: |
| return FLASH_SECTOR20; |
| case 0x15000: |
| return FLASH_SECTOR21; |
| case 0x16000: |
| return FLASH_SECTOR22; |
| case 0x17000: |
| return FLASH_SECTOR23; |
| case 0x18000: |
| return FLASH_SECTOR24; |
| case 0x19000: |
| return FLASH_SECTOR25; |
| case 0x1A000: |
| return FLASH_SECTOR26; |
| case 0x1B000: |
| return FLASH_SECTOR27; |
| case 0x1C000: |
| return FLASH_SECTOR28; |
| case 0x1D000: |
| return FLASH_SECTOR29; |
| case 0x1E000: |
| return FLASH_SECTOR30; |
| case 0x1F000: |
| return FLASH_SECTOR31; |
| default: |
| ASSERT(false); |
| return 0; |
| } |
| } |
| |
| void FlashCtl_getMemoryInfo(uint32_t addr, uint32_t *sectorNum, |
| uint32_t *bankNum) |
| { |
| uint32_t bankLimit; |
| |
| bankLimit = SysCtl_getFlashSize() / 2; |
| |
| if (addr > bankLimit) |
| { |
| *(sectorNum) = FLASH_BANK1; |
| addr = (addr - bankLimit); |
| } else |
| { |
| *(sectorNum) = FLASH_BANK0; |
| } |
| |
| *(bankNum) = (addr - __MAIN_MEMORY_START__) / 4096; |
| } |
| |
| static bool _FlashCtl_Program8(uint32_t src, uint32_t dest, uint32_t mTries) |
| { |
| uint32_t ii; |
| uint8_t data; |
| |
| /* Enabling the correct verification settings */ |
| FlashCtl_setProgramVerification(FLASH_REGPRE | FLASH_REGPOST); |
| FlashCtl_clearProgramVerification(FLASH_BURSTPOST | FLASH_BURSTPRE); |
| |
| data = HWREG8(src); |
| |
| for (ii = 0; ii < mTries; ii++) |
| { |
| /* Clearing flags */ |
| FLCTL->CLRIFG |= (FLASH_PROGRAM_ERROR | FLASH_POSTVERIFY_FAILED |
| | FLASH_PREVERIFY_FAILED | FLASH_WRDPRGM_COMPLETE); |
| |
| HWREG8(dest) = data; |
| |
| while (!(FlashCtl_getInterruptStatus() & FLASH_WRDPRGM_COMPLETE)) |
| { |
| __no_operation(); |
| } |
| |
| /* Pre-Verify */ |
| if ((BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_VER_PRE_OFS) |
| && BITBAND_PERI(FLCTL->IFG, FLCTL_IFG_AVPRE_OFS))) |
| { |
| data = __FlashCtl_remaskData8Pre(data, dest); |
| |
| if (data != 0xFF) |
| { |
| FlashCtl_clearProgramVerification(FLASH_REGPRE); |
| continue; |
| } |
| |
| } |
| |
| /* Post Verify */ |
| if ((BITBAND_PERI(FLCTL->IFG, FLCTL_IFG_AVPST_OFS))) |
| { |
| data = __FlashCtl_remaskData8Post(data, dest); |
| |
| /* Seeing if we actually need to do another pulse */ |
| if (data == 0xFF) |
| return true; |
| |
| FlashCtl_setProgramVerification(FLASH_REGPRE | FLASH_REGPOST); |
| continue; |
| } |
| |
| /* If we got this far, return true */ |
| return true; |
| |
| } |
| |
| return false; |
| |
| } |
| |
| static bool _FlashCtl_Program32(uint32_t src, uint32_t dest, uint32_t mTries) |
| { |
| uint32_t ii; |
| uint32_t data; |
| |
| /* Enabling the correct verification settings */ |
| FlashCtl_setProgramVerification(FLASH_REGPRE | FLASH_REGPOST); |
| FlashCtl_clearProgramVerification(FLASH_BURSTPOST | FLASH_BURSTPRE); |
| |
| data = HWREG32(src); |
| |
| for (ii = 0; ii < mTries; ii++) |
| { |
| /* Clearing flags */ |
| FLCTL->CLRIFG |= (FLASH_PROGRAM_ERROR | FLASH_POSTVERIFY_FAILED |
| | FLASH_PREVERIFY_FAILED | FLASH_WRDPRGM_COMPLETE); |
| |
| HWREG32(dest) = data; |
| |
| while (!(FlashCtl_getInterruptStatus() & FLASH_WRDPRGM_COMPLETE)) |
| { |
| __no_operation(); |
| } |
| |
| /* Pre-Verify */ |
| if ((BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_VER_PRE_OFS) |
| && BITBAND_PERI(FLCTL->IFG, FLCTL_IFG_AVPRE_OFS))) |
| { |
| data = __FlashCtl_remaskData32Pre(data, dest); |
| |
| if (data != 0xFFFFFFFF) |
| { |
| |
| FlashCtl_clearProgramVerification(FLASH_REGPRE); |
| continue; |
| } |
| |
| } |
| |
| /* Post Verify */ |
| if ((BITBAND_PERI(FLCTL->IFG, FLCTL_IFG_AVPST_OFS))) |
| { |
| data = __FlashCtl_remaskData32Post(data, dest); |
| |
| /* Seeing if we actually need to do another pulse */ |
| if (data == 0xFFFFFFFF) |
| return true; |
| |
| FlashCtl_setProgramVerification(FLASH_REGPRE | FLASH_REGPOST); |
| continue; |
| } |
| |
| /* If we got this far, return true */ |
| return true; |
| |
| } |
| |
| return false; |
| |
| } |
| |
| static bool _FlashCtl_ProgramBurst(uint32_t src, uint32_t dest, uint32_t length, |
| uint32_t mTries) |
| { |
| uint32_t bCalc, otpOffset, ii, jj; |
| bool res; |
| |
| /* Setting verification */ |
| FlashCtl_clearProgramVerification(FLASH_REGPRE | FLASH_REGPOST); |
| FlashCtl_setProgramVerification(FLASH_BURSTPOST | FLASH_BURSTPRE); |
| |
| /* Assume Failure */ |
| res = false; |
| |
| /* Waiting for idle status */ |
| while ((FLCTL->PRGBRST_CTLSTAT & FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_MASK) |
| != FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_0) |
| { |
| BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_CLR_STAT_OFS) = 1; |
| } |
| |
| /* Setting/clearing INFO flash flags as appropriate */ |
| if (dest > __MAIN_MEMORY_END__) |
| { |
| FLCTL->PRGBRST_CTLSTAT = (FLCTL->PRGBRST_CTLSTAT |
| & ~FLCTL_PRGBRST_CTLSTAT_TYPE_MASK) | FLCTL_PRGBRST_CTLSTAT_TYPE_1; |
| otpOffset = __INFO_FLASH_TECH_START__; |
| } else |
| { |
| FLCTL->PRGBRST_CTLSTAT = (FLCTL->PRGBRST_CTLSTAT |
| & ~FLCTL_PRGBRST_CTLSTAT_TYPE_MASK) | FLCTL_PRGBRST_CTLSTAT_TYPE_0; |
| otpOffset = __MAIN_MEMORY_START__; |
| } |
| |
| bCalc = 0; |
| FLCTL->PRGBRST_STARTADDR = (dest - otpOffset); |
| |
| /* Initially populating the burst registers */ |
| while (bCalc < 16 && length != 0) |
| { |
| HWREG32(__getBurstProgramRegs[bCalc]) = HWREG32(src); |
| bCalc++; |
| length -= 4; |
| src += 4; |
| } |
| |
| for (ii = 0; ii < mTries; ii++) |
| { |
| /* Clearing Flags */ |
| FLCTL->CLRIFG |= (FLASH_BRSTPRGM_COMPLETE | FLASH_POSTVERIFY_FAILED |
| | FLASH_PREVERIFY_FAILED); |
| |
| /* Waiting for idle status */ |
| while ((FLCTL->PRGBRST_CTLSTAT & FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_MASK) |
| != FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_0) |
| { |
| BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_CLR_STAT_OFS) = 1; |
| } |
| |
| /* Start the burst program */ |
| FLCTL->PRGBRST_CTLSTAT = (FLCTL->PRGBRST_CTLSTAT |
| & ~(FLCTL_PRGBRST_CTLSTAT_LEN_MASK)) |
| | ((bCalc / 4) << FLASH_BURST_PRG_BIT) |
| | FLCTL_PRGBRST_CTLSTAT_START; |
| |
| /* Waiting for the burst to complete */ |
| while ((FLCTL->PRGBRST_CTLSTAT & |
| FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_MASK) |
| != FLASH_PRGBRSTCTLSTAT_BURSTSTATUS_COMPLETE) |
| { |
| __no_operation(); |
| } |
| |
| /* Checking for errors and clearing/masking */ |
| |
| /* Address Error */ |
| if (BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_ADDR_ERR_OFS)) |
| { |
| goto BurstCleanUp; |
| } |
| |
| /* Pre-Verify Error */ |
| if (BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_AUTO_PRE_OFS) && BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_PRE_ERR_OFS)) |
| { |
| __FlashCtl_remaskBurstDataPre(dest, bCalc * 4); |
| |
| for (jj = 0; jj < bCalc; jj++) |
| { |
| if (HWREG32(__getBurstProgramRegs[jj]) |
| != 0xFFFFFFFF) |
| { |
| FlashCtl_clearProgramVerification(FLASH_BURSTPRE); |
| break; |
| } |
| } |
| |
| if (jj != bCalc) |
| continue; |
| } |
| |
| /* Post-Verify Error */ |
| if (BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_PST_ERR_OFS)) |
| { |
| __FlashCtl_remaskBurstDataPost(dest, bCalc * 4); |
| |
| for (jj = 0; jj < bCalc; jj++) |
| { |
| if ((HWREG32(__getBurstProgramRegs[jj])) |
| != 0xFFFFFFFF) |
| { |
| FlashCtl_setProgramVerification( |
| FLASH_BURSTPOST | FLASH_BURSTPRE); |
| break; |
| } |
| } |
| |
| if (jj != bCalc) |
| continue; |
| |
| } |
| |
| /* If we got this far, the program happened */ |
| res = true; |
| goto BurstCleanUp; |
| } |
| |
| BurstCleanUp: |
| /* Waiting for idle status */ |
| while ((FLCTL->PRGBRST_CTLSTAT & FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_MASK) |
| != FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_0) |
| { |
| BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_CLR_STAT_OFS) = 1; |
| } |
| return res; |
| } |
| |
| void FlashCtl_enableReadBuffering(uint_fast8_t memoryBank, |
| uint_fast8_t accessMethod) |
| { |
| if (memoryBank == FLASH_BANK0 && accessMethod == FLASH_DATA_READ) |
| BITBAND_PERI(FLCTL->BANK0_RDCTL, FLCTL_BANK0_RDCTL_BUFD_OFS) = 1; |
| else if (memoryBank == FLASH_BANK1 && accessMethod == FLASH_DATA_READ) |
| BITBAND_PERI(FLCTL->BANK1_RDCTL, FLCTL_BANK1_RDCTL_BUFD_OFS) = 1; |
| else if (memoryBank == FLASH_BANK0 |
| && accessMethod == FLASH_INSTRUCTION_FETCH) |
| BITBAND_PERI(FLCTL->BANK0_RDCTL, FLCTL_BANK0_RDCTL_BUFI_OFS) = 1; |
| else if (memoryBank == FLASH_BANK1 |
| && accessMethod == FLASH_INSTRUCTION_FETCH) |
| BITBAND_PERI(FLCTL->BANK1_RDCTL, FLCTL_BANK1_RDCTL_BUFI_OFS) = 1; |
| else |
| ASSERT(false); |
| } |
| |
| void FlashCtl_disableReadBuffering(uint_fast8_t memoryBank, |
| uint_fast8_t accessMethod) |
| { |
| if (memoryBank == FLASH_BANK0 && accessMethod == FLASH_DATA_READ) |
| BITBAND_PERI(FLCTL->BANK0_RDCTL, FLCTL_BANK0_RDCTL_BUFD_OFS) = 0; |
| else if (memoryBank == FLASH_BANK1 && accessMethod == FLASH_DATA_READ) |
| BITBAND_PERI(FLCTL->BANK1_RDCTL, FLCTL_BANK1_RDCTL_BUFD_OFS) = 0; |
| else if (memoryBank == FLASH_BANK0 |
| && accessMethod == FLASH_INSTRUCTION_FETCH) |
| BITBAND_PERI(FLCTL->BANK0_RDCTL, FLCTL_BANK0_RDCTL_BUFI_OFS) = 0; |
| else if (memoryBank == FLASH_BANK1 |
| && accessMethod == FLASH_INSTRUCTION_FETCH) |
| BITBAND_PERI(FLCTL->BANK1_RDCTL, FLCTL_BANK1_RDCTL_BUFI_OFS) = 0; |
| else |
| ASSERT(false); |
| } |
| |
| bool FlashCtl_unprotectSector(uint_fast8_t memorySpace, uint32_t sectorMask) |
| { |
| switch (memorySpace) |
| { |
| case FLASH_MAIN_MEMORY_SPACE_BANK0: |
| FLCTL->BANK0_MAIN_WEPROT &= ~sectorMask; |
| break; |
| case FLASH_MAIN_MEMORY_SPACE_BANK1: |
| FLCTL->BANK1_MAIN_WEPROT &= ~sectorMask; |
| break; |
| case FLASH_INFO_MEMORY_SPACE_BANK0: |
| ASSERT(sectorMask <= 0x04); |
| FLCTL->BANK0_INFO_WEPROT &= ~sectorMask; |
| break; |
| case FLASH_INFO_MEMORY_SPACE_BANK1: |
| ASSERT(sectorMask <= 0x04); |
| FLCTL->BANK1_INFO_WEPROT &= ~sectorMask; |
| break; |
| |
| default: |
| ASSERT(false); |
| |
| } |
| |
| return !FlashCtl_isSectorProtected(memorySpace, sectorMask); |
| } |
| |
| bool FlashCtl_protectSector(uint_fast8_t memorySpace, uint32_t sectorMask) |
| { |
| switch (memorySpace) |
| { |
| case FLASH_MAIN_MEMORY_SPACE_BANK0: |
| FLCTL->BANK0_MAIN_WEPROT |= sectorMask; |
| break; |
| case FLASH_MAIN_MEMORY_SPACE_BANK1: |
| FLCTL->BANK1_MAIN_WEPROT |= sectorMask; |
| break; |
| case FLASH_INFO_MEMORY_SPACE_BANK0: |
| ASSERT(sectorMask <= 0x04); |
| FLCTL->BANK0_INFO_WEPROT |= sectorMask; |
| break; |
| case FLASH_INFO_MEMORY_SPACE_BANK1: |
| ASSERT(sectorMask <= 0x04); |
| FLCTL->BANK1_INFO_WEPROT |= sectorMask; |
| break; |
| |
| default: |
| ASSERT(false); |
| |
| } |
| |
| return FlashCtl_isSectorProtected(memorySpace, sectorMask); |
| } |
| |
| bool FlashCtl_isSectorProtected(uint_fast8_t memorySpace, uint32_t sector) |
| { |
| switch (memorySpace) |
| { |
| case FLASH_MAIN_MEMORY_SPACE_BANK0: |
| return FLCTL->BANK0_MAIN_WEPROT & sector; |
| case FLASH_MAIN_MEMORY_SPACE_BANK1: |
| return FLCTL->BANK1_MAIN_WEPROT & sector; |
| case FLASH_INFO_MEMORY_SPACE_BANK0: |
| ASSERT(sector <= 0x04); |
| return FLCTL->BANK0_INFO_WEPROT & sector; |
| case FLASH_INFO_MEMORY_SPACE_BANK1: |
| ASSERT(sector <= 0x04); |
| return FLCTL->BANK1_INFO_WEPROT & sector; |
| default: |
| return false; |
| } |
| } |
| |
| bool FlashCtl_verifyMemory(void* verifyAddr, uint32_t length, |
| uint_fast8_t pattern) |
| { |
| uint32_t memoryPattern, addr, otpOffset; |
| uint32_t b0WaitState, b1WaitState, intStatus; |
| uint32_t bankOneStart, startBank, endBank; |
| uint_fast8_t b0readMode, b1readMode; |
| uint_fast8_t memoryType; |
| bool res; |
| |
| ASSERT(pattern == FLASH_0_PATTERN || pattern == FLASH_1_PATTERN); |
| |
| /* Saving interrupt context and disabling interrupts for program |
| * operation |
| */ |
| intStatus = CPU_primask(); |
| Interrupt_disableMaster(); |
| |
| /* Casting and determining the memory that we need to use */ |
| addr = (uint32_t) verifyAddr; |
| memoryType = |
| (addr > __MAIN_MEMORY_END__) ? FLASH_INFO_SPACE : FLASH_MAIN_SPACE; |
| |
| /* Assuming Failure */ |
| res = false; |
| |
| /* Finding out which bank we are in */ |
| if(addr > SysCtl_getFlashSize()) |
| { |
| bankOneStart = __INFO_FLASH_TECH_MIDDLE__; |
| } |
| else |
| { |
| bankOneStart = SysCtl_getFlashSize() / 2; |
| } |
| startBank = addr < (bankOneStart) ? FLASH_BANK0 : FLASH_BANK1; |
| endBank = (addr + length) < (bankOneStart) ? FLASH_BANK0 : FLASH_BANK1; |
| |
| /* Saving context and changing read modes */ |
| b0WaitState = FlashCtl_getWaitState(startBank); |
| b0readMode = FlashCtl_getReadMode(startBank); |
| |
| /* Setting the wait state to account for the mode */ |
| FlashCtl_setWaitState(startBank, (2 * b0WaitState) + 1); |
| |
| if(startBank != endBank) |
| { |
| b1WaitState = FlashCtl_getWaitState(endBank); |
| b1readMode = FlashCtl_getReadMode(endBank); |
| FlashCtl_setWaitState(endBank, (2 * b1WaitState) + 1); |
| } |
| |
| /* Changing to the relevant VERIFY mode */ |
| if (pattern == FLASH_1_PATTERN) |
| { |
| FlashCtl_setReadMode(startBank, FLASH_ERASE_VERIFY_READ_MODE); |
| |
| if(startBank != endBank) |
| { |
| FlashCtl_setReadMode(endBank, FLASH_ERASE_VERIFY_READ_MODE); |
| } |
| |
| memoryPattern = 0xFFFFFFFF; |
| } else |
| { |
| FlashCtl_setReadMode(startBank, FLASH_PROGRAM_VERIFY_READ_MODE); |
| |
| if(startBank != endBank) |
| { |
| FlashCtl_setReadMode(endBank, FLASH_PROGRAM_VERIFY_READ_MODE); |
| } |
| |
| memoryPattern = 0; |
| } |
| |
| /* Taking care of byte accesses */ |
| while ((addr & 0x03) && (length > 0)) |
| { |
| if (HWREG8(addr++) != ((uint8_t) memoryPattern)) |
| goto FlashVerifyCleanup; |
| length--; |
| } |
| |
| /* Making sure we are aligned by 128-bit address */ |
| while (((addr & 0x0F)) && (length > 3)) |
| { |
| if (HWREG32(addr) != memoryPattern) |
| goto FlashVerifyCleanup; |
| |
| addr = addr + 4; |
| length = length - 4; |
| } |
| |
| /* Burst Verify */ |
| if (length > 63) |
| { |
| /* Setting/clearing INFO flash flags as appropriate */ |
| if (addr > __MAIN_MEMORY_END__) |
| { |
| FLCTL->RDBRST_CTLSTAT = (FLCTL->RDBRST_CTLSTAT |
| & ~FLCTL_RDBRST_CTLSTAT_MEM_TYPE_MASK) |
| | FLCTL_RDBRST_CTLSTAT_MEM_TYPE_1; |
| otpOffset = __INFO_FLASH_TECH_START__; |
| } else |
| { |
| FLCTL->RDBRST_CTLSTAT = (FLCTL->RDBRST_CTLSTAT |
| & ~FLCTL_RDBRST_CTLSTAT_MEM_TYPE_MASK) |
| | FLCTL_RDBRST_CTLSTAT_MEM_TYPE_0; |
| otpOffset = __MAIN_MEMORY_START__; |
| } |
| |
| /* Clearing any lingering fault flags and preparing burst verify*/ |
| BITBAND_PERI(FLCTL->RDBRST_CTLSTAT, |
| FLCTL_RDBRST_CTLSTAT_CLR_STAT_OFS) = 1; |
| FLCTL->RDBRST_FAILCNT = 0; |
| FLCTL->RDBRST_STARTADDR = addr - otpOffset; |
| FLCTL->RDBRST_LEN = (length & 0xFFFFFFF0); |
| addr += FLCTL->RDBRST_LEN; |
| length = length & 0xF; |
| |
| /* Starting Burst Verify */ |
| FLCTL->RDBRST_CTLSTAT = (FLCTL_RDBRST_CTLSTAT_STOP_FAIL | pattern |
| | memoryType | FLCTL_RDBRST_CTLSTAT_START); |
| |
| /* While the burst read hasn't finished */ |
| while ((FLCTL->RDBRST_CTLSTAT & FLCTL_RDBRST_CTLSTAT_BRST_STAT_MASK) |
| != FLCTL_RDBRST_CTLSTAT_BRST_STAT_3) |
| { |
| __no_operation(); |
| } |
| |
| /* Checking for a verification/access error/failure */ |
| if (BITBAND_PERI(FLCTL->RDBRST_CTLSTAT, |
| FLCTL_RDBRST_CTLSTAT_CMP_ERR_OFS) |
| || BITBAND_PERI(FLCTL->RDBRST_CTLSTAT, |
| FLCTL_RDBRST_CTLSTAT_ADDR_ERR_OFS) |
| || FLCTL->RDBRST_FAILCNT) |
| { |
| goto FlashVerifyCleanup; |
| } |
| } |
| |
| /* Remaining Words */ |
| while (length > 3) |
| { |
| if (HWREG32(addr) != memoryPattern) |
| goto FlashVerifyCleanup; |
| |
| addr = addr + 4; |
| length = length - 4; |
| } |
| |
| /* Remaining Bytes */ |
| while (length > 0) |
| { |
| if (HWREG8(addr++) != ((uint8_t) memoryPattern)) |
| goto FlashVerifyCleanup; |
| length--; |
| } |
| |
| /* If we got this far, that means it no failure happened */ |
| res = true; |
| |
| FlashVerifyCleanup: |
| |
| /* Clearing the Read Burst flag and returning */ |
| BITBAND_PERI(FLCTL->RDBRST_CTLSTAT, |
| FLCTL_RDBRST_CTLSTAT_CLR_STAT_OFS) = 1; |
| |
| FlashCtl_setReadMode(startBank, b0readMode); |
| FlashCtl_setWaitState(startBank, b0WaitState); |
| |
| if(startBank != endBank) |
| { |
| FlashCtl_setReadMode(endBank, b1readMode); |
| FlashCtl_setWaitState(endBank, b1WaitState); |
| } |
| |
| if(intStatus == 0) |
| Interrupt_enableMaster(); |
| |
| return res; |
| } |
| |
| bool FlashCtl_setReadMode(uint32_t flashBank, uint32_t readMode) |
| { |
| |
| if (FLCTL->POWER_STAT & FLCTL_POWER_STAT_RD_2T) |
| return false; |
| |
| if (flashBank == FLASH_BANK0) |
| { |
| FLCTL->BANK0_RDCTL = (FLCTL->BANK0_RDCTL |
| & ~FLCTL_BANK0_RDCTL_RD_MODE_MASK) | readMode; |
| while ((FLCTL->BANK0_RDCTL & FLCTL_BANK0_RDCTL_RD_MODE_MASK) |
| != readMode) |
| ; |
| } else if (flashBank == FLASH_BANK1) |
| { |
| FLCTL->BANK1_RDCTL = (FLCTL->BANK1_RDCTL |
| & ~FLCTL_BANK1_RDCTL_RD_MODE_MASK) | readMode; |
| while ((FLCTL->BANK1_RDCTL & FLCTL_BANK1_RDCTL_RD_MODE_MASK) |
| != readMode) |
| ; |
| } else |
| { |
| ASSERT(false); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| uint32_t FlashCtl_getReadMode(uint32_t flashBank) |
| { |
| if (flashBank == FLASH_BANK0) |
| { |
| return (FLCTL->BANK0_RDCTL & FLCTL_BANK0_RDCTL_RD_MODE_MASK); |
| } else if (flashBank == FLASH_BANK1) |
| { |
| return (FLCTL->BANK1_RDCTL & FLCTL_BANK1_RDCTL_RD_MODE_MASK); |
| } else |
| { |
| ASSERT(false); |
| return 0; |
| } |
| } |
| |
| void FlashCtl_initiateMassErase(void) |
| { |
| /* Clearing old mass erase flags */ |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, FLCTL_ERASE_CTLSTAT_CLR_STAT_OFS) = 1; |
| |
| /* Performing the mass erase */ |
| FLCTL->ERASE_CTLSTAT |= (FLCTL_ERASE_CTLSTAT_MODE |
| | FLCTL_ERASE_CTLSTAT_START); |
| } |
| |
| bool FlashCtl_performMassErase(void) |
| { |
| uint32_t userFlash, ii, sector, intStatus; |
| bool res; |
| |
| /* Saving interrupt context and disabling interrupts for program |
| * operation |
| */ |
| intStatus = CPU_primask(); |
| Interrupt_disableMaster(); |
| |
| /* Assume Failure */ |
| res = false; |
| |
| /* Clearing old mass erase flags */ |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, FLCTL_ERASE_CTLSTAT_CLR_STAT_OFS) = 1; |
| |
| /* Performing the mass erase */ |
| FLCTL->ERASE_CTLSTAT |= (FLCTL_ERASE_CTLSTAT_MODE |
| | FLCTL_ERASE_CTLSTAT_START); |
| |
| while ((FLCTL->ERASE_CTLSTAT & FLCTL_ERASE_CTLSTAT_STATUS_MASK) |
| == FLCTL_ERASE_CTLSTAT_STATUS_1 |
| || (FLCTL->ERASE_CTLSTAT & FLCTL_ERASE_CTLSTAT_STATUS_MASK) |
| == FLCTL_ERASE_CTLSTAT_STATUS_2) |
| { |
| __no_operation(); |
| } |
| |
| /* Return false if an address error */ |
| if (BITBAND_PERI(FLCTL->ERASE_CTLSTAT, FLCTL_ERASE_CTLSTAT_ADDR_ERR_OFS)) |
| goto MassEraseCleanup; |
| |
| /* Changing to erase verify */ |
| userFlash = SysCtl_getFlashSize() / 2; |
| |
| for (ii = __MAIN_MEMORY_START__; ii < userFlash; ii += 4096) |
| { |
| sector = getUserFlashSector(ii); |
| |
| if (!((FLCTL->BANK0_MAIN_WEPROT) & sector)) |
| { |
| if (!FlashCtl_verifyMemory((void*) ii, 4096, FLASH_1_PATTERN)) |
| { |
| if (!FlashCtl_eraseSector(ii)) |
| goto MassEraseCleanup; |
| } |
| } |
| |
| if (!(FLCTL->BANK1_MAIN_WEPROT & sector)) |
| { |
| if (!FlashCtl_verifyMemory((void*) (ii + userFlash), 4096, |
| FLASH_1_PATTERN)) |
| { |
| if (!FlashCtl_eraseSector(ii + userFlash)) |
| goto MassEraseCleanup; |
| } |
| } |
| |
| if (sector < FLCTL_BANK0_MAIN_WEPROT_PROT2) |
| { |
| if (!(FLCTL->BANK0_INFO_WEPROT & sector)) |
| { |
| if (!FlashCtl_verifyMemory( |
| (void*) (ii + __INFO_FLASH_TECH_START__), 4096, |
| FLASH_1_PATTERN)) |
| { |
| if (!FlashCtl_eraseSector(ii + __INFO_FLASH_TECH_START__)) |
| goto MassEraseCleanup; |
| } |
| } |
| |
| if (!(FLCTL->BANK1_INFO_WEPROT & sector)) |
| { |
| if (!FlashCtl_verifyMemory((void*) (ii + (0x202000)), 4096, |
| FLASH_1_PATTERN)) |
| { |
| if (!FlashCtl_eraseSector(ii + (0x202000))) |
| goto MassEraseCleanup; |
| } |
| } |
| |
| } |
| } |
| |
| /* If we got this far, the mass erase happened */ |
| res = true; |
| |
| MassEraseCleanup: |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, FLCTL_ERASE_CTLSTAT_CLR_STAT_OFS) = 1; |
| |
| if(intStatus == 0) |
| Interrupt_enableMaster(); |
| |
| return res; |
| } |
| |
| bool FlashCtl_eraseSector(uint32_t addr) |
| { |
| uint_fast8_t memoryType, ii; |
| uint32_t otpOffset = 0; |
| uint32_t intStatus; |
| uint_fast8_t mTries, tlvLength; |
| SysCtl_FlashTLV_Info *flInfo; |
| bool res; |
| |
| /* Saving interrupt context and disabling interrupts for program |
| * operation |
| */ |
| intStatus = CPU_primask(); |
| Interrupt_disableMaster(); |
| |
| /* Assuming Failure */ |
| res = false; |
| |
| memoryType = |
| addr > __MAIN_MEMORY_END__ ? FLASH_INFO_SPACE : FLASH_MAIN_SPACE; |
| |
| /* Parsing the TLV and getting the maximum erase pulses */ |
| SysCtl_getTLVInfo(TLV_TAG_FLASHCTL, 0, &tlvLength, (uint32_t**) &flInfo); |
| |
| if (tlvLength == 0 || flInfo->maxErasePulses == 0) |
| { |
| mTries = MAX_ERASE_NO_TLV; |
| } else |
| { |
| mTries = flInfo->maxErasePulses; |
| } |
| |
| /* We can only erase on 4KB boundaries */ |
| while (addr & 0xFFF) |
| { |
| addr--; |
| } |
| |
| /* Clearing the status */ |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, FLCTL_ERASE_CTLSTAT_CLR_STAT_OFS) = 1; |
| |
| if (memoryType == FLASH_INFO_SPACE) |
| { |
| otpOffset = __INFO_FLASH_TECH_START__; |
| FLCTL->ERASE_CTLSTAT = (FLCTL->ERASE_CTLSTAT |
| & ~(FLCTL_ERASE_CTLSTAT_TYPE_MASK)) | FLCTL_ERASE_CTLSTAT_TYPE_1; |
| |
| } else |
| { |
| otpOffset = __MAIN_MEMORY_START__; |
| FLCTL->ERASE_CTLSTAT = (FLCTL->ERASE_CTLSTAT |
| & ~(FLCTL_ERASE_CTLSTAT_TYPE_MASK)) | FLCTL_ERASE_CTLSTAT_TYPE_0; |
| } |
| |
| /* Clearing old flags and setting up the erase */ |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, FLCTL_ERASE_CTLSTAT_MODE_OFS) = 0; |
| FLCTL->ERASE_SECTADDR = addr - otpOffset; |
| |
| for (ii = 0; ii < mTries; ii++) |
| { |
| /* Clearing the status */ |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, FLCTL_ERASE_CTLSTAT_CLR_STAT_OFS) = |
| 1; |
| |
| /* Starting the erase */ |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, |
| FLCTL_ERASE_CTLSTAT_START_OFS) = 1; |
| |
| while ((FLCTL->ERASE_CTLSTAT & FLCTL_ERASE_CTLSTAT_STATUS_MASK) |
| == FLCTL_ERASE_CTLSTAT_STATUS_1 |
| || (FLCTL->ERASE_CTLSTAT & FLCTL_ERASE_CTLSTAT_STATUS_MASK) |
| == FLCTL_ERASE_CTLSTAT_STATUS_2) |
| { |
| __no_operation(); |
| } |
| |
| /* Return false if an address error */ |
| if (BITBAND_PERI(FLCTL->ERASE_CTLSTAT, |
| FLCTL_ERASE_CTLSTAT_ADDR_ERR_OFS)) |
| { |
| goto SectorEraseCleanup; |
| } |
| /* Erase verifying */ |
| if (FlashCtl_verifyMemory((void*) addr, 4096, FLASH_1_PATTERN)) |
| { |
| res = true; |
| goto SectorEraseCleanup; |
| } |
| |
| } |
| |
| SectorEraseCleanup: |
| |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, FLCTL_ERASE_CTLSTAT_CLR_STAT_OFS) = 1; |
| |
| if(intStatus == 0) |
| Interrupt_enableMaster(); |
| |
| return res; |
| } |
| |
| void FlashCtl_initiateSectorErase(uint32_t addr) |
| { |
| uint_fast8_t memoryType; |
| uint32_t otpOffset = 0; |
| |
| memoryType = |
| addr > __MAIN_MEMORY_END__ ? FLASH_INFO_SPACE : FLASH_MAIN_SPACE; |
| |
| /* We can only erase on 4KB boundaries */ |
| while (addr & 0xFFF) |
| { |
| addr--; |
| } |
| |
| /* Clearing the status */ |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, FLCTL_ERASE_CTLSTAT_CLR_STAT_OFS) = 1; |
| |
| if (memoryType == FLASH_INFO_SPACE) |
| { |
| otpOffset = __INFO_FLASH_TECH_START__; |
| FLCTL->ERASE_CTLSTAT = (FLCTL->ERASE_CTLSTAT |
| & ~(FLCTL_ERASE_CTLSTAT_TYPE_MASK)) | FLCTL_ERASE_CTLSTAT_TYPE_1; |
| |
| } else |
| { |
| otpOffset = __MAIN_MEMORY_START__; |
| FLCTL->ERASE_CTLSTAT = (FLCTL->ERASE_CTLSTAT |
| & ~(FLCTL_ERASE_CTLSTAT_TYPE_MASK)) | FLCTL_ERASE_CTLSTAT_TYPE_0; |
| } |
| |
| /* Clearing old flags and setting up the erase */ |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, FLCTL_ERASE_CTLSTAT_MODE_OFS) = 0; |
| FLCTL->ERASE_SECTADDR = addr - otpOffset; |
| |
| /* Starting the erase */ |
| BITBAND_PERI(FLCTL->ERASE_CTLSTAT, |
| FLCTL_ERASE_CTLSTAT_START_OFS) = 1; |
| |
| } |
| |
| bool FlashCtl_programMemory(void* src, void* dest, uint32_t length) |
| { |
| uint32_t destAddr, srcAddr, burstLength, intStatus; |
| bool res; |
| uint_fast8_t mTries, tlvLength; |
| SysCtl_FlashTLV_Info *flInfo; |
| |
| /* Saving interrupt context and disabling interrupts for program |
| * operation |
| */ |
| intStatus = CPU_primask(); |
| Interrupt_disableMaster(); |
| |
| /* Parsing the TLV and getting the maximum erase pulses */ |
| SysCtl_getTLVInfo(TLV_TAG_FLASHCTL, 0, &tlvLength, (uint32_t**) &flInfo); |
| |
| if (tlvLength == 0 || flInfo->maxProgramPulses == 0) |
| { |
| mTries = MAX_PROGRAM_NO_TLV; |
| } else |
| { |
| mTries = flInfo->maxProgramPulses; |
| } |
| |
| /* Casting to integers */ |
| srcAddr = (uint32_t) src; |
| destAddr = (uint32_t) dest; |
| |
| /* Enabling word programming */ |
| FlashCtl_enableWordProgramming(FLASH_IMMEDIATE_WRITE_MODE); |
| |
| /* Assume failure */ |
| res = false; |
| |
| /* Taking care of byte accesses */ |
| while ((destAddr & 0x03) && length > 0) |
| { |
| if (!_FlashCtl_Program8(srcAddr, destAddr, mTries)) |
| { |
| goto FlashProgramCleanUp; |
| } else |
| { |
| srcAddr++; |
| destAddr++; |
| length--; |
| } |
| } |
| |
| /* Taking care of word accesses */ |
| while ((destAddr & 0x0F) && (length > 3)) |
| { |
| if (!_FlashCtl_Program32(srcAddr, destAddr, mTries)) |
| { |
| goto FlashProgramCleanUp; |
| } else |
| { |
| srcAddr += 4; |
| destAddr += 4; |
| length -= 4; |
| } |
| } |
| |
| /* Taking care of burst programs */ |
| while (length > 16) |
| { |
| burstLength = length > 63 ? 64 : length & 0xFFFFFFF0; |
| |
| if (!_FlashCtl_ProgramBurst(srcAddr, destAddr, burstLength, mTries)) |
| { |
| goto FlashProgramCleanUp; |
| } else |
| { |
| srcAddr += burstLength; |
| destAddr += burstLength; |
| length -= burstLength; |
| } |
| } |
| |
| /* Remaining word accesses */ |
| while (length > 3) |
| { |
| if (!_FlashCtl_Program32(srcAddr, destAddr, mTries)) |
| { |
| goto FlashProgramCleanUp; |
| } else |
| { |
| srcAddr+=4; |
| destAddr+=4; |
| length-=4; |
| } |
| } |
| |
| /* Remaining byte accesses */ |
| while (length > 0) |
| { |
| if (!_FlashCtl_Program8(srcAddr, destAddr, mTries)) |
| { |
| goto FlashProgramCleanUp; |
| } else |
| { |
| srcAddr++; |
| destAddr++; |
| length--; |
| } |
| } |
| |
| /* If we got this far that means that we succeeded */ |
| res = true; |
| |
| FlashProgramCleanUp: |
| |
| if(intStatus == 0) |
| Interrupt_enableMaster(); |
| |
| FlashCtl_disableWordProgramming(); |
| return res; |
| |
| } |
| void FlashCtl_setProgramVerification(uint32_t verificationSetting) |
| { |
| if ((verificationSetting & FLASH_BURSTPOST)) |
| BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_AUTO_PST_OFS) = 1; |
| |
| if ((verificationSetting & FLASH_BURSTPRE)) |
| BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_AUTO_PRE_OFS) = 1; |
| |
| if ((verificationSetting & FLASH_REGPRE)) |
| BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_VER_PRE_OFS) = 1; |
| |
| if ((verificationSetting & FLASH_REGPOST)) |
| BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_VER_PST_OFS) = 1; |
| } |
| |
| void FlashCtl_clearProgramVerification(uint32_t verificationSetting) |
| { |
| if ((verificationSetting & FLASH_BURSTPOST)) |
| BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_AUTO_PST_OFS) = 0; |
| |
| if ((verificationSetting & FLASH_BURSTPRE)) |
| BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_AUTO_PRE_OFS) = 0; |
| |
| if ((verificationSetting & FLASH_REGPRE)) |
| BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_VER_PRE_OFS) = 0; |
| |
| if ((verificationSetting & FLASH_REGPOST)) |
| BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_VER_PST_OFS) = 0; |
| |
| } |
| |
| void FlashCtl_enableWordProgramming(uint32_t mode) |
| { |
| if (mode == FLASH_IMMEDIATE_WRITE_MODE) |
| { |
| BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_ENABLE_OFS) = 1; |
| BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_MODE_OFS) = 0; |
| |
| } else if (mode == FLASH_COLLATED_WRITE_MODE) |
| { |
| BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_ENABLE_OFS) = 1; |
| BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_MODE_OFS) = 1; |
| } |
| } |
| |
| void FlashCtl_disableWordProgramming(void) |
| { |
| BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_ENABLE_OFS) = 0; |
| } |
| |
| uint32_t FlashCtl_isWordProgrammingEnabled(void) |
| { |
| if (!BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_ENABLE_OFS)) |
| { |
| return 0; |
| } else if (BITBAND_PERI(FLCTL->PRG_CTLSTAT, FLCTL_PRG_CTLSTAT_MODE_OFS)) |
| return FLASH_COLLATED_WRITE_MODE; |
| else |
| return FLASH_IMMEDIATE_WRITE_MODE; |
| } |
| |
| void FlashCtl_setWaitState(uint32_t flashBank, uint32_t waitState) |
| { |
| if (flashBank == FLASH_BANK0) |
| { |
| FLCTL->BANK0_RDCTL = (FLCTL->BANK0_RDCTL |
| & ~FLCTL_BANK0_RDCTL_WAIT_MASK) | (waitState << FLCTL_BANK0_RDCTL_WAIT_OFS); |
| } else if (flashBank == FLASH_BANK1) |
| { |
| FLCTL->BANK1_RDCTL = (FLCTL->BANK1_RDCTL |
| & ~FLCTL_BANK1_RDCTL_WAIT_MASK) | (waitState << FLCTL_BANK1_RDCTL_WAIT_OFS); |
| } else |
| { |
| ASSERT(false); |
| } |
| } |
| |
| uint32_t FlashCtl_getWaitState(uint32_t flashBank) |
| { |
| if (flashBank == FLASH_BANK0) |
| { |
| return (FLCTL->BANK0_RDCTL & FLCTL_BANK0_RDCTL_WAIT_MASK) >> FLCTL_BANK0_RDCTL_WAIT_OFS; |
| } else if (flashBank == FLASH_BANK1) |
| { |
| return (FLCTL->BANK1_RDCTL & FLCTL_BANK1_RDCTL_WAIT_MASK) >> FLCTL_BANK1_RDCTL_WAIT_OFS; |
| } else |
| { |
| ASSERT(false); |
| return 0; |
| } |
| } |
| |
| void FlashCtl_enableInterrupt(uint32_t flags) |
| { |
| FLCTL->IE |= flags; |
| } |
| |
| void FlashCtl_disableInterrupt(uint32_t flags) |
| { |
| FLCTL->IE &= ~flags; |
| } |
| |
| uint32_t FlashCtl_getInterruptStatus(void) |
| { |
| return FLCTL->IFG; |
| } |
| |
| uint32_t FlashCtl_getEnabledInterruptStatus(void) |
| { |
| return FlashCtl_getInterruptStatus() & FLCTL->IE; |
| } |
| |
| void FlashCtl_clearInterruptFlag(uint32_t flags) |
| { |
| FLCTL->CLRIFG |= flags; |
| } |
| |
| void FlashCtl_registerInterrupt(void (*intHandler)(void)) |
| { |
| // |
| // Register the interrupt handler, returning an error if an error occurs. |
| // |
| Interrupt_registerInterrupt(INT_FLCTL, intHandler); |
| |
| // |
| // Enable the system control interrupt. |
| // |
| Interrupt_enableInterrupt(INT_FLCTL); |
| } |
| |
| void FlashCtl_unregisterInterrupt(void) |
| { |
| // |
| // Disable the interrupt. |
| // |
| Interrupt_disableInterrupt(INT_FLCTL); |
| |
| // |
| // Unregister the interrupt handler. |
| // |
| Interrupt_unregisterInterrupt(INT_FLCTL); |
| } |
| |
| uint8_t __FlashCtl_remaskData8Post(uint8_t data, uint32_t addr) |
| { |
| uint32_t readMode, waitState, bankProgram, bankOneStart; |
| |
| /* Changing the waitstate and read mode of whichever bank we are in */ |
| /* Finding out which bank we are in */ |
| if(addr > SysCtl_getFlashSize()) |
| { |
| bankOneStart = __INFO_FLASH_TECH_MIDDLE__; |
| } |
| else |
| { |
| bankOneStart = SysCtl_getFlashSize() / 2; |
| } |
| |
| bankProgram = |
| addr < (bankOneStart) ? FLASH_BANK0 : FLASH_BANK1; |
| |
| /* Saving the current wait states and read mode */ |
| waitState = FlashCtl_getWaitState(bankProgram); |
| readMode = FlashCtl_getReadMode(bankProgram); |
| |
| /* Setting the wait state to account for the mode */ |
| FlashCtl_setWaitState(bankProgram, (2 * waitState) + 1); |
| |
| /* Changing to PROGRAM VERIFY mode */ |
| FlashCtl_setReadMode(bankProgram, FLASH_PROGRAM_VERIFY_READ_MODE); |
| |
| data = ~(~(data) & HWREG8(addr)); |
| |
| /* Setting the wait state to account for the mode */ |
| FlashCtl_setReadMode(bankProgram, readMode); |
| FlashCtl_setWaitState(bankProgram, waitState); |
| |
| return data; |
| } |
| |
| uint8_t __FlashCtl_remaskData8Pre(uint8_t data, uint32_t addr) |
| { |
| uint32_t readMode, waitState, bankProgram, bankOneStart; |
| |
| /* Changing the waitstate and read mode of whichever bank we are in */ |
| /* Finding out which bank we are in */ |
| if(addr > SysCtl_getFlashSize()) |
| { |
| bankOneStart = __INFO_FLASH_TECH_MIDDLE__; |
| } |
| else |
| { |
| bankOneStart = SysCtl_getFlashSize() / 2; |
| } |
| |
| bankProgram = |
| addr < (bankOneStart) ? FLASH_BANK0 : FLASH_BANK1; |
| |
| /* Saving the current wait states and read mode */ |
| waitState = FlashCtl_getWaitState(bankProgram); |
| readMode = FlashCtl_getReadMode(bankProgram); |
| |
| /* Setting the wait state to account for the mode */ |
| FlashCtl_setWaitState(bankProgram, (2 * waitState) + 1); |
| |
| /* Changing to PROGRAM VERIFY mode */ |
| FlashCtl_setReadMode(bankProgram, FLASH_PROGRAM_VERIFY_READ_MODE); |
| |
| data |= ~(HWREG8(addr) | data); |
| |
| /* Setting the wait state to account for the mode */ |
| FlashCtl_setReadMode(bankProgram, readMode); |
| FlashCtl_setWaitState(bankProgram, waitState); |
| |
| return data; |
| } |
| |
| uint32_t __FlashCtl_remaskData32Post(uint32_t data, uint32_t addr) |
| { |
| uint32_t bankProgramStart, bankProgramEnd, bank1Start; |
| uint32_t b0WaitState, b0ReadMode, b1WaitState, b1ReadMode; |
| |
| /* Changing the waitstate and read mode of whichever bank we are in */ |
| /* Finding out which bank we are in */ |
| if(addr > SysCtl_getFlashSize()) |
| { |
| bank1Start = __INFO_FLASH_TECH_MIDDLE__; |
| } |
| else |
| { |
| bank1Start = SysCtl_getFlashSize() / 2; |
| } |
| |
| bankProgramStart = addr < bank1Start ? FLASH_BANK0 : FLASH_BANK1; |
| bankProgramEnd = (addr + 4) < bank1Start ? FLASH_BANK0 : FLASH_BANK1; |
| |
| /* Saving the current wait states and read mode */ |
| b0WaitState = FlashCtl_getWaitState(bankProgramStart); |
| b0ReadMode = FlashCtl_getReadMode(bankProgramStart); |
| FlashCtl_setWaitState(bankProgramStart, (2 * b0WaitState) + 1); |
| FlashCtl_setReadMode(bankProgramStart, FLASH_PROGRAM_VERIFY_READ_MODE); |
| |
| if (bankProgramStart != bankProgramEnd) |
| { |
| b1WaitState = FlashCtl_getWaitState(bankProgramEnd); |
| b1ReadMode = FlashCtl_getReadMode(bankProgramEnd); |
| FlashCtl_setWaitState(bankProgramEnd, (2 * b1WaitState) + 1); |
| FlashCtl_setReadMode(bankProgramEnd, FLASH_PROGRAM_VERIFY_READ_MODE); |
| } |
| |
| data = ~(~(data) & HWREG32(addr)); |
| |
| /* Setting the wait state to account for the mode */ |
| FlashCtl_setReadMode(bankProgramStart, b0ReadMode); |
| FlashCtl_setWaitState(bankProgramStart, b0WaitState); |
| |
| if (bankProgramStart != bankProgramEnd) |
| { |
| FlashCtl_setReadMode(bankProgramEnd, b1ReadMode); |
| FlashCtl_setWaitState(bankProgramEnd, b1WaitState); |
| } |
| |
| return data; |
| } |
| |
| uint32_t __FlashCtl_remaskData32Pre(uint32_t data, uint32_t addr) |
| { |
| uint32_t bankProgramStart, bankProgramEnd, bank1Start; |
| uint32_t b0WaitState, b0ReadMode, b1WaitState, b1ReadMode; |
| |
| /* Changing the waitstate and read mode of whichever bank we are in */ |
| /* Finding out which bank we are in */ |
| if(addr > SysCtl_getFlashSize()) |
| { |
| bank1Start = __INFO_FLASH_TECH_MIDDLE__; |
| } |
| else |
| { |
| bank1Start = SysCtl_getFlashSize() / 2; |
| } |
| |
| bankProgramStart = addr < bank1Start ? FLASH_BANK0 : FLASH_BANK1; |
| bankProgramEnd = (addr + 4) < bank1Start ? FLASH_BANK0 : FLASH_BANK1; |
| |
| /* Saving the current wait states and read mode */ |
| b0WaitState = FlashCtl_getWaitState(bankProgramStart); |
| b0ReadMode = FlashCtl_getReadMode(bankProgramStart); |
| FlashCtl_setWaitState(bankProgramStart, (2 * b0WaitState) + 1); |
| FlashCtl_setReadMode(bankProgramStart, FLASH_PROGRAM_VERIFY_READ_MODE); |
| |
| if (bankProgramStart != bankProgramEnd) |
| { |
| b1WaitState = FlashCtl_getWaitState(bankProgramEnd); |
| b1ReadMode = FlashCtl_getReadMode(bankProgramEnd); |
| FlashCtl_setWaitState(bankProgramEnd, (2 * b1WaitState) + 1); |
| FlashCtl_setReadMode(bankProgramEnd, FLASH_PROGRAM_VERIFY_READ_MODE); |
| } |
| |
| data |= ~(HWREG32(addr) | data); |
| |
| /* Setting the wait state to account for the mode */ |
| FlashCtl_setReadMode(bankProgramStart, b0ReadMode); |
| FlashCtl_setWaitState(bankProgramStart, b0WaitState); |
| |
| if (bankProgramStart != bankProgramEnd) |
| { |
| FlashCtl_setReadMode(bankProgramEnd, b1ReadMode); |
| FlashCtl_setWaitState(bankProgramEnd, b1WaitState); |
| } |
| |
| return data; |
| } |
| |
| void __FlashCtl_remaskBurstDataPre(uint32_t addr, uint32_t size) |
| { |
| |
| uint32_t bankProgramStart, bankProgramEnd, bank1Start, ii; |
| uint32_t b0WaitState, b0ReadMode, b1WaitState, b1ReadMode; |
| |
| /* Waiting for idle status */ |
| while ((FLCTL->PRGBRST_CTLSTAT & FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_MASK) |
| != FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_0) |
| { |
| BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_CLR_STAT_OFS) = 1; |
| } |
| |
| /* Changing the waitstate and read mode of whichever bank we are in */ |
| /* Finding out which bank we are in */ |
| if(addr > SysCtl_getFlashSize()) |
| { |
| bank1Start = __INFO_FLASH_TECH_MIDDLE__; |
| } |
| else |
| { |
| bank1Start = SysCtl_getFlashSize() / 2; |
| } |
| |
| bankProgramStart = addr < bank1Start ? FLASH_BANK0 : FLASH_BANK1; |
| bankProgramEnd = (addr + size) < bank1Start ? FLASH_BANK0 : FLASH_BANK1; |
| |
| /* Saving the current wait states and read mode */ |
| b0WaitState = FlashCtl_getWaitState(bankProgramStart); |
| b0ReadMode = FlashCtl_getReadMode(bankProgramStart); |
| FlashCtl_setWaitState(bankProgramStart, (2 * b0WaitState) + 1); |
| FlashCtl_setReadMode(bankProgramStart, FLASH_PROGRAM_VERIFY_READ_MODE); |
| |
| if (bankProgramStart != bankProgramEnd) |
| { |
| b1WaitState = FlashCtl_getWaitState(bankProgramEnd); |
| b1ReadMode = FlashCtl_getReadMode(bankProgramEnd); |
| FlashCtl_setWaitState(bankProgramEnd, (2 * b1WaitState) + 1); |
| FlashCtl_setReadMode(bankProgramEnd, FLASH_PROGRAM_VERIFY_READ_MODE); |
| } |
| |
| /* Going through each BURST program register and masking out for pre |
| * verifcation |
| */ |
| size = (size / 4); |
| for (ii = 0; ii < size; ii++) |
| { |
| HWREG32(__getBurstProgramRegs[ii]) |= |
| ~(HWREG32(__getBurstProgramRegs[ii]) |
| | HWREG32(addr)); |
| addr += 4; |
| } |
| |
| /* Setting the wait state to account for the mode */ |
| FlashCtl_setReadMode(bankProgramStart, b0ReadMode); |
| FlashCtl_setWaitState(bankProgramStart, b0WaitState); |
| |
| if (bankProgramStart != bankProgramEnd) |
| { |
| FlashCtl_setReadMode(bankProgramEnd, b1ReadMode); |
| FlashCtl_setWaitState(bankProgramEnd, b1WaitState); |
| } |
| |
| } |
| void __FlashCtl_remaskBurstDataPost(uint32_t addr, uint32_t size) |
| { |
| uint32_t bankProgramStart, bankProgramEnd, bank1Start, ii; |
| uint32_t b0WaitState, b0ReadMode, b1WaitState, b1ReadMode; |
| |
| /* Waiting for idle status */ |
| while ((FLCTL->PRGBRST_CTLSTAT & FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_MASK) |
| != FLCTL_PRGBRST_CTLSTAT_BURST_STATUS_0) |
| { |
| BITBAND_PERI(FLCTL->PRGBRST_CTLSTAT, |
| FLCTL_PRGBRST_CTLSTAT_CLR_STAT_OFS) = 1; |
| } |
| |
| /* Changing the waitstate and read mode of whichever bank we are in */ |
| /* Finding out which bank we are in */ |
| if(addr > SysCtl_getFlashSize()) |
| { |
| bank1Start = __INFO_FLASH_TECH_MIDDLE__; |
| } |
| else |
| { |
| bank1Start = SysCtl_getFlashSize() / 2; |
| } |
| |
| bankProgramStart = addr < bank1Start ? FLASH_BANK0 : FLASH_BANK1; |
| bankProgramEnd = (addr + size) < bank1Start ? FLASH_BANK0 : FLASH_BANK1; |
| |
| /* Saving the current wait states and read mode */ |
| b0WaitState = FlashCtl_getWaitState(bankProgramStart); |
| b0ReadMode = FlashCtl_getReadMode(bankProgramStart); |
| FlashCtl_setWaitState(bankProgramStart, (2 * b0WaitState) + 1); |
| FlashCtl_setReadMode(bankProgramStart, FLASH_PROGRAM_VERIFY_READ_MODE); |
| |
| if (bankProgramStart != bankProgramEnd) |
| { |
| b1WaitState = FlashCtl_getWaitState(bankProgramEnd); |
| b1ReadMode = FlashCtl_getReadMode(bankProgramEnd); |
| FlashCtl_setWaitState(bankProgramEnd, (2 * b1WaitState) + 1); |
| FlashCtl_setReadMode(bankProgramEnd, FLASH_PROGRAM_VERIFY_READ_MODE); |
| } |
| |
| /* Going through each BURST program register and masking out for post |
| * verifcation if needed |
| */ |
| size = (size / 4); |
| for (ii = 0; ii < size; ii++) |
| { |
| HWREG32(__getBurstProgramRegs[ii]) = ~(~(HWREG32( |
| __getBurstProgramRegs[ii])) & HWREG32(addr)); |
| |
| addr += 4; |
| } |
| |
| /* Setting the wait state to account for the mode */ |
| FlashCtl_setReadMode(bankProgramStart, b0ReadMode); |
| FlashCtl_setWaitState(bankProgramStart, b0WaitState); |
| |
| if (bankProgramStart != bankProgramEnd) |
| { |
| FlashCtl_setReadMode(bankProgramEnd, b1ReadMode); |
| FlashCtl_setWaitState(bankProgramEnd, b1WaitState); |
| } |
| } |