source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/hardware/arduino/avr/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/FLASHC/flashc.c @ 4837

Last change on this file since 4837 was 4837, checked in by daduve, 2 years ago

Adding new version

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