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