blob: 97104d5ea54ad303f38533a9d0a65d461c7acefc [file] [log] [blame]
Christina Quast8be71e42014-12-02 13:06: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"
75
76#include <assert.h>
77
78/*----------------------------------------------------------------------------
79 * Exported functions
80 *----------------------------------------------------------------------------*/
81
82/**
83 * \brief Enables the flash ready interrupt source on the EEFC peripheral.
84 *
85 * \param efc Pointer to a Efc instance
86 */
87extern void EFC_EnableFrdyIt( Efc* efc )
88{
89 efc->EEFC_FMR |= EEFC_FMR_FRDY ;
90}
91
92/**
93 * \brief Disables the flash ready interrupt source on the EEFC peripheral.
94 *
95 * \param efc Pointer to a Efc instance
96 */
97
98extern void EFC_DisableFrdyIt( Efc* efc )
99{
100 efc->EEFC_FMR &= ~((uint32_t)EEFC_FMR_FRDY) ;
101}
102
103
104/**
105 * \brief Set read/write wait state on the EEFC perpherial.
106 *
107 * \param efc Pointer to a Efc instance
108 * \param cycles the number of wait states in cycle.
109 */
110
111extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles )
112{
113 uint32_t dwValue ;
114
115 dwValue = efc->EEFC_FMR ;
116 dwValue &= ~((uint32_t)EEFC_FMR_FWS_Msk) ;
117 dwValue |= EEFC_FMR_FWS(ucCycles);
118 efc->EEFC_FMR = dwValue ;
119}
120
121/**
122 * \brief Returns the current status of the EEFC.
123 *
124 * \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE).
125 *
126 * \param efc Pointer to a Efc instance
127 */
128extern uint32_t EFC_GetStatus( Efc* efc )
129{
130 return efc->EEFC_FSR ;
131}
132
133/**
134 * \brief Returns the result of the last executed command.
135 *
136 * \param efc Pointer to a Efc instance
137 */
138extern uint32_t EFC_GetResult( Efc* efc )
139{
140 return efc->EEFC_FRR ;
141}
142
143/**
144 * \brief Translates the given address page and offset values.
145 * \note The resulting values are stored in the provided variables if they are not null.
146 *
147 * \param efc Pointer to a Efc instance
148 * \param address Address to translate.
149 * \param pPage First page accessed.
150 * \param pOffset Byte offset in first page.
151 */
152extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset )
153{
154 Efc *pEfc ;
155 uint16_t wPage ;
156 uint16_t wOffset ;
157
158 assert( dwAddress >= IFLASH_ADDR ) ;
159 assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
160
161 pEfc = EFC ;
162 wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE;
163 wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE;
164
165 TRACE_DEBUG( "Translated 0x%08X to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ;
166 /* Store values */
167 if ( pEfc )
168 {
169 *ppEfc = pEfc ;
170 }
171
172 if ( pwPage )
173 {
174 *pwPage = wPage ;
175 }
176
177 if ( pwOffset )
178 {
179 *pwOffset = wOffset ;
180 }
181}
182
183/**
184 * \brief Computes the address of a flash access given the page and offset.
185 *
186 * \param efc Pointer to a Efc instance
187 * \param page Page number.
188 * \param offset Byte offset inside page.
189 * \param pAddress Computed address (optional).
190 */
191extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress )
192{
193 uint32_t dwAddress ;
194
195 assert( efc ) ;
196 assert( wPage <= IFLASH_NB_OF_PAGES ) ;
197 assert( wOffset < IFLASH_PAGE_SIZE ) ;
198
199 /* Compute address */
200 dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ;
201
202 /* Store result */
203 if ( pdwAddress != NULL )
204 {
205 *pdwAddress = dwAddress ;
206 }
207}
208
209/**
210 * \brief Starts the executing the given command on the EEFC and returns as soon as the command is started.
211 *
212 * \note It does NOT set the FMCN field automatically.
213 * \param efc Pointer to a Efc instance
214 * \param command Command to execute.
215 * \param argument Command argument (should be 0 if not used).
216 */
217extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument )
218{
219 /* Check command & argument */
220 switch ( dwCommand )
221 {
222 case EFC_FCMD_WP:
223 case EFC_FCMD_WPL:
224 case EFC_FCMD_EWP:
225 case EFC_FCMD_EWPL:
226 case EFC_FCMD_SLB:
227 case EFC_FCMD_CLB:
228 assert( dwArgument < IFLASH_NB_OF_PAGES ) ;
229 break ;
230
231 case EFC_FCMD_SFB:
232 case EFC_FCMD_CFB:
233 assert( dwArgument < 2 ) ;
234 break;
235
236 case EFC_FCMD_GETD:
237 case EFC_FCMD_EA:
238 case EFC_FCMD_GLB:
239 case EFC_FCMD_GFB:
240 case EFC_FCMD_STUI:
241 assert( dwArgument == 0 ) ;
242 break;
243
244 default: assert( 0 ) ;
245 }
246
247 /* Start command Embedded flash */
248 assert( (efc->EEFC_FSR & EEFC_FMR_FRDY) == EEFC_FMR_FRDY ) ;
249 efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
250}
251
252/**
253 * \brief Performs the given command and wait until its completion (or an error).
254 *
255 * \param efc Pointer to a Efc instance
256 * \param command Command to perform.
257 * \param argument Optional command argument.
258 *
259 * \return 0 if successful, otherwise returns an error code.
260 */
261
262extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP )
263{
264 if ( dwUseIAP != 0 )
265 {
266 /* Pointer on IAP function in ROM */
267 static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ;
268
269 IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ;
270 IAP_PerformCommand( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ;
271
272 return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ;
273 }
274 else
275 {
276 uint32_t dwStatus ;
277
278 efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
279 do
280 {
281 dwStatus = efc->EEFC_FSR ;
282 }
283 while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ;
284
285 return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ;
286 }
287}
288
289