From b05771fb2628014e922e08b24d2e3a08dd65ea34 Mon Sep 17 00:00:00 2001
From: Rodrigo L. Rosa <rodrigorosa.lg@gmail.com>
Date: Wed, 1 Jun 2011 17:07:44 -0700
Subject: [PATCH] verification for flash

---
 src/target/dsp5680xx.c |  112 +++++++++++++++++++++++++++++++++---------------
 src/target/dsp5680xx.h |    4 ++
 2 files changed, 81 insertions(+), 35 deletions(-)

diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c
index f2f2dba..e889ab3 100644
--- a/src/target/dsp5680xx.c
+++ b/src/target/dsp5680xx.c
@@ -28,7 +28,7 @@
 #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.
@@ -158,16 +158,11 @@ int dsp5680xx_target_status(struct target * target, uint8_t * jtag_st, uint16_t
 }
 
 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;
 }
@@ -179,7 +174,6 @@ static int dsp5680xx_poll(struct target *target){
   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);
@@ -606,8 +600,7 @@ static int eonce_rx_lower_data(struct target * target,uint16_t * data_read)
 /* move.l #value,y */
 #define eonce_move_long_to_y(target,value) eonce_execute_instruction(target,3,0xe417,value&0xffff,value>>16)
 
-static int eonce_move_value_to_pc(struct target * target, uint32_t value)
-{
+static int eonce_move_value_to_pc(struct target * target, uint32_t value){
   if (!(target->state == TARGET_HALTED)){
     LOG_ERROR("Target must be halted to move PC. Target state = %d.",target->state);
     return ERROR_TARGET_NOT_HALTED;
@@ -620,16 +613,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)
 {
-  //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)));
+  err_check_propagate(retval);
+  retval = eonce_move_long_to_r0(target,((MC568013_EONCE_TX_RX_ADDR)+(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);
@@ -723,7 +715,7 @@ static int dsp5680xx_read_32_single(struct target * target, uint32_t address, ui
   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;
 }
 
@@ -811,22 +803,19 @@ 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_reset = FLUSH_COUNT_WRITE;
-  int counter = counter_reset;
-
+  int counter = FLUSH_COUNT_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_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;
 
@@ -904,7 +893,7 @@ static int dsp5680xx_write_32(struct target * target, uint32_t address, uint32_t
 
 //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;
@@ -983,7 +972,28 @@ static int dsp5680xx_read_buffer(struct target * target, uint32_t address, uint3
 }
 
 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
+ //TODO implement.
+  //This will make openocd do the work, but it will fail because of the word/byte addressing issues.
+  return ERROR_FAIL;
+}
+
+// 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){
@@ -1035,7 +1045,7 @@ int dsp5680xx_f_protect_check(struct target * target, uint8_t * protected) {
   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);
@@ -1067,6 +1077,8 @@ static int dsp5680xx_f_execute_command(struct target * target, uint16_t command,
   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){
@@ -1135,6 +1147,23 @@ static int eonce_set_hfmdiv(struct target * target){
   return ERROR_OK;
 }
 
+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 = eonce_enter_debug_mode(target,NULL);
+    err_check_propagate(retval);
+  }
+  retval = dsp5680xx_f_execute_command(target,HFM_CALCULATE_DATA_SIGNATURE,address,words,&hfm_ustat,1);
+  err_check_propagate(retval);
+  if (hfm_ustat&HFM_USTAT_MASK_PVIOL_ACCER){
+    retval = ERROR_TARGET_FAILURE;
+    err_check(retval,"HFM exec error:pviol and/or accer bits set.");
+  }
+  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){
   int retval;
   uint16_t hfm_ustat;
@@ -1160,7 +1189,7 @@ int dsp5680xx_f_erase_check(struct target * target, uint8_t * erased){
 
   // 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+0*HFM_SECTOR_SIZE,0,&hfm_ustat,1); // blank check
   err_check_propagate(retval);
   if (hfm_ustat&HFM_USTAT_MASK_PVIOL_ACCER){
 	retval = ERROR_TARGET_FAILURE;
@@ -1214,7 +1243,7 @@ int dsp5680xx_f_erase(struct target * target, int first, int last){
     // 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);
+	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;
@@ -1277,8 +1306,8 @@ int dsp5680xx_f_wr(struct target * target, uint8_t *buffer, uint32_t address, ui
   int retval = ERROR_OK;
   uint16_t* buff16 = (uint16_t *) buffer;
   if (dsp5680xx_target_status(target,NULL,NULL) != TARGET_HALTED){
-    retval = dsp5680xx_halt(target);
-	err_check_propagate(retval);
+    retval = eonce_enter_debug_mode(target,NULL);
+    err_check_propagate(retval);
   }
   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   // Check if flash is erased
@@ -1342,11 +1371,12 @@ int dsp5680xx_f_wr(struct target * target, uint8_t *buffer, uint32_t address, ui
   int counter_reset = FLUSH_COUNT_FLASH;
   int counter = counter_reset;
   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_REAL); i++){
+    if(--counter==0){
+      context.flush = 1;
+      counter = counter_reset;
+    }
     retval = eonce_tx_upper_data(target,buff16[i],&drscan_data);
 	if(retval!=ERROR_OK){
 	  context.flush = 1;
@@ -1355,6 +1385,18 @@ int dsp5680xx_f_wr(struct target * target, uint8_t *buffer, uint32_t address, ui
 	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;
 }
 
diff --git a/src/target/dsp5680xx.h b/src/target/dsp5680xx.h
index 9f66ee7..2057844 100644
--- a/src/target/dsp5680xx.h
+++ b/src/target/dsp5680xx.h
@@ -26,6 +26,7 @@
 #include <jtag/jtag.h>
 
 #define S_FILE_DATA_OFFSET 0x200000
+#define EONCE_MEM_MAP_OFFSET 0xFF0000
 
 //----------------------------------------------------------------
 // JTAG
@@ -124,6 +125,9 @@
 #define DSP5680XX_ONCE_OPABDR   0x13 /* OnCE Program Address Register—Decode cycle (OPABDR) */
 //----------------------------------------------------------------
 
+#define WORKSPACE_DRAM_ADDR 0x0000
+#define WORKSPACE_PRAM_ADDR 0x8200
+
 #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.
 //----------------------------------------------------------------
-- 
1.7.0.4

