00001 /* ---------------------------------------------------------------------------- */ 00002 /* Atmel Microcontroller Software Support */ 00003 /* SAM Software Package License */ 00004 /* ---------------------------------------------------------------------------- */ 00005 /* Copyright (c) 2015, Atmel Corporation */ 00006 /* */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without */ 00010 /* modification, are permitted provided that the following condition is met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, */ 00013 /* this list of conditions and the disclaimer below. */ 00014 /* */ 00015 /* Atmel's name may not be used to endorse or promote products derived from */ 00016 /* this software without specific prior written permission. */ 00017 /* */ 00018 /* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ 00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ 00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ 00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */ 00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ 00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ 00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ 00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ 00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ 00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00028 /* ---------------------------------------------------------------------------- */ 00029 00030 /** \addtogroup efc_module Working with EEFC 00031 * \ingroup peripherals_module 00032 * 00033 * The EEFC driver provides the interface to configure and use the EEFC 00034 * peripheral. 00035 * 00036 * The user needs to set the number of wait states depending on the frequency 00037 * used.\n 00038 * Configure number of cycles for flash read/write operations in the FWS field 00039 * of EEFC_FMR. 00040 * 00041 * It offers a function to send flash command to EEFC and waits for the 00042 * flash to be ready. 00043 * 00044 * To send flash command, the user could do in either of following way: 00045 * <ul> 00046 * <li>Write a correct key, command and argument in EEFC_FCR. </li> 00047 * <li>Or, Use IAP (In Application Programming) function which is executed from 00048 * ROM directly, this allows flash programming to be done by code running in 00049 * flash.</li> 00050 * <li>Once the command is achieved, it can be detected even by polling 00051 * EEFC_FSR or interrupt. 00052 * </ul> 00053 * 00054 * The command argument could be a page number,GPNVM number or nothing, it 00055 * depends on the command itself. Some useful functions in this driver could 00056 * help user translate physical flash address into a page number and vice verse. 00057 * 00058 * For more accurate information, please look at the EEFC section of the 00059 * Datasheet. 00060 * 00061 * Related files :\n 00062 * \ref efc.c\n 00063 * \ref efc.h.\n 00064 */ 00065 /*@{*/ 00066 /*@}*/ 00067 00068 00069 /** 00070 * \file 00071 * 00072 * Implementation of Enhanced Embedded Flash Controller (EEFC). 00073 * 00074 */ 00075 00076 00077 /*---------------------------------------------------------------------------- 00078 * Headers 00079 *----------------------------------------------------------------------------*/ 00080 #include "chip.h" 00081 00082 #include <assert.h> 00083 00084 00085 /*---------------------------------------------------------------------------- 00086 * Macro 00087 *----------------------------------------------------------------------------*/ 00088 #define EEFC_FCR_FCMD(value) ((EEFC_FCR_FCMD_Msk & ((value) << EEFC_FCR_FCMD_Pos))) 00089 00090 /*---------------------------------------------------------------------------- 00091 * Exported functions 00092 *----------------------------------------------------------------------------*/ 00093 00094 extern void EFC_WriteFMR(Efc *efc, uint32_t dwFmr); 00095 00096 #ifdef __ICCARM__ 00097 extern __ramfunc void EFC_WriteFMR(Efc *efc, uint32_t dwFmr) 00098 #else 00099 __attribute__ ((section (".ramfunc"))) 00100 extern void EFC_WriteFMR(Efc *efc, uint32_t dwFmr) 00101 #endif 00102 { 00103 efc->EEFC_FMR = dwFmr; 00104 } 00105 00106 /** 00107 * \brief Enables the flash ready interrupt source on the EEFC peripheral. 00108 * 00109 * \param efc Pointer to a Efc instance 00110 */ 00111 extern void EFC_EnableFrdyIt(Efc *efc) 00112 { 00113 uint32_t dwFmr; 00114 00115 dwFmr = efc->EEFC_FMR |= EEFC_FMR_FRDY; 00116 EFC_WriteFMR(efc, dwFmr); 00117 } 00118 00119 /** 00120 * \brief Disables the flash ready interrupt source on the EEFC peripheral. 00121 * 00122 * \param efc Pointer to a Efc instance 00123 */ 00124 extern void EFC_DisableFrdyIt(Efc *efc) 00125 { 00126 uint32_t dwFmr; 00127 00128 dwFmr = efc->EEFC_FMR & (~EEFC_FMR_FRDY); 00129 EFC_WriteFMR(efc, dwFmr); 00130 } 00131 00132 00133 /** 00134 * \brief Set read/write wait state on the EEFC peripheral. 00135 * 00136 * \param efc Pointer to a Efc instance 00137 * \param cycles the number of wait states in cycle. 00138 */ 00139 extern void EFC_SetWaitState(Efc *efc, uint8_t ucCycles) 00140 { 00141 uint32_t dwFmr; 00142 00143 dwFmr = efc->EEFC_FMR; 00144 dwFmr &= ~((uint32_t)EEFC_FMR_FWS_Msk); 00145 dwFmr |= EEFC_FMR_FWS(ucCycles); 00146 EFC_WriteFMR(efc, dwFmr); 00147 } 00148 00149 /** 00150 * \brief Returns the current status of the EEFC. 00151 * 00152 * \note Keep in mind that this function clears the value of some status bits 00153 * (LOCKE, PROGE). 00154 * 00155 * \param efc Pointer to a Efc instance 00156 */ 00157 extern uint32_t EFC_GetStatus(Efc *efc) 00158 { 00159 return efc->EEFC_FSR; 00160 } 00161 00162 /** 00163 * \brief Returns the result of the last executed command. 00164 * 00165 * \param efc Pointer to a Efc instance 00166 */ 00167 extern uint32_t EFC_GetResult(Efc *efc) 00168 { 00169 return efc->EEFC_FRR; 00170 } 00171 00172 /** 00173 * \brief Translates the given address page and offset values. 00174 * \note The resulting values are stored in the provided variables if they are 00175 * not null. 00176 * 00177 * \param efc Pointer to a Efc instance 00178 * \param address Address to translate. 00179 * \param pPage First page accessed. 00180 * \param pOffset Byte offset in first page. 00181 */ 00182 extern void EFC_TranslateAddress(Efc **ppEfc, uint32_t dwAddress, 00183 uint16_t *pwPage, 00184 uint16_t *pwOffset) 00185 { 00186 assert(dwAddress >= IFLASH_ADDR); 00187 assert(dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)); 00188 00189 /* Store values */ 00190 if (ppEfc) 00191 *ppEfc = EFC; 00192 00193 if (pwPage) 00194 *pwPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE; 00195 00196 if (pwOffset) { 00197 *pwOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE;; 00198 } 00199 } 00200 00201 00202 /** 00203 * \brief Computes the address of a flash access given the page and offset. 00204 * 00205 * \param efc Pointer to a Efc instance 00206 * \param page Page number. 00207 * \param offset Byte offset inside page. 00208 * \param pAddress Computed address (optional). 00209 */ 00210 extern void EFC_ComputeAddress(Efc *efc, uint16_t wPage, uint16_t wOffset, 00211 uint32_t *pdwAddress) 00212 { 00213 uint32_t dwAddress; 00214 00215 /* Stop warning */ 00216 efc = efc; 00217 00218 assert(efc); 00219 assert(wPage <= IFLASH_NB_OF_PAGES); 00220 assert(wOffset < IFLASH_PAGE_SIZE); 00221 dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset; 00222 00223 /* Store result */ 00224 if (pdwAddress != NULL) 00225 *pdwAddress = dwAddress; 00226 } 00227 00228 /** 00229 * \brief Performs the given command and wait until its completion (or an error). 00230 * 00231 * \param efc Pointer to a Efc instance 00232 * \param command Command to perform. 00233 * \param argument Optional command argument. 00234 * 00235 * \return 0 if successful, otherwise returns an error code. 00236 */ 00237 00238 extern uint32_t EFC_PerformCommand(Efc *efc, uint32_t dwCommand, 00239 uint32_t dwArgument, uint32_t dwUseIAP) 00240 { 00241 if (dwUseIAP != 0) { 00242 /* Pointer on IAP function in ROM */ 00243 static uint32_t (*IAP_PerformCommand)(uint32_t, uint32_t); 00244 00245 IAP_PerformCommand = (uint32_t (*)(uint32_t, uint32_t)) 00246 * ((uint32_t *)CHIP_FLASH_IAP_ADDRESS); 00247 00248 if (efc == EFC) { 00249 IAP_PerformCommand(0, EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(dwArgument) 00250 | EEFC_FCR_FCMD(dwCommand)); 00251 } 00252 00253 return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR)); 00254 } else { 00255 uint32_t dwStatus; 00256 00257 efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(dwArgument) 00258 | EEFC_FCR_FCMD(dwCommand); 00259 00260 do { 00261 dwStatus = efc->EEFC_FSR; 00262 } while ((dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY); 00263 00264 return (dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR)); 00265 } 00266 } 00267 00268 /** 00269 * \brief Set flash access mode. 00270 * 00271 * \param dwMode - 0:128-bit, (1<<24):64-bit 00272 */ 00273 extern void EFC_SetFlashAccessMode(Efc *efc, uint32_t dwMode) 00274 { 00275 uint32_t dwFmr; 00276 00277 dwFmr = dwMode; 00278 EFC_WriteFMR(efc, dwFmr); 00279 } 00280