diff options
author | Rodrigo L. Rosa <rodrigorosa.lg@gmail.com> | 2011-06-10 12:19:58 -0700 |
---|---|---|
committer | Øyvind Harboe <oyvind.harboe@zylin.com> | 2011-06-12 11:18:27 +0200 |
commit | f4a3db0d4a353ccc6d701a2645390ef9039e0d02 (patch) | |
tree | c3dd4536a060e41f744e0174e8080d296465f0e0 | |
parent | 56d3927abf2d2c6c49f3ae6ad6c2f353168d5a60 (diff) | |
download | riscv-openocd-f4a3db0d4a353ccc6d701a2645390ef9039e0d02.zip riscv-openocd-f4a3db0d4a353ccc6d701a2645390ef9039e0d02.tar.gz riscv-openocd-f4a3db0d4a353ccc6d701a2645390ef9039e0d02.tar.bz2 |
fix flash driver size, sector erase
-rw-r--r-- | src/flash/nor/dsp5680xx_flash.c | 68 | ||||
-rw-r--r-- | src/target/dsp5680xx.c | 174 | ||||
-rw-r--r-- | src/target/dsp5680xx.h | 19 |
3 files changed, 98 insertions, 163 deletions
diff --git a/src/flash/nor/dsp5680xx_flash.c b/src/flash/nor/dsp5680xx_flash.c index e9c4e82..4e7a0b6 100644 --- a/src/flash/nor/dsp5680xx_flash.c +++ b/src/flash/nor/dsp5680xx_flash.c @@ -41,17 +41,13 @@ struct dsp5680xx_flash_bank { }; static int dsp5680xx_build_sector_list(struct flash_bank *bank){ - //LOG_USER("%s not implemented",__FUNCTION__); - //return ERROR_OK; - - // sector size is 512 - // bank->num_sectors = bank->size / 512; // Bank size is actually 0x2000, but it is set much higher as part of the workaround for byte/word addressing issues. + uint32_t offset = HFM_FLASH_BASE_ADDR; bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); int i; for (i = 0; i < bank->num_sectors; ++i){ - bank->sectors[i].offset = 0;// not implemented. + bank->sectors[i].offset = i*HFM_SECTOR_SIZE; bank->sectors[i].size = HFM_SECTOR_SIZE; - //offset += bank->sectors[i].size; + offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = -1; } @@ -67,9 +63,9 @@ FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command){ nbank = malloc(sizeof(struct dsp5680xx_flash_bank)); bank->base = HFM_FLASH_BASE_ADDR; - bank->size = HFM_SIZE; // top 4k not accessible + bank->size = HFM_SIZE_BYTES; // top 4k not accessible bank->driver_priv = nbank; - bank->num_sectors = HFM_SECTOR_COUNT;// This number is anything >0. not really used. + bank->num_sectors = HFM_SECTOR_COUNT; dsp5680xx_build_sector_list(bank); return ERROR_OK; @@ -77,30 +73,40 @@ FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command){ static int dsp5680xx_flash_protect_check(struct flash_bank *bank){ int retval = ERROR_OK; - uint8_t protected = 0; - if(bank->sectors[0].is_protected == -1){ + uint16_t protected = 0; retval = dsp5680xx_f_protect_check(bank->target,&protected); - if(retval == ERROR_OK) - if(protected) - bank->sectors[0].is_protected = 1; - else - bank->sectors[0].is_protected = 0; - else - bank->sectors[0].is_protected = -1; + if(retval != ERROR_OK){ + for(int i = 0;i<HFM_SECTOR_COUNT;i++) + bank->sectors[i].is_protected = -1; + return ERROR_OK; + } + for(int i = 0;i<HFM_SECTOR_COUNT/2;i++){ + if(protected & 1){ + bank->sectors[2*i].is_protected = 1; + bank->sectors[2*i+1].is_protected = 1; + }else{ + bank->sectors[2*i].is_protected = 0; + bank->sectors[2*i+1].is_protected = 0; + } + protected = (protected >> 1); } return retval; } static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first, int last){ + // This applies security to flash module after next reset, it does not actually apply protection (protection refers to undesired access from the core) int retval; if(set){ retval = dsp5680xx_f_lock(bank->target); - if(retval == ERROR_OK) - bank->sectors[0].is_protected = 1; + if(retval == ERROR_OK){ + for(int i = first;i<last;i++) + bank->sectors[i].is_protected = 1; + } }else{ retval = dsp5680xx_f_unlock(bank->target); if(retval == ERROR_OK) - bank->sectors[0].is_protected = 0; + for(int i = first;i<last;i++) + bank->sectors[i].is_protected = 0; } return retval; } @@ -167,24 +173,30 @@ static int dsp5680xx_flash_erase(struct flash_bank * bank, int first, int last){ int retval; retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last); if(retval == ERROR_OK) - bank->sectors[0].is_erased = 1; + for(int i = first;i<=last;i++) + bank->sectors[i].is_erased = 1; else - bank->sectors[0].is_erased = -1; + // If an error occurred unknown status is set even though some sector could have been correctly erased. + for(int i = first;i<=last;i++) + bank->sectors[i].is_erased = -1; return retval; } static int dsp5680xx_flash_erase_check(struct flash_bank * bank){ int retval = ERROR_OK; uint8_t erased = 0; - if(bank->sectors[0].is_erased == -1){ - retval = dsp5680xx_f_erase_check(bank->target,&erased); + uint32_t i; + for(i=0;i<HFM_SECTOR_COUNT;i++){ + if(bank->sectors[i].is_erased == -1){ + retval = dsp5680xx_f_erase_check(bank->target,&erased,i); if (retval != ERROR_OK){ - bank->sectors[0].is_erased = -1; + bank->sectors[i].is_erased = -1; }else{ if(erased) - bank->sectors[0].is_erased = 1; + bank->sectors[i].is_erased = 1; else - bank->sectors[0].is_erased = 0; + bank->sectors[i].is_erased = 0; + } } } return retval; diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index 9eba374..c79ee3a 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -244,17 +244,6 @@ static int eonce_read_status_reg(struct target * target, uint16_t * data){ return retval; } -static int dsp5680xx_obase_addr(struct target * target, uint32_t * addr){ - // Finds out the default value of the OBASE register address. - int retval; - uint32_t data_to_shift_into_dr;// just to make jtag happy - retval = eonce_instruction_exec(target,DSP5680XX_ONCE_OBASE,1,0,0,NULL); - err_check_propagate(retval); - retval = dsp5680xx_drscan(target,(uint8_t *)& data_to_shift_into_dr,(uint8_t *) addr, 8); - err_check_propagate(retval); - return retval; -} - static int dsp5680xx_halt(struct target *target){ int retval; uint8_t jtag_status; @@ -614,24 +603,15 @@ static int eonce_move_value_to_pc(struct target * target, uint32_t value) static int eonce_load_TX_RX_to_r0(struct target * target) { - uint32_t obase_addr; - int retval = dsp5680xx_obase_addr(target,& obase_addr); - err_check_propagate(retval); - retval = eonce_move_long_to_r0(target,((MC568013_EONCE_TX_RX_ADDR)+(obase_addr<<16))); + int retval; + retval = eonce_move_long_to_r0(target,((MC568013_EONCE_TX_RX_ADDR)+(MC568013_EONCE_OBASE_ADDR<<16))); return retval; } static int eonce_load_TX_RX_high_to_r0(struct target * target) { - uint32_t obase_addr; - int retval = dsp5680xx_obase_addr(target,& obase_addr); - err_check_propagate(retval); - if(!(obase_addr && 0xff)){ - LOG_USER("%s: OBASE address read as 0x%04X instead of 0xFF.",__FUNCTION__,obase_addr); - return ERROR_FAIL; - } - eonce_move_long_to_r0(target,((MC568013_EONCE_TX1_RX1_HIGH_ADDR)+(obase_addr<<16))); - err_check_propagate(retval); + int retval = 0; + retval = eonce_move_long_to_r0(target,((MC568013_EONCE_TX1_RX1_HIGH_ADDR)+(MC568013_EONCE_OBASE_ADDR<<16))); return retval; } @@ -804,11 +784,11 @@ static int dsp5680xx_write_8(struct target * target, uint32_t address, uint32_t uint16_t * data_w = (uint16_t *)data; uint32_t iter; - int counter = FLUSH_COUNT_WRITE; + int counter = FLUSH_COUNT_READ_WRITE; for(iter = 0; iter<count/2; iter++){ if(--counter==0){ context.flush = 1; - counter = FLUSH_COUNT_WRITE; + counter = FLUSH_COUNT_READ_WRITE; } retval = dsp5680xx_write_16_single(target,address+iter,data_w[iter], pmem); if(retval != ERROR_OK){ @@ -843,14 +823,12 @@ static int dsp5680xx_write_16(struct target * target, uint32_t address, uint32_t err_check(retval,"Target must be halted."); }; uint32_t iter; - - int counter_reset = FLUSH_COUNT_WRITE; - int counter = counter_reset; + int counter = FLUSH_COUNT_READ_WRITE; for(iter = 0; iter<count; iter++){ if(--counter==0){ context.flush = 1; - counter = counter_reset; + counter = FLUSH_COUNT_READ_WRITE; } retval = dsp5680xx_write_16_single(target,address+iter,data[iter], pmem); if(retval != ERROR_OK){ @@ -871,14 +849,12 @@ static int dsp5680xx_write_32(struct target * target, uint32_t address, uint32_t err_check(retval,"Target must be halted."); }; uint32_t iter; - - int counter_reset = FLUSH_COUNT_WRITE; - int counter = counter_reset; + int counter = FLUSH_COUNT_READ_WRITE; for(iter = 0; iter<count; iter++){ if(--counter==0){ context.flush = 1; - counter = counter_reset; + counter = FLUSH_COUNT_READ_WRITE; } retval = dsp5680xx_write_32_single(target,address+(iter<<1),data[iter], pmem); if(retval != ERROR_OK){ @@ -1026,29 +1002,19 @@ static int dsp5680xx_soft_reset_halt(struct target *target){ return retval; } -int dsp5680xx_f_protect_check(struct target * target, uint8_t * protected) { - uint16_t i,j; +int dsp5680xx_f_protect_check(struct target * target, uint16_t * protected) { + uint16_t aux; int retval; if (dsp5680xx_target_status(target,NULL,NULL) != TARGET_HALTED){ retval = dsp5680xx_halt(target); err_check_propagate(retval); } - retval = eonce_load_TX_RX_high_to_r0(target); - err_check_propagate(retval); - retval = eonce_move_value_to_y0(target,0x1234); - err_check_propagate(retval); - retval = eonce_move_y0_at_r0(target); - err_check_propagate(retval); - retval = eonce_rx_upper_data(target,&i); - err_check_propagate(retval); - retval = eonce_move_value_to_y0(target,0x4321); - err_check_propagate(retval); - retval = eonce_move_y0_at_r0(target); - err_check_propagate(retval); - retval = eonce_rx_upper_data(target,&j); + if(protected == NULL){ + err_check(ERROR_FAIL,"NULL pointer not valid."); + } + retval = dsp5680xx_read_16_single(target,HFM_BASE_ADDR|HFM_PROT,&aux,0); err_check_propagate(retval); - if(protected!=NULL) - *protected = (uint8_t) ((i!=0x1234)||(j!=0x4321)); + *protected = aux; return retval; } @@ -1171,32 +1137,15 @@ static int dsp5680xx_f_signature(struct target * target, uint32_t address, uint3 return retval; } -int dsp5680xx_f_erase_check(struct target * target, uint8_t * erased){ +int dsp5680xx_f_erase_check(struct target * target, uint8_t * erased,uint32_t sector){ int retval; uint16_t hfm_ustat; if (dsp5680xx_target_status(target,NULL,NULL) != TARGET_HALTED){ retval = dsp5680xx_halt(target); err_check_propagate(retval); } - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - // Check security - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - uint8_t protected; - retval = dsp5680xx_f_protect_check(target,&protected); - err_check_propagate(retval); - if(protected){ - retval = ERROR_TARGET_FAILURE; - err_check(retval,"Failed to erase, flash is still protected."); - } - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - // Set hfmdiv - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - retval = eonce_set_hfmdiv(target); - err_check_propagate(retval); - // Check if chip is already erased. - // Since only mass erase is currently implemented, only the first sector is checked (assuming no code will leave it unused) - retval = dsp5680xx_f_execute_command(target,HFM_ERASE_VERIFY,HFM_FLASH_BASE_ADDR+0*HFM_SECTOR_SIZE,0,&hfm_ustat,1); // blank check + retval = dsp5680xx_f_execute_command(target,HFM_ERASE_VERIFY,HFM_FLASH_BASE_ADDR+sector*HFM_SECTOR_SIZE/2,0,&hfm_ustat,1); // blank check err_check_propagate(retval); if (hfm_ustat&HFM_USTAT_MASK_PVIOL_ACCER){ retval = ERROR_TARGET_FAILURE; @@ -1206,17 +1155,25 @@ int dsp5680xx_f_erase_check(struct target * target, uint8_t * erased){ *erased = (uint8_t)(hfm_ustat&HFM_USTAT_MASK_BLANK); return retval; } + +static int erase_sector(struct target * target, int sector, uint16_t * hfm_ustat){ + int retval; + retval = dsp5680xx_f_execute_command(target,HFM_PAGE_ERASE,HFM_FLASH_BASE_ADDR+sector*HFM_SECTOR_SIZE/2,0,hfm_ustat,1); + err_check_propagate(retval); + return retval; +} + +static int mass_erase(struct target * target, uint16_t * hfm_ustat){ + int retval; + retval = dsp5680xx_f_execute_command(target,HFM_MASS_ERASE,0,0,hfm_ustat,1); + return retval; +} int dsp5680xx_f_erase(struct target * target, int first, int last){ - //TODO implement erasing individual sectors. int retval; - if(first||last){ - retval = ERROR_FAIL; - err_check(retval,"Sector erasing not implemented. Call with first=last=0."); - } if (dsp5680xx_target_status(target,NULL,NULL) != TARGET_HALTED){ retval = dsp5680xx_halt(target); - err_check_propagate(retval); + err_check_propagate(retval); } // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // Reset SIM @@ -1224,49 +1181,25 @@ int dsp5680xx_f_erase(struct target * target, int first, int last){ retval = dsp5680xx_f_SIM_reset(target); err_check_propagate(retval); // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - // Check security - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - uint8_t protected; - retval = dsp5680xx_f_protect_check(target,&protected); - err_check_propagate(retval); - if(protected){ - retval = ERROR_TARGET_FAILURE; - err_check(retval,"Cannot flash, security is still enabled."); - } - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // Set hfmdiv // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- retval = eonce_set_hfmdiv(target); err_check_propagate(retval); - // Check if chip is already erased. - // Since only mass erase is currently implemented, only the first sector is checked (assuming no code will leave it unused) - uint8_t erased; - retval = dsp5680xx_f_erase_check(target,&erased); - err_check_propagate(retval); - if (erased) - LOG_USER("Flash blank - mass erase skipped."); - else{ - // Execute mass erase command. - uint16_t hfm_ustat; - uint16_t hfm_cmd = HFM_MASS_ERASE; - retval = dsp5680xx_f_execute_command(target,hfm_cmd,HFM_FLASH_BASE_ADDR+0*HFM_SECTOR_SIZE,0,&hfm_ustat,1); - err_check_propagate(retval); - if (hfm_ustat&HFM_USTAT_MASK_PVIOL_ACCER){ - retval = ERROR_TARGET_FAILURE; - err_check(retval,"pviol and/or accer bits set. HFM command execution error"); - } - // Verify flash was successfully erased. - retval = dsp5680xx_f_erase_check(target,&erased); + uint16_t hfm_ustat; + int do_mass_erase = ((!(first|last)) || ((first==0)&&(last == (HFM_SECTOR_COUNT-1)))); + if(do_mass_erase){ + //Mass erase + retval = mass_erase(target,&hfm_ustat); + err_check_propagate(retval); + last = HFM_SECTOR_COUNT-1; + }else{ + for(int i = first;i<=last;i++){ + retval = erase_sector(target,i,&hfm_ustat); err_check_propagate(retval); - if(retval == ERROR_OK){ - if (erased) - LOG_USER("Flash mass erased and checked blank."); - else - LOG_WARNING("Flash mass erased, but still not blank!"); - } } - return retval; + } + return ERROR_OK; } // Algorithm for programming normal p: flash @@ -1317,16 +1250,6 @@ int dsp5680xx_f_wr(struct target * target, uint8_t *buffer, uint32_t address, ui err_check_propagate(retval); } // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - // Check if flash is erased - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - uint8_t erased; - retval = dsp5680xx_f_erase_check(target,&erased); - err_check_propagate(retval); - if(!erased){ - retval = ERROR_FAIL; - err_check(retval,"Flash must be erased before flashing."); - } - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // Download the pgm that flashes. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- uint32_t my_favourite_ram_address = 0x8700; // This seems to be a safe address. This one is the one used by codewarrior in 56801x_flash.cfg @@ -1375,14 +1298,13 @@ int dsp5680xx_f_wr(struct target * target, uint8_t *buffer, uint32_t address, ui retval = dsp5680xx_resume(target,0,my_favourite_ram_address,0,0); err_check_propagate(retval); - int counter_reset = FLUSH_COUNT_FLASH; - int counter = counter_reset; + int counter = FLUSH_COUNT_FLASH; context.flush = 0; uint32_t i; - for(i=1; (i<count/2)&&(i<HFM_SIZE_REAL); i++){ + for(i=1; (i<count/2)&&(i<HFM_SIZE_WORDS); i++){ if(--counter==0){ context.flush = 1; - counter = counter_reset; + counter = FLUSH_COUNT_FLASH; } retval = eonce_tx_upper_data(target,buff16[i],&drscan_data); if(retval!=ERROR_OK){ diff --git a/src/target/dsp5680xx.h b/src/target/dsp5680xx.h index 9f66ee7..da494c9 100644 --- a/src/target/dsp5680xx.h +++ b/src/target/dsp5680xx.h @@ -124,8 +124,8 @@ #define DSP5680XX_ONCE_OPABDR 0x13 /* OnCE Program Address Register—Decode cycle (OPABDR) */ //---------------------------------------------------------------- -#define FLUSH_COUNT_WRITE 4095 // This value works, higher values (and lower...) may work as well. -#define FLUSH_COUNT_FLASH 7 // Waiting for longer queues will cause flashing errors. +#define FLUSH_COUNT_READ_WRITE 8192 // This value works, higher values (and lower...) may work as well. +#define FLUSH_COUNT_FLASH 8192 //---------------------------------------------------------------- // HFM (flash module) Commands (ref:MC56F801xRM.pdf@159) //---------------------------------------------------------------- @@ -160,12 +160,13 @@ #define HFM_USTAT_MASK_BLANK 0x4 #define HFM_USTAT_MASK_PVIOL_ACCER 0x30 -#define HFM_CLK_DEFAULT 0x29 +#define HFM_CLK_DEFAULT 0x40 #define HFM_FLASH_BASE_ADDR 0x0 -#define HFM_SIZE 0x8000 // This is not true for 56F8013, but it is necessary to get the byte/word addressing workaround to actually work. -#define HFM_SIZE_REAL 0x2000 -#define HFM_SECTOR_SIZE 0x8000 // 512 bytes pages. -#define HFM_SECTOR_COUNT 1 +#define HFM_SIZE_BYTES 0x4000 // bytes +#define HFM_SIZE_WORDS 0x2000 // words +#define HFM_SECTOR_SIZE 0x200 // Size in bytes +#define HFM_SECTOR_COUNT 0x20 +// A 16K block in pages of 256 words. #define HFM_LOCK_FLASH 0xE70A #define HFM_LOCK_ADDR_L 0x1FF7 @@ -204,9 +205,9 @@ static inline struct dsp5680xx_common *target_to_dsp5680xx(struct target *target int dsp5680xx_f_wr(struct target * target, uint8_t *buffer, uint32_t address, uint32_t count); -int dsp5680xx_f_erase_check(struct target * target,uint8_t * erased); +int dsp5680xx_f_erase_check(struct target * target,uint8_t * erased, uint32_t sector); int dsp5680xx_f_erase(struct target * target, int first, int last); -int dsp5680xx_f_protect_check(struct target * target, uint8_t * protected); +int dsp5680xx_f_protect_check(struct target * target, uint16_t * protected); int dsp5680xx_f_lock(struct target * target); int dsp5680xx_f_unlock(struct target * target); |