blob: b6a028e99740c077c87de03b07f666495c5b8fb5 [file] [log] [blame]
Harald Weltee9eaf902017-02-26 12:52:01 +01001/* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2009, Atmel Corporation
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
13 *
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
28 */
29
30/** \addtogroup efc_module Working with EEFC
31 * The EEFC driver provides the interface to configure and use the EEFC
32 * peripheral.
33 *
34 * The user needs to set the number of wait states depending on the frequency used.\n
35 * Configure number of cycles for flash read/write operations in the FWS field of EEFC_FMR.
36 *
37 * It offers a function to send flash command to EEFC and waits for the
38 * flash to be ready.
39 *
40 * To send flash command, the user could do in either of following way:
41 * <ul>
42 * <li>Write a correct key, command and argument in EEFC_FCR. </li>
43 * <li>Or, Use IAP (In Application Programming) function which is executed from
44 * ROM directly, this allows flash programming to be done by code running in flash.</li>
45 * <li>Once the command is achieved, it can be detected even by polling EEFC_FSR or interrupt.
46 * </ul>
47 *
48 * The command argument could be a page number,GPNVM number or nothing, it depends on
49 * the command itself. Some useful functions in this driver could help user tranlate physical
50 * flash address into a page number and vice verse.
51 *
52 * For more accurate information, please look at the EEFC section of the
53 * Datasheet.
54 *
55 * Related files :\n
56 * \ref efc.c\n
57 * \ref efc.h.\n
58*/
59/*@{*/
60/*@}*/
61
62
63/**
64 * \file
65 *
66 * Implementation of Enhanced Embedded Flash Controller (EEFC).
67 *
68 */
69
70
71/*----------------------------------------------------------------------------
72 * Headers
73 *----------------------------------------------------------------------------*/
74#include "chip.h"
Harald Weltea05ccc92017-02-26 12:52:28 +010075#include "efc.h"
Harald Weltee9eaf902017-02-26 12:52:01 +010076
77#include <assert.h>
78
79/*----------------------------------------------------------------------------
80 * Exported functions
81 *----------------------------------------------------------------------------*/
82
83/**
84 * \brief Enables the flash ready interrupt source on the EEFC peripheral.
85 *
86 * \param efc Pointer to a Efc instance
87 */
88extern void EFC_EnableFrdyIt( Efc* efc )
89{
90 efc->EEFC_FMR |= EEFC_FMR_FRDY ;
91}
92
93/**
94 * \brief Disables the flash ready interrupt source on the EEFC peripheral.
95 *
96 * \param efc Pointer to a Efc instance
97 */
98
99extern void EFC_DisableFrdyIt( Efc* efc )
100{
101 efc->EEFC_FMR &= ~((uint32_t)EEFC_FMR_FRDY) ;
102}
103
104
105/**
106 * \brief Set read/write wait state on the EEFC perpherial.
107 *
108 * \param efc Pointer to a Efc instance
109 * \param cycles the number of wait states in cycle.
110 */
111
112extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles )
113{
114 uint32_t dwValue ;
115
116 dwValue = efc->EEFC_FMR ;
117 dwValue &= ~((uint32_t)EEFC_FMR_FWS_Msk) ;
118 dwValue |= EEFC_FMR_FWS(ucCycles);
119 efc->EEFC_FMR = dwValue ;
120}
121
122/**
123 * \brief Returns the current status of the EEFC.
124 *
125 * \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE).
126 *
127 * \param efc Pointer to a Efc instance
128 */
129extern uint32_t EFC_GetStatus( Efc* efc )
130{
131 return efc->EEFC_FSR ;
132}
133
134/**
135 * \brief Returns the result of the last executed command.
136 *
137 * \param efc Pointer to a Efc instance
138 */
139extern uint32_t EFC_GetResult( Efc* efc )
140{
141 return efc->EEFC_FRR ;
142}
143
144/**
145 * \brief Translates the given address page and offset values.
146 * \note The resulting values are stored in the provided variables if they are not null.
147 *
148 * \param efc Pointer to a Efc instance
149 * \param address Address to translate.
150 * \param pPage First page accessed.
151 * \param pOffset Byte offset in first page.
152 */
153extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset )
154{
155 Efc *pEfc ;
156 uint16_t wPage ;
157 uint16_t wOffset ;
158
159 assert( dwAddress >= IFLASH_ADDR ) ;
160 assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
161
162 pEfc = EFC ;
163 wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE;
164 wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE;
165
166 TRACE_DEBUG( "Translated 0x%08X to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ;
167 /* Store values */
168 if ( pEfc )
169 {
170 *ppEfc = pEfc ;
171 }
172
173 if ( pwPage )
174 {
175 *pwPage = wPage ;
176 }
177
178 if ( pwOffset )
179 {
180 *pwOffset = wOffset ;
181 }
182}
183
184/**
185 * \brief Computes the address of a flash access given the page and offset.
186 *
187 * \param efc Pointer to a Efc instance
188 * \param page Page number.
189 * \param offset Byte offset inside page.
190 * \param pAddress Computed address (optional).
191 */
192extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress )
193{
194 uint32_t dwAddress ;
195
196 assert( efc ) ;
197 assert( wPage <= IFLASH_NB_OF_PAGES ) ;
198 assert( wOffset < IFLASH_PAGE_SIZE ) ;
199
200 /* Compute address */
201 dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ;
202
203 /* Store result */
204 if ( pdwAddress != NULL )
205 {
206 *pdwAddress = dwAddress ;
207 }
208}
209
210/**
211 * \brief Starts the executing the given command on the EEFC and returns as soon as the command is started.
212 *
213 * \note It does NOT set the FMCN field automatically.
214 * \param efc Pointer to a Efc instance
215 * \param command Command to execute.
216 * \param argument Command argument (should be 0 if not used).
217 */
218extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument )
219{
220 /* Check command & argument */
221 switch ( dwCommand )
222 {
223 case EFC_FCMD_WP:
224 case EFC_FCMD_WPL:
225 case EFC_FCMD_EWP:
226 case EFC_FCMD_EWPL:
227 case EFC_FCMD_SLB:
228 case EFC_FCMD_CLB:
229 assert( dwArgument < IFLASH_NB_OF_PAGES ) ;
230 break ;
231
232 case EFC_FCMD_SFB:
233 case EFC_FCMD_CFB:
234 assert( dwArgument < 2 ) ;
235 break;
236
237 case EFC_FCMD_GETD:
238 case EFC_FCMD_EA:
239 case EFC_FCMD_GLB:
240 case EFC_FCMD_GFB:
241 case EFC_FCMD_STUI:
242 assert( dwArgument == 0 ) ;
243 break;
244
245 default: assert( 0 ) ;
246 }
247
248 /* Start command Embedded flash */
249 assert( (efc->EEFC_FSR & EEFC_FMR_FRDY) == EEFC_FMR_FRDY ) ;
250 efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
251}
252
253/**
254 * \brief Performs the given command and wait until its completion (or an error).
255 *
256 * \param efc Pointer to a Efc instance
257 * \param command Command to perform.
258 * \param argument Optional command argument.
259 *
260 * \return 0 if successful, otherwise returns an error code.
261 */
262
263extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP )
264{
265 if ( dwUseIAP != 0 )
266 {
267 /* Pointer on IAP function in ROM */
268 static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ;
269
270 IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ;
271 IAP_PerformCommand( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ;
272
273 return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ;
274 }
275 else
276 {
277 uint32_t dwStatus ;
278
279 efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
280 do
281 {
282 dwStatus = efc->EEFC_FSR ;
283 }
284 while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ;
285
286 return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ;
287 }
288}
289
290