00001
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include <avr32/io.h>
00049 #include <stddef.h>
00050 #include "compiler.h"
00051 #include "flashcdw.h"
00052
00053
00056
00057
00058 typedef union
00059 {
00060 unsigned long fcr;
00061 avr32_flashcdw_fcr_t FCR;
00062 } u_avr32_flashcdw_fcr_t;
00063
00064 typedef union
00065 {
00066 unsigned long fcmd;
00067 avr32_flashcdw_fcmd_t FCMD;
00068 } u_avr32_flashcdw_fcmd_t;
00069
00071
00072
00075
00076
00077
00078 unsigned int flashcdw_get_flash_size(void)
00079 {
00080 static const unsigned int FLASH_SIZE[1 << AVR32_FLASHCDW_FPR_FSZ_SIZE] =
00081 {
00082 4 << 10,
00083 8 << 10,
00084 16 << 10,
00085 32 << 10,
00086 48 << 10,
00087 64 << 10,
00088 96 << 10,
00089 128 << 10,
00090 192 << 10,
00091 256 << 10,
00092 384 << 10,
00093 512 << 10,
00094 768 << 10,
00095 1024 << 10,
00096 2048 << 10
00097 };
00098 return FLASH_SIZE[(AVR32_FLASHCDW.fpr & AVR32_FLASHCDW_FPR_FSZ_MASK) >> AVR32_FLASHCDW_FPR_FSZ_OFFSET];
00099 }
00100
00101
00102 unsigned int flashcdw_get_page_count(void)
00103 {
00104 return flashcdw_get_flash_size() / AVR32_FLASHCDW_PAGE_SIZE;
00105 }
00106
00107
00108 unsigned int flashcdw_get_page_count_per_region(void)
00109 {
00110 return flashcdw_get_page_count() / AVR32_FLASHCDW_REGIONS;
00111 }
00112
00113
00114 unsigned int flashcdw_get_page_region(int page_number)
00115 {
00116 return ((page_number >= 0) ? page_number : flashcdw_get_page_number()) / flashcdw_get_page_count_per_region();
00117 }
00118
00119
00120 unsigned int flashcdw_get_region_first_page_number(unsigned int region)
00121 {
00122 return region * flashcdw_get_page_count_per_region();
00123 }
00124
00125
00127
00128
00131
00132
00133
00134 unsigned int flashcdw_get_wait_state(void)
00135 {
00136 return (AVR32_FLASHCDW.fcr & AVR32_FLASHCDW_FCR_FWS_MASK) >> AVR32_FLASHCDW_FCR_FWS_OFFSET;
00137 }
00138
00139
00140 void flashcdw_set_wait_state(unsigned int wait_state)
00141 {
00142 u_avr32_flashcdw_fcr_t u_avr32_flashcdw_fcr = {AVR32_FLASHCDW.fcr};
00143 u_avr32_flashcdw_fcr.FCR.fws = wait_state;
00144 AVR32_FLASHCDW.fcr = u_avr32_flashcdw_fcr.fcr;
00145 }
00146
00147
00148 void flashcdw_set_flash_waitstate_and_readmode(unsigned long cpu_f_hz)
00149 {
00150 if(cpu_f_hz > AVR32_FLASHCDW_FWS_0_MAX_FREQ)
00151 {
00152 if(cpu_f_hz <= AVR32_FLASHCDW_FWS_1_MAX_FREQ)
00153 {
00154
00155 flashcdw_set_wait_state(1);
00156 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_HSDIS, -1);
00157 }
00158 else
00159 {
00160
00161 flashcdw_set_wait_state(1);
00162 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_HSEN, -1);
00163 }
00164 }
00165 else
00166 {
00167
00168 flashcdw_set_wait_state(0);
00169 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_HSDIS, -1);
00170 }
00171 }
00172
00173
00174 Bool flashcdw_is_ready_int_enabled(void)
00175 {
00176 return ((AVR32_FLASHCDW.fcr & AVR32_FLASHCDW_FCR_FRDY_MASK) != 0);
00177 }
00178
00179
00180 void flashcdw_enable_ready_int(Bool enable)
00181 {
00182 u_avr32_flashcdw_fcr_t u_avr32_flashcdw_fcr = {AVR32_FLASHCDW.fcr};
00183 u_avr32_flashcdw_fcr.FCR.frdy = (enable != FALSE);
00184 AVR32_FLASHCDW.fcr = u_avr32_flashcdw_fcr.fcr;
00185 }
00186
00187
00188 Bool flashcdw_is_lock_error_int_enabled(void)
00189 {
00190 return ((AVR32_FLASHCDW.fcr & AVR32_FLASHCDW_FCR_LOCKE_MASK) != 0);
00191 }
00192
00193
00194 void flashcdw_enable_lock_error_int(Bool enable)
00195 {
00196 u_avr32_flashcdw_fcr_t u_avr32_flashcdw_fcr = {AVR32_FLASHCDW.fcr};
00197 u_avr32_flashcdw_fcr.FCR.locke = (enable != FALSE);
00198 AVR32_FLASHCDW.fcr = u_avr32_flashcdw_fcr.fcr;
00199 }
00200
00201
00202 Bool flashcdw_is_prog_error_int_enabled(void)
00203 {
00204 return ((AVR32_FLASHCDW.fcr & AVR32_FLASHCDW_FCR_PROGE_MASK) != 0);
00205 }
00206
00207
00208 void flashcdw_enable_prog_error_int(Bool enable)
00209 {
00210 u_avr32_flashcdw_fcr_t u_avr32_flashcdw_fcr = {AVR32_FLASHCDW.fcr};
00211 u_avr32_flashcdw_fcr.FCR.proge = (enable != FALSE);
00212 AVR32_FLASHCDW.fcr = u_avr32_flashcdw_fcr.fcr;
00213 }
00214
00215
00217
00218
00221
00222
00223
00224 Bool flashcdw_is_ready(void)
00225 {
00226 return ((AVR32_FLASHCDW.fsr & AVR32_FLASHCDW_FSR_FRDY_MASK) != 0);
00227 }
00228
00229
00230 void flashcdw_default_wait_until_ready(void)
00231 {
00232 while (!flashcdw_is_ready());
00233 }
00234
00235
00236 void (*volatile flashcdw_wait_until_ready)(void) = flashcdw_default_wait_until_ready;
00237
00238
00249 static unsigned int flashcdw_get_error_status(void)
00250 {
00251 return AVR32_FLASHCDW.fsr & (AVR32_FLASHCDW_FSR_LOCKE_MASK |
00252 AVR32_FLASHCDW_FSR_PROGE_MASK);
00253 }
00254
00255
00260 static unsigned int flashcdw_error_status = 0;
00261
00262
00263 Bool flashcdw_is_lock_error(void)
00264 {
00265 return ((flashcdw_error_status & AVR32_FLASHCDW_FSR_LOCKE_MASK) != 0);
00266 }
00267
00268
00269 Bool flashcdw_is_programming_error(void)
00270 {
00271 return ((flashcdw_error_status & AVR32_FLASHCDW_FSR_PROGE_MASK) != 0);
00272 }
00273
00274
00275 Bool flashcdw_is_high_speed_enabled(void)
00276 {
00277 return ((AVR32_FLASHCDW.fsr & AVR32_FLASHCDW_FSR_HSMODE_MASK) != 0);
00278 }
00279
00280
00282
00283
00286
00287
00288
00289 unsigned int flashcdw_get_command(void)
00290 {
00291 return (AVR32_FLASHCDW.fcmd & AVR32_FLASHCDW_FCMD_CMD_MASK) >> AVR32_FLASHCDW_FCMD_CMD_OFFSET;
00292 }
00293
00294
00295 unsigned int flashcdw_get_page_number(void)
00296 {
00297 return (AVR32_FLASHCDW.fcmd & AVR32_FLASHCDW_FCMD_PAGEN_MASK) >> AVR32_FLASHCDW_FCMD_PAGEN_OFFSET;
00298 }
00299
00300
00301 void flashcdw_issue_command(unsigned int command, int page_number)
00302 {
00303 u_avr32_flashcdw_fcmd_t u_avr32_flashcdw_fcmd;
00304 flashcdw_wait_until_ready();
00305 u_avr32_flashcdw_fcmd.fcmd = AVR32_FLASHCDW.fcmd;
00306 u_avr32_flashcdw_fcmd.FCMD.cmd = command;
00307 if (page_number >= 0) u_avr32_flashcdw_fcmd.FCMD.pagen = page_number;
00308 u_avr32_flashcdw_fcmd.FCMD.key = AVR32_FLASHCDW_FCMD_KEY_KEY;
00309 AVR32_FLASHCDW.fcmd = u_avr32_flashcdw_fcmd.fcmd;
00310 flashcdw_error_status = flashcdw_get_error_status();
00311 flashcdw_wait_until_ready();
00312 }
00313
00314
00316
00317
00320
00321
00322
00323 void flashcdw_no_operation(void)
00324 {
00325 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_NOP, -1);
00326 }
00327
00328
00329 void flashcdw_erase_all(void)
00330 {
00331 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_EA, -1);
00332 }
00333
00334
00336
00337
00340
00341
00342
00343 Bool flashcdw_is_security_bit_active(void)
00344 {
00345 return ((AVR32_FLASHCDW.fsr & AVR32_FLASHCDW_FSR_SECURITY_MASK) != 0);
00346 }
00347
00348
00349 void flashcdw_activate_security_bit(void)
00350 {
00351 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_SSB, -1);
00352 }
00353
00354
00355 unsigned int flashcdw_get_bootloader_protected_size(void)
00356 {
00357 unsigned int bootprot = (1 << AVR32_FLASHCDW_FGPFRLO_BOOTPROT_SIZE) - 1 -
00358 flashcdw_read_gp_fuse_bitfield(AVR32_FLASHCDW_FGPFRLO_BOOTPROT_OFFSET,
00359 AVR32_FLASHCDW_FGPFRLO_BOOTPROT_SIZE);
00360 return (bootprot) ? AVR32_FLASHCDW_PAGE_SIZE << bootprot : 0;
00361 }
00362
00363
00364 unsigned int flashcdw_set_bootloader_protected_size(unsigned int bootprot_size)
00365 {
00366 flashcdw_set_gp_fuse_bitfield(AVR32_FLASHCDW_FGPFRLO_BOOTPROT_OFFSET,
00367 AVR32_FLASHCDW_FGPFRLO_BOOTPROT_SIZE,
00368 (1 << AVR32_FLASHCDW_FGPFRLO_BOOTPROT_SIZE) - 1 -
00369 ((bootprot_size) ?
00370 32 - clz((((min(max(bootprot_size, AVR32_FLASHCDW_PAGE_SIZE << 1),
00371 AVR32_FLASHCDW_PAGE_SIZE <<
00372 ((1 << AVR32_FLASHCDW_FGPFRLO_BOOTPROT_SIZE) - 1)) +
00373 AVR32_FLASHCDW_PAGE_SIZE - 1) /
00374 AVR32_FLASHCDW_PAGE_SIZE) << 1) - 1) - 1 :
00375 0));
00376 return flashcdw_get_bootloader_protected_size();
00377 }
00378
00379
00380 Bool flashcdw_is_external_privileged_fetch_locked(void)
00381 {
00382 return (!flashcdw_read_gp_fuse_bit(AVR32_FLASHCDW_FGPFRLO_EPFL_OFFSET));
00383 }
00384
00385
00386 void flashcdw_lock_external_privileged_fetch(Bool lock)
00387 {
00388 flashcdw_set_gp_fuse_bit(AVR32_FLASHCDW_FGPFRLO_EPFL_OFFSET, !lock);
00389 }
00390
00391 Bool flashcdw_is_jtag_user_protection_enabled(void)
00392 {
00393 return (!flashcdw_read_gp_fuse_bit(AVR32_FLASHCDW_FGPFRLO_UPROT_OFFSET));
00394 }
00395
00396 void flashcdw_enable_jtag_user_protection(void)
00397 {
00398 flashcdw_set_gp_fuse_bit(AVR32_FLASHCDW_FGPFRLO_UPROT_OFFSET, FALSE);
00399 }
00400
00401 void flashcdw_disable_jtag_user_protection(void)
00402 {
00403 flashcdw_set_gp_fuse_bit(AVR32_FLASHCDW_FGPFRLO_UPROT_OFFSET, TRUE);
00404 }
00405
00406 Bool flashcdw_is_secure_state_enabled(void)
00407 {
00408 U64 temp = flashcdw_read_gp_fuse_bitfield(AVR32_FLASHCDW_FGPFRLO_SECURE_OFFSET,
00409 AVR32_FLASHCDW_FGPFRLO_SECURE_SIZE);
00410 if((AVR32_FLASHCDW_FGPFRLO_SECURE_SSEN_SSDDIS == temp) || (AVR32_FLASHCDW_FGPFRLO_SECURE_SSEN_SSDEN == temp))
00411 return TRUE;
00412 else
00413 return FALSE;
00414 }
00415
00416 Bool flashcdw_is_secure_state_debug_enabled(void)
00417 {
00418 return( AVR32_FLASHCDW_FGPFRLO_SECURE_SSEN_SSDEN
00419 == flashcdw_read_gp_fuse_bitfield(AVR32_FLASHCDW_FGPFRLO_SECURE_OFFSET,
00420 AVR32_FLASHCDW_FGPFRLO_SECURE_SIZE) );
00421 }
00422
00423 void flashcdw_enable_secure_state_no_debug(void)
00424 {
00425 flashcdw_write_gp_fuse_bitfield(AVR32_FLASHCDW_FGPFRLO_SECURE_OFFSET,
00426 AVR32_FLASHCDW_FGPFRLO_SECURE_SIZE,
00427 AVR32_FLASHCDW_FGPFRLO_SECURE_SSEN_SSDDIS);
00428 }
00429
00430 void flashcdw_enable_secure_state_with_debug(void)
00431 {
00432 flashcdw_write_gp_fuse_bitfield(AVR32_FLASHCDW_FGPFRLO_SECURE_OFFSET,
00433 AVR32_FLASHCDW_FGPFRLO_SECURE_SIZE,
00434 AVR32_FLASHCDW_FGPFRLO_SECURE_SSEN_SSDEN);
00435 }
00436
00437 Bool flashcdw_is_page_region_locked(int page_number)
00438 {
00439 return flashcdw_is_region_locked(flashcdw_get_page_region(page_number));
00440 }
00441
00442
00443 Bool flashcdw_is_region_locked(unsigned int region)
00444 {
00445 return ((AVR32_FLASHCDW.fsr & AVR32_FLASHCDW_FSR_LOCK0_MASK << (region & (AVR32_FLASHCDW_REGIONS - 1))) != 0);
00446 }
00447
00448
00449 void flashcdw_lock_page_region(int page_number, Bool lock)
00450 {
00451 flashcdw_issue_command((lock) ? AVR32_FLASHCDW_FCMD_CMD_LP : AVR32_FLASHCDW_FCMD_CMD_UP, page_number);
00452 }
00453
00454
00455 void flashcdw_lock_region(unsigned int region, Bool lock)
00456 {
00457 flashcdw_lock_page_region(flashcdw_get_region_first_page_number(region), lock);
00458 }
00459
00460
00461 void flashcdw_lock_all_regions(Bool lock)
00462 {
00463 unsigned int error_status = 0;
00464 unsigned int region = AVR32_FLASHCDW_REGIONS;
00465 while (region)
00466 {
00467 flashcdw_lock_region(--region, lock);
00468 error_status |= flashcdw_error_status;
00469 }
00470 flashcdw_error_status = error_status;
00471 }
00472
00473
00475
00476
00479
00480
00481
00482 Bool flashcdw_read_gp_fuse_bit(unsigned int gp_fuse_bit)
00483 {
00484 return ((flashcdw_read_all_gp_fuses() & 1ULL << (gp_fuse_bit & 0x3F)) != 0);
00485 }
00486
00487
00488 U64 flashcdw_read_gp_fuse_bitfield(unsigned int pos, unsigned int width)
00489 {
00490 return flashcdw_read_all_gp_fuses() >> (pos & 0x3F) & ((1ULL << min(width, 64)) - 1);
00491 }
00492
00493
00494 U8 flashcdw_read_gp_fuse_byte(unsigned int gp_fuse_byte)
00495 {
00496 return flashcdw_read_all_gp_fuses() >> ((gp_fuse_byte & 0x07) << 3);
00497 }
00498
00499
00500 U64 flashcdw_read_all_gp_fuses(void)
00501 {
00502 return AVR32_FLASHCDW.fgpfrlo | (U64)AVR32_FLASHCDW.fgpfrhi << 32;
00503 }
00504
00505
00506 Bool flashcdw_erase_gp_fuse_bit(unsigned int gp_fuse_bit, Bool check)
00507 {
00508 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_EGPB, gp_fuse_bit & 0x3F);
00509 return (check) ? flashcdw_read_gp_fuse_bit(gp_fuse_bit) : TRUE;
00510 }
00511
00512
00513 Bool flashcdw_erase_gp_fuse_bitfield(unsigned int pos, unsigned int width, Bool check)
00514 {
00515 unsigned int error_status = 0;
00516 unsigned int gp_fuse_bit;
00517 pos &= 0x3F;
00518 width = min(width, 64);
00519 for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++)
00520 {
00521 flashcdw_erase_gp_fuse_bit(gp_fuse_bit, FALSE);
00522 error_status |= flashcdw_error_status;
00523 }
00524 flashcdw_error_status = error_status;
00525 return (check) ? (flashcdw_read_gp_fuse_bitfield(pos, width) == (1ULL << width) - 1) : TRUE;
00526 }
00527
00528
00529 Bool flashcdw_erase_gp_fuse_byte(unsigned int gp_fuse_byte, Bool check)
00530 {
00531 unsigned int error_status;
00532 unsigned int current_gp_fuse_byte;
00533 U64 value = flashcdw_read_all_gp_fuses();
00534 flashcdw_erase_all_gp_fuses(FALSE);
00535 error_status = flashcdw_error_status;
00536 for (current_gp_fuse_byte = 0; current_gp_fuse_byte < 8; current_gp_fuse_byte++, value >>= 8)
00537 {
00538 if (current_gp_fuse_byte != gp_fuse_byte)
00539 {
00540 flashcdw_write_gp_fuse_byte(current_gp_fuse_byte, value);
00541 error_status |= flashcdw_error_status;
00542 }
00543 }
00544 flashcdw_error_status = error_status;
00545 return (check) ? (flashcdw_read_gp_fuse_byte(gp_fuse_byte) == 0xFF) : TRUE;
00546 }
00547
00548
00549 Bool flashcdw_erase_all_gp_fuses(Bool check)
00550 {
00551 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_EAGPF, -1);
00552 return (check) ? (flashcdw_read_all_gp_fuses() == 0xFFFFFFFFFFFFFFFFULL) : TRUE;
00553 }
00554
00555
00556 void flashcdw_write_gp_fuse_bit(unsigned int gp_fuse_bit, Bool value)
00557 {
00558 if (!value)
00559 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_WGPB, gp_fuse_bit & 0x3F);
00560 }
00561
00562
00563 void flashcdw_write_gp_fuse_bitfield(unsigned int pos, unsigned int width, U64 value)
00564 {
00565 unsigned int error_status = 0;
00566 unsigned int gp_fuse_bit;
00567 pos &= 0x3F;
00568 width = min(width, 64);
00569 for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++, value >>= 1)
00570 {
00571 flashcdw_write_gp_fuse_bit(gp_fuse_bit, value & 0x01);
00572 error_status |= flashcdw_error_status;
00573 }
00574 flashcdw_error_status = error_status;
00575 }
00576
00577
00578 void flashcdw_write_gp_fuse_byte(unsigned int gp_fuse_byte, U8 value)
00579 {
00580 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_PGPFB, (gp_fuse_byte & 0x07) | value << 3);
00581 }
00582
00583
00584 void flashcdw_write_all_gp_fuses(U64 value)
00585 {
00586 unsigned int error_status = 0;
00587 unsigned int gp_fuse_byte;
00588 for (gp_fuse_byte = 0; gp_fuse_byte < 8; gp_fuse_byte++, value >>= 8)
00589 {
00590 flashcdw_write_gp_fuse_byte(gp_fuse_byte, value);
00591 error_status |= flashcdw_error_status;
00592 }
00593 flashcdw_error_status = error_status;
00594 }
00595
00596
00597 void flashcdw_set_gp_fuse_bit(unsigned int gp_fuse_bit, Bool value)
00598 {
00599 if (value)
00600 flashcdw_erase_gp_fuse_bit(gp_fuse_bit, FALSE);
00601 else
00602 flashcdw_write_gp_fuse_bit(gp_fuse_bit, FALSE);
00603 }
00604
00605
00606 void flashcdw_set_gp_fuse_bitfield(unsigned int pos, unsigned int width, U64 value)
00607 {
00608 unsigned int error_status = 0;
00609 unsigned int gp_fuse_bit;
00610 pos &= 0x3F;
00611 width = min(width, 64);
00612 for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++, value >>= 1)
00613 {
00614 flashcdw_set_gp_fuse_bit(gp_fuse_bit, value & 0x01);
00615 error_status |= flashcdw_error_status;
00616 }
00617 flashcdw_error_status = error_status;
00618 }
00619
00620
00621 void flashcdw_set_gp_fuse_byte(unsigned int gp_fuse_byte, U8 value)
00622 {
00623 unsigned int error_status;
00624 switch (value)
00625 {
00626 case 0xFF:
00627 flashcdw_erase_gp_fuse_byte(gp_fuse_byte, FALSE);
00628 break;
00629 case 0x00:
00630 flashcdw_write_gp_fuse_byte(gp_fuse_byte, 0x00);
00631 break;
00632 default:
00633 flashcdw_erase_gp_fuse_byte(gp_fuse_byte, FALSE);
00634 error_status = flashcdw_error_status;
00635 flashcdw_write_gp_fuse_byte(gp_fuse_byte, value);
00636 flashcdw_error_status |= error_status;
00637 }
00638 }
00639
00640
00641 void flashcdw_set_all_gp_fuses(U64 value)
00642 {
00643 unsigned int error_status;
00644 switch (value)
00645 {
00646 case 0xFFFFFFFFFFFFFFFFULL:
00647 flashcdw_erase_all_gp_fuses(FALSE);
00648 break;
00649 case 0x0000000000000000ULL:
00650 flashcdw_write_all_gp_fuses(0x0000000000000000ULL);
00651 break;
00652 default:
00653 flashcdw_erase_all_gp_fuses(FALSE);
00654 error_status = flashcdw_error_status;
00655 flashcdw_write_all_gp_fuses(value);
00656 flashcdw_error_status |= error_status;
00657 }
00658 }
00659
00660
00662
00663
00666
00667
00668
00669 void flashcdw_clear_page_buffer(void)
00670 {
00671 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_CPB, -1);
00672 }
00673
00674
00675 Bool flashcdw_is_page_erased(void)
00676 {
00677 return ((AVR32_FLASHCDW.fsr & AVR32_FLASHCDW_FSR_QPRR_MASK) != 0);
00678 }
00679
00680
00681 Bool flashcdw_quick_page_read(int page_number)
00682 {
00683 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_QPR, page_number);
00684 return flashcdw_is_page_erased();
00685 }
00686
00687
00688 Bool flashcdw_erase_page(int page_number, Bool check)
00689 {
00690 Bool page_erased = TRUE;
00691 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_EP, page_number);
00692 if (check)
00693 {
00694 unsigned int error_status = flashcdw_error_status;
00695 page_erased = flashcdw_quick_page_read(-1);
00696 flashcdw_error_status |= error_status;
00697 }
00698 return page_erased;
00699 }
00700
00701
00702 Bool flashcdw_erase_all_pages(Bool check)
00703 {
00704 Bool all_pages_erased = TRUE;
00705 unsigned int error_status = 0;
00706 unsigned int page_number = flashcdw_get_page_count();
00707 while (page_number)
00708 {
00709 all_pages_erased &= flashcdw_erase_page(--page_number, check);
00710 error_status |= flashcdw_error_status;
00711 }
00712 flashcdw_error_status = error_status;
00713 return all_pages_erased;
00714 }
00715
00716
00717 void flashcdw_write_page(int page_number)
00718 {
00719 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_WP, page_number);
00720 }
00721
00722
00723 Bool flashcdw_quick_user_page_read(void)
00724 {
00725 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_QPRUP, -1);
00726 return flashcdw_is_page_erased();
00727 }
00728
00729
00730 Bool flashcdw_erase_user_page(Bool check)
00731 {
00732 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_EUP, -1);
00733 return (check) ? flashcdw_quick_user_page_read() : TRUE;
00734 }
00735
00736
00737 void flashcdw_write_user_page(void)
00738 {
00739 flashcdw_issue_command(AVR32_FLASHCDW_FCMD_CMD_WUP, -1);
00740 }
00741
00742
00743 volatile void *flashcdw_memset8(volatile void *dst, U8 src, size_t nbytes, Bool erase)
00744 {
00745 return flashcdw_memset16(dst, src | (U16)src << 8, nbytes, erase);
00746 }
00747
00748
00749 volatile void *flashcdw_memset16(volatile void *dst, U16 src, size_t nbytes, Bool erase)
00750 {
00751 return flashcdw_memset32(dst, src | (U32)src << 16, nbytes, erase);
00752 }
00753
00754
00755 volatile void *flashcdw_memset32(volatile void *dst, U32 src, size_t nbytes, Bool erase)
00756 {
00757 return flashcdw_memset64(dst, src | (U64)src << 32, nbytes, erase);
00758 }
00759
00760
00761 volatile void *flashcdw_memset64(volatile void *dst, U64 src, size_t nbytes, Bool erase)
00762 {
00763
00764 UnionCVPtr flash_array_end;
00765 UnionVPtr dest;
00766 Union64 source = {0};
00767 StructCVPtr dest_end;
00768 UnionCVPtr flash_page_source_end;
00769 Bool incomplete_flash_page_end;
00770 Union64 flash_dword;
00771 UnionVPtr tmp;
00772 unsigned int error_status = 0;
00773 unsigned int i;
00774
00775
00776 flash_array_end.u8ptr = AVR32_FLASH + flashcdw_get_flash_size();
00777 dest.u8ptr = dst;
00778 for (i = (Get_align((U32)dest.u8ptr, sizeof(U64)) - 1) & (sizeof(U64) - 1);
00779 src; i = (i - 1) & (sizeof(U64) - 1))
00780 {
00781 source.u8[i] = src;
00782 src >>= 8;
00783 }
00784 dest_end.u8ptr = dest.u8ptr + nbytes;
00785
00786
00787 if (dest.u8ptr < AVR32_FLASH)
00788 {
00789 dest.u8ptr = AVR32_FLASH;
00790 }
00791 else if (flash_array_end.u8ptr <= dest.u8ptr && dest.u8ptr < AVR32_FLASHCDW_USER_PAGE)
00792 {
00793 dest.u8ptr = AVR32_FLASHCDW_USER_PAGE;
00794 }
00795
00796
00797 if (dest_end.u8ptr > AVR32_FLASHCDW_USER_PAGE + AVR32_FLASHCDW_USER_PAGE_SIZE)
00798 {
00799 dest_end.u8ptr = AVR32_FLASHCDW_USER_PAGE + AVR32_FLASHCDW_USER_PAGE_SIZE;
00800 }
00801 else if (AVR32_FLASHCDW_USER_PAGE >= dest_end.u8ptr && dest_end.u8ptr > flash_array_end.u8ptr)
00802 {
00803 dest_end.u8ptr = flash_array_end.u8ptr;
00804 }
00805
00806
00807 dest_end.u16ptr = (U16 *)Align_down((U32)dest_end.u8ptr, sizeof(U16));
00808 dest_end.u32ptr = (U32 *)Align_down((U32)dest_end.u16ptr, sizeof(U32));
00809 dest_end.u64ptr = (U64 *)Align_down((U32)dest_end.u32ptr, sizeof(U64));
00810
00811
00812 while (dest.u8ptr < dest_end.u8ptr)
00813 {
00814
00815 flashcdw_clear_page_buffer();
00816 error_status |= flashcdw_error_status;
00817
00818
00819 flash_page_source_end.u64ptr =
00820 (U64 *)min((U32)dest_end.u64ptr,
00821 Align_down((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE) + AVR32_FLASHCDW_PAGE_SIZE);
00822
00823
00824 incomplete_flash_page_end = (Align_down((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE) >=
00825 Align_down((U32)dest_end.u8ptr, AVR32_FLASHCDW_PAGE_SIZE));
00826
00827
00828 flash_dword.u64 = source.u64;
00829
00830
00831 if (!Test_align((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE))
00832 {
00833
00834
00835
00836
00837 for (tmp.u8ptr = (U8 *)Align_down((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE);
00838 tmp.u64ptr < (U64 *)Align_down((U32)dest.u8ptr, sizeof(U64));
00839 tmp.u64ptr++)
00840 {
00841 *tmp.u32ptr = *tmp.u32ptr;
00842 *(tmp.u32ptr+1) = *(tmp.u32ptr+1);
00843 }
00844
00845
00846 if (!Test_align((U32)dest.u8ptr, sizeof(U64)))
00847 {
00848
00849
00850
00851
00852
00853 for (i = 0; i < Get_align((U32)dest.u8ptr, sizeof(U64)); i++)
00854 flash_dword.u8[i] = *tmp.u8ptr++;
00855
00856
00857 dest.u64ptr = (U64 *)Align_down((U32)dest.u8ptr, sizeof(U64));
00858
00859
00860 if (dest.u64ptr < dest_end.u64ptr)
00861 {
00862
00863 *dest.u32ptr++ = flash_dword.u32[0];
00864 *dest.u32ptr++ = flash_dword.u32[1];
00865 flash_dword.u64 = source.u64;
00866 }
00867 }
00868 }
00869
00870
00871 for (i = flash_page_source_end.u64ptr - dest.u64ptr; i; i--)
00872 {
00873 *dest.u32ptr++ = source.u32[0];
00874 *dest.u32ptr++ = source.u32[1];
00875 }
00876
00877
00878 if (incomplete_flash_page_end)
00879 {
00880
00881
00882
00883 {
00884 tmp.u8ptr = (volatile U8 *)dest_end.u8ptr;
00885
00886
00887 if (!Test_align((U32)dest_end.u8ptr, sizeof(U64)))
00888 {
00889
00890 for (i = Get_align((U32)dest_end.u8ptr, sizeof(U64)); i < sizeof(U64); i++)
00891 flash_dword.u8[i] = *tmp.u8ptr++;
00892
00893
00894 *dest.u32ptr++ = flash_dword.u32[0];
00895 *dest.u32ptr++ = flash_dword.u32[1];
00896 }
00897
00898
00899 for (; !Test_align((U32)tmp.u64ptr, AVR32_FLASHCDW_PAGE_SIZE); tmp.u64ptr++)
00900 {
00901 *tmp.u32ptr = *tmp.u32ptr;
00902 *(tmp.u32ptr+1) = *(tmp.u32ptr+1);
00903 }
00904 }
00905 }
00906
00907
00908 if (dest.u8ptr <= AVR32_FLASHCDW_USER_PAGE)
00909 {
00910
00911 if (erase)
00912 {
00913 flashcdw_erase_page(-1, FALSE);
00914 error_status |= flashcdw_error_status;
00915 }
00916 flashcdw_write_page(-1);
00917 error_status |= flashcdw_error_status;
00918
00919
00920 if (dest.u8ptr >= flash_array_end.u8ptr)
00921 dest.u8ptr = AVR32_FLASHCDW_USER_PAGE;
00922 }
00923
00924 else
00925 {
00926
00927 if (erase)
00928 {
00929 flashcdw_erase_user_page(FALSE);
00930 error_status |= flashcdw_error_status;
00931 }
00932 flashcdw_write_user_page();
00933 error_status |= flashcdw_error_status;
00934 }
00935 }
00936
00937
00938 flashcdw_error_status = error_status;
00939
00940
00941 return dst;
00942 }
00943
00944
00945 volatile void *flashcdw_memcpy(volatile void *dst, const void *src, size_t nbytes, Bool erase)
00946 {
00947
00948 UnionCVPtr flash_array_end;
00949 UnionVPtr dest;
00950 UnionCPtr source;
00951 StructCVPtr dest_end;
00952 UnionCVPtr flash_page_source_end;
00953 Bool incomplete_flash_page_end;
00954 Union64 flash_dword;
00955 Bool flash_dword_pending = FALSE;
00956 UnionVPtr tmp;
00957 unsigned int error_status = 0;
00958 unsigned int i, j;
00959
00960
00961 flash_array_end.u8ptr = AVR32_FLASH + flashcdw_get_flash_size();
00962 dest.u8ptr = dst;
00963 source.u8ptr = src;
00964 dest_end.u8ptr = dest.u8ptr + nbytes;
00965
00966
00967 if (dest.u8ptr < AVR32_FLASH)
00968 {
00969 source.u8ptr += AVR32_FLASH - dest.u8ptr;
00970 dest.u8ptr = AVR32_FLASH;
00971 }
00972 else if (flash_array_end.u8ptr <= dest.u8ptr && dest.u8ptr < AVR32_FLASHCDW_USER_PAGE)
00973 {
00974 source.u8ptr += AVR32_FLASHCDW_USER_PAGE - dest.u8ptr;
00975 dest.u8ptr = AVR32_FLASHCDW_USER_PAGE;
00976 }
00977
00978
00979 if (dest_end.u8ptr > AVR32_FLASHCDW_USER_PAGE + AVR32_FLASHCDW_USER_PAGE_SIZE)
00980 {
00981 dest_end.u8ptr = AVR32_FLASHCDW_USER_PAGE + AVR32_FLASHCDW_USER_PAGE_SIZE;
00982 }
00983 else if (AVR32_FLASHCDW_USER_PAGE >= dest_end.u8ptr && dest_end.u8ptr > flash_array_end.u8ptr)
00984 {
00985 dest_end.u8ptr = flash_array_end.u8ptr;
00986 }
00987
00988
00989 dest_end.u16ptr = (U16 *)Align_down((U32)dest_end.u8ptr, sizeof(U16));
00990 dest_end.u32ptr = (U32 *)Align_down((U32)dest_end.u16ptr, sizeof(U32));
00991 dest_end.u64ptr = (U64 *)Align_down((U32)dest_end.u32ptr, sizeof(U64));
00992
00993
00994 while (dest.u8ptr < dest_end.u8ptr)
00995 {
00996
00997 flashcdw_clear_page_buffer();
00998 error_status |= flashcdw_error_status;
00999
01000
01001 flash_page_source_end.u64ptr =
01002 (U64 *)min((U32)dest_end.u64ptr,
01003 Align_down((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE) + AVR32_FLASHCDW_PAGE_SIZE);
01004
01005
01006 incomplete_flash_page_end = (Align_down((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE) >=
01007 Align_down((U32)dest_end.u8ptr, AVR32_FLASHCDW_PAGE_SIZE));
01008
01009
01010 if (!Test_align((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE))
01011 {
01012
01013
01014
01015
01016 for (tmp.u8ptr = (U8 *)Align_down((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE);
01017 tmp.u64ptr < (U64 *)Align_down((U32)dest.u8ptr, sizeof(U64));
01018 tmp.u64ptr++)
01019 {
01020 *tmp.u32ptr = *tmp.u32ptr;
01021 *(tmp.u32ptr+1) = *(tmp.u32ptr+1);
01022 }
01023
01024
01025 if (!Test_align((U32)dest.u8ptr, sizeof(U64)))
01026 {
01027
01028
01029
01030
01031
01032 for (i = 0; i < Get_align((U32)dest.u8ptr, sizeof(U64)); i++)
01033 flash_dword.u8[i] = *tmp.u8ptr++;
01034
01035
01036 for (; i < sizeof(U64); i++)
01037 flash_dword.u8[i] = *source.u8ptr++;
01038
01039
01040 dest.u64ptr = (U64 *)Align_down((U32)dest.u8ptr, sizeof(U64));
01041
01042
01043 if (dest.u64ptr < dest_end.u64ptr)
01044 {
01045
01046 *dest.u32ptr++ = flash_dword.u32[0];
01047 *dest.u32ptr++ = flash_dword.u32[1];
01048 }
01049
01050
01051 else flash_dword_pending = TRUE;
01052 }
01053 }
01054
01055
01056
01057 switch (Get_align((U32)source.u8ptr, sizeof(U32)))
01058 {
01059 case 0:
01060 for (i = flash_page_source_end.u64ptr - dest.u64ptr; i; i--)
01061 {
01062 *dest.u32ptr++ = *source.u32ptr++;
01063 *dest.u32ptr++ = *source.u32ptr++;
01064 }
01065 break;
01066
01067 case sizeof(U16):
01068 for (i = flash_page_source_end.u64ptr - dest.u64ptr; i; i--)
01069 {
01070 for (j = 0; j < sizeof(U64) / sizeof(U16); j++) flash_dword.u16[j] = *source.u16ptr++;
01071 *dest.u32ptr++ = flash_dword.u32[0];
01072 *dest.u32ptr++ = flash_dword.u32[1];
01073 }
01074 break;
01075
01076 default:
01077 for (i = flash_page_source_end.u64ptr - dest.u64ptr; i; i--)
01078 {
01079 for (j = 0; j < sizeof(U64); j++) flash_dword.u8[j] = *source.u8ptr++;
01080 *dest.u32ptr++ = flash_dword.u32[0];
01081 *dest.u32ptr++ = flash_dword.u32[1];
01082 }
01083 }
01084
01085
01086 if (incomplete_flash_page_end)
01087 {
01088
01089 if (flash_dword_pending) i = Get_align((U32)dest_end.u8ptr, sizeof(U64));
01090
01091 else
01092 {
01093
01094 for (i = 0; i < Get_align((U32)dest_end.u8ptr, sizeof(U64)); i++)
01095 flash_dword.u8[i] = *source.u8ptr++;
01096 }
01097
01098
01099
01100
01101 {
01102 tmp.u8ptr = (volatile U8 *)dest_end.u8ptr;
01103
01104
01105 if (!Test_align((U32)dest_end.u8ptr, sizeof(U64)))
01106 {
01107
01108 for (; i < sizeof(U64); i++)
01109 flash_dword.u8[i] = *tmp.u8ptr++;
01110
01111
01112 *dest.u32ptr++ = flash_dword.u32[0];
01113 *dest.u32ptr++ = flash_dword.u32[1];
01114 }
01115
01116
01117 for (; !Test_align((U32)tmp.u64ptr, AVR32_FLASHCDW_PAGE_SIZE); tmp.u64ptr++)
01118 {
01119 *tmp.u32ptr = *tmp.u32ptr;
01120 *(tmp.u32ptr+1) = *(tmp.u32ptr+1);
01121 }
01122 }
01123 }
01124
01125
01126 if (dest.u8ptr <= AVR32_FLASHCDW_USER_PAGE)
01127 {
01128
01129 if (erase)
01130 {
01131 flashcdw_erase_page(-1, FALSE);
01132 error_status |= flashcdw_error_status;
01133 }
01134 flashcdw_write_page(-1);
01135 error_status |= flashcdw_error_status;
01136
01137
01138 if (dest.u8ptr >= flash_array_end.u8ptr)
01139 {
01140 source.u8ptr += AVR32_FLASHCDW_USER_PAGE - dest.u8ptr;
01141 dest.u8ptr = AVR32_FLASHCDW_USER_PAGE;
01142 }
01143 }
01144
01145 else
01146 {
01147
01148 if (erase)
01149 {
01150 flashcdw_erase_user_page(FALSE);
01151 error_status |= flashcdw_error_status;
01152 }
01153 flashcdw_write_user_page();
01154 error_status |= flashcdw_error_status;
01155 }
01156 }
01157
01158
01159 flashcdw_error_status = error_status;
01160
01161
01162 return dst;
01163 }
01164