1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2012, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
30 /** \addtogroup efc_module Working with EEFC
\r
31 * \ingroup peripherals_module
\r
32 * The EEFC driver provides the interface to configure and use the EEFC
\r
35 * The user needs to set the number of wait states depending on the frequency used.\n
\r
36 * Configure number of cycles for flash read/write operations in the FWS field of EEFC_FMR.
\r
38 * It offers a function to send flash command to EEFC and waits for the
\r
39 * flash to be ready.
\r
41 * To send flash command, the user could do in either of following way:
\r
43 * <li>Write a correct key, command and argument in EEFC_FCR. </li>
\r
44 * <li>Or, Use IAP (In Application Programming) function which is executed from
\r
45 * ROM directly, this allows flash programming to be done by code running in flash.</li>
\r
46 * <li>Once the command is achieved, it can be detected even by polling EEFC_FSR or interrupt.
\r
49 * The command argument could be a page number,GPNVM number or nothing, it depends on
\r
50 * the command itself. Some useful functions in this driver could help user tranlate physical
\r
51 * flash address into a page number and vice verse.
\r
53 * For more accurate information, please look at the EEFC section of the
\r
67 * Implementation of Enhanced Embedded Flash Controller (EEFC).
\r
72 /*----------------------------------------------------------------------------
\r
74 *----------------------------------------------------------------------------*/
\r
79 #define EEFC_FCR_FCMD(value) ((EEFC_FCR_FCMD_Msk & ((value) << EEFC_FCR_FCMD_Pos)))
\r
81 /*----------------------------------------------------------------------------
\r
82 * Exported functions
\r
83 *----------------------------------------------------------------------------*/
\r
85 extern void EFC_WriteFMR( Efc* efc, uint32_t dwFmr );
\r
88 extern __ramfunc void EFC_WriteFMR( Efc* efc, uint32_t dwFmr )
\r
90 __attribute__ ((section (".ramfunc")))
\r
91 extern void EFC_WriteFMR( Efc* efc, uint32_t dwFmr )
\r
94 efc->EEFC_FMR = dwFmr;
\r
98 * \brief Enables the flash ready interrupt source on the EEFC peripheral.
\r
100 * \param efc Pointer to a Efc instance
\r
102 extern void EFC_EnableFrdyIt( Efc* efc )
\r
106 dwFmr = efc->EEFC_FMR |= EEFC_FMR_FRDY;
\r
107 EFC_WriteFMR(efc, dwFmr);
\r
111 * \brief Disables the flash ready interrupt source on the EEFC peripheral.
\r
113 * \param efc Pointer to a Efc instance
\r
115 extern void EFC_DisableFrdyIt( Efc* efc )
\r
119 dwFmr = efc->EEFC_FMR & (~EEFC_FMR_FRDY);
\r
120 EFC_WriteFMR(efc, dwFmr);
\r
125 * \brief Set read/write wait state on the EEFC perpherial.
\r
127 * \param efc Pointer to a Efc instance
\r
128 * \param cycles the number of wait states in cycle.
\r
130 extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles )
\r
134 dwFmr = efc->EEFC_FMR ;
\r
135 dwFmr &= ~((uint32_t)EEFC_FMR_FWS_Msk) ;
\r
136 dwFmr |= EEFC_FMR_FWS(ucCycles);
\r
137 EFC_WriteFMR(efc, dwFmr);
\r
141 * \brief Returns the current status of the EEFC.
\r
143 * \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE).
\r
145 * \param efc Pointer to a Efc instance
\r
147 extern uint32_t EFC_GetStatus( Efc* efc )
\r
149 return efc->EEFC_FSR ;
\r
153 * \brief Returns the result of the last executed command.
\r
155 * \param efc Pointer to a Efc instance
\r
157 extern uint32_t EFC_GetResult( Efc* efc )
\r
159 return efc->EEFC_FRR ;
\r
163 * \brief Translates the given address page and offset values.
\r
164 * \note The resulting values are stored in the provided variables if they are not null.
\r
166 * \param efc Pointer to a Efc instance
\r
167 * \param address Address to translate.
\r
168 * \param pPage First page accessed.
\r
169 * \param pOffset Byte offset in first page.
\r
171 extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset )
\r
173 assert( dwAddress >= IFLASH_ADDR ) ;
\r
174 assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
\r
184 *pwPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE ;
\r
189 *pwOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE; ;
\r
195 * \brief Computes the address of a flash access given the page and offset.
\r
197 * \param efc Pointer to a Efc instance
\r
198 * \param page Page number.
\r
199 * \param offset Byte offset inside page.
\r
200 * \param pAddress Computed address (optional).
\r
202 extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress )
\r
204 uint32_t dwAddress ;
\r
210 assert( wPage <= IFLASH_NB_OF_PAGES ) ;
\r
211 assert( wOffset < IFLASH_PAGE_SIZE ) ;
\r
212 dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ;
\r
215 if ( pdwAddress != NULL )
\r
217 *pdwAddress = dwAddress ;
\r
224 * \brief Performs the given command and wait until its completion (or an error).
\r
226 * \param efc Pointer to a Efc instance
\r
227 * \param command Command to perform.
\r
228 * \param argument Optional command argument.
\r
230 * \return 0 if successful, otherwise returns an error code.
\r
233 extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP )
\r
235 if ( dwUseIAP != 0 )
\r
237 /* Pointer on IAP function in ROM */
\r
238 static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ;
\r
240 IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ;
\r
242 IAP_PerformCommand( 0, EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ;
\r
244 return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR)) ;
\r
248 uint32_t dwStatus ;
\r
250 efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
\r
253 dwStatus = efc->EEFC_FSR ;
\r
255 while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ;
\r
257 return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR) ) ;
\r
262 * \brief Set flash access mode.
\r
264 * \param dwMode - 0:128-bit, (1<<24):64-bit
\r
266 extern void EFC_SetFlashAccessMode(Efc* efc, uint32_t dwMode)
\r
270 dwFmr = (efc->EEFC_FMR & (~EEFC_FMR_FAM)) | dwMode;
\r
271 EFC_WriteFMR(efc, dwFmr);
\r