diff options
author | Rodrigo L. Rosa <rodrigorosa.lg@gmail.com> | 2011-06-10 12:24:27 -0700 |
---|---|---|
committer | Øyvind Harboe <oyvind.harboe@zylin.com> | 2011-06-12 11:18:27 +0200 |
commit | d343941386bfa274cd64f8f384fc51a695f9f626 (patch) | |
tree | ee7e66cf02753070cf8d2dcdf741ceaf9a0939ac /src | |
parent | cbe201fe6bb2f004957ff8174b53c6d4ecd5bae6 (diff) |
doxy & cleanup
Diffstat (limited to 'src')
-rw-r--r-- | src/flash/nor/dsp5680xx_flash.c | 92 | ||||
-rw-r--r-- | src/target/dsp5680xx.c | 768 | ||||
-rw-r--r-- | src/target/dsp5680xx.h | 79 |
3 files changed, 593 insertions, 346 deletions
diff --git a/src/flash/nor/dsp5680xx_flash.c b/src/flash/nor/dsp5680xx_flash.c index b919f564..4ed72066 100644 --- a/src/flash/nor/dsp5680xx_flash.c +++ b/src/flash/nor/dsp5680xx_flash.c @@ -23,6 +23,19 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +/** + * @file dsp5680xx_flash.c + * @author Rodrigo L. Rosa <rodrigorosa.LG@gmail.com> + * @date Thu Jun 9 18:21:58 2011 + * + * @brief This file implements the basic functions to run flashing commands + * from the TCL interface. + * It allows the user to flash the Freescale 5680xx DSP. + * + * + */ + + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -71,6 +84,15 @@ FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command){ return ERROR_OK; } +/** + * A memory mapped register (PROT) holds information regarding sector protection. + * Protection refers to undesired core access. + * The value in this register is loaded from flash upon reset. + * + * @param bank + * + * @return + */ static int dsp5680xx_flash_protect_check(struct flash_bank *bank){ int retval = ERROR_OK; uint16_t protected = 0; @@ -93,6 +115,18 @@ static int dsp5680xx_flash_protect_check(struct flash_bank *bank){ return retval; } +/** + * Protection funcionality is not implemented. + * The current implementation applies/removes security on the chip. + * The chip is effectively secured/unsecured after the first reset following the execution of this function. + * + * @param bank + * @param set Apply or remove security on the chip. + * @param first This parameter is ignored. + * @param last This parameter is ignored. + * + * @return + */ 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; @@ -103,24 +137,16 @@ static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first, return retval; } -/* -static int dsp5680xx_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count){ - LOG_USER("%s not implemented",__FUNCTION__); - return ERROR_OK; -} - -static int dsp5680xx_write_single(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count){ - LOG_USER("%s not implemented",__FUNCTION__); - return ERROR_OK; -} -*/ - -//-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -//-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -// Flash stuff test -//-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -//-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - +/** + * The dsp5680xx use word addressing. The "/2" that appear in the following code are a workaround for the fact that OpenOCD uses byte addressing. + * + * @param bank + * @param buffer Data to write to flash. + * @param offset + * @param count In bytes (2 bytes per address). + * + * @return + */ static int dsp5680xx_flash_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count){ int retval; if((offset + count/2)>bank->size){ @@ -151,19 +177,17 @@ static int dsp5680xx_flash_info(struct flash_bank *bank, char *buf, int buf_size snprintf(buf, buf_size, "\ndsp5680xx flash driver info:\n - Currently only full erase/lock/unlock are implemented. \n - Call with bank==0 and sector 0 to 0.\n - Protect requires arp_init-reset to complete. \n - Before removing protection the master tap must be selected, and arp_init-reset is required to complete unlocking."); return ERROR_OK; } -/* -static int dsp5680xx_set_write_enable(struct target *target, int enable){ - LOG_USER("%s not implemented",__FUNCTION__); - return ERROR_OK; -} - - -static int dsp5680xx_check_flash_completion(struct target* target, unsigned int timeout_ms){ - LOG_USER("%s not implemented",__FUNCTION__); - return ERROR_OK; -} -*/ +/** + * The flash module (FM) on the dsp5680xx supports both individual sector and mass erase of the flash memory. + * If this function is called with @first == @last == 0 or if @first is the first sector (#0) and @last is the last sector then the mass erase command is executed (much faster than erasing each sector individually). + * + * @param bank + * @param first + * @param last + * + * @return + */ 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); @@ -177,6 +201,14 @@ static int dsp5680xx_flash_erase(struct flash_bank * bank, int first, int last){ return retval; } +/** + * The flash module (FM) on the dsp5680xx support a blank check function. + * This function executes the FM's blank check functionality on each and every sector. + * + * @param bank + * + * @return + */ static int dsp5680xx_flash_erase_check(struct flash_bank * bank){ int retval = ERROR_OK; uint8_t erased = 0; diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index f3f25a17..9afda424 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -31,18 +31,6 @@ #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 eonce_instruction_exec(struct target * target, uint8_t instr, uint8_t rw, uint8_t go, uint8_t ex, uint8_t * eonce_status); -static int eonce_load_TX_RX_to_r0(struct target * target); -static int eonce_enter_debug_mode(struct target * target, uint16_t * eonce_status); -static int eonce_read_status_reg(struct target * target, uint16_t * data); -static int eonce_pc_store(struct target * target); -static int eonce_move_value_to_pc(struct target * target, uint32_t value); -static int dsp5680xx_jtag_status(struct target *target, uint8_t * status); -static int dsp5680xx_resume(struct target *target, int current, uint32_t address,int handle_breakpoints, int debug_execution); -static int dsp5680xx_halt(struct target *target); -static int dsp5680xx_write(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t * buffer); - int dsp5680xx_execute_queue(void){ int retval; retval = jtag_execute_queue(); @@ -50,14 +38,6 @@ int dsp5680xx_execute_queue(void){ return retval; } -static int eonce_exit_debug_mode(struct target * target,uint8_t * eonce_status){ - int retval; - retval = eonce_instruction_exec(target,0x1F,0,0,1,eonce_status); - err_check_propagate(retval); - return retval; -} - - static int dsp5680xx_drscan(struct target * target, uint8_t * data_to_shift_into_dr, uint8_t * data_shifted_out_of_dr, int len){ // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // @@ -115,116 +95,12 @@ static int dsp5680xx_irscan(struct target * target, uint32_t * data_to_shift_int //is the casting necessary? jtag_add_plain_ir_scan(ir_len,(uint8_t *)data_to_shift_into_ir,(uint8_t *)data_shifted_out_of_ir, TAP_IDLE); if(context.flush){ - retval = dsp5680xx_execute_queue(); - err_check_propagate(retval); + retval = dsp5680xx_execute_queue(); + err_check_propagate(retval); } 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(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 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){ - context.stored_pc = 0; - 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_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; -} - static int dsp5680xx_jtag_status(struct target *target, uint8_t * status){ uint32_t read_from_ir; uint32_t instr; @@ -237,57 +113,6 @@ static int dsp5680xx_jtag_status(struct target *target, uint8_t * status){ return ERROR_OK; } -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; -} - -static int dsp5680xx_halt(struct target *target){ - int retval; - uint16_t eonce_status; - 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_resume(struct target *target, int current, uint32_t address,int handle_breakpoints, int debug_execution){ - if(target->state == TARGET_RUNNING){ - LOG_USER("Target already running."); - return ERROR_OK; - } - int retval; - uint8_t eonce_status; - if(!current){ - retval = eonce_move_value_to_pc(target,address); - err_check_propagate(retval); - } - - int retry = 20; - while(retry-- > 1){ - retval = eonce_exit_debug_mode(target,&eonce_status ); - err_check_propagate(retval); - if(eonce_status == DSP5680XX_ONCE_OSCR_NORMAL_M) - break; - } - if(retry == 0){ - retval = ERROR_TARGET_FAILURE; - err_check(retval,"Failed to resume..."); - }else{ - target->state = TARGET_RUNNING; - } - LOG_DEBUG("EOnCE status: 0x%02X.",eonce_status); - return ERROR_OK; -} - static int jtag_data_read(struct target * target, uint32_t * data_read, int num_bits){ uint32_t bogus_instr; int retval = dsp5680xx_drscan(target,(uint8_t *) & bogus_instr,(uint8_t *) data_read,num_bits); @@ -314,37 +139,18 @@ static int jtag_data_write(struct target * target, uint32_t instr,int num_bits, #define jtag_data_write24(target,instr,data_read) jtag_data_write(target,instr,24,data_read) #define jtag_data_write32(target,instr,data_read) jtag_data_write(target,instr,32,data_read) -static int eonce_enter_debug_mode(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; - return ERROR_OK; - }else{ - retval = ERROR_TARGET_FAILURE; - err_check(retval,"Failed to set EOnCE module to debug mode."); - } - if(eonce_status!=NULL) - *eonce_status = data_read_from_dr; - return ERROR_OK; -} +/** + * Executes DSP instruction. + * + * @param target + * @param instr Instruction to execute. + * @param rw + * @param go + * @param ex + * @param eonce_status Value read from the EOnCE status register. + * + * @return + */ static int eonce_instruction_exec(struct target * target, uint8_t instr, uint8_t rw, uint8_t go, uint8_t ex,uint8_t * eonce_status){ int retval; @@ -357,15 +163,14 @@ static int eonce_instruction_exec(struct target * target, uint8_t instr, uint8_t return retval; } -/* Executes DSP instruction */ -/* wrappers for parameter conversion between eonce_execute_instruction and eonce_execute_instructionX */ +///wrappers for parameter conversion between eonce_execute_instruction and eonce_execute_instructionX + #define eonce_execute_instruction_1(target,opcode1,opcode2,opcode3) eonce_execute_instruction1(target,opcode1) #define eonce_execute_instruction_2(target,opcode1,opcode2,opcode3) eonce_execute_instruction2(target,opcode1,opcode2) #define eonce_execute_instruction_3(target,opcode1,opcode2,opcode3) eonce_execute_instruction3(target,opcode1,opcode2,opcode3) -/* the macro itself */ #define eonce_execute_instruction(target,words,opcode1,opcode2,opcode3) eonce_execute_instruction_##words(target,opcode1,opcode2,opcode3) -/* Executes one word DSP instruction */ +/// Executes one word DSP instruction static int eonce_execute_instruction1(struct target * target, uint16_t opcode){ int retval; retval = eonce_instruction_exec(target,0x04,0,1,0,NULL); @@ -375,7 +180,7 @@ static int eonce_execute_instruction1(struct target * target, uint16_t opcode){ return retval; } -/* Executes two word DSP instruction */ +/// Executes two word DSP instruction static int eonce_execute_instruction2(struct target * target,uint16_t opcode1, uint16_t opcode2){ int retval; retval = eonce_instruction_exec(target,0x04,0,0,0,NULL); @@ -389,7 +194,7 @@ static int eonce_execute_instruction2(struct target * target,uint16_t opcode1, u return retval; } -/* Executes three word DSP instruction */ +/// Executes three word DSP instruction static int eonce_execute_instruction3(struct target * target, uint16_t opcode1,uint16_t opcode2,uint16_t opcode3){ int retval; retval = eonce_instruction_exec(target,0x04,0,0,0,NULL); @@ -407,15 +212,16 @@ static int eonce_execute_instruction3(struct target * target, uint16_t opcode1,u return retval; } -/* --------------- Real-time data exchange --------------- */ -/* - The EOnCE Transmit (OTX) and Receive (ORX) registers are data memory mapped, each with an upper and lower 16 bit word. - Transmit and receive directions are defined from the core’s perspective. - The core writes to the Transmit register and reads the Receive register, and the host through JTAG writes to the Receive register and reads the Transmit register. - Both registers have a combined data memory mapped OTXRXSR which provides indication when each may be accessed. -ref: eonce_rev.1.0_0208081.pdf@36 +/** + * --------------- Real-time data exchange --------------- + * The EOnCE Transmit (OTX) and Receive (ORX) registers are data memory mapped, each with an upper and lower 16 bit word. + * Transmit and receive directions are defined from the core’s perspective. + * The core writes to the Transmit register and reads the Receive register, and the host through JTAG writes to the Receive register and reads the Transmit register. + * Both registers have a combined data memory mapped OTXRXSR which provides indication when each may be accessed. + *ref: eonce_rev.1.0_0208081.pdf@36 */ +/// writes data into upper ORx register of the target static int eonce_tx_upper_data(struct target * target, uint16_t data, uint32_t * eonce_status_low){ int retval; retval = eonce_instruction_exec(target,DSP5680XX_ONCE_ORX1,0,0,0,NULL); @@ -425,7 +231,7 @@ static int eonce_tx_upper_data(struct target * target, uint16_t data, uint32_t * return retval; } -/* writes data into lower ORx register of the target */ +/// writes data into lower ORx register of the target #define eonce_tx_lower_data(target,data) eonce_instruction_exec(target,DSP5680XX_ONCE_ORX,0,0,0,NULL);\ jtag_data_write16(target,data) @@ -461,119 +267,124 @@ static int eonce_rx_lower_data(struct target * target,uint16_t * data_read) return retval; } -/* -- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- -*/ -/* -- -- -- -- --- -- -- -Core Instructions- -- -- -- --- -- -- -- --- -- -*/ -/* -- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- -*/ -/* move.l #value,r0 */ +/** + * -- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- + * -- -- -- -- --- -- -- -Core Instructions- -- -- -- --- -- -- -- --- -- + * -- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- + */ + +/// move.l #value,r0 #define eonce_move_long_to_r0(target,value) eonce_execute_instruction(target,3,0xe418,value&0xffff,value>>16) -/* move.l #value,n */ +/// move.l #value,n #define eonce_move_long_to_n(target,value) eonce_execute_instruction(target,3,0xe41e,value&0xffff,value>>16) -/* move x:(r0),y0 */ +/// move x:(r0),y0 #define eonce_move_at_r0_to_y0(target) eonce_execute_instruction(target,1,0xF514,0,0) -/* move x:(r0),y1 */ +/// move x:(r0),y1 #define eonce_move_at_r0_to_y1(target) eonce_execute_instruction(target,1,0xF714,0,0) -/* move.l x:(r0),y */ +/// move.l x:(r0),y #define eonce_move_long_at_r0_y(target) eonce_execute_instruction(target,1,0xF734,0,0) -/* move y0,x:(r0) */ +/// move y0,x:(r0) #define eonce_move_y0_at_r0(target) eonce_execute_instruction(target,1,0xd514,0,0) -/* bfclr #value,x:(r0) */ +/// bfclr #value,x:(r0) #define eonce_bfclr_at_r0(target,value) eonce_execute_instruction(target,2,0x8040,value,0) -/* move #value,y0 */ +/// move #value,y0 #define eonce_move_value_to_y0(target,value) eonce_execute_instruction(target,2,0x8745,value,0) -/* move.w y0,x:(r0)+ */ +/// move.w y0,x:(r0)+ #define eonce_move_y0_at_r0_inc(target) eonce_execute_instruction(target,1,0xd500,0,0) -/* move.w y0,p:(r0)+ */ +/// move.w y0,p:(r0)+ #define eonce_move_y0_at_pr0_inc(target) eonce_execute_instruction(target,1,0x8560,0,0) -/* move.w p:(r0)+,y0 */ +/// move.w p:(r0)+,y0 #define eonce_move_at_pr0_inc_to_y0(target) eonce_execute_instruction(target,1,0x8568,0,0) -/* move.w p:(r0)+,y1 */ +/// move.w p:(r0)+,y1 #define eonce_move_at_pr0_inc_to_y1(target) eonce_execute_instruction(target,1,0x8768,0,0) -/* move.l #value,r2 */ +/// move.l #value,r2 #define eonce_move_long_to_r2(target,value) eonce_execute_instruction(target,3,0xe41A,value&0xffff,value>>16) -/* move y0,x:(r2) */ +/// move y0,x:(r2) #define eonce_move_y0_at_r2(target) eonce_execute_instruction(target,1,0xd516,0,0) -/* move.w #<value>,x:(r2) */ +/// move.w #<value>,x:(r2) #define eonce_move_value_at_r2(target,value) eonce_execute_instruction(target,2,0x8642,value,0) -/* move.w #<value>,x:(r0) */ +/// move.w #<value>,x:(r0) #define eonce_move_value_at_r0(target,value) eonce_execute_instruction(target,2,0x8640,value,0) -/* move.w #<value>,x:(R2+<disp>) */ +/// move.w #<value>,x:(R2+<disp>) #define eonce_move_value_at_r2_disp(target,value,disp) eonce_execute_instruction(target,3,0x8646,value,disp) -/* move.w x:(r2),Y0 */ +/// move.w x:(r2),Y0 #define eonce_move_at_r2_to_y0(target) eonce_execute_instruction(target,1,0xF516,0,0) -/* move.w p:(r2)+,y0 */ +/// move.w p:(r2)+,y0 #define eonce_move_at_pr2_inc_to_y0(target) eonce_execute_instruction(target,1,0x856A,0,0) -/* move.l #value,r3 */ +/// move.l #value,r3 #define eonce_move_long_to_r1(target,value) eonce_execute_instruction(target,3,0xE419,value&0xffff,value>>16) -/* move.l #value,r3 */ +/// move.l #value,r3 #define eonce_move_long_to_r3(target,value) eonce_execute_instruction(target,3,0xE41B,value&0xffff,value>>16) -/* move.w y0,p:(r3)+ */ +/// move.w y0,p:(r3)+ #define eonce_move_y0_at_pr3_inc(target) eonce_execute_instruction(target,1,0x8563,0,0) -/* move.w y0,x:(r3) */ +/// move.w y0,x:(r3) #define eonce_move_y0_at_r3(target) eonce_execute_instruction(target,1,0xD503,0,0) -/* move pc,r4 */ +/// move.l #value,r4 +#define eonce_move_long_to_r4(target,value) eonce_execute_instruction(target,3,0xE41C,value&0xffff,value>>16) + +/// move pc,r4 #define eonce_move_pc_to_r4(target) eonce_execute_instruction(target,1,0xE716,0,0) -/* move.l r4,y */ +/// move.l r4,y #define eonce_move_r4_to_y(target) eonce_execute_instruction(target,1,0xe764,0,0) -/* move.w p:(r0)+,y0 */ +/// move.w p:(r0)+,y0 #define eonce_move_at_pr0_inc_to_y0(target) eonce_execute_instruction(target,1,0x8568,0,0) -/* move.w x:(r0)+,y0 */ +/// move.w x:(r0)+,y0 #define eonce_move_at_r0_inc_to_y0(target) eonce_execute_instruction(target,1,0xf500,0,0) -/* move x:(r0),y0 */ +/// move x:(r0),y0 #define eonce_move_at_r0_y0(target) eonce_execute_instruction(target,1,0xF514,0,0) -/* nop */ +/// nop #define eonce_nop(target) eonce_execute_instruction(target,1,0xe700,0,0) -/* move.w x:(R2+<disp>),Y0 */ +/// move.w x:(R2+<disp>),Y0 #define eonce_move_at_r2_disp_to_y0(target,disp) eonce_execute_instruction(target,2,0xF542,disp,0) -/* move.w y1,x:(r2) */ +/// move.w y1,x:(r2) #define eonce_move_y1_at_r2(target) eonce_execute_instruction(target,1,0xd716,0,0) -/* move.w y1,x:(r0) */ +/// move.w y1,x:(r0) #define eonce_move_y1_at_r0(target) eonce_execute_instruction(target,1,0xd714,0,0) -/* move.bp y0,x:(r0)+ */ +/// move.bp y0,x:(r0)+ #define eonce_move_byte_y0_at_r0(target) eonce_execute_instruction(target,1,0xd5a0,0,0) -/* move.w y1,p:(r0)+ */ +/// move.w y1,p:(r0)+ #define eonce_move_y1_at_pr0_inc(target) eonce_execute_instruction(target,1,0x8760,0,0) -/* move.w y1,x:(r0)+ */ +/// move.w y1,x:(r0)+ #define eonce_move_y1_at_r0_inc(target) eonce_execute_instruction(target,1,0xD700,0,0) -/* move.l #value,y */ +/// 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; @@ -598,6 +409,88 @@ static int eonce_load_TX_RX_high_to_r0(struct target * target) 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(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(target,0x1F,0,0,1,eonce_status); + err_check_propagate(retval); + return retval; +} + +/** + * 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; + 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; + return ERROR_OK; + }else{ + retval = ERROR_TARGET_FAILURE; + err_check(retval,"Failed to set EOnCE module to debug mode."); + } + if(eonce_status!=NULL) + *eonce_status = data_read_from_dr; + return ERROR_OK; +} + +/** + * Reads the current value of the program counter and stores it. + * + * @param target + * + * @return + */ static int eonce_pc_store(struct target * target){ uint32_t tmp = 0; int retval; @@ -616,6 +509,155 @@ static int eonce_pc_store(struct target * target){ 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){ + context.stored_pc = 0; + 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; + 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; +} + +static int dsp5680xx_resume(struct target *target, int current, uint32_t address,int handle_breakpoints, int debug_execution){ + if(target->state == TARGET_RUNNING){ + LOG_USER("Target already running."); + return ERROR_OK; + } + int retval; + uint8_t eonce_status; + if(!current){ + retval = eonce_move_value_to_pc(target,address); + err_check_propagate(retval); + } + + int retry = 20; + while(retry-- > 1){ + retval = eonce_exit_debug_mode(target,&eonce_status ); + err_check_propagate(retval); + if(eonce_status == DSP5680XX_ONCE_OSCR_NORMAL_M) + break; + } + if(retry == 0){ + retval = ERROR_TARGET_FAILURE; + err_check(retval,"Failed to resume..."); + }else{ + target->state = TARGET_RUNNING; + } + LOG_DEBUG("EOnCE status: 0x%02X.",eonce_status); + return ERROR_OK; +} + + + + + + +/** + * The value of @address determines if it corresponds to P: (program) or X: (data) memory. If the address is over 0x200000 then it is considered X: memory, and @pmem = 0. + * The special case of 0xFFXXXX is not modified, since it allows to read out the memory mapped EOnCE registers. + * + * @param address + * @param pmem + * + * @return + */ static int dsp5680xx_convert_address(uint32_t * address, int * pmem){ // Distinguish data memory (x:) from program memory (p:) by the address. // Addresses over S_FILE_DATA_OFFSET are considered (x:) memory. @@ -679,7 +721,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 = ((tmp<<16) | (*data_read));//This enables opencd crc to succeed, even though it's very slow. + *data_read = ((tmp<<16) | (*data_read));//This enables OpenOCD crc to succeed (when it should) return retval; } @@ -734,7 +776,6 @@ static int dsp5680xx_read(struct target * target, uint32_t address, unsigned siz return retval; } -//TODO doxy static int dsp5680xx_write_16_single(struct target *target, uint32_t address, uint16_t data, uint8_t w_pmem){ int retval = 0; retval = eonce_move_long_to_r0(target,address); @@ -751,7 +792,6 @@ static int dsp5680xx_write_16_single(struct target *target, uint32_t address, ui return retval; } -//TODO doxy static int dsp5680xx_write_32_single(struct target *target, uint32_t address, uint32_t data, int w_pmem){ int retval = 0; retval = eonce_move_long_to_r0(target,address); @@ -864,7 +904,18 @@ static int dsp5680xx_write_32(struct target * target, uint32_t address, uint32_t return retval; } -//TODO doxy +/** + * Writes @buffer to memory. + * The parameter @address determines whether @buffer should be written to P: (program) memory or X: (data) memory. + * + * @param target + * @param address + * @param size Bytes (1), Half words (2), Words (4). + * @param count In bytes. + * @param buffer + * + * @return + */ 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 0x12345678 as 0x5678 0x0012 if(target->state != TARGET_HALTED){ @@ -888,7 +939,7 @@ static int dsp5680xx_write(struct target *target, uint32_t address, uint32_t siz break; default: retval = ERROR_TARGET_DATA_ABORT; - err_check(retval,"Invalid data size.") + err_check(retval,"Invalid data size."); break; } return retval; @@ -907,21 +958,49 @@ static int dsp5680xx_write_buffer(struct target * target, uint32_t address, uint return dsp5680xx_write(target, address, 1, size, buffer); } +/** + * This function is called by verify_image, it is used to read data from memory. + * + * @param target + * @param address Word addressing. + * @param size In bytes. + * @param buffer + * + * @return + */ static int dsp5680xx_read_buffer(struct target * target, uint32_t address, uint32_t size, uint8_t * buffer){ if(target->state != TARGET_HALTED){ LOG_USER("Target must be halted."); return ERROR_OK; } - // 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); } +/** + * This function is not implemented. + * It returns an error in order to get OpenOCD to do read out the data and calculate the CRC, or try a binary comparison. + * + * @param target + * @param address Start address of the image. + * @param size In bytes. + * @param checksum + * + * @return + */ static int dsp5680xx_checksum_memory(struct target * target, uint32_t address, uint32_t size, uint32_t * checksum){ - return ERROR_FAIL;// This will make OpenOCD do the read out the data and verify it. + return ERROR_FAIL; } |