]> git.sur5r.net Git - freertos/blob - Demo/Common/drivers/Atmel/at91lib/peripherals/eefc/eefc.c
Atmel provided hardware specifics.
[freertos] / Demo / Common / drivers / Atmel / at91lib / peripherals / eefc / eefc.c
1 /* ----------------------------------------------------------------------------\r
2  *         ATMEL Microcontroller Software Support \r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2008, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\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
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\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
16  *\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
28  */\r
29 \r
30 #ifndef trace_LEVEL\r
31     #define trace_LEVEL trace_INFO\r
32 #endif\r
33 \r
34 //------------------------------------------------------------------------------\r
35 //         Headers\r
36 //------------------------------------------------------------------------------\r
37 \r
38 #include "eefc.h"\r
39 \r
40 #ifdef BOARD_FLASH_EEFC\r
41 \r
42 #include <utility/assert.h>\r
43 #include <utility/trace.h>\r
44 \r
45 //------------------------------------------------------------------------------\r
46 //         Global functions\r
47 //------------------------------------------------------------------------------\r
48 \r
49 //------------------------------------------------------------------------------\r
50 /// Enables the flash ready interrupt source on the EEFC peripheral.\r
51 //------------------------------------------------------------------------------\r
52 void EFC_EnableFrdyIt(void)\r
53 {\r
54     AT91C_BASE_EFC->EFC_FMR |= AT91C_EFC_FRDY;\r
55 }\r
56 \r
57 //------------------------------------------------------------------------------\r
58 /// Disables the flash ready interrupt source on the EEFC peripheral.\r
59 //------------------------------------------------------------------------------\r
60 void EFC_DisableFrdyIt(void)\r
61 {\r
62     AT91C_BASE_EFC->EFC_FMR &= ~AT91C_EFC_FRDY;\r
63 }\r
64 \r
65 //------------------------------------------------------------------------------\r
66 /// Translates the given address page and offset values. The resulting\r
67 /// values are stored in the provided variables if they are not null.\r
68 /// \param address  Address to translate.\r
69 /// \param pPage  First page accessed.\r
70 /// \param pOffset  Byte offset in first page.\r
71 //------------------------------------------------------------------------------\r
72 void EFC_TranslateAddress(\r
73     unsigned int address,\r
74     unsigned short *pPage,\r
75     unsigned short *pOffset)\r
76 {\r
77     unsigned short page;\r
78     unsigned short offset;\r
79 \r
80     SANITY_CHECK(address >= AT91C_IFLASH);\r
81     SANITY_CHECK(address <= (AT91C_IFLASH + AT91C_IFLASH_SIZE));\r
82 \r
83     // Calculate page & offset\r
84     page = (address - AT91C_IFLASH) / AT91C_IFLASH_PAGE_SIZE;\r
85     offset = (address - AT91C_IFLASH) % AT91C_IFLASH_PAGE_SIZE;\r
86     trace_LOG(trace_DEBUG,\r
87               "-D- Translated 0x%08X to page=%d and offset=%d\n\r",\r
88               address, page, offset);\r
89 \r
90     // Store values\r
91     if (pPage) {\r
92 \r
93         *pPage = page;\r
94     }\r
95     if (pOffset) {\r
96 \r
97         *pOffset = offset;\r
98     }\r
99 }\r
100 \r
101 //------------------------------------------------------------------------------\r
102 /// Computes the address of a flash access given the page and offset.\r
103 /// \param page  Page number.\r
104 /// \param offset  Byte offset inside page.\r
105 /// \param pAddress  Computed address (optional).\r
106 //------------------------------------------------------------------------------\r
107 void EFC_ComputeAddress(\r
108     unsigned short page,\r
109     unsigned short offset,\r
110     unsigned int *pAddress)\r
111 {\r
112     unsigned int address;\r
113 \r
114     SANITY_CHECK(page <= AT91C_IFLASH_NB_OF_PAGES);\r
115     SANITY_CHECK(offset < AT91C_IFLASH_PAGE_SIZE);\r
116 \r
117     // Compute address\r
118     address = AT91C_IFLASH + page * AT91C_IFLASH_PAGE_SIZE + offset;\r
119 \r
120     // Store result\r
121     if (pAddress) {\r
122 \r
123         *pAddress = address;\r
124     }\r
125 }\r
126 \r
127 //------------------------------------------------------------------------------\r
128 /// Starts the executing the given command on the EEFC. This function returns\r
129 /// as soon as the command is started. It does NOT set the FMCN field automatically.\r
130 /// \param command  Command to execute.\r
131 /// \param argument  Command argument (should be 0 if not used).\r
132 //------------------------------------------------------------------------------\r
133 void EFC_StartCommand(unsigned char command, unsigned short argument)\r
134 {\r
135     // Check command & argument\r
136     switch (command) {\r
137 \r
138         case AT91C_EFC_FCMD_WP:\r
139         case AT91C_EFC_FCMD_WPL:\r
140         case AT91C_EFC_FCMD_EWP: \r
141         case AT91C_EFC_FCMD_EWPL:\r
142         case AT91C_EFC_FCMD_EPL:\r
143         case AT91C_EFC_FCMD_EPA:\r
144         case AT91C_EFC_FCMD_SLB:\r
145         case AT91C_EFC_FCMD_CLB:\r
146             ASSERT(argument < AT91C_IFLASH_NB_OF_PAGES,\r
147                    "-F- Embedded flash has only %d pages\n\r",\r
148                    AT91C_IFLASH_NB_OF_PAGES);\r
149             break;\r
150 \r
151         case AT91C_EFC_FCMD_SFB:\r
152         case AT91C_EFC_FCMD_CFB:\r
153             ASSERT(argument < EFC_NUM_GPNVMS, "-F- Embedded flash has only %d GPNVMs\n\r", EFC_NUM_GPNVMS);\r
154             break;\r
155 \r
156         case AT91C_EFC_FCMD_GETD:\r
157         case AT91C_EFC_FCMD_EA:\r
158         case AT91C_EFC_FCMD_GLB:\r
159         case AT91C_EFC_FCMD_GFB:\r
160             ASSERT(argument == 0, "-F- Argument is meaningless for the given command.\n\r");\r
161             break;\r
162 \r
163         default: ASSERT(0, "-F- Unknown command %d\n\r", command);\r
164     }\r
165 \r
166     // Start commandEmbedded flash \r
167     ASSERT((AT91C_BASE_EFC->EFC_FSR & AT91C_EFC_FRDY) == AT91C_EFC_FRDY, "-F- EEFC is not ready\n\r");\r
168     AT91C_BASE_EFC->EFC_FCR = (0x5A << 24) | (argument << 8) | command;\r
169 }\r
170 \r
171 //------------------------------------------------------------------------------\r
172 /// Performs the given command and wait until its completion (or an error).\r
173 /// Returns 0 if successful; otherwise returns an error code.\r
174 /// \param command  Command to perform.\r
175 /// \param argument  Optional command argument.\r
176 //------------------------------------------------------------------------------\r
177 #ifdef __ICCARM__\r
178 __ramfunc\r
179 #else\r
180 __attribute__ ((section (".ramfunc")))\r
181 #endif\r
182 unsigned char EFC_PerformCommand(unsigned char command, unsigned short argument)\r
183 {\r
184     unsigned int status;\r
185 \r
186 #ifdef BOARD_FLASH_IAP_ADDRESS\r
187     // Pointer on IAP function in ROM\r
188     static void (*IAP_PerformCommand)(unsigned int);\r
189     IAP_PerformCommand = (void (*)(unsigned int)) *((unsigned int *) BOARD_FLASH_IAP_ADDRESS);\r
190 \r
191     // Check if IAP function is implemented (opcode in SWI != 'b' or 'ldr') */\r
192     if ((((((unsigned long) IAP_PerformCommand >> 24) & 0xFF) != 0xEA) &&\r
193         (((unsigned long) IAP_PerformCommand >> 24) & 0xFF) != 0xE5)) {\r
194 \r
195         IAP_PerformCommand((0x5A << 24) | (argument << 8) | command);\r
196         return (AT91C_BASE_EFC->EFC_FSR & (AT91C_EFC_LOCKE | AT91C_EFC_FCMDE));\r
197     }\r
198 #endif\r
199 \r
200     AT91C_BASE_EFC->EFC_FCR = (0x5A << 24) | (argument << 8) | command;\r
201     do {\r
202 \r
203         status = AT91C_BASE_EFC->EFC_FSR;\r
204     }\r
205     while ((status & AT91C_EFC_FRDY) != AT91C_EFC_FRDY);\r
206 \r
207     return (status & (AT91C_EFC_LOCKE | AT91C_EFC_FCMDE));\r
208 }\r
209 \r
210 //------------------------------------------------------------------------------\r
211 /// Returns the current status of the EEFC. Keep in mind that this function clears\r
212 /// the value of some status bits (LOCKE, PROGE).\r
213 //------------------------------------------------------------------------------\r
214 unsigned int EFC_GetStatus(void)\r
215 {\r
216     return AT91C_BASE_EFC->EFC_FSR;\r
217 }\r
218 \r
219 //------------------------------------------------------------------------------\r
220 /// Returns the result of the last executed command.\r
221 //------------------------------------------------------------------------------\r
222 unsigned int EFC_GetResult(void) {\r
223 \r
224     return AT91C_BASE_EFC->EFC_FRR;\r
225 }\r
226 \r
227 #endif //#ifdef BOARD_FLASH_EEFC\r
228 \r