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 *tmp.u64ptr = *tmp.u64ptr;
00841
00842
00843 if (!Test_align((U32)dest.u8ptr, sizeof(U64)))
00844 {
00845
00846
00847
00848
00849
00850 for (i = 0; i < Get_align((U32)dest.u8ptr, sizeof(U64)); i++)
00851 flash_dword.u8[i] = *tmp.u8ptr++;
00852
00853
00854 dest.u64ptr = (U64 *)Align_down((U32)dest.u8ptr, sizeof(U64));
00855
00856
00857 if (dest.u64ptr < dest_end.u64ptr)
00858 {
00859
00860 *dest.u64ptr++ = flash_dword.u64;
00861 flash_dword.u64 = source.u64;
00862 }
00863 }
00864 }
00865
00866
00867 for (i = flash_page_source_end.u64ptr - dest.u64ptr; i; i--)
00868 *dest.u64ptr++ = source.u64;
00869
00870
00871 if (incomplete_flash_page_end)
00872 {
00873
00874
00875
00876 {
00877 tmp.u8ptr = (volatile U8 *)dest_end.u8ptr;
00878
00879
00880 if (!Test_align((U32)dest_end.u8ptr, sizeof(U64)))
00881 {
00882
00883 for (i = Get_align((U32)dest_end.u8ptr, sizeof(U64)); i < sizeof(U64); i++)
00884 flash_dword.u8[i] = *tmp.u8ptr++;
00885
00886
00887 *dest.u64ptr++ = flash_dword.u64;
00888 }
00889
00890
00891 for (; !Test_align((U32)tmp.u64ptr, AVR32_FLASHCDW_PAGE_SIZE); tmp.u64ptr++)
00892 *tmp.u64ptr = *tmp.u64ptr;
00893 }
00894 }
00895
00896
00897 if (dest.u8ptr <= AVR32_FLASHCDW_USER_PAGE)
00898 {
00899
00900 if (erase)
00901 {
00902 flashcdw_erase_page(-1, FALSE);
00903 error_status |= flashcdw_error_status;
00904 }
00905 flashcdw_write_page(-1);
00906 error_status |= flashcdw_error_status;
00907
00908
00909 if (dest.u8ptr >= flash_array_end.u8ptr)
00910 dest.u8ptr = AVR32_FLASHCDW_USER_PAGE;
00911 }
00912
00913 else
00914 {
00915
00916 if (erase)
00917 {
00918 flashcdw_erase_user_page(FALSE);
00919 error_status |= flashcdw_error_status;
00920 }
00921 flashcdw_write_user_page();
00922 error_status |= flashcdw_error_status;
00923 }
00924 }
00925
00926
00927 flashcdw_error_status = error_status;
00928
00929
00930 return dst;
00931 }
00932
00933
00934 volatile void *flashcdw_memcpy(volatile void *dst, const void *src, size_t nbytes, Bool erase)
00935 {
00936
00937 UnionCVPtr flash_array_end;
00938 UnionVPtr dest;
00939 UnionCPtr source;
00940 StructCVPtr dest_end;
00941 UnionCVPtr flash_page_source_end;
00942 Bool incomplete_flash_page_end;
00943 Union64 flash_dword;
00944 Bool flash_dword_pending = FALSE;
00945 UnionVPtr tmp;
00946 unsigned int error_status = 0;
00947 unsigned int i, j;
00948
00949
00950 flash_array_end.u8ptr = AVR32_FLASH + flashcdw_get_flash_size();
00951 dest.u8ptr = dst;
00952 source.u8ptr = src;
00953 dest_end.u8ptr = dest.u8ptr + nbytes;
00954
00955
00956 if (dest.u8ptr < AVR32_FLASH)
00957 {
00958 source.u8ptr += AVR32_FLASH - dest.u8ptr;
00959 dest.u8ptr = AVR32_FLASH;
00960 }
00961 else if (flash_array_end.u8ptr <= dest.u8ptr && dest.u8ptr < AVR32_FLASHCDW_USER_PAGE)
00962 {
00963 source.u8ptr += AVR32_FLASHCDW_USER_PAGE - dest.u8ptr;
00964 dest.u8ptr = AVR32_FLASHCDW_USER_PAGE;
00965 }
00966
00967
00968 if (dest_end.u8ptr > AVR32_FLASHCDW_USER_PAGE + AVR32_FLASHCDW_USER_PAGE_SIZE)
00969 {
00970 dest_end.u8ptr = AVR32_FLASHCDW_USER_PAGE + AVR32_FLASHCDW_USER_PAGE_SIZE;
00971 }
00972 else if (AVR32_FLASHCDW_USER_PAGE >= dest_end.u8ptr && dest_end.u8ptr > flash_array_end.u8ptr)
00973 {
00974 dest_end.u8ptr = flash_array_end.u8ptr;
00975 }
00976
00977
00978 dest_end.u16ptr = (U16 *)Align_down((U32)dest_end.u8ptr, sizeof(U16));
00979 dest_end.u32ptr = (U32 *)Align_down((U32)dest_end.u16ptr, sizeof(U32));
00980 dest_end.u64ptr = (U64 *)Align_down((U32)dest_end.u32ptr, sizeof(U64));
00981
00982
00983 while (dest.u8ptr < dest_end.u8ptr)
00984 {
00985
00986 flashcdw_clear_page_buffer();
00987 error_status |= flashcdw_error_status;
00988
00989
00990 flash_page_source_end.u64ptr =
00991 (U64 *)min((U32)dest_end.u64ptr,
00992 Align_down((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE) + AVR32_FLASHCDW_PAGE_SIZE);
00993
00994
00995 incomplete_flash_page_end = (Align_down((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE) >=
00996 Align_down((U32)dest_end.u8ptr, AVR32_FLASHCDW_PAGE_SIZE));
00997
00998
00999 if (!Test_align((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE))
01000 {
01001
01002
01003
01004
01005 for (tmp.u8ptr = (U8 *)Align_down((U32)dest.u8ptr, AVR32_FLASHCDW_PAGE_SIZE);
01006 tmp.u64ptr < (U64 *)Align_down((U32)dest.u8ptr, sizeof(U64));
01007 tmp.u64ptr++)
01008 *tmp.u64ptr = *tmp.u64ptr;
01009
01010
01011 if (!Test_align((U32)dest.u8ptr, sizeof(U64)))
01012 {
01013
01014
01015
01016
01017
01018 for (i = 0; i < Get_align((U32)dest.u8ptr, sizeof(U64)); i++)
01019 flash_dword.u8[i] = *tmp.u8ptr++;
01020
01021
01022 for (; i < sizeof(U64); i++)
01023 flash_dword.u8[i] = *source.u8ptr++;
01024
01025
01026 dest.u64ptr = (U64 *)Align_down((U32)dest.u8ptr, sizeof(U64));
01027
01028
01029 if (dest.u64ptr < dest_end.u64ptr)
01030 {
01031
01032 *dest.u64ptr++ = flash_dword.u64;
01033 }
01034
01035
01036 else flash_dword_pending = TRUE;
01037 }
01038 }
01039
01040
01041
01042 switch (Get_align((U32)source.u8ptr, sizeof(U32)))
01043 {
01044 case 0:
01045 for (i = flash_page_source_end.u64ptr - dest.u64ptr; i; i--)
01046 *dest.u64ptr++ = *source.u64ptr++;
01047 break;
01048
01049 case sizeof(U16):
01050 for (i = flash_page_source_end.u64ptr - dest.u64ptr; i; i--)
01051 {
01052 for (j = 0; j < sizeof(U64) / sizeof(U16); j++) flash_dword.u16[j] = *source.u16ptr++;
01053 *dest.u64ptr++ = flash_dword.u64;
01054 }
01055 break;
01056
01057 default:
01058 for (i = flash_page_source_end.u64ptr - dest.u64ptr; i; i--)
01059 {
01060 for (j = 0; j < sizeof(U64); j++) flash_dword.u8[j] = *source.u8ptr++;
01061 *dest.u64ptr++ = flash_dword.u64;
01062 }
01063 }
01064
01065
01066 if (incomplete_flash_page_end)
01067 {
01068
01069 if (flash_dword_pending) i = Get_align((U32)dest_end.u8ptr, sizeof(U64));
01070
01071 else
01072 {
01073
01074 for (i = 0; i < Get_align((U32)dest_end.u8ptr, sizeof(U64)); i++)
01075 flash_dword.u8[i] = *source.u8ptr++;
01076 }
01077
01078
01079
01080
01081 {
01082 tmp.u8ptr = (volatile U8 *)dest_end.u8ptr;
01083
01084
01085 if (!Test_align((U32)dest_end.u8ptr, sizeof(U64)))
01086 {
01087
01088 for (; i < sizeof(U64); i++)
01089 flash_dword.u8[i] = *tmp.u8ptr++;
01090
01091
01092 *dest.u64ptr++ = flash_dword.u64;
01093 }
01094
01095
01096 for (; !Test_align((U32)tmp.u64ptr, AVR32_FLASHCDW_PAGE_SIZE); tmp.u64ptr++)
01097 *tmp.u64ptr = *tmp.u64ptr;
01098 }
01099 }
01100
01101
01102 if (dest.u8ptr <= AVR32_FLASHCDW_USER_PAGE)
01103 {
01104
01105 if (erase)
01106 {
01107 flashcdw_erase_page(-1, FALSE);
01108 error_status |= flashcdw_error_status;
01109 }
01110 flashcdw_write_page(-1);
01111 error_status |= flashcdw_error_status;
01112
01113
01114 if (dest.u8ptr >= flash_array_end.u8ptr)
01115 {
01116 source.u8ptr += AVR32_FLASHCDW_USER_PAGE - dest.u8ptr;
01117 dest.u8ptr = AVR32_FLASHCDW_USER_PAGE;
01118 }
01119 }
01120
01121 else
01122 {
01123
01124 if (erase)
01125 {
01126 flashcdw_erase_user_page(FALSE);
01127 error_status |= flashcdw_error_status;
01128 }
01129 flashcdw_write_user_page();
01130 error_status |= flashcdw_error_status;
01131 }
01132 }
01133
01134
01135 flashcdw_error_status = error_status;
01136
01137
01138 return dst;
01139 }
01140