summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/flashd.c
diff options
context:
space:
mode:
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.c595
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;
-}
-