1 /**
2 * \file
3 *
4 * \brief Non volatile memories management for SAM devices
5 *
6 * Copyright (c) 2012-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46 #include "common_nvm.h"
47 #include "conf_board.h"
48 #include "flash_efc.h"
49 #include "string.h"
50
nvm_init(mem_type_t mem)51 status_code_t nvm_init(mem_type_t mem)
52 {
53 switch (mem) {
54 case INT_FLASH:
55 #if SAM4S
56 case INT_USERPAGE:
57 #endif
58 break;
59
60 #if defined(USE_EXTMEM) && defined(CONF_BOARD_AT45DBX)
61 case AT45DBX:
62 /* Initialize dataflash */
63 at45dbx_init();
64 /* Perform memory check */
65 if (!at45dbx_mem_check()) {
66 return ERR_NO_MEMORY;
67 }
68 break;
69 #endif
70
71 default:
72 return ERR_INVALID_ARG;
73 }
74
75 return STATUS_OK;
76 }
77
nvm_read_char(mem_type_t mem,uint32_t address,uint8_t * data)78 status_code_t nvm_read_char(mem_type_t mem, uint32_t address, uint8_t *data)
79 {
80 switch (mem) {
81 case INT_FLASH:
82 *data = *((uint8_t *)(address));
83 break;
84
85 #if SAM4S
86 case INT_USERPAGE:
87 {
88 /*! This function creates a buffer of IFLASH_PAGE_SIZE to
89 * read the data from starting of user signature */
90 uint32_t buffer[IFLASH_PAGE_SIZE];
91 uint32_t offset = address - IFLASH_ADDR;
92 if (offset < 0) {
93 return ERR_INVALID_ARG;
94 }
95
96 flash_read_user_signature(buffer, offset);
97 *data = buffer[offset];
98 break;
99 }
100 #endif
101
102 #if defined(USE_EXTMEM) && defined(CONF_BOARD_AT45DBX)
103 case AT45DBX:
104 if (!at45dbx_read_byte_open(address)) {
105 return ERR_BAD_ADDRESS;
106 }
107
108 *data = at45dbx_read_byte();
109 at45dbx_read_close();
110 break;
111 #endif
112
113 default:
114 return ERR_INVALID_ARG;
115 }
116
117 return STATUS_OK;
118 }
119
nvm_write_char(mem_type_t mem,uint32_t address,uint8_t data)120 status_code_t nvm_write_char(mem_type_t mem, uint32_t address, uint8_t data)
121 {
122 switch (mem) {
123 case INT_FLASH:
124 #if SAM4S
125
126 if (flash_write(address, (const void *)&data, 1,
127 false)) {
128 return ERR_INVALID_ARG;
129 }
130
131 #else
132 if (flash_write(address, (const void *)&data, 1, true)) {
133 return ERR_INVALID_ARG;
134 }
135
136 #endif
137 break;
138
139 #if SAM4S
140 case INT_USERPAGE:
141 if (flash_write_user_signature((const void *)&data, 1)) {
142 return ERR_INVALID_ARG;
143 }
144 break;
145 #endif
146
147 #if defined(USE_EXTMEM) && defined(CONF_BOARD_AT45DBX)
148 case AT45DBX:
149 if (!at45dbx_write_byte_open(address)) {
150 return ERR_BAD_ADDRESS;
151 }
152
153 at45dbx_write_byte(data);
154 at45dbx_write_close();
155 break;
156 #endif
157
158 default:
159 return ERR_INVALID_ARG;
160 }
161
162 return STATUS_OK;
163 }
164
nvm_read(mem_type_t mem,uint32_t address,void * buffer,uint32_t len)165 status_code_t nvm_read(mem_type_t mem, uint32_t address, void *buffer,
166 uint32_t len)
167 {
168 switch (mem) {
169 case INT_FLASH:
170 memcpy(buffer, (const void *)address, len);
171 break;
172
173 #if SAM4S
174 case INT_USERPAGE:
175 {
176 /*! This function creates a buffer of IFLASH_PAGE_SIZE to
177 * read the data from starting of user signature */
178 uint32_t temp_buff[IFLASH_PAGE_SIZE], *buff = buffer;
179
180 /* Read from the starting of user signature */
181 if (flash_read_user_signature(temp_buff, len)) {
182 return ERR_INVALID_ARG;
183 }
184
185 /* Calculate offset and copy required number of bytes */
186 for (uint16_t i = 0; i < len; i++) {
187 *buff = temp_buff[address - IFLASH_ADDR + i];
188 buff++;
189 }
190 break;
191 }
192 #endif
193
194 #if defined(USE_EXTMEM) && defined(CONF_BOARD_AT45DBX)
195 case AT45DBX:
196 {
197 if (len == AT45DBX_SECTOR_SIZE) {
198 uint32_t sector = address / AT45DBX_SECTOR_SIZE;
199 if (!at45dbx_read_sector_open(sector)) {
200 return ERR_BAD_ADDRESS;
201 }
202
203 at45dbx_read_sector_to_ram(buffer);
204 at45dbx_read_close();
205 } else {
206 if (!at45dbx_read_byte_open(address)) {
207 return ERR_BAD_ADDRESS;
208 }
209 uint8_t *buf = (uint8_t *)buffer;
210 while (len--) {
211 *buf++ = at45dbx_read_byte();
212 }
213 at45dbx_read_close();
214 }
215
216 }
217 break;
218 #endif
219
220 default:
221 return ERR_INVALID_ARG;
222 }
223
224 return STATUS_OK;
225 }
226
nvm_write(mem_type_t mem,uint32_t address,void * buffer,uint32_t len)227 status_code_t nvm_write(mem_type_t mem, uint32_t address, void *buffer,
228 uint32_t len)
229 {
230 switch (mem) {
231 case INT_FLASH:
232 #if SAM4S
233
234 if (flash_write(address, (const void *)buffer, len, false)) {
235 return ERR_INVALID_ARG;
236 }
237
238 #else
239 if (flash_write(address, (const void *)buffer, len, true)) {
240 return ERR_INVALID_ARG;
241 }
242
243 #endif
244 break;
245
246 #if SAM4S
247 case INT_USERPAGE:
248 if (flash_write_user_signature((const void *)buffer, len)) {
249 return ERR_INVALID_ARG;
250 }
251 break;
252 #endif
253
254 #if defined(USE_EXTMEM) && defined(CONF_BOARD_AT45DBX)
255 case AT45DBX:
256 {
257 if (len == AT45DBX_SECTOR_SIZE) {
258 uint32_t sector = address / AT45DBX_SECTOR_SIZE;
259 if (!at45dbx_write_sector_open(sector)) {
260 return ERR_BAD_ADDRESS;
261 }
262
263 at45dbx_write_sector_from_ram((const void *)buffer);
264 at45dbx_write_close();
265 } else {
266 if (!at45dbx_write_byte_open(address)) {
267 return ERR_BAD_ADDRESS;
268 }
269 uint8_t *buf = (uint8_t *)buffer;
270 while (len--) {
271 at45dbx_write_byte(*buf++);
272 }
273 at45dbx_write_close();
274 }
275 }
276 break;
277 #endif
278
279 default:
280 return ERR_INVALID_ARG;
281 }
282
283 return STATUS_OK;
284 }
285
nvm_page_erase(mem_type_t mem,uint32_t page_number)286 status_code_t nvm_page_erase(mem_type_t mem, uint32_t page_number)
287 {
288 switch (mem) {
289 case INT_FLASH:
290 {
291 #if SAM4S
292 /*! Page erase function erases minimum 8 pages in Flash */
293 if (flash_erase_page((uint32_t)(page_number * IFLASH_PAGE_SIZE),
294 IFLASH_ERASE_PAGES_8)) {
295 return ERR_INVALID_ARG;
296 }
297
298 #else
299 uint32_t buffer[IFLASH_PAGE_SIZE], byte_address;
300 for (uint16_t i = 0; i < IFLASH_PAGE_SIZE; i++) {
301 buffer[i] = 0xFFFFFFFF;
302 }
303 byte_address = page_number * IFLASH_PAGE_SIZE;
304
305 /* Erase and write FFs to a page as there is no function for
306 * erase */
307 if (!flash_write(byte_address, (const void *)buffer,
308 IFLASH_PAGE_SIZE, true)) {
309 return ERR_INVALID_ARG;
310 }
311
312 #endif
313 break;
314 }
315
316 #if SAM4S
317 case INT_USERPAGE:
318 flash_erase_user_signature();
319 break;
320 #endif
321
322 default:
323 return ERR_INVALID_ARG;
324 }
325
326 return STATUS_OK;
327 }
328
nvm_get_size(mem_type_t mem,uint32_t * size)329 status_code_t nvm_get_size(mem_type_t mem, uint32_t *size)
330 {
331 switch (mem) {
332 case INT_FLASH:
333 *size = (uint32_t)IFLASH_SIZE;
334 break;
335
336 #if SAM4S
337 case INT_USERPAGE:
338 *size = (uint32_t)IFLASH_PAGE_SIZE;
339 break;
340 #endif
341
342 #if defined(USE_EXTMEM) && defined(CONF_BOARD_AT45DBX)
343 case AT45DBX:
344 *size = (uint32_t)AT45DBX_MEM_SIZE;
345 break;
346 #endif
347
348 default:
349 return ERR_INVALID_ARG;
350 }
351
352 return STATUS_OK;
353 }
354
nvm_get_page_size(mem_type_t mem,uint32_t * size)355 status_code_t nvm_get_page_size(mem_type_t mem, uint32_t *size)
356 {
357 switch (mem) {
358 case INT_FLASH:
359 #if SAM4S
360 case INT_USERPAGE:
361 #endif
362 *size = (uint32_t)IFLASH_PAGE_SIZE;
363 break;
364
365 default:
366 return ERR_INVALID_ARG;
367 }
368
369 return STATUS_OK;
370 }
371
nvm_get_pagenumber(mem_type_t mem,uint32_t address,uint32_t * num)372 status_code_t nvm_get_pagenumber(mem_type_t mem, uint32_t address,
373 uint32_t *num)
374 {
375 switch (mem) {
376 case INT_FLASH:
377 *num = (uint32_t)(address / IFLASH_PAGE_SIZE);
378 break;
379
380 default:
381 return ERR_INVALID_ARG;
382 }
383
384 return STATUS_OK;
385 }
386
nvm_set_security_bit(void)387 status_code_t nvm_set_security_bit(void)
388 {
389 if (!flash_enable_security_bit()) {
390 return ERR_INVALID_ARG;
391 }
392
393 return STATUS_OK;
394 }
395