+/// move.w y1,p:(r0)+
+#define core_move_y1_at_pr0_inc(target) dsp5680xx_exe_generic(target,1,0x8760,0,0)
+
+/// move.w y1,x:(r0)+
+#define core_move_y1_at_r0_inc(target) dsp5680xx_exe_generic(target,1,0xD700,0,0)
+
+/// move.l #value,y
+#define core_move_long_to_y(target,value) dsp5680xx_exe_generic(target,3,0xe417,value&0xffff,value>>16)
+
+static int core_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;
+ };
+ int retval;
+ retval = dsp5680xx_exe_generic(target,3,0xE71E,value&0xffff,value>>16);
+ err_check_propagate(retval);
+ return retval;
+}
+
+static int eonce_load_TX_RX_to_r0(struct target * target)
+{
+ int retval;
+ retval = core_move_long_to_r0(target,((MC568013_EONCE_TX_RX_ADDR)+(MC568013_EONCE_OBASE_ADDR<<16)));
+ return retval;
+}
+
+static int core_load_TX_RX_high_addr_to_r0(struct target * target)
+{
+ int retval = 0;
+ retval = core_move_long_to_r0(target,((MC568013_EONCE_TX1_RX1_HIGH_ADDR)+(MC568013_EONCE_OBASE_ADDR<<16)));
+ return retval;
+}
+
+static int dsp5680xx_read_core_reg(struct target * target, uint8_t reg_addr, uint16_t * data_read)
+{
+ //TODO implement a general version of this which matches what openocd uses.
+ int retval;
+ uint32_t dummy_data_to_shift_into_dr;
+ retval = eonce_instruction_exec_single(target,reg_addr,1,0,0,NULL);
+ err_check_propagate(retval);
+ retval = dsp5680xx_drscan(target,(uint8_t *)& dummy_data_to_shift_into_dr,(uint8_t *) data_read, 8);
+ err_check_propagate(retval);
+ LOG_DEBUG("Reg. data: 0x%02X.",*data_read);
+ return retval;
+}
+
+static int eonce_read_status_reg(struct target * target, uint16_t * data){
+ int retval;
+ retval = dsp5680xx_read_core_reg(target,DSP5680XX_ONCE_OSR,data);
+ err_check_propagate(retval);
+ return retval;
+}
+
+/**
+ * Takes the core out of debug mode.
+ *
+ * @param target
+ * @param eonce_status Data read from the EOnCE status register.
+ *
+ * @return
+ */
+static int eonce_exit_debug_mode(struct target * target,uint8_t * eonce_status){
+ int retval;
+ retval = eonce_instruction_exec_single(target,0x1F,0,0,1,eonce_status);
+ err_check_propagate(retval);
+ return retval;
+}
+
+int switch_tap(struct target * target, struct jtag_tap * master_tap,struct jtag_tap * core_tap){
+ int retval = ERROR_OK;
+ uint32_t instr;
+ uint32_t ir_out;//not used, just to make jtag happy.
+ if(master_tap == NULL){
+ master_tap = jtag_tap_by_string("dsp568013.chp");
+ if(master_tap == NULL){
+ retval = ERROR_FAIL;
+ err_check(retval,"Failed to get master tap.");
+ }
+ }
+ if(core_tap == NULL){
+ core_tap = jtag_tap_by_string("dsp568013.cpu");
+ if(core_tap == NULL){
+ retval = ERROR_FAIL;
+ err_check(retval,"Failed to get core tap.");
+ }
+ }
+
+ if(!(((int)master_tap->enabled) ^ ((int)core_tap->enabled))){
+ LOG_WARNING("Wrong tap enabled/disabled status:\nMaster tap:%d\nCore Tap:%d\nOnly one tap should be enabled at a given time.\n",(int)master_tap->enabled,(int)core_tap->enabled);
+ }
+
+ if(master_tap->enabled){
+ instr = 0x5;
+ retval = dsp5680xx_irscan(target, & instr, & ir_out,DSP5680XX_JTAG_MASTER_TAP_IRLEN);
+ err_check_propagate(retval);
+ instr = 0x2;
+ retval = dsp5680xx_drscan(target,(uint8_t *) & instr,(uint8_t *) & ir_out,4);
+ err_check_propagate(retval);
+ core_tap->enabled = true;
+ master_tap->enabled = false;
+ }else{
+ instr = 0x08;
+ retval = dsp5680xx_irscan(target, & instr, & ir_out,DSP5680XX_JTAG_CORE_TAP_IRLEN);
+ err_check_propagate(retval);
+ instr = 0x1;
+ retval = dsp5680xx_drscan(target,(uint8_t *) & instr,(uint8_t *) & ir_out,4);
+ err_check_propagate(retval);
+ core_tap->enabled = false;
+ master_tap->enabled = true;
+ }
+ return retval;
+}
+
+#define TIME_DIV_FREESCALE 0.3
+/**
+ * Puts the core into debug mode, enabling the EOnCE module.
+ *
+ * @param target
+ * @param eonce_status Data read from the EOnCE status register.
+ *
+ * @return
+ */
+static int eonce_enter_debug_mode(struct target * target, uint16_t * eonce_status){
+ int retval = ERROR_OK;
+ uint32_t instr = JTAG_INSTR_DEBUG_REQUEST;
+ uint32_t ir_out;//not used, just to make jtag happy.
+ uint16_t instr_16;
+ uint16_t read_16;
+
+ struct jtag_tap * tap_chp;
+ struct jtag_tap * tap_cpu;
+ tap_chp = jtag_tap_by_string("dsp568013.chp");
+ if(tap_chp == NULL){
+ retval = ERROR_FAIL;
+ err_check(retval,"Failed to get master tap.");
+ }
+ tap_cpu = jtag_tap_by_string("dsp568013.cpu");
+ if(tap_cpu == NULL){
+ retval = ERROR_FAIL;
+ err_check(retval,"Failed to get master tap.");
+ }
+
+ tap_chp->enabled = false;
+ retval = switch_tap(target,tap_chp,tap_cpu);
+ err_check_propagate(retval);
+
+ instr = MASTER_TAP_CMD_IDCODE;
+ retval = dsp5680xx_irscan(target, & instr, & ir_out,DSP5680XX_JTAG_MASTER_TAP_IRLEN);
+ err_check_propagate(retval);
+ usleep(TIME_DIV_FREESCALE*100*1000);
+
+ // Enable EOnCE module
+ jtag_add_reset(0,1);
+ usleep(TIME_DIV_FREESCALE*200*1000);
+ instr = 0x0606ffff;// This was selected experimentally.
+ retval = dsp5680xx_drscan(target,(uint8_t *) & instr,(uint8_t *) & ir_out,32);
+ err_check_propagate(retval);
+ // ir_out now hold tap idcode
+
+ // Enable core tap
+ retval = switch_tap(target,tap_chp,tap_cpu);
+ err_check_propagate(retval);
+
+ instr = JTAG_INSTR_ENABLE_ONCE;
+ //Two rounds of jtag 0x6 (enable eonce) to enable EOnCE.
+ retval = dsp5680xx_irscan(target, & instr, & ir_out,DSP5680XX_JTAG_CORE_TAP_IRLEN);
+ err_check_propagate(retval);
+ instr = JTAG_INSTR_DEBUG_REQUEST;
+ retval = dsp5680xx_irscan(target, & instr, & ir_out,DSP5680XX_JTAG_CORE_TAP_IRLEN);
+ err_check_propagate(retval);
+ instr_16 = 0x1;
+ retval = dsp5680xx_drscan(target,(uint8_t *) & instr_16,(uint8_t *) & read_16,8);
+ instr_16 = 0x20;
+ retval = dsp5680xx_drscan(target,(uint8_t *) & instr_16,(uint8_t *) & read_16,8);
+ usleep(TIME_DIV_FREESCALE*100*1000);
+ jtag_add_reset(0,0);
+ usleep(TIME_DIV_FREESCALE*300*1000);
+
+ instr = JTAG_INSTR_ENABLE_ONCE;
+ //Two rounds of jtag 0x6 (enable eonce) to enable EOnCE.
+ for(int i = 0; i<3; i++){
+ retval = dsp5680xx_irscan(target, & instr, & ir_out,DSP5680XX_JTAG_CORE_TAP_IRLEN);
+ err_check_propagate(retval);
+ }
+
+ for(int i = 0; i<3; i++){
+ instr_16 = 0x86;
+ dsp5680xx_drscan(target,(uint8_t *) & instr_16,(uint8_t *) & read_16,16);
+ instr_16 = 0xff;
+ dsp5680xx_drscan(target,(uint8_t *) & instr_16,(uint8_t *) & read_16,16);
+ }
+
+ // Verify that debug mode is enabled
+ uint16_t data_read_from_dr;
+ retval = eonce_read_status_reg(target,&data_read_from_dr);
+ err_check_propagate(retval);
+ if((data_read_from_dr&0x30) == 0x30){
+ LOG_DEBUG("EOnCE successfully entered debug mode.");
+ target->state = TARGET_HALTED;
+ retval = ERROR_OK;
+ }else{
+ LOG_DEBUG("Failed to set EOnCE module to debug mode.");
+ retval = ERROR_TARGET_FAILURE;
+ }
+ if(eonce_status!=NULL)
+ *eonce_status = data_read_from_dr;
+ return retval;
+}
+
+/**
+ * Reads the current value of the program counter and stores it.
+ *
+ * @param target
+ *
+ * @return
+ */
+static int eonce_pc_store(struct target * target){
+ uint8_t tmp[2];
+ int retval;
+ retval = core_move_pc_to_r4(target);
+ err_check_propagate(retval);
+ retval = core_move_r4_to_y(target);
+ err_check_propagate(retval);
+ retval = eonce_load_TX_RX_to_r0(target);
+ err_check_propagate(retval);
+ retval = core_move_y0_at_r0(target);
+ err_check_propagate(retval);
+ retval = core_rx_lower_data(target,tmp);
+ err_check_propagate(retval);
+ LOG_USER("PC value: 0x%X%X\n",tmp[1],tmp[0]);
+ dsp5680xx_context.stored_pc = (tmp[0]|(tmp[1]<<8));
+ return ERROR_OK;
+}
+
+static int dsp5680xx_target_create(struct target *target, Jim_Interp * interp){
+ struct dsp5680xx_common *dsp5680xx = calloc(1, sizeof(struct dsp5680xx_common));
+ target->arch_info = dsp5680xx;
+ return ERROR_OK;
+}