OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_AVR32_UC3/] [DRIVERS/] [FLASHC/] [flashc.c] - Blame information for rev 583

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.