+ 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;
+}
+
+static 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, DSP5680XX_ERROR_JTAG_TAP_FIND_MASTER, "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, DSP5680XX_ERROR_JTAG_TAP_FIND_CORE, "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;
+}
+
+/**
+ * Puts the core into debug mode, enabling the EOnCE module.
+ * This will not always work, eonce_enter_debug_mode executes much
+ * more complicated routine, which is guaranteed to work, but requires
+ * a reset. This will complicate comm with the flash module, since
+ * after a reset clock divisors must be set again.
+ * This implementation works most of the time, and is not accesible to the
+ * user.
+ *
+ * @param target
+ * @param eonce_status Data read from the EOnCE status register.
+ *
+ * @return
+ */
+static int eonce_enter_debug_mode_without_reset(struct target * target, uint16_t * eonce_status){
+ int retval;
+ uint32_t instr = JTAG_INSTR_DEBUG_REQUEST;
+ uint32_t ir_out;//not used, just to make jtag happy.
+ // Debug request #1
+ retval = dsp5680xx_irscan(target,& instr,& ir_out,DSP5680XX_JTAG_CORE_TAP_IRLEN);
+ err_check_propagate(retval);
+
+ // Enable EOnCE module
+ 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);
+ retval = dsp5680xx_irscan(target, & instr, & ir_out,DSP5680XX_JTAG_CORE_TAP_IRLEN);
+ err_check_propagate(retval);
+ // 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{
+ retval = ERROR_TARGET_FAILURE;
+ /**
+ * No error msg here, since there is still hope with full halting sequence
+ */
+ err_check_propagate(retval);
+ }
+ if(eonce_status!=NULL)
+ *eonce_status = data_read_from_dr;
+ 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;
+
+ // First try the easy way
+ retval = eonce_enter_debug_mode_without_reset(target,eonce_status);
+ if(retval == ERROR_OK)
+ return retval;
+
+ 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, DSP5680XX_ERROR_JTAG_TAP_FIND_MASTER, "Failed to get master tap.");
+ }
+ tap_cpu = jtag_tap_by_string("dsp568013.cpu");
+ if(tap_cpu == NULL){
+ retval = ERROR_FAIL;
+ err_check(retval, DSP5680XX_ERROR_JTAG_TAP_FIND_CORE, "Failed to get master tap.");
+ }
+
+ // Enable master tap
+ tap_chp->enabled = true;
+ tap_cpu->enabled = false;
+
+ instr = MASTER_TAP_CMD_IDCODE;
+ retval = dsp5680xx_irscan(target, & instr, & ir_out,DSP5680XX_JTAG_MASTER_TAP_IRLEN);
+ err_check_propagate(retval);
+ jtag_add_sleep(TIME_DIV_FREESCALE*100*1000);
+
+ // Enable EOnCE module
+ jtag_add_reset(0,1);
+ jtag_add_sleep(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
+ tap_chp->enabled = true;
+ 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);
+ err_check_propagate(retval);
+ instr_16 = 0x20;
+ retval = dsp5680xx_drscan(target,(uint8_t *) & instr_16,(uint8_t *) & read_16,8);
+ err_check_propagate(retval);
+ jtag_add_sleep(TIME_DIV_FREESCALE*100*1000);
+ jtag_add_reset(0,0);
+ jtag_add_sleep(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{
+ const char *msg = "Failed to set EOnCE module to debug mode";
+ retval = ERROR_TARGET_FAILURE;
+ err_check(retval, DSP5680XX_ERROR_ENTER_DEBUG_MODE, msg);
+ }
+ 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;
+}
+
+static int dsp5680xx_init_target(struct command_context *cmd_ctx, struct target *target){
+ dsp5680xx_context.stored_pc = 0;
+ dsp5680xx_context.flush = 1;
+ LOG_DEBUG("target initiated!");
+ //TODO core tap must be enabled before running these commands, currently this is done in the .cfg tcl script.
+ return ERROR_OK;
+}
+
+static int dsp5680xx_arch_state(struct target *target){
+ LOG_USER("%s not implemented yet.",__FUNCTION__);
+ return ERROR_OK;
+}
+
+int dsp5680xx_target_status(struct target * target, uint8_t * jtag_st, uint16_t * eonce_st){
+ return target->state;
+}
+
+static int dsp5680xx_assert_reset(struct target *target){
+ target->state = TARGET_RESET;
+ return ERROR_OK;
+}
+
+static int dsp5680xx_deassert_reset(struct target *target){
+ target->state = TARGET_RUNNING;
+ return ERROR_OK;
+}
+
+static int dsp5680xx_halt(struct target *target){
+ int retval;
+ uint16_t eonce_status = 0xbeef;
+ if(target->state == TARGET_HALTED){
+ LOG_USER("Target already halted.");
+ return ERROR_OK;
+ }
+ retval = eonce_enter_debug_mode(target,&eonce_status);
+ err_check_propagate(retval);
+ retval = eonce_pc_store(target);
+ err_check_propagate(retval);
+ //TODO is it useful to store the pc?
+ return retval;
+}
+
+static int dsp5680xx_poll(struct target *target){
+ int retval;
+ uint8_t jtag_status;
+ uint8_t eonce_status;
+ uint16_t read_tmp;
+ retval = dsp5680xx_jtag_status(target,&jtag_status);
+ err_check_propagate(retval);
+ if (jtag_status == JTAG_STATUS_DEBUG)
+ if (target->state != TARGET_HALTED){
+ retval = eonce_enter_debug_mode(target,&read_tmp);
+ err_check_propagate(retval);
+ eonce_status = (uint8_t) read_tmp;
+ if((eonce_status&EONCE_STAT_MASK) != DSP5680XX_ONCE_OSCR_DEBUG_M){
+ LOG_WARNING("%s: Failed to put EOnCE in debug mode. Is flash locked?...",__FUNCTION__);
+ return ERROR_TARGET_FAILURE;
+ }else{
+ target->state = TARGET_HALTED;
+ return ERROR_OK;
+ }
+ }
+ if (jtag_status == JTAG_STATUS_NORMAL){
+ if(target->state == TARGET_RESET){
+ retval = dsp5680xx_halt(target);
+ err_check_propagate(retval);
+ retval = eonce_exit_debug_mode(target,&eonce_status);
+ err_check_propagate(retval);
+ if((eonce_status&EONCE_STAT_MASK) != DSP5680XX_ONCE_OSCR_NORMAL_M){
+ LOG_WARNING("%s: JTAG running, but cannot make EOnCE run. Try resetting...",__FUNCTION__);
+ return ERROR_TARGET_FAILURE;
+ }else{
+ target->state = TARGET_RUNNING;
+ return ERROR_OK;
+ }
+ }
+ if(target->state != TARGET_RUNNING){
+ retval = eonce_read_status_reg(target,&read_tmp);
+ err_check_propagate(retval);
+ eonce_status = (uint8_t) read_tmp;
+ if((eonce_status&EONCE_STAT_MASK) != DSP5680XX_ONCE_OSCR_NORMAL_M){
+ LOG_WARNING("Inconsistent target status. Restart!");
+ return ERROR_TARGET_FAILURE;
+ }
+ }
+ target->state = TARGET_RUNNING;
+ return ERROR_OK;
+ }
+ if(jtag_status == JTAG_STATUS_DEAD){
+ LOG_ERROR("%s: Cannot communicate with JTAG. Check connection...",__FUNCTION__);
+ target->state = TARGET_UNKNOWN;
+ return ERROR_TARGET_FAILURE;
+ };
+ if (target->state == TARGET_UNKNOWN){
+ LOG_ERROR("%s: Target status invalid - communication failure",__FUNCTION__);
+ return ERROR_TARGET_FAILURE;
+ };
+ return ERROR_OK;