diff options
Diffstat (limited to 'c/src/lib/libbsp/arm/atsam/libraries/libchip/source/flashd.c')
-rw-r--r-- | c/src/lib/libbsp/arm/atsam/libraries/libchip/source/flashd.c | 595 |
1 files changed, 0 insertions, 595 deletions
diff --git a/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/flashd.c b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/flashd.c deleted file mode 100644 index 298b16ac17..0000000000 --- a/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/flashd.c +++ /dev/null @@ -1,595 +0,0 @@ -/* ---------------------------------------------------------------------------- */ -/* Atmel Microcontroller Software Support */ -/* SAM Software Package License */ -/* ---------------------------------------------------------------------------- */ -/* Copyright (c) 2015, Atmel Corporation */ -/* */ -/* All rights reserved. */ -/* */ -/* Redistribution and use in source and binary forms, with or without */ -/* modification, are permitted provided that the following condition is met: */ -/* */ -/* - Redistributions of source code must retain the above copyright notice, */ -/* this list of conditions and the disclaimer below. */ -/* */ -/* Atmel's name may not be used to endorse or promote products derived from */ -/* this software without specific prior written permission. */ -/* */ -/* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ -/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ -/* DISCLAIMED. IN NO EVENT SHALL ATMEL 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. */ -/* ---------------------------------------------------------------------------- */ - -/** \addtogroup flashd_module Flash Memory Interface - * The flash driver manages the programming, erasing, locking and unlocking - * sequences with dedicated commands. - * - * To implement flash programming operation, the user has to follow these few - * steps : - * <ul> - * <li>Configure flash wait states to initializes the flash. </li> - * <li>Checks whether a region to be programmed is locked. </li> - * <li>Unlocks the user region to be programmed if the region have locked - * before.</li> - * <li>Erases the user page before program (optional).</li> - * <li>Writes the user page from the page buffer.</li> - * <li>Locks the region of programmed area if any.</li> - * </ul> - * - * Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable - * data corruption. - * A check of this validity and padding for 32-bit alignment should be done in - * write algorithm. - * Lock/unlock range associated with the user address range is automatically - * translated. - * - * This security bit can be enabled through the command "Set General Purpose - * NVM Bit 0". - * - * A 128-bit factory programmed unique ID could be read to serve several - * purposes. - * - * The driver accesses the flash memory by calling the lowlevel module provided - * in \ref efc_module. - * For more accurate information, please look at the EEFC section of the - * Datasheet. - * - * Related files :\n - * \ref flashd.c\n - * \ref flashd.h.\n - * \ref efc.c\n - * \ref efc.h.\n - */ -/*@{*/ -/*@}*/ - - -/** - * \file - * - * The flash driver provides the unified interface for flash program operations. - * - */ - -/*---------------------------------------------------------------------------- - * Headers - *----------------------------------------------------------------------------*/ -#include "chip.h" - -#include <string.h> -#include <assert.h> - -/*---------------------------------------------------------------------------- - * Definitions - *----------------------------------------------------------------------------*/ - -#define GPNVM_NUM_MAX 9 - -/*---------------------------------------------------------------------------- - * Local variables - *----------------------------------------------------------------------------*/ - -static uint32_t _pdwPageBuffer[IFLASH_PAGE_SIZE / sizeof(uint32_t)]; -static uint32_t _dwUseIAP = 1; /* Use IAP interface by default. */ - - -/*---------------------------------------------------------------------------- - * Local functions - *----------------------------------------------------------------------------*/ - - -/** - * \brief Computes the lock range associated with the given address range. - * - * \param dwStart Start address of lock range. - * \param dwEnd End address of lock range. - * \param pdwActualStart Actual start address of lock range. - * \param pdwActualEnd Actual end address of lock range. - */ -static void ComputeLockRange(uint32_t dwStart, uint32_t dwEnd, - uint32_t *pdwActualStart, uint32_t *pdwActualEnd) -{ - Efc *pStartEfc; - Efc *pEndEfc; - uint16_t wStartPage; - uint16_t wEndPage; - uint16_t wNumPagesInRegion; - uint16_t wActualStartPage; - uint16_t wActualEndPage; - - /* Convert start and end address in page numbers */ - EFC_TranslateAddress(&pStartEfc, dwStart, &wStartPage, 0); - EFC_TranslateAddress(&pEndEfc, dwEnd, &wEndPage, 0); - - /* Find out the first page of the first region to lock */ - wNumPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE; - wActualStartPage = wStartPage - (wStartPage % wNumPagesInRegion); - wActualEndPage = wEndPage; - - if ((wEndPage % wNumPagesInRegion) != 0) - wActualEndPage += wNumPagesInRegion - (wEndPage % wNumPagesInRegion); - - /* Store actual page numbers */ - EFC_ComputeAddress(pStartEfc, wActualStartPage, 0, pdwActualStart); - EFC_ComputeAddress(pEndEfc, wActualEndPage, 0, pdwActualEnd); - TRACE_DEBUG("Actual lock range is 0x%06X - 0x%06X\n\r", - (unsigned int)*pdwActualStart, (unsigned int)*pdwActualEnd); -} - - -/*---------------------------------------------------------------------------- - * Exported functions - *----------------------------------------------------------------------------*/ - -/** - * \brief Initializes the flash driver. - * - * \param dwMCk Master clock frequency in Hz. - * \param dwUseIAP 0: use EEFC controller interface, 1: use IAP interface. - * dwUseIAP should be set to 1 when running out of flash. - */ - -extern void FLASHD_Initialize(uint32_t dwMCk, uint32_t dwUseIAP) -{ - dwMCk = dwMCk; /* avoid warnings */ - - EFC_DisableFrdyIt(EFC); - _dwUseIAP = dwUseIAP; -} - -/** - * \brief Erases the entire flash. - * - * \param dwAddress Flash start address. - * \return 0 if successful; otherwise returns an error code. - */ -extern uint32_t FLASHD_Erase(uint32_t dwAddress) -{ - Efc *pEfc; - uint16_t wPage; - uint16_t wOffset; - uint32_t dwError; - - assert((dwAddress >= IFLASH_ADDR) - || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE))); - - /* Translate write address */ - EFC_TranslateAddress(&pEfc, dwAddress, &wPage, &wOffset); - dwError = EFC_PerformCommand(pEfc, EFC_FCMD_EA, 0, _dwUseIAP); - - return dwError; -} - -/** - * \brief Erases flash by sector. - * - * \param dwAddress Start address of be erased sector. - * - * \return 0 if successful; otherwise returns an error code. - */ -extern uint32_t FLASHD_EraseSector(uint32_t dwAddress) -{ - Efc *pEfc; - uint16_t wPage; - uint16_t wOffset; - uint32_t dwError; - - assert((dwAddress >= IFLASH_ADDR) - || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE))); - - /* Translate write address */ - EFC_TranslateAddress(&pEfc, dwAddress, &wPage, &wOffset); - dwError = EFC_PerformCommand(pEfc, EFC_FCMD_ES, wPage, _dwUseIAP); - - return dwError; -} - -/** - * \brief Erases flash by pages. - * - * \param dwAddress Start address of be erased pages. - * \param dwPageNum Number of pages to be erased with EPA command (4, 8, 16, 32) - * - * \return 0 if successful; otherwise returns an error code. - */ -extern uint32_t FLASHD_ErasePages(uint32_t dwAddress, uint32_t dwPageNum) -{ - Efc *pEfc; - uint16_t wPage; - uint16_t wOffset; - uint32_t dwError; - static uint32_t dwFarg; - - assert((dwAddress >= IFLASH_ADDR) - || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE))); - - /* Translate write address */ - EFC_TranslateAddress(&pEfc, dwAddress, &wPage, &wOffset); - - /* Get FARG field for EPA command: - * The first page to be erased is specified in the FARG[15:2] field of - * the MC_FCR register. The first page number must be modulo 4, 8,16 or 32 - * according to the number of pages to erase at the same time. - * - * The 2 lowest bits of the FARG field define the number of pages to - * be erased (FARG[1:0]). - */ - if (dwPageNum == 32) { - wPage &= ~(32u - 1u); - dwFarg = (wPage) | 3; /* 32 pages */ - } else if (dwPageNum == 16) { - wPage &= ~(16u - 1u); - dwFarg = (wPage) | 2; /* 16 pages */ - } else if (dwPageNum == 8) { - wPage &= ~(8u - 1u); - dwFarg = (wPage) | 1; /* 8 pages */ - } else { - wPage &= ~(4u - 1u); - dwFarg = (wPage) | 0; /* 4 pages */ - } - - dwError = EFC_PerformCommand(pEfc, EFC_FCMD_EPA, dwFarg, _dwUseIAP); - - return dwError; -} - - -/** - * \brief Writes a data buffer in the internal flash - * - * \note This function works in polling mode, and thus only returns when the - * data has been effectively written. - * \param address Write address. - * \param pBuffer Data buffer. - * \param size Size of data buffer in bytes. - * \return 0 if successful, otherwise returns an error code. - */ -extern uint32_t FLASHD_Write(uint32_t dwAddress, - const void *pvBuffer, uint32_t dwSize) -{ - Efc *pEfc; - uint16_t page; - uint16_t offset; - uint32_t writeSize; - uint32_t pageAddress; - uint16_t padding; - uint32_t dwError; - uint32_t dwIdx; - uint32_t *pAlignedDestination; - uint8_t *pucPageBuffer = (uint8_t *)_pdwPageBuffer; - - assert(pvBuffer); - assert(dwAddress >= IFLASH_ADDR); - assert((dwAddress + dwSize) <= (IFLASH_ADDR + IFLASH_SIZE)); - - /* Translate write address */ - EFC_TranslateAddress(&pEfc, dwAddress, &page, &offset); - - /* Write all pages */ - while (dwSize > 0) { - /* Copy data in temporary buffer to avoid alignment problems */ - writeSize = min((uint32_t)IFLASH_PAGE_SIZE - offset, dwSize); - EFC_ComputeAddress(pEfc, page, 0, &pageAddress); - padding = IFLASH_PAGE_SIZE - offset - writeSize; - - /* Pre-buffer data */ - memcpy(pucPageBuffer, (void *) pageAddress, offset); - - /* Buffer data */ - memcpy(pucPageBuffer + offset, pvBuffer, writeSize); - - /* Post-buffer data */ - memcpy(pucPageBuffer + offset + writeSize, - (void *) (pageAddress + offset + writeSize), padding); - - /* Write page - * Writing 8-bit and 16-bit data is not allowed and may - lead to unpredictable data corruption - */ - pAlignedDestination = (uint32_t *)pageAddress; - - for (dwIdx = 0; dwIdx < (IFLASH_PAGE_SIZE / sizeof(uint32_t)); ++ dwIdx) { - *pAlignedDestination++ = _pdwPageBuffer[dwIdx]; - memory_barrier() - } - - /* Cache coherence operation before flash write*/ - SCB_CleanDCache_by_Addr((uint32_t *)pageAddress, IFLASH_PAGE_SIZE); - - /* Note: It is not possible to use Erase and write Command (EWP) on all Flash - (this command is available on the First 2 Small Sector, 16K Bytes). - For the next block, Erase them first then use Write page command. */ - - /* Send writing command */ - dwError = EFC_PerformCommand(pEfc, EFC_FCMD_WP, page, _dwUseIAP); - - if (dwError) - return dwError; - - /* Progression */ - pvBuffer = (void *)((uint32_t) pvBuffer + writeSize); - dwSize -= writeSize; - page++; - offset = 0; - } - - return 0; -} - -/** - * \brief Locks all the regions in the given address range. The actual lock - * range is reported through two output parameters. - * - * \param start Start address of lock range. - * \param end End address of lock range. - * \param pActualStart Start address of the actual lock range (optional). - * \param pActualEnd End address of the actual lock range (optional). - * \return 0 if successful, otherwise returns an error code. - */ -extern uint32_t FLASHD_Lock(uint32_t start, uint32_t end, - uint32_t *pActualStart, uint32_t *pActualEnd) -{ - Efc *pEfc; - uint32_t actualStart, actualEnd; - uint16_t startPage, endPage; - uint32_t dwError; - uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE; - - /* Compute actual lock range and store it */ - ComputeLockRange(start, end, &actualStart, &actualEnd); - - if (pActualStart != NULL) - *pActualStart = actualStart; - - if (pActualEnd != NULL) - *pActualEnd = actualEnd; - - /* Compute page numbers */ - EFC_TranslateAddress(&pEfc, actualStart, &startPage, 0); - EFC_TranslateAddress(0, actualEnd, &endPage, 0); - - /* Lock all pages */ - while (startPage < endPage) { - dwError = EFC_PerformCommand(pEfc, EFC_FCMD_SLB, startPage, _dwUseIAP); - - if (dwError) - return dwError; - - startPage += numPagesInRegion; - } - - return 0; -} - -/** - * \brief Unlocks all the regions in the given address range. The actual unlock - * range is reported through two output parameters. - * \param start Start address of unlock range. - * \param end End address of unlock range. - * \param pActualStart Start address of the actual unlock range (optional). - * \param pActualEnd End address of the actual unlock range (optional). - * \return 0 if successful, otherwise returns an error code. - */ -extern uint32_t FLASHD_Unlock(uint32_t start, uint32_t end, - uint32_t *pActualStart, uint32_t *pActualEnd) -{ - Efc *pEfc; - uint32_t actualStart, actualEnd; - uint16_t startPage, endPage; - uint32_t dwError; - uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE; - - /* Compute actual unlock range and store it */ - ComputeLockRange(start, end, &actualStart, &actualEnd); - - if (pActualStart != NULL) - *pActualStart = actualStart; - - if (pActualEnd != NULL) - *pActualEnd = actualEnd; - - /* Compute page numbers */ - EFC_TranslateAddress(&pEfc, actualStart, &startPage, 0); - EFC_TranslateAddress(0, actualEnd, &endPage, 0); - - /* Unlock all pages */ - while (startPage < endPage) { - dwError = EFC_PerformCommand(pEfc, EFC_FCMD_CLB, startPage, _dwUseIAP); - - if (dwError) - return dwError; - - startPage += numPagesInRegion; - } - - return 0; -} - -/** - * \brief Returns the number of locked regions inside the given address range. - * - * \param start Start address of range - * \param end End address of range. - */ -extern uint32_t FLASHD_IsLocked(uint32_t start, uint32_t end) -{ - uint32_t i, j; - Efc *pEfc; - uint16_t startPage, endPage; - uint8_t startRegion, endRegion; - uint32_t numPagesInRegion; - uint32_t status[IFLASH_NB_OF_LOCK_BITS / 32u]; - uint32_t numLockedRegions = 0; - - assert(end >= start); - assert((start >= IFLASH_ADDR) && (end <= IFLASH_ADDR + IFLASH_SIZE)); - - /* Compute page numbers */ - EFC_TranslateAddress(&pEfc, start, &startPage, 0); - EFC_TranslateAddress(0, end, &endPage, 0); - - /* Compute region numbers */ - numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE; - startRegion = startPage / numPagesInRegion; - endRegion = endPage / numPagesInRegion; - - if ((endPage % numPagesInRegion) != 0) - endRegion++; - - /* Retrieve lock status */ - EFC_PerformCommand(pEfc, EFC_FCMD_GLB, 0, _dwUseIAP); - - for (i = 0; i < (IFLASH_NB_OF_LOCK_BITS / 32u); i++) - status[i] = EFC_GetResult(pEfc); - - /* Check status of each involved region */ - while (startRegion < endRegion) { - i = startRegion / 32u; - j = startRegion % 32u; - - if ((status[i] & (1 << j)) != 0) - numLockedRegions++; - - startRegion++; - } - - return numLockedRegions; -} - -/** - * \brief Check if the given GPNVM bit is set or not. - * - * \param gpnvm GPNVM bit index. - * \returns 1 if the given GPNVM bit is currently set; otherwise returns 0. - */ -extern uint32_t FLASHD_IsGPNVMSet(uint8_t ucGPNVM) -{ - uint32_t dwStatus; - - assert(ucGPNVM < GPNVM_NUM_MAX); - - /* Get GPNVMs status */ - EFC_PerformCommand(EFC, EFC_FCMD_GFB, 0, _dwUseIAP); - dwStatus = EFC_GetResult(EFC); - - /* Check if GPNVM is set */ - if ((dwStatus & (1 << ucGPNVM)) != 0) - return 1; - else - return 0; -} - -/** - * \brief Sets the selected GPNVM bit. - * - * \param gpnvm GPNVM bit index. - * \returns 0 if successful; otherwise returns an error code. - */ -extern uint32_t FLASHD_SetGPNVM(uint8_t ucGPNVM) -{ - assert(ucGPNVM < GPNVM_NUM_MAX); - - if (!FLASHD_IsGPNVMSet(ucGPNVM)) - return EFC_PerformCommand(EFC, EFC_FCMD_SFB, ucGPNVM, _dwUseIAP); - else - return 0; -} - -/** - * \brief Clears the selected GPNVM bit. - * - * \param gpnvm GPNVM bit index. - * \returns 0 if successful; otherwise returns an error code. - */ -extern uint32_t FLASHD_ClearGPNVM(uint8_t ucGPNVM) -{ - assert(ucGPNVM < GPNVM_NUM_MAX); - - if (FLASHD_IsGPNVMSet(ucGPNVM)) - return EFC_PerformCommand(EFC, EFC_FCMD_CFB, ucGPNVM, _dwUseIAP); - else - return 0; -} - -/** - * \brief Read the unique ID. - * - * \param pdwUniqueID pointer on a 4bytes char containing the unique ID value. - * \returns 0 if successful; otherwise returns an error code. - */ -#ifdef __ICCARM__ - extern __ramfunc uint32_t FLASHD_ReadUniqueID(uint32_t *pdwUniqueID) -#else - __attribute__ ((section (".ramfunc"))) - uint32_t FLASHD_ReadUniqueID(uint32_t *pdwUniqueID) -#endif -{ - uint32_t status; - - if (pdwUniqueID == NULL) - return 1; - - pdwUniqueID[0] = 0; - pdwUniqueID[1] = 0; - pdwUniqueID[2] = 0; - pdwUniqueID[3] = 0; - - /* Send the Start Read unique Identifier command (STUI) by writing the Flash - Command Register with the STUI command.*/ - EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EFC_FCMD_STUI; - - /* When the Unique Identifier is ready to be read, the FRDY bit in the Flash - Programming Status Register (EEFC_FSR) falls. */ - do { - status = EFC->EEFC_FSR; - } while ((status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY); - - /* The Unique Identifier is located in the first 128 bits of the Flash - memory mapping. So, at the address 0x400000-0x40000F. */ - pdwUniqueID[0] = *(uint32_t *)IFLASH_ADDR; - pdwUniqueID[1] = *(uint32_t *)(IFLASH_ADDR + 4); - pdwUniqueID[2] = *(uint32_t *)(IFLASH_ADDR + 8); - pdwUniqueID[3] = *(uint32_t *)(IFLASH_ADDR + 12); - - /* To stop the Unique Identifier mode, the user needs to send the Stop Read - unique Identifier command (SPUI) by writing the Flash Command Register - with the SPUI command. */ - EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EFC_FCMD_SPUI; - - /* When the Stop read Unique Unique Identifier command (SPUI) has been - performed, the FRDY bit in the Flash Programming Status Register (EEFC_FSR) - rises. */ - do { - status = EFC->EEFC_FSR; - } while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY); - - return 0; -} - |