#include "target_type.h"
#include "dsp5680xx.h"
-#define err_check(retval,err_msg) if(retval != ERROR_OK){LOG_ERROR("%s: %s.",__FUNCTION__,err_msg);return retval;}
+#define err_check(retval,err_msg) if(retval != ERROR_OK){LOG_ERROR("%s: %d %s.",__FUNCTION__,__LINE__,err_msg);return retval;}
#define err_check_propagate(retval) if(retval!=ERROR_OK){return retval;}
// Forward declarations, could try to optimize this.
}
static int dsp5680xx_assert_reset(struct target *target){
- //TODO verify the sleeps are necessary
- jtag_add_reset(1,0);
target->state = TARGET_RESET;
- jtag_add_sleep(500);
- usleep(1000);
return ERROR_OK;
}
static int dsp5680xx_deassert_reset(struct target *target){
- jtag_add_reset(0,0);
target->state = TARGET_RUNNING;
return ERROR_OK;
}
uint16_t read_tmp;
retval = dsp5680xx_jtag_status(target,&jtag_status);
err_check_propagate(retval);
- LOG_DEBUG("JTAG 0x%02X",jtag_status);//TODO remove!!
if (jtag_status == JTAG_STATUS_DEBUG)
if (target->state != TARGET_HALTED){
retval = eonce_enter_debug_mode(target,&read_tmp);
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;
static int eonce_load_TX_RX_to_r0(struct target * target)
{
- //TODO add error control
- uint32_t obase_addr;
- int retval = dsp5680xx_obase_addr(target,& obase_addr);
- 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)
{
- //TODO add error control
- 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;
}
uint16_t tmp;
retval = eonce_rx_upper_data(target,&tmp);
err_check_propagate(retval);
- *data_read = (((*data_read)<<16) | tmp);
+ *data_read = ((tmp<<16) | (*data_read));//This enables opencd crc to succeed, even though it's very slow.
return retval;
}
retval = dsp5680xx_convert_address(&address, &pmem);
err_check_propagate(retval);
+ context.flush = 0;
+ int counter = FLUSH_COUNT_READ_WRITE;
+
for (unsigned i=0; i<count; i++){
+ if(--counter==0){
+ context.flush = 1;
+ counter = FLUSH_COUNT_FLASH;
+ }
switch (size){
case 1:
if(!(i%2)){
break;
}
err_check_propagate(retval);
+ context.flush = 0;
}
+
+ context.flush = 1;
+ retval = dsp5680xx_execute_queue();
+ err_check_propagate(retval);
+
return retval;
}
uint16_t * data_w = (uint16_t *)data;
uint32_t iter;
- int counter_reset = FLUSH_COUNT_WRITE;
- int counter = counter_reset;
-
+ int counter = FLUSH_COUNT_READ_WRITE;
for(iter = 0; iter<count/2; iter++){
- if(--counter==0){
- context.flush = 1;
- counter = counter_reset;
- }
-
+ if(--counter==0){
+ context.flush = 1;
+ counter = FLUSH_COUNT_READ_WRITE;
+ }
retval = dsp5680xx_write_16_single(target,address+iter,data_w[iter], pmem);
if(retval != ERROR_OK){
LOG_ERROR("%s: Could not write to p:0x%04X",__FUNCTION__,address);
- context.flush = 1;
+ context.flush = 1;
return retval;
}
- context.flush = 0;
+ context.flush = 0;
}
context.flush = 1;
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){
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){
//TODO doxy
static int dsp5680xx_write(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t * buffer){
- //TODO Cannot write 32bit to odd address, will write 0x1234567 to as 0x5678 0x0012
+ //TODO Cannot write 32bit to odd address, will write 0x12345678 as 0x5678 0x0012
if(target->state != TARGET_HALTED){
LOG_USER("Target must be halted.");
return ERROR_OK;
LOG_USER("Target must be halted.");
return ERROR_OK;
}
- // byte addressing!
- int retval = ERROR_OK;
- int pmem = 1;
- uint16_t tmp_wrd= 0;
-
- retval = dsp5680xx_convert_address(&address, &pmem);
- err_check_propagate(retval);
-
- for (unsigned i=0; i<size; i++)
- if(!(i%2)){
- retval = dsp5680xx_read_16_single(target, address + i/2, &tmp_wrd, pmem);
- err_check_propagate(retval);
- //TODO find a better solution. endiannes differs from normal read, otherwise the openocd crc would do weird stuff.
- buffer[i+1] = (uint8_t) (tmp_wrd>>8);
- buffer[i] = (uint8_t) (tmp_wrd&0xff);
- }
- return retval;
+ // read_buffer is called when the verify_image command is executed.
+ // The "/2" solves the byte/word addressing issue.
+ return dsp5680xx_read(target,address,2,size/2,buffer);
}
static int dsp5680xx_checksum_memory(struct target * target, uint32_t address, uint32_t size, uint32_t * checksum){
- return ERROR_FAIL; //this makes openocd do the crc
+ return ERROR_FAIL;// This will make OpenOCD do the read out the data and verify it.
+}
+
+// Data signature algorithm used by the core FM (flash module)
+static int perl_crc(uint16_t * buff16,uint32_t word_count){
+ uint16_t checksum = 0xffff;
+ uint16_t data,fbmisr;
+ uint32_t i;
+ for(i=0;i<word_count;i++){
+ data = buff16[i];
+ fbmisr = (checksum & 2)>>1 ^ (checksum & 4)>>2 ^ (checksum & 16)>>4 ^ (checksum & 0x8000)>>15;
+ checksum = (data ^ ((checksum << 1) | fbmisr));
+ }
+ i--;
+ for(;!(i&0x80000000);i--){
+ data = buff16[i];
+ fbmisr = (checksum & 2)>>1 ^ (checksum & 4)>>2 ^ (checksum & 16)>>4 ^ (checksum & 0x8000)>>15;
+ checksum = (data ^ ((checksum << 1) | fbmisr));
+ }
+ return checksum;
}
int dsp5680xx_f_SIM_reset(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;
}
-static int dsp5680xx_f_execute_command(struct target * target, uint16_t command, uint32_t address, uint16_t * hfm_ustat, int pmem){
+static int dsp5680xx_f_execute_command(struct target * target, uint16_t command, uint32_t address, uint32_t data, uint16_t * hfm_ustat, int pmem){
int retval;
retval = eonce_load_TX_RX_high_to_r0(target);
err_check_propagate(retval);
err_check_propagate(retval);
retval = eonce_move_value_at_r2_disp(target,0x00,HFM_PROTB); // write to HMF_PROTB, clear protection
err_check_propagate(retval);
+ retval = eonce_move_value_to_y0(target,data);
+ err_check_propagate(retval);
retval = eonce_move_long_to_r3(target,address); // write to the flash block
err_check_propagate(retval);
if (pmem){
return ERROR_OK;
}
-int dsp5680xx_f_erase_check(struct target * target, uint8_t * erased){
+static int dsp5680xx_f_signature(struct target * target, uint32_t address, uint32_t words, uint16_t * signature){
int retval;
uint16_t hfm_ustat;
if (dsp5680xx_target_status(target,NULL,NULL) != TARGET_HALTED){
- retval = dsp5680xx_halt(target);
+ retval = eonce_enter_debug_mode(target,NULL);
err_check_propagate(retval);
}
- // -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- // Check security
- // -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- uint8_t protected;
- retval = dsp5680xx_f_protect_check(target,&protected);
+ retval = dsp5680xx_f_execute_command(target,HFM_CALCULATE_DATA_SIGNATURE,address,words,&hfm_ustat,1);
err_check_propagate(retval);
- if(protected){
- retval = ERROR_TARGET_FAILURE;
- err_check(retval,"Failed to erase, flash is still protected.");
+ if (hfm_ustat&HFM_USTAT_MASK_PVIOL_ACCER){
+ retval = ERROR_TARGET_FAILURE;
+ err_check(retval,"HFM exec error:pviol and/or accer bits set.");
}
- // -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- // Set hfmdiv
- // -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- retval = eonce_set_hfmdiv(target);
- err_check_propagate(retval);
+ retval = dsp5680xx_read_16_single(target, HFM_BASE_ADDR|HFM_DATA, signature, 0);
+ return retval;
+}
+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 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,&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;
*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
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,&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
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
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;
- for(uint32_t i=1; (i<count/2)&&(i<HFM_SIZE_REAL); i++){
- if(--counter==0){
- context.flush = 1;
- counter = counter_reset;
- }
+ uint32_t i;
+ for(i=1; (i<count/2)&&(i<HFM_SIZE_WORDS); i++){
+ if(--counter==0){
+ context.flush = 1;
+ counter = FLUSH_COUNT_FLASH;
+ }
retval = eonce_tx_upper_data(target,buff16[i],&drscan_data);
if(retval!=ERROR_OK){
context.flush = 1;
context.flush = 0;
}
context.flush = 1;
+ // -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+ // Verify flash
+ // -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+ uint16_t signature;
+ uint16_t pc_crc;
+ retval = dsp5680xx_f_signature(target,address,i,&signature);
+ err_check_propagate(retval);
+ pc_crc = perl_crc(buff16,i);
+ if(pc_crc != signature){
+ retval = ERROR_FAIL;
+ err_check(retval,"Flashed data failed CRC check, flash again!");
+ }
return retval;
}
+
+
int dsp5680xx_f_unlock(struct target * target){
int retval;
if(target->tap->enabled){