1 /**
2 * \file
3 *
4 * \brief FLASHC driver for AVR32 UC3.
5 *
6 * Copyright (c) 2009-2018 Microchip Technology Inc. and its subsidiaries.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Subject to your compliance with these terms, you may use Microchip
13 * software and any derivatives exclusively with Microchip products.
14 * It is your responsibility to comply with third party license terms applicable
15 * to your use of third party software (including open source software) that
16 * may accompany Microchip software.
17 *
18 * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
19 * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
20 * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
21 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
22 * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
23 * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
24 * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
25 * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
26 * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
27 * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
28 * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
29 *
30 * \asf_license_stop
31 *
32 */
33 /*
34 * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
35 */
36
37
38 #include <avr32/io.h>
39 #include <stddef.h>
40 #include "compiler.h"
41 #include "flashc.h"
42
43
44 /*! \name FLASHC Writable Bit-Field Registers
45 */
46 //! @{
47
48 typedef union {
49 unsigned long fcr;
50 avr32_flashc_fcr_t FCR;
51 } u_avr32_flashc_fcr_t;
52
53 typedef union {
54 unsigned long fcmd;
55 avr32_flashc_fcmd_t FCMD;
56 } u_avr32_flashc_fcmd_t;
57
58 //! @}
59
60
61 /*! \name Flash Properties
62 */
63 //! @{
64
65
flashc_get_flash_size(void)66 unsigned int flashc_get_flash_size(void)
67 {
68 #if (AVR32_FLASHC_H_VERSION >= 300)
69 const uint16_t FLASH_SIZE[] = {
70 4,
71 8,
72 16,
73 32,
74 48,
75 64,
76 96,
77 128,
78 192,
79 256,
80 384,
81 512,
82 768,
83 1024,
84 2048,
85 };
86 return ((unsigned int)FLASH_SIZE[(AVR32_FLASHC.pr & AVR32_FLASHC_PR_FSZ_MASK)
87 >> AVR32_FLASHC_PR_FSZ_OFFSET])<<10;
88
89 #else // in older flashc version, FSZ is located in FSR register
90 const uint16_t FLASH_SIZE[] = {
91 32,
92 64,
93 128,
94 256,
95 384,
96 512,
97 768,
98 1024,
99 };
100 return ((unsigned int)FLASH_SIZE[(AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_FSZ_MASK)
101 >> AVR32_FLASHC_FSR_FSZ_OFFSET]) << 10;
102 #endif
103 }
104
105
flashc_get_page_count(void)106 unsigned int flashc_get_page_count(void)
107 {
108 return flashc_get_flash_size() / AVR32_FLASHC_PAGE_SIZE;
109 }
110
111
flashc_get_page_count_per_region(void)112 unsigned int flashc_get_page_count_per_region(void)
113 {
114 return flashc_get_page_count() / AVR32_FLASHC_REGIONS;
115 }
116
117
flashc_get_page_region(int page_number)118 unsigned int flashc_get_page_region(int page_number)
119 {
120 return ((page_number >= 0) ? page_number
121 : flashc_get_page_number()) / flashc_get_page_count_per_region();
122 }
123
124
flashc_get_region_first_page_number(unsigned int region)125 unsigned int flashc_get_region_first_page_number(unsigned int region)
126 {
127 return region * flashc_get_page_count_per_region();
128 }
129
130
131 //! @}
132
133
134 /*! \name FLASHC Control
135 */
136 //! @{
137
138
flashc_get_wait_state(void)139 unsigned int flashc_get_wait_state(void)
140 {
141 return (AVR32_FLASHC.fcr & AVR32_FLASHC_FCR_FWS_MASK) >> AVR32_FLASHC_FCR_FWS_OFFSET;
142 }
143
144
flashc_set_wait_state(unsigned int wait_state)145 void flashc_set_wait_state(unsigned int wait_state)
146 {
147 u_avr32_flashc_fcr_t u_avr32_flashc_fcr = {AVR32_FLASHC.fcr};
148 u_avr32_flashc_fcr.FCR.fws = wait_state;
149 AVR32_FLASHC.fcr = u_avr32_flashc_fcr.fcr;
150 }
151
152
flashc_set_bus_freq(unsigned int cpu_f_hz)153 void flashc_set_bus_freq(unsigned int cpu_f_hz)
154 {
155 if (cpu_f_hz >= AVR32_FLASHC_FWS_0_MAX_FREQ) {
156 // Set 1 WS.
157 flashc_set_wait_state(1);
158 } else {
159 // Set 0 WS.
160 flashc_set_wait_state(0);
161 }
162 }
163
flashc_is_ready_int_enabled(void)164 bool flashc_is_ready_int_enabled(void)
165 {
166 return ((AVR32_FLASHC.fcr & AVR32_FLASHC_FCR_FRDY_MASK) != 0);
167 }
168
169
flashc_enable_ready_int(bool enable)170 void flashc_enable_ready_int(bool enable)
171 {
172 u_avr32_flashc_fcr_t u_avr32_flashc_fcr = {AVR32_FLASHC.fcr};
173 u_avr32_flashc_fcr.FCR.frdy = (enable != false);
174 AVR32_FLASHC.fcr = u_avr32_flashc_fcr.fcr;
175 }
176
177
flashc_is_lock_error_int_enabled(void)178 bool flashc_is_lock_error_int_enabled(void)
179 {
180 return ((AVR32_FLASHC.fcr & AVR32_FLASHC_FCR_LOCKE_MASK) != 0);
181 }
182
183
flashc_enable_lock_error_int(bool enable)184 void flashc_enable_lock_error_int(bool enable)
185 {
186 u_avr32_flashc_fcr_t u_avr32_flashc_fcr = {AVR32_FLASHC.fcr};
187 u_avr32_flashc_fcr.FCR.locke = (enable != false);
188 AVR32_FLASHC.fcr = u_avr32_flashc_fcr.fcr;
189 }
190
191
flashc_is_prog_error_int_enabled(void)192 bool flashc_is_prog_error_int_enabled(void)
193 {
194 return ((AVR32_FLASHC.fcr & AVR32_FLASHC_FCR_PROGE_MASK) != 0);
195 }
196
197
flashc_enable_prog_error_int(bool enable)198 void flashc_enable_prog_error_int(bool enable)
199 {
200 u_avr32_flashc_fcr_t u_avr32_flashc_fcr = {AVR32_FLASHC.fcr};
201 u_avr32_flashc_fcr.FCR.proge = (enable != false);
202 AVR32_FLASHC.fcr = u_avr32_flashc_fcr.fcr;
203 }
204
205
206 //! @}
207
208
209 /*! \name FLASHC Status
210 */
211 //! @{
212
213
flashc_is_ready(void)214 bool flashc_is_ready(void)
215 {
216 return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_FRDY_MASK) != 0);
217 }
218
219
flashc_default_wait_until_ready(void)220 void flashc_default_wait_until_ready(void)
221 {
222 while (!flashc_is_ready());
223 }
224
225
226 void (*volatile flashc_wait_until_ready)(void) = flashc_default_wait_until_ready;
227
228
229 /*! \brief Gets the error status of the FLASHC.
230 *
231 * \return The error status of the FLASHC built up from
232 * \c AVR32_FLASHC_FSR_LOCKE_MASK and \c AVR32_FLASHC_FSR_PROGE_MASK.
233 *
234 * \warning This hardware error status is cleared by all functions reading the
235 * Flash Status Register (FSR). This function is therefore not part of
236 * the driver's API which instead presents \ref flashc_is_lock_error
237 * and \ref flashc_is_programming_error.
238 */
flashc_get_error_status(void)239 static unsigned int flashc_get_error_status(void)
240 {
241 return AVR32_FLASHC.fsr & (AVR32_FLASHC_FSR_LOCKE_MASK |
242 AVR32_FLASHC_FSR_PROGE_MASK);
243 }
244
245
246 //! Sticky error status of the FLASHC.
247 //! This variable is updated by functions that issue FLASHC commands. It
248 //! contains the cumulated FLASHC error status of all the FLASHC commands issued
249 //! by a function.
250 static unsigned int flashc_error_status = 0;
251
252
flashc_is_lock_error(void)253 bool flashc_is_lock_error(void)
254 {
255 return ((flashc_error_status & AVR32_FLASHC_FSR_LOCKE_MASK) != 0);
256 }
257
258
flashc_is_programming_error(void)259 bool flashc_is_programming_error(void)
260 {
261 return ((flashc_error_status & AVR32_FLASHC_FSR_PROGE_MASK) != 0);
262 }
263
264
265 //! @}
266
267
268 /*! \name FLASHC Command Control
269 */
270 //! @{
271
272
flashc_get_command(void)273 unsigned int flashc_get_command(void)
274 {
275 return (AVR32_FLASHC.fcmd & AVR32_FLASHC_FCMD_CMD_MASK) >> AVR32_FLASHC_FCMD_CMD_OFFSET;
276 }
277
278
flashc_get_page_number(void)279 unsigned int flashc_get_page_number(void)
280 {
281 return (AVR32_FLASHC.fcmd & AVR32_FLASHC_FCMD_PAGEN_MASK) >> AVR32_FLASHC_FCMD_PAGEN_OFFSET;
282 }
283
284
flashc_issue_command(unsigned int command,int page_number)285 void flashc_issue_command(unsigned int command, int page_number)
286 {
287 u_avr32_flashc_fcmd_t u_avr32_flashc_fcmd;
288
289 flashc_wait_until_ready();
290 u_avr32_flashc_fcmd.fcmd = AVR32_FLASHC.fcmd;
291 u_avr32_flashc_fcmd.FCMD.cmd = command;
292 if (page_number >= 0) {
293 u_avr32_flashc_fcmd.FCMD.pagen = page_number;
294 }
295 u_avr32_flashc_fcmd.FCMD.key = AVR32_FLASHC_FCMD_KEY_KEY;
296 AVR32_FLASHC.fcmd = u_avr32_flashc_fcmd.fcmd;
297 flashc_error_status = flashc_get_error_status();
298 flashc_wait_until_ready();
299 }
300
301
302 //! @}
303
304
305 /*! \name FLASHC Global Commands
306 */
307 //! @{
308
309
flashc_no_operation(void)310 void flashc_no_operation(void)
311 {
312 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_NOP, -1);
313 }
314
315
flashc_erase_all(void)316 void flashc_erase_all(void)
317 {
318 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EA, -1);
319 }
320
321
322 //! @}
323
324
325 /*! \name FLASHC Protection Mechanisms
326 */
327 //! @{
328
329
flashc_is_security_bit_active(void)330 bool flashc_is_security_bit_active(void)
331 {
332 return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_SECURITY_MASK) != 0);
333 }
334
335
flashc_activate_security_bit(void)336 void flashc_activate_security_bit(void)
337 {
338 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_SSB, -1);
339 }
340
341
flashc_get_bootloader_protected_size(void)342 unsigned int flashc_get_bootloader_protected_size(void)
343 {
344 unsigned int bootprot = (1 << AVR32_FLASHC_FGPFRLO_BOOTPROT_SIZE) - 1 -
345 flashc_read_gp_fuse_bitfield(AVR32_FLASHC_FGPFRLO_BOOTPROT_OFFSET,
346 AVR32_FLASHC_FGPFRLO_BOOTPROT_SIZE);
347 return (bootprot) ? AVR32_FLASHC_PAGE_SIZE << bootprot : 0;
348 }
349
350
flashc_set_bootloader_protected_size(unsigned int bootprot_size)351 unsigned int flashc_set_bootloader_protected_size(unsigned int bootprot_size)
352 {
353 flashc_set_gp_fuse_bitfield(AVR32_FLASHC_FGPFRLO_BOOTPROT_OFFSET,
354 AVR32_FLASHC_FGPFRLO_BOOTPROT_SIZE,
355 (1 << AVR32_FLASHC_FGPFRLO_BOOTPROT_SIZE) - 1 -
356 ((bootprot_size) ?
357 32 - clz((((min(max(bootprot_size, AVR32_FLASHC_PAGE_SIZE << 1),
358 AVR32_FLASHC_PAGE_SIZE <<
359 ((1 << AVR32_FLASHC_FGPFRLO_BOOTPROT_SIZE) - 1)) +
360 AVR32_FLASHC_PAGE_SIZE - 1) /
361 AVR32_FLASHC_PAGE_SIZE) << 1) - 1) - 1 :
362 0));
363 return flashc_get_bootloader_protected_size();
364 }
365
366
flashc_is_external_privileged_fetch_locked(void)367 bool flashc_is_external_privileged_fetch_locked(void)
368 {
369 return (!flashc_read_gp_fuse_bit(AVR32_FLASHC_FGPFRLO_EPFL_OFFSET));
370 }
371
372
flashc_lock_external_privileged_fetch(bool lock)373 void flashc_lock_external_privileged_fetch(bool lock)
374 {
375 flashc_set_gp_fuse_bit(AVR32_FLASHC_FGPFRLO_EPFL_OFFSET, !lock);
376 }
377
378
flashc_is_page_region_locked(int page_number)379 bool flashc_is_page_region_locked(int page_number)
380 {
381 return flashc_is_region_locked(flashc_get_page_region(page_number));
382 }
383
384
flashc_is_region_locked(unsigned int region)385 bool flashc_is_region_locked(unsigned int region)
386 {
387 return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_LOCK0_MASK << (region & (AVR32_FLASHC_REGIONS - 1))) != 0);
388 }
389
390
flashc_lock_page_region(int page_number,bool lock)391 void flashc_lock_page_region(int page_number, bool lock)
392 {
393 flashc_issue_command((lock) ? AVR32_FLASHC_FCMD_CMD_LP : AVR32_FLASHC_FCMD_CMD_UP, page_number);
394 }
395
396
flashc_lock_region(unsigned int region,bool lock)397 void flashc_lock_region(unsigned int region, bool lock)
398 {
399 flashc_lock_page_region(flashc_get_region_first_page_number(region), lock);
400 }
401
402
flashc_lock_all_regions(bool lock)403 void flashc_lock_all_regions(bool lock)
404 {
405 unsigned int error_status = 0;
406 unsigned int region = AVR32_FLASHC_REGIONS;
407
408 while (region) {
409 flashc_lock_region(--region, lock);
410 error_status |= flashc_error_status;
411 }
412 flashc_error_status = error_status;
413 }
414
415
416 //! @}
417
418
419 /*! \name Access to General-Purpose Fuses
420 */
421 //! @{
422
423
flashc_read_gp_fuse_bit(unsigned int gp_fuse_bit)424 bool flashc_read_gp_fuse_bit(unsigned int gp_fuse_bit)
425 {
426 return ((flashc_read_all_gp_fuses() & 1ULL << (gp_fuse_bit & 0x3F)) != 0);
427 }
428
429
flashc_read_gp_fuse_bitfield(unsigned int pos,unsigned int width)430 uint64_t flashc_read_gp_fuse_bitfield(unsigned int pos, unsigned int width)
431 {
432 return flashc_read_all_gp_fuses() >> (pos & 0x3F) & ((1ULL << min(width, 64)) - 1);
433 }
434
435
flashc_read_gp_fuse_byte(unsigned int gp_fuse_byte)436 uint8_t flashc_read_gp_fuse_byte(unsigned int gp_fuse_byte)
437 {
438 return flashc_read_all_gp_fuses() >> ((gp_fuse_byte & 0x07) << 3);
439 }
440
441
flashc_read_all_gp_fuses(void)442 uint64_t flashc_read_all_gp_fuses(void)
443 {
444 return AVR32_FLASHC.fgpfrlo | (uint64_t)AVR32_FLASHC.fgpfrhi << 32;
445 }
446
447
flashc_erase_gp_fuse_bit(unsigned int gp_fuse_bit,bool check)448 bool flashc_erase_gp_fuse_bit(unsigned int gp_fuse_bit, bool check)
449 {
450 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EGPB, gp_fuse_bit & 0x3F);
451 return (check) ? flashc_read_gp_fuse_bit(gp_fuse_bit) : true;
452 }
453
454
flashc_erase_gp_fuse_bitfield(unsigned int pos,unsigned int width,bool check)455 bool flashc_erase_gp_fuse_bitfield(unsigned int pos, unsigned int width, bool check)
456 {
457 unsigned int error_status = 0;
458 unsigned int gp_fuse_bit;
459
460 pos &= 0x3F;
461 width = min(width, 64);
462 for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++) {
463 flashc_erase_gp_fuse_bit(gp_fuse_bit, false);
464 error_status |= flashc_error_status;
465 }
466 flashc_error_status = error_status;
467 return (check) ? (flashc_read_gp_fuse_bitfield(pos, width) == (1ULL << width) - 1) : true;
468 }
469
470
flashc_erase_gp_fuse_byte(unsigned int gp_fuse_byte,bool check)471 bool flashc_erase_gp_fuse_byte(unsigned int gp_fuse_byte, bool check)
472 {
473 unsigned int error_status;
474 unsigned int current_gp_fuse_byte;
475
476 uint64_t value = flashc_read_all_gp_fuses();
477 flashc_erase_all_gp_fuses(false);
478 error_status = flashc_error_status;
479
480 for (current_gp_fuse_byte = 0; current_gp_fuse_byte < 8; current_gp_fuse_byte++, value >>= 8) {
481 if (current_gp_fuse_byte != gp_fuse_byte) {
482 flashc_write_gp_fuse_byte(current_gp_fuse_byte, value);
483 error_status |= flashc_error_status;
484 }
485 }
486 flashc_error_status = error_status;
487 return (check) ? (flashc_read_gp_fuse_byte(gp_fuse_byte) == 0xFF) : true;
488 }
489
490
flashc_erase_all_gp_fuses(bool check)491 bool flashc_erase_all_gp_fuses(bool check)
492 {
493 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EAGPF, -1);
494 return (check) ? (flashc_read_all_gp_fuses() == 0xFFFFFFFFFFFFFFFFULL) : true;
495 }
496
497
flashc_write_gp_fuse_bit(unsigned int gp_fuse_bit,bool value)498 void flashc_write_gp_fuse_bit(unsigned int gp_fuse_bit, bool value)
499 {
500 if (!value) {
501 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_WGPB, gp_fuse_bit & 0x3F);
502 }
503 }
504
505
flashc_write_gp_fuse_bitfield(unsigned int pos,unsigned int width,uint64_t value)506 void flashc_write_gp_fuse_bitfield(unsigned int pos, unsigned int width, uint64_t value)
507 {
508 unsigned int error_status = 0;
509 unsigned int gp_fuse_bit;
510
511 pos &= 0x3F;
512 width = min(width, 64);
513
514 for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++, value >>= 1) {
515 flashc_write_gp_fuse_bit(gp_fuse_bit, value & 0x01);
516 error_status |= flashc_error_status;
517 }
518
519 flashc_error_status = error_status;
520 }
521
522
flashc_write_gp_fuse_byte(unsigned int gp_fuse_byte,uint8_t value)523 void flashc_write_gp_fuse_byte(unsigned int gp_fuse_byte, uint8_t value)
524 {
525 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_PGPFB, (gp_fuse_byte & 0x07) | value << 3);
526 }
527
528
flashc_write_all_gp_fuses(uint64_t value)529 void flashc_write_all_gp_fuses(uint64_t value)
530 {
531 unsigned int error_status = 0;
532 unsigned int gp_fuse_byte;
533
534 for (gp_fuse_byte = 0; gp_fuse_byte < 8; gp_fuse_byte++, value >>= 8) {
535 flashc_write_gp_fuse_byte(gp_fuse_byte, value);
536 error_status |= flashc_error_status;
537 }
538
539 flashc_error_status = error_status;
540 }
541
542
flashc_set_gp_fuse_bit(unsigned int gp_fuse_bit,bool value)543 void flashc_set_gp_fuse_bit(unsigned int gp_fuse_bit, bool value)
544 {
545 if (value) {
546 flashc_erase_gp_fuse_bit(gp_fuse_bit, false);
547 } else {
548 flashc_write_gp_fuse_bit(gp_fuse_bit, false);
549 }
550 }
551
552
flashc_set_gp_fuse_bitfield(unsigned int pos,unsigned int width,uint64_t value)553 void flashc_set_gp_fuse_bitfield(unsigned int pos, unsigned int width, uint64_t value)
554 {
555 unsigned int error_status = 0;
556 unsigned int gp_fuse_bit;
557
558 pos &= 0x3F;
559 width = min(width, 64);
560
561 for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++, value >>= 1) {
562 flashc_set_gp_fuse_bit(gp_fuse_bit, value & 0x01);
563 error_status |= flashc_error_status;
564 }
565
566 flashc_error_status = error_status;
567 }
568
569
flashc_set_gp_fuse_byte(unsigned int gp_fuse_byte,uint8_t value)570 void flashc_set_gp_fuse_byte(unsigned int gp_fuse_byte, uint8_t value)
571 {
572 unsigned int error_status;
573
574 switch (value) {
575 case 0xFF:
576 flashc_erase_gp_fuse_byte(gp_fuse_byte, false);
577 break;
578
579 case 0x00:
580 flashc_write_gp_fuse_byte(gp_fuse_byte, 0x00);
581 break;
582
583 default:
584 flashc_erase_gp_fuse_byte(gp_fuse_byte, false);
585 error_status = flashc_error_status;
586 flashc_write_gp_fuse_byte(gp_fuse_byte, value);
587 flashc_error_status |= error_status;
588 break;
589 }
590 }
591
592
flashc_set_all_gp_fuses(uint64_t value)593 void flashc_set_all_gp_fuses(uint64_t value)
594 {
595 unsigned int error_status;
596
597 switch (value) {
598 case 0xFFFFFFFFFFFFFFFFULL:
599 flashc_erase_all_gp_fuses(false);
600 break;
601
602 case 0x0000000000000000ULL:
603 flashc_write_all_gp_fuses(0x0000000000000000ULL);
604 break;
605
606 default:
607 flashc_erase_all_gp_fuses(false);
608 error_status = flashc_error_status;
609 flashc_write_all_gp_fuses(value);
610 flashc_error_status |= error_status;
611 break;
612 }
613 }
614
615
616 //! @}
617
618
619 /*! \name Access to Flash Pages
620 */
621 //! @{
622
623
flashc_clear_page_buffer(void)624 void flashc_clear_page_buffer(void)
625 {
626 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_CPB, -1);
627 }
628
629
flashc_is_page_erased(void)630 bool flashc_is_page_erased(void)
631 {
632 return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_QPRR_MASK) != 0);
633 }
634
635
flashc_quick_page_read(int page_number)636 bool flashc_quick_page_read(int page_number)
637 {
638 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_QPR, page_number);
639 return flashc_is_page_erased();
640 }
641
642
flashc_erase_page(int page_number,bool check)643 bool flashc_erase_page(int page_number, bool check)
644 {
645 bool page_erased = true;
646
647 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EP, page_number);
648 if (check) {
649 unsigned int error_status = flashc_error_status;
650 page_erased = flashc_quick_page_read(-1);
651 flashc_error_status |= error_status;
652 }
653 return page_erased;
654 }
655
656
flashc_erase_all_pages(bool check)657 bool flashc_erase_all_pages(bool check)
658 {
659 bool all_pages_erased = true;
660 unsigned int error_status = 0;
661 unsigned int page_number = flashc_get_page_count();
662
663 while (page_number) {
664 all_pages_erased &= flashc_erase_page(--page_number, check);
665 error_status |= flashc_error_status;
666 }
667 flashc_error_status = error_status;
668 return all_pages_erased;
669 }
670
671
flashc_write_page(int page_number)672 void flashc_write_page(int page_number)
673 {
674 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_WP, page_number);
675 }
676
677
flashc_quick_user_page_read(void)678 bool flashc_quick_user_page_read(void)
679 {
680 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_QPRUP, -1);
681 return flashc_is_page_erased();
682 }
683
684
flashc_erase_user_page(bool check)685 bool flashc_erase_user_page(bool check)
686 {
687 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EUP, -1);
688 return (check) ? flashc_quick_user_page_read() : true;
689 }
690
691
flashc_write_user_page(void)692 void flashc_write_user_page(void)
693 {
694 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_WUP, -1);
695 }
696
697
flashc_memset8(volatile void * dst,uint8_t src,size_t nbytes,bool erase)698 volatile void *flashc_memset8(volatile void *dst, uint8_t src, size_t nbytes, bool erase)
699 {
700 return flashc_memset16(dst, src | (uint16_t)src << 8, nbytes, erase);
701 }
702
703
flashc_memset16(volatile void * dst,uint16_t src,size_t nbytes,bool erase)704 volatile void *flashc_memset16(volatile void *dst, uint16_t src, size_t nbytes, bool erase)
705 {
706 return flashc_memset32(dst, src | (uint32_t)src << 16, nbytes, erase);
707 }
708
709
flashc_memset32(volatile void * dst,uint32_t src,size_t nbytes,bool erase)710 volatile void *flashc_memset32(volatile void *dst, uint32_t src, size_t nbytes, bool erase)
711 {
712 return flashc_memset64(dst, src | (uint64_t)src << 32, nbytes, erase);
713 }
714
715
flashc_memset64(volatile void * dst,uint64_t src,size_t nbytes,bool erase)716 volatile void *flashc_memset64(volatile void *dst, uint64_t src, size_t nbytes, bool erase)
717 {
718 // Use aggregated pointers to have several alignments available for a same address.
719 UnionCVPtr flash_array_end;
720 UnionVPtr dest;
721 Union64 source = {0};
722 StructCVPtr dest_end;
723 UnionCVPtr flash_page_source_end;
724 bool incomplete_flash_page_end;
725 Union64 flash_dword;
726 UnionVPtr tmp;
727 unsigned int error_status = 0;
728 unsigned int i;
729
730 // Reformat arguments.
731 flash_array_end.u8ptr = AVR32_FLASH + flashc_get_flash_size();
732 dest.u8ptr = dst;
733 for (i = (Get_align((uint32_t)dest.u8ptr, sizeof(uint64_t)) - 1) & (sizeof(uint64_t) - 1);
734 src; i = (i - 1) & (sizeof(uint64_t) - 1)) {
735 source.u8[i] = src;
736 src >>= 8;
737 }
738 dest_end.u8ptr = dest.u8ptr + nbytes;
739
740 // If destination is outside flash, go to next flash page if any.
741 if (dest.u8ptr < AVR32_FLASH) {
742 dest.u8ptr = AVR32_FLASH;
743 } else if (flash_array_end.u8ptr <= dest.u8ptr && dest.u8ptr < AVR32_FLASHC_USER_PAGE) {
744 dest.u8ptr = AVR32_FLASHC_USER_PAGE;
745 }
746
747 // If end of destination is outside flash, move it to the end of the previous flash page if any.
748 if (dest_end.u8ptr > AVR32_FLASHC_USER_PAGE + AVR32_FLASHC_USER_PAGE_SIZE) {
749 dest_end.u8ptr = AVR32_FLASHC_USER_PAGE + AVR32_FLASHC_USER_PAGE_SIZE;
750 } else if (AVR32_FLASHC_USER_PAGE >= dest_end.u8ptr && dest_end.u8ptr > flash_array_end.u8ptr) {
751 dest_end.u8ptr = flash_array_end.u8ptr;
752 }
753
754 // Align each end of destination pointer with its natural boundary.
755 dest_end.u16ptr = (uint16_t *)Align_down((uint32_t)dest_end.u8ptr, sizeof(uint16_t));
756 dest_end.u32ptr = (uint32_t *)Align_down((uint32_t)dest_end.u16ptr, sizeof(uint32_t));
757 dest_end.u64ptr = (uint64_t *)Align_down((uint32_t)dest_end.u32ptr, sizeof(uint64_t));
758
759 // While end of destination is not reached...
760 while (dest.u8ptr < dest_end.u8ptr) {
761 // Clear the page buffer in order to prepare data for a flash page write.
762 flashc_clear_page_buffer();
763 error_status |= flashc_error_status;
764
765 // Determine where the source data will end in the current flash page.
766 flash_page_source_end.u64ptr =
767 (uint64_t *)min((uint32_t)dest_end.u64ptr,
768 Align_down((uint32_t)dest.u8ptr, AVR32_FLASHC_PAGE_SIZE) + AVR32_FLASHC_PAGE_SIZE);
769
770 // Determine if the current destination page has an incomplete end.
771 incomplete_flash_page_end = (Align_down((uint32_t)dest.u8ptr, AVR32_FLASHC_PAGE_SIZE) >=
772 Align_down((uint32_t)dest_end.u8ptr, AVR32_FLASHC_PAGE_SIZE));
773
774 // Use a flash double-word buffer to manage unaligned accesses.
775 flash_dword.u64 = source.u64;
776
777 // If destination does not point to the beginning of the current flash page...
778 if (!Test_align((uint32_t)dest.u8ptr, AVR32_FLASHC_PAGE_SIZE)) {
779 // Fill the beginning of the page buffer with the current flash page data.
780 // This is required by the hardware, even if page erase is not requested,
781 // in order to be able to write successfully to erased parts of flash
782 // pages that have already been written to.
783 for (tmp.u8ptr = (uint8_t *)Align_down((uint32_t)dest.u8ptr, AVR32_FLASHC_PAGE_SIZE);
784 tmp.u64ptr < (uint64_t *)Align_down((uint32_t)dest.u8ptr, sizeof(uint64_t));
785 tmp.u64ptr++) {
786 *tmp.u64ptr = *tmp.u64ptr;
787 }
788
789 // If destination is not 64-bit aligned...
790 if (!Test_align((uint32_t)dest.u8ptr, sizeof(uint64_t))) {
791 // Fill the beginning of the flash double-word buffer with the current
792 // flash page data.
793 // This is required by the hardware, even if page erase is not
794 // requested, in order to be able to write successfully to erased parts
795 // of flash pages that have already been written to.
796 for (i = 0; i < Get_align((uint32_t)dest.u8ptr, sizeof(uint64_t)); i++) {
797 flash_dword.u8[i] = *tmp.u8ptr++;
798 }
799
800 // Align the destination pointer with its 64-bit boundary.
801 dest.u64ptr = (uint64_t *)Align_down((uint32_t)dest.u8ptr, sizeof(uint64_t));
802
803 // If the current destination double-word is not the last one...
804 if (dest.u64ptr < dest_end.u64ptr) {
805 // Write the flash double-word buffer to the page buffer and reinitialize it.
806 *dest.u64ptr++ = flash_dword.u64;
807 flash_dword.u64 = source.u64;
808 }
809 }
810 }
811
812 // Write the source data to the page buffer with 64-bit alignment.
813 for (i = flash_page_source_end.u64ptr - dest.u64ptr; i; i--) {
814 *dest.u64ptr++ = source.u64;
815 }
816
817 // If the current destination page has an incomplete end...
818 if (incomplete_flash_page_end) {
819 // This is required by the hardware, even if page erase is not requested,
820 // in order to be able to write successfully to erased parts of flash
821 // pages that have already been written to.
822 {
823 tmp.u8ptr = (volatile uint8_t *)dest_end.u8ptr;
824
825 // If end of destination is not 64-bit aligned...
826 if (!Test_align((uint32_t)dest_end.u8ptr, sizeof(uint64_t))) {
827 // Fill the end of the flash double-word buffer with the current flash page data.
828 for (i = Get_align((uint32_t)dest_end.u8ptr, sizeof(uint64_t)); i < sizeof(uint64_t); i++)
829 flash_dword.u8[i] = *tmp.u8ptr++;
830
831 // Write the flash double-word buffer to the page buffer.
832 *dest.u64ptr++ = flash_dword.u64;
833 }
834
835 // Fill the end of the page buffer with the current flash page data.
836 for (; !Test_align((uint32_t)tmp.u64ptr, AVR32_FLASHC_PAGE_SIZE); tmp.u64ptr++) {
837 *tmp.u64ptr = *tmp.u64ptr;
838 }
839 }
840 }
841
842 // If the current flash page is in the flash array...
843 if (dest.u8ptr <= AVR32_FLASHC_USER_PAGE) {
844 // Erase the current page if requested and write it from the page buffer.
845 if (erase) {
846 flashc_erase_page(-1, false);
847 error_status |= flashc_error_status;
848 }
849 flashc_write_page(-1);
850 error_status |= flashc_error_status;
851
852 // If the end of the flash array is reached, go to the User page.
853 if (dest.u8ptr >= flash_array_end.u8ptr) {
854 dest.u8ptr = AVR32_FLASHC_USER_PAGE;
855 }
856 } else {
857 // Erase the User page if requested and write it from the page buffer.
858 if (erase) {
859 flashc_erase_user_page(false);
860 error_status |= flashc_error_status;
861 }
862 flashc_write_user_page();
863 error_status |= flashc_error_status;
864 }
865 }
866
867 // Update the FLASHC error status.
868 flashc_error_status = error_status;
869
870 // Return the initial destination pointer as the standard memset function does.
871 return dst;
872 }
873
874
flashc_memcpy(volatile void * dst,const void * src,size_t nbytes,bool erase)875 volatile void *flashc_memcpy(volatile void *dst, const void *src, size_t nbytes, bool erase)
876 {
877 uint16_t page_pos;
878 Union64 flash_dword;
879 uint8_t i;
880 bool b_user_page;
881 unsigned int error_status = 0;
882 uint8_t* flash_add;
883 uint8_t* dest_add=(uint8_t*)dst;
884 const uint8_t* src_buf=(const uint8_t*)src;
885
886 // Copy area must be in flash array or flash user page
887 Assert( (((uint8_t *)dst >= AVR32_FLASH)
888 && (((uint8_t *)dst + nbytes) <= (AVR32_FLASH + flashc_get_flash_size())))
889 || (((uint8_t *)dst >= AVR32_FLASHC_USER_PAGE)
890 && (((uint8_t *)dst + nbytes) <= (AVR32_FLASHC_USER_PAGE + AVR32_FLASHC_USER_PAGE_SIZE))) );
891
892 b_user_page = (volatile uint8_t *)dst >= AVR32_FLASHC_USER_PAGE;
893
894 flash_add = (uint8_t*)((uint32_t)dest_add - ((uint32_t)dest_add % AVR32_FLASHC_PAGE_SIZE));
895
896 while (nbytes) {
897 // Clear the page buffer in order to prepare data for a flash page write.
898 flashc_clear_page_buffer();
899 error_status |= flashc_error_status;
900
901 // Loop in the page
902 for (page_pos=0; page_pos<AVR32_FLASHC_PAGE_SIZE; page_pos+=sizeof(uint64_t) ) {
903 // Read the flash double-word buffer
904 flash_dword.u64 = *(volatile uint64_t*)flash_add;
905
906 // Update double-word if necessary
907 for (i = 0; i < sizeof(uint64_t); i++) {
908 if (nbytes && (flash_add == dest_add)) {
909 // Update page with data source
910 flash_dword.u8[i] = *src_buf++;
911 dest_add++;
912 nbytes--;
913 }
914 flash_add++;
915 }
916
917 // Write the flash double-word buffer to the page buffer.
918 *(volatile uint64_t*)((uint32_t)flash_add - sizeof(uint64_t))= flash_dword.u64;
919 }
920
921 // Erase the current page if requested and write it from the page buffer.
922 if (erase) {
923 (b_user_page)? flashc_erase_user_page(false) : flashc_erase_page(-1, false);
924 error_status |= flashc_error_status;
925 }
926
927 // Write the page
928 (b_user_page)? flashc_write_user_page() : flashc_write_page(-1);
929 error_status |= flashc_error_status;
930 }
931 // Update the FLASHC error status.
932 flashc_error_status = error_status;
933
934 // Return the initial destination pointer as the standard memcpy function does.
935 return dst;
936 }
937
938
939 #if UC3C
flashc_set_flash_waitstate_and_readmode(unsigned long cpu_f_hz)940 void flashc_set_flash_waitstate_and_readmode(unsigned long cpu_f_hz)
941 {
942 //! Device-specific data
943 #undef AVR32_FLASHC_FWS_0_MAX_FREQ
944 #undef AVR32_FLASHC_FWS_1_MAX_FREQ
945 #undef AVR32_FLASHC_HSEN_FWS_0_MAX_FREQ
946 #undef AVR32_FLASHC_HSEN_FWS_1_MAX_FREQ
947 #define AVR32_FLASHC_FWS_0_MAX_FREQ 33000000
948 #define AVR32_FLASHC_FWS_1_MAX_FREQ 66000000
949 #define AVR32_FLASHC_HSEN_FWS_0_MAX_FREQ 33000000
950 #define AVR32_FLASHC_HSEN_FWS_1_MAX_FREQ 72000000
951 // These defines are missing from or wrong in the toolchain header files uc3cxxx.h
952 // Put a Bugzilla
953
954 if (cpu_f_hz > AVR32_FLASHC_HSEN_FWS_0_MAX_FREQ) { // > 33MHz
955 // Set a wait-state
956 flashc_set_wait_state(1);
957 if (cpu_f_hz <= AVR32_FLASHC_FWS_1_MAX_FREQ) { // <= 66MHz and >33Mhz
958 // Disable the high-speed read mode.
959 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);
960 } else { // > 66Mhz
961 // Enable the high-speed read mode.
962 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSEN, -1);
963 }
964 } else { // <= 33 MHz
965 // Disable wait-state
966 flashc_set_wait_state(0);
967 // Disable the high-speed read mode.
968 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);
969 }
970 }
971 #endif // UC3C device-specific implementation
972
973 //! @}
974