00001
00044 #include <string.h>
00045 #include <assert.h>
00046 #include "flash_efc.h"
00047
00049
00050 #ifdef __cplusplus
00051 extern "C" {
00052 #endif
00053
00054
00055
00064 #if SAM4E
00065
00066 # define FLASH_USER_SIG_SIZE (512)
00067 #endif
00068
00069 #if SAM4S
00070
00071 # define EFC EFC0
00072
00073 # define FLASH_USER_SIG_SIZE (512)
00074
00075 # define IFLASH_ADDR IFLASH0_ADDR
00076
00077 # define IFLASH_PAGE_SIZE IFLASH0_PAGE_SIZE
00078
00079 # define IFLASH_LOCK_REGION_SIZE IFLASH0_LOCK_REGION_SIZE
00080 #endif
00081
00082
00083 # define EFC EFC0
00084
00085 # define GPNVM_NUM_MAX 3
00086
00087 # define IFLASH_ADDR IFLASH0_ADDR
00088
00089 # define IFLASH_PAGE_SIZE IFLASH0_PAGE_SIZE
00090
00091 # define IFLASH_LOCK_REGION_SIZE IFLASH0_LOCK_REGION_SIZE
00092
00093
00094 static uint32_t gs_ul_page_buffer[IFLASH_PAGE_SIZE / sizeof(uint32_t)];
00095
00106 static void translate_address(Efc **pp_efc, uint32_t ul_addr,
00107 uint16_t *pus_page, uint16_t *pus_offset)
00108 {
00109 Efc *p_efc;
00110 uint16_t us_page;
00111 uint16_t us_offset;
00112
00113 if (ul_addr >= IFLASH1_ADDR) {
00114 p_efc = EFC1;
00115 us_page = (ul_addr - IFLASH1_ADDR) / IFLASH1_PAGE_SIZE;
00116 us_offset = (ul_addr - IFLASH1_ADDR) % IFLASH1_PAGE_SIZE;
00117 } else {
00118 p_efc = EFC0;
00119 us_page = (ul_addr - IFLASH0_ADDR) / IFLASH0_PAGE_SIZE;
00120 us_offset = (ul_addr - IFLASH0_ADDR) % IFLASH0_PAGE_SIZE;
00121 }
00122
00123
00124 if (pp_efc) {
00125 *pp_efc = p_efc;
00126 }
00127
00128 if (pus_page) {
00129 *pus_page = us_page;
00130 }
00131
00132 if (pus_offset) {
00133 *pus_offset = us_offset;
00134 }
00135 }
00136
00145 static void compute_address(Efc *p_efc, uint16_t us_page, uint16_t us_offset,
00146 uint32_t *pul_addr)
00147 {
00148 uint32_t ul_addr;
00149
00150
00151 #ifdef EFC1
00152
00153 ul_addr = (p_efc == EFC0) ?
00154 IFLASH0_ADDR + us_page * IFLASH_PAGE_SIZE + us_offset :
00155 IFLASH1_ADDR + us_page * IFLASH_PAGE_SIZE + us_offset;
00156
00157
00158 #else
00159
00160 UNUSED(p_efc);
00161
00162 ul_addr = IFLASH_ADDR + us_page * IFLASH_PAGE_SIZE + us_offset;
00163 #endif
00164
00165
00166 if (pul_addr != NULL) {
00167 *pul_addr = ul_addr;
00168 }
00169 }
00170
00179 static void compute_lock_range(uint32_t ul_start, uint32_t ul_end,
00180 uint32_t *pul_actual_start, uint32_t *pul_actual_end)
00181 {
00182 uint32_t ul_actual_start, ul_actual_end;
00183
00184 ul_actual_start = ul_start - (ul_start % IFLASH_LOCK_REGION_SIZE);
00185 ul_actual_end = ul_end - (ul_end % IFLASH_LOCK_REGION_SIZE) +
00186 IFLASH_LOCK_REGION_SIZE - 1;
00187
00188 if (pul_actual_start) {
00189 *pul_actual_start = ul_actual_start;
00190 }
00191
00192 if (pul_actual_end) {
00193 *pul_actual_end = ul_actual_end;
00194 }
00195 }
00196
00205 uint32_t flash_init(uint32_t ul_mode, uint32_t ul_fws)
00206 {
00207 efc_init(EFC, ul_mode, ul_fws);
00208
00209 #ifdef EFC1
00210 efc_init(EFC1, ul_mode, ul_fws);
00211 #endif
00212
00213 return FLASH_RC_OK;
00214 }
00215
00224 uint32_t flash_set_wait_state(uint32_t ul_address, uint32_t ul_fws)
00225 {
00226 Efc *p_efc;
00227
00228 translate_address(&p_efc, ul_address, NULL, NULL);
00229 efc_set_wait_state(p_efc, ul_fws);
00230
00231 return FLASH_RC_OK;
00232 }
00233
00242 uint32_t flash_set_wait_state_adaptively(uint32_t ul_address)
00243 {
00244 Efc *p_efc;
00245 uint32_t clock = SystemCoreClock;
00246
00247 translate_address(&p_efc, ul_address, NULL, NULL);
00248
00249
00250 if (clock < CHIP_FREQ_FWS_0) {
00251 efc_set_wait_state(p_efc, 0);
00252 } else if (clock < CHIP_FREQ_FWS_1) {
00253 efc_set_wait_state(p_efc, 1);
00254 } else if (clock < CHIP_FREQ_FWS_2) {
00255 efc_set_wait_state(p_efc, 2);
00256 } else if (clock < CHIP_FREQ_FWS_3) {
00257 efc_set_wait_state(p_efc, 3);
00258 } else {
00259 efc_set_wait_state(p_efc, 4);
00260 }
00261 return FLASH_RC_OK;
00262 }
00263
00271 uint32_t flash_get_wait_state(uint32_t ul_address)
00272 {
00273 Efc *p_efc;
00274
00275 translate_address(&p_efc, ul_address, NULL, NULL);
00276 return efc_get_wait_state(p_efc);
00277 }
00278
00288 uint32_t flash_get_descriptor(uint32_t ul_address,
00289 uint32_t *pul_flash_descriptor, uint32_t ul_size)
00290 {
00291 Efc *p_efc;
00292 uint32_t ul_tmp;
00293 uint32_t ul_cnt;
00294
00295 translate_address(&p_efc, ul_address, NULL, NULL);
00296
00297
00298 if (FLASH_RC_OK != efc_perform_command(p_efc, EFC_FCMD_GETD, 0)) {
00299 return 0;
00300 } else {
00301
00302 for (ul_cnt = 0;; ul_cnt++) {
00303 ul_tmp = efc_get_result(p_efc);
00304 if ((ul_size > ul_cnt) && (ul_tmp != 0)) {
00305 *pul_flash_descriptor++ = ul_tmp;
00306 } else {
00307 break;
00308 }
00309 }
00310 }
00311
00312 return ul_cnt;
00313 }
00314
00325 uint32_t flash_get_page_count(const uint32_t *pul_flash_descriptor)
00326 {
00327 return (pul_flash_descriptor[1] / pul_flash_descriptor[2]);
00328 }
00329
00340 uint32_t flash_get_page_count_per_region(const uint32_t *pul_flash_descriptor)
00341 {
00342 return (pul_flash_descriptor[4] / pul_flash_descriptor[2]);
00343 }
00344
00355 uint32_t flash_get_region_count(const uint32_t *pul_flash_descriptor)
00356 {
00357 return (pul_flash_descriptor[3]);
00358 }
00359
00371 uint32_t flash_erase_all(uint32_t ul_address)
00372 {
00373 Efc *p_efc;
00374
00375 translate_address(&p_efc, ul_address, NULL, NULL);
00376
00377 if (EFC_RC_OK != efc_perform_command(p_efc, EFC_FCMD_EA, 0)) {
00378 return FLASH_RC_ERROR;
00379 }
00380
00381 return FLASH_RC_OK;
00382 }
00383
00384 #if SAM3SD8
00385
00395 uint32_t flash_erase_plane(uint32_t ul_address)
00396 {
00397 Efc *p_efc;
00398 uint16_t us_page;
00399
00400 translate_address(&p_efc, ul_address, &us_page, NULL);
00401
00402 if (EFC_RC_OK != efc_perform_command(p_efc, EFC_FCMD_EPL, us_page)) {
00403 return FLASH_RC_ERROR;
00404 }
00405
00406 return FLASH_RC_OK;
00407 }
00408 #endif
00409
00410 #if (SAM4S || SAM4E)
00411
00418 uint32_t flash_erase_page(uint32_t ul_address, uint8_t uc_page_num)
00419 {
00420 Efc *p_efc;
00421 uint16_t us_page;
00422
00423 if (uc_page_num >= IFLASH_ERASE_PAGES_INVALID) {
00424 return FLASH_RC_INVALID;
00425 }
00426
00427 if (ul_address & (IFLASH_PAGE_SIZE - 1)) {
00428 return FLASH_RC_INVALID;
00429 }
00430
00431 translate_address(&p_efc, ul_address, &us_page, NULL);
00432
00433 if (EFC_RC_OK != efc_perform_command(p_efc, EFC_FCMD_EPA,
00434 (us_page | uc_page_num))) {
00435 return FLASH_RC_ERROR;
00436 }
00437
00438 return FLASH_RC_OK;
00439 }
00440
00451 uint32_t flash_erase_sector(uint32_t ul_address)
00452 {
00453 Efc *p_efc;
00454 uint16_t us_page;
00455
00456 translate_address(&p_efc, ul_address, &us_page, NULL);
00457
00458 if (EFC_RC_OK != efc_perform_command(p_efc, EFC_FCMD_ES, us_page)) {
00459 return FLASH_RC_ERROR;
00460 }
00461
00462 return FLASH_RC_OK;
00463 }
00464 #endif
00465
00482 uint32_t flash_write(uint32_t ul_address, const void *p_buffer,
00483 uint32_t ul_size, uint32_t ul_erase_flag)
00484 {
00485 Efc *p_efc;
00486 uint32_t ul_fws_temp;
00487 uint16_t us_page;
00488 uint16_t us_offset;
00489 uint32_t writeSize;
00490 uint32_t ul_page_addr;
00491 uint16_t us_padding;
00492 uint32_t ul_error;
00493 uint32_t ul_idx;
00494 uint32_t *p_aligned_dest;
00495 uint8_t *puc_page_buffer = (uint8_t *) gs_ul_page_buffer;
00496
00497 translate_address(&p_efc, ul_address, &us_page, &us_offset);
00498
00499
00500 ul_fws_temp = efc_get_wait_state(p_efc);
00501 efc_set_wait_state(p_efc, 6);
00502
00503
00504 while (ul_size > 0) {
00505
00506 writeSize = Min((uint32_t) IFLASH_PAGE_SIZE - us_offset,
00507 ul_size);
00508 compute_address(p_efc, us_page, 0, &ul_page_addr);
00509 us_padding = IFLASH_PAGE_SIZE - us_offset - writeSize;
00510
00511
00512 memcpy(puc_page_buffer, (void *)ul_page_addr, us_offset);
00513
00514
00515 memcpy(puc_page_buffer + us_offset, p_buffer, writeSize);
00516
00517
00518 memcpy(puc_page_buffer + us_offset + writeSize,
00519 (void *)(ul_page_addr + us_offset + writeSize),
00520 us_padding);
00521
00522
00523
00524
00525
00526 p_aligned_dest = (uint32_t *) ul_page_addr;
00527 for (ul_idx = 0; ul_idx < (IFLASH_PAGE_SIZE / sizeof(uint32_t));
00528 ++ul_idx) {
00529 *p_aligned_dest++ = gs_ul_page_buffer[ul_idx];
00530 }
00531
00532 if (ul_erase_flag) {
00533 ul_error = efc_perform_command(p_efc, EFC_FCMD_EWP,
00534 us_page);
00535 } else {
00536 ul_error = efc_perform_command(p_efc, EFC_FCMD_WP,
00537 us_page);
00538 }
00539
00540 if (ul_error) {
00541 return ul_error;
00542 }
00543
00544
00545 p_buffer = (void *)((uint32_t) p_buffer + writeSize);
00546 ul_size -= writeSize;
00547 us_page++;
00548 us_offset = 0;
00549 }
00550
00551
00552 efc_set_wait_state(p_efc, ul_fws_temp);
00553
00554 return FLASH_RC_OK;
00555 }
00556
00557
00569 uint32_t flash_lock(uint32_t ul_start, uint32_t ul_end,
00570 uint32_t *pul_actual_start, uint32_t *pul_actual_end)
00571 {
00572 Efc *p_efc;
00573 uint32_t ul_actual_start, ul_actual_end;
00574 uint16_t us_start_page, us_end_page;
00575 uint32_t ul_error;
00576 uint16_t us_num_pages_in_region =
00577 IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
00578
00579
00580 compute_lock_range(ul_start, ul_end, &ul_actual_start, &ul_actual_end);
00581
00582 if (pul_actual_start != NULL) {
00583 *pul_actual_start = ul_actual_start;
00584 }
00585
00586 if (pul_actual_end != NULL) {
00587 *pul_actual_end = ul_actual_end;
00588 }
00589
00590
00591 translate_address(&p_efc, ul_actual_start, &us_start_page, 0);
00592 translate_address(0, ul_actual_end, &us_end_page, 0);
00593
00594
00595 while (us_start_page < us_end_page) {
00596 ul_error = efc_perform_command(p_efc, EFC_FCMD_SLB, us_start_page);
00597
00598 if (ul_error) {
00599 return ul_error;
00600 }
00601 us_start_page += us_num_pages_in_region;
00602 }
00603
00604 return FLASH_RC_OK;
00605 }
00606
00618 uint32_t flash_unlock(uint32_t ul_start, uint32_t ul_end,
00619 uint32_t *pul_actual_start, uint32_t *pul_actual_end)
00620 {
00621 Efc *p_efc;
00622 uint32_t ul_actual_start, ul_actual_end;
00623 uint16_t us_start_page, us_end_page;
00624 uint32_t ul_error;
00625 uint16_t us_num_pages_in_region =
00626 IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
00627
00628
00629 compute_lock_range(ul_start, ul_end, &ul_actual_start, &ul_actual_end);
00630 if (pul_actual_start != NULL) {
00631 *pul_actual_start = ul_actual_start;
00632 }
00633 if (pul_actual_end != NULL) {
00634 *pul_actual_end = ul_actual_end;
00635 }
00636
00637
00638 translate_address(&p_efc, ul_actual_start, &us_start_page, 0);
00639 translate_address(0, ul_actual_end, &us_end_page, 0);
00640
00641
00642 while (us_start_page < us_end_page) {
00643 ul_error = efc_perform_command(p_efc, EFC_FCMD_CLB,
00644 us_start_page);
00645 if (ul_error) {
00646 return ul_error;
00647 }
00648 us_start_page += us_num_pages_in_region;
00649 }
00650
00651 return FLASH_RC_OK;
00652 }
00653
00662 uint32_t flash_is_locked(uint32_t ul_start, uint32_t ul_end)
00663 {
00664 Efc *p_efc;
00665 uint16_t us_start_page, us_end_page;
00666 uint8_t uc_start_region, uc_end_region;
00667 uint16_t us_num_pages_in_region;
00668 uint32_t ul_status;
00669 uint32_t ul_error;
00670 uint32_t ul_num_locked_regions = 0;
00671 uint32_t ul_count = 0;
00672 uint32_t ul_bit = 0;
00673
00674
00675 translate_address(&p_efc, ul_start, &us_start_page, 0);
00676 translate_address(0, ul_end, &us_end_page, 0);
00677
00678
00679 us_num_pages_in_region = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
00680 uc_start_region = us_start_page / us_num_pages_in_region;
00681 uc_end_region = us_end_page / us_num_pages_in_region;
00682
00683
00684 ul_error = efc_perform_command(p_efc, EFC_FCMD_GLB, 0);
00685
00686
00687 ul_status = efc_get_result(p_efc);
00688 while (!(ul_count <= uc_start_region &&
00689 uc_start_region < (ul_count + 32))) {
00690 ul_status = efc_get_result(p_efc);
00691 ul_count += 32;
00692 }
00693
00694
00695 ul_bit = uc_start_region - ul_count;
00696
00697
00698 ul_count = uc_end_region - uc_start_region + 1;
00699
00700 while (ul_count > 0) {
00701 if (ul_status & (1 << (ul_bit))) {
00702 ul_num_locked_regions++;
00703 }
00704
00705 ul_count -= 1;
00706 ul_bit += 1;
00707 if (ul_bit == 32) {
00708 ul_status = efc_get_result(p_efc);
00709 ul_bit = 0;
00710 }
00711 }
00712
00713 return ul_num_locked_regions;
00714 }
00715
00723 uint32_t flash_set_gpnvm(uint32_t ul_gpnvm)
00724 {
00725 if (ul_gpnvm >= GPNVM_NUM_MAX) {
00726 return FLASH_RC_INVALID;
00727 }
00728
00729 if (FLASH_RC_YES == flash_is_gpnvm_set(ul_gpnvm)) {
00730 return FLASH_RC_OK;
00731 }
00732
00733 if (EFC_RC_OK == efc_perform_command(EFC, EFC_FCMD_SGPB, ul_gpnvm)) {
00734 return FLASH_RC_OK;
00735 }
00736
00737 return FLASH_RC_ERROR;
00738 }
00739
00747 uint32_t flash_clear_gpnvm(uint32_t ul_gpnvm)
00748 {
00749 if (ul_gpnvm >= GPNVM_NUM_MAX) {
00750 return FLASH_RC_INVALID;
00751 }
00752
00753 if (FLASH_RC_NO == flash_is_gpnvm_set(ul_gpnvm)) {
00754 return FLASH_RC_OK;
00755 }
00756
00757 if (EFC_RC_OK == efc_perform_command(EFC, EFC_FCMD_CGPB, ul_gpnvm)) {
00758 return FLASH_RC_OK;
00759 }
00760
00761 return FLASH_RC_ERROR;
00762 }
00763
00772 uint32_t flash_is_gpnvm_set(uint32_t ul_gpnvm)
00773 {
00774 uint32_t ul_gpnvm_bits;
00775
00776 if (ul_gpnvm >= GPNVM_NUM_MAX) {
00777 return FLASH_RC_INVALID;
00778 }
00779
00780 if (EFC_RC_OK != efc_perform_command(EFC, EFC_FCMD_GGPB, 0)) {
00781 return FLASH_RC_ERROR;
00782 }
00783
00784 ul_gpnvm_bits = efc_get_result(EFC);
00785 if (ul_gpnvm_bits & (1 << ul_gpnvm)) {
00786 return FLASH_RC_YES;
00787 }
00788
00789 return FLASH_RC_NO;
00790 }
00791
00797 uint32_t flash_enable_security_bit(void)
00798 {
00799 return flash_set_gpnvm(0);
00800 }
00801
00808 uint32_t flash_is_security_bit_enabled(void)
00809 {
00810 return flash_is_gpnvm_set(0);
00811 }
00812
00821 uint32_t flash_read_unique_id(uint32_t *pul_data, uint32_t ul_size)
00822 {
00823 uint32_t uid_buf[4];
00824 uint32_t ul_idx;
00825
00826 if (FLASH_RC_OK != efc_perform_read_sequence(EFC, EFC_FCMD_STUI,
00827 EFC_FCMD_SPUI, uid_buf, 4)) {
00828 return FLASH_RC_ERROR;
00829 }
00830
00831 if (ul_size > 4) {
00832
00833 ul_size = 4;
00834 }
00835
00836 for (ul_idx = 0; ul_idx < ul_size; ul_idx++) {
00837 pul_data[ul_idx] = uid_buf[ul_idx];
00838 }
00839
00840 return FLASH_RC_OK;
00841 }
00842
00843 #if (SAM4S || SAM4E)
00844
00852 uint32_t flash_read_user_signature(uint32_t *p_data, uint32_t ul_size)
00853 {
00854 if (ul_size > FLASH_USER_SIG_SIZE) {
00855
00856 ul_size = FLASH_USER_SIG_SIZE;
00857 }
00858
00859
00860 if (FLASH_RC_OK != efc_perform_read_sequence(EFC, EFC_FCMD_STUS,
00861 EFC_FCMD_SPUS, p_data, ul_size)) {
00862 return FLASH_RC_ERROR;
00863 }
00864
00865 return FLASH_RC_OK;
00866 }
00867
00877 uint32_t flash_write_user_signature(uint32_t ul_address, const void *p_buffer,
00878 uint32_t ul_size)
00879 {
00880
00881 if (ul_size > FLASH_USER_SIG_SIZE) {
00882 return FLASH_RC_INVALID;
00883 }
00884
00885
00886 flash_write(ul_address, p_buffer, ul_size, 0);
00887
00888
00889 if (FLASH_RC_OK != efc_perform_command(EFC, EFC_FCMD_WUS, 0)) {
00890 return FLASH_RC_ERROR;
00891 }
00892
00893 return FLASH_RC_OK;
00894 }
00895
00901 uint32_t flash_erase_user_signature(void)
00902 {
00903
00904 return efc_perform_command(EFC, EFC_FCMD_EUS, 0);
00905 }
00906 #endif
00907
00909
00911
00912 #ifdef __cplusplus
00913 }
00914 #endif
00915
00916