//! Resynchronizes communication with the target in case of noise on the CLK line, etc. //! //! @return \ref BDM_RC_OK => success \n //! \ref BDM_RC_NO_CONNECTION => no connection with target //! U8 bdmcf_resync(void) { U8 bitCount; U16 data; (void)bdmcf_tx_msg(_BDMCF_CMD_NOP); // Send in 3 NOPs to clear any error (void)bdmcf_tx_msg(_BDMCF_CMD_NOP); (void)bdmcf_rx_msg(&data); if ((data&3)==0) { // The last NOP did not return the expected value (at least one of the two bits should be 1) return(BDM_RC_NO_CONNECTION); } for (bitCount=20; bitCount>0; bitCount--) { // Now start sending in another NOP and watch the result if (bdmcf_txrx_start()==0) { break; // The first 0 is the status bit } } if (bitCount==0) { // No status bit found in 20 bits return(BDM_RC_NO_CONNECTION); } // Transmitted & received the status bit, finish the NOP bdmcf_tx16(_BDMCF_CMD_NOP); return(BDM_RC_OK); }
//! Resynchronizes communication with the target in case of noise on the CLK line, etc. //! //! @return \ref BDM_RC_OK => success \n //! \ref BDM_RC_NO_CONNECTION => no connection with target //! U8 bdmcf_resync(void) { U8 bitCount; U16 data; U8 status; (void)bdmcf_tx_msg(_BDMCF_CMD_NOP); // Send in 3 NOPs to clear any error (void)bdmcf_tx_msg(_BDMCF_CMD_NOP); status = bdmcf_rx_msg(&data); if (status == 1) { // Check for cases that are unlikely to be chance on loss of sync // and likely to confuse the sync which looks for a single zero bit switch (data) { case BDMCF_RES_BUS_ERROR : // 1,00000000,00000001 return BDM_RC_CF_BUS_ERROR; case BDMCF_RES_NOT_READY : // 1,00000000,00000000 return BDM_RC_CF_NOT_READY; default : // Fall through break; } } for (bitCount=20; bitCount>0; bitCount--) { // Now start sending in another NOP and watch the result if (bdmcf_txrx_start()==0) { break; // The first 0 is the status bit } } if (bitCount==0) { // No status bit found in 20 bits return(BDM_RC_NO_CONNECTION); } // Transmitted & received the status bit, finish the NOP bdmcf_tx16(_BDMCF_CMD_NOP); return(BDM_RC_OK); }
/* returns number of bytes left in the buffer (at position command_buffer+0) to be sent back as response */ unsigned char command_exec(void) { led_state = LED_BLINK; /* blink the LED to indicate a command */ if (command_buffer[1]==CMD_GET_LAST_STATUS) { /* need to process this special command before status of the last command is lost */ return(1); } command_buffer[0] = command_buffer[1]; /* assume the command will execute OK */ switch (command_buffer[1]) { /* commands which execute the same way irrespective of selected target type */ case CMD_GET_VER: /* get HW & SW version */ *((unsigned int *)(command_buffer+1)) = VERSION; return(3); /* return cmd + 2 bytes of version */ case CMD_SET_TARGET: /* set target type */ cable_status.target_type = command_buffer[2]; if (cable_status.target_type==CF_BDM) { bdmcf_init(); /* initialise the BDM interface */ bdmcf_resync(); /* synchronize with the target */ return(1); } if (cable_status.target_type==JTAG) { jtag_init(); /* initialise JTAG */ return(1); } break; /* unknown target type */ case CMD_SET_BOOT: /* request bootloader action on next power-up */ if ((command_buffer[2]=='B')&&(command_buffer[3]=='O')&&(command_buffer[4]=='O')&&(command_buffer[5]=='T')) { force_bootloader(); /* program the flash */ return(1); } break; case CMD_RESET: /* reset; one 8-bit parameter: ==0 reset to BDM mode, !=0 reset to normal mode */ bdmcf_reset(command_buffer[2]); return(1); case CMD_GET_STATUS: /* returns 16-bit status of the cable; bit0 - target reset detected, bit1 - current state of the RSTO pin */ command_buffer[1]=0; /* the PCB has a pull-down on the input, so only trust that RSTO is low if an edge was detected */ command_buffer[2]=0; /* cannot put a pull-up on the pin as the single layer PCB is too tight to allow it */ if (cable_status.reset==RESET_DETECTED) { command_buffer[2]|=RESET_DETECTED_MASK; /* reset detected */ cable_status.reset=NO_RESET_ACTIVITY; /* clear the flag */ } #ifdef INVERT if (RSTO_IN==0) command_buffer[2]|=RSTO_STATE_MASK; /* the RSTO pin is currently high */ #else if (RSTO_IN==1) command_buffer[2]|=RSTO_STATE_MASK; /* the RSTO pin is currently high */ #endif return(3); #ifdef STACK_SIZE_EVALUATION case CMD_GET_STACK_SIZE: /* parameters: none, returns 16-bit stack size required by the application so far */ { unsigned char *ptr; ptr = (unsigned char *)__SEG_START_SSTACK; while ((*ptr)==0x55) ptr++; *((unsigned int *)(command_buffer+1)) = (unsigned char *)__SEG_END_SSTACK - ptr; } return(2); #endif default: if (cable_status.target_type==CF_BDM) { /* commands which execute depending on the selected target type */ switch (command_buffer[1]) { case CMD_HALT: /* stop execution of user code by asserting the BKPT line; no parameters */ bdmcf_halt(); return(1); case CMD_GO: /* start code execution from current PC address; no parameters */ bdmcf_tx_msg(BDMCF_CMD_RDMREG); /* get CSR */ if (bdmcf_rx(2,command_buffer+12)) break; /* CSR is received into command_data+12,+13,+14,+15 */ *(command_buffer+15)&=~0x10; /* clear the SSM bit */ *((unsigned int *)(command_buffer+10))=BDMCF_CMD_WDMREG; bdmcf_tx(3,command_buffer+10); /* write the CSR back */ if (bdmcf_complete_chk(BDMCF_CMD_GO)) break; /* GO */ #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); case CMD_STEP: /* step over a single instruction; no parameters */ bdmcf_tx_msg(BDMCF_CMD_RDMREG); /* get CSR */ if (bdmcf_rx(2,command_buffer+12)) break; /* CSR is received into command_data+12,+13,+14,+15 */ *(command_buffer+15)|=0x10; /* set the SSM bit - Single Step Mode */ *((unsigned int *)(command_buffer+10))=BDMCF_CMD_WDMREG; bdmcf_tx(3,command_buffer+10); /* write the CSR back */ if (bdmcf_complete_chk(BDMCF_CMD_GO)) break; /* GO */ #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); case CMD_READ_CREG: /* read control register; parameter 16-bit register address, returns 32-bit control register contents */ bdmcf_tx_msg(BDMCF_CMD_RCREG); /* send the command */ bdmcf_tx_msg(0); /* and the register address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); if (bdmcf_rx(2,command_buffer+1)) break; /* the 4 bytes of the register contents are received into command_buffer+1,+2,+3,+4 */ return(5); case CMD_WRITE_CREG: /* write control register; parameter 16-bit register address & the 32-bit control register contents to be written */ bdmcf_tx_msg(BDMCF_CMD_WCREG); /* send the command */ bdmcf_tx_msg(0); /* the register address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); /* and the register value */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+6))); #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); case CMD_READ_DREG: /* read debug register; parameter 8-bit register number to read, returns 32-bit debug module register contents */ bdmcf_tx_msg(BDMCF_CMD_RDMREG+command_buffer[2]); /* send the command */ if (bdmcf_rx(2,command_buffer+1)) break; /* the 4 bytes of the register contents are received into command_buffer+1,+2,+3,+4 */ return(5); case CMD_WRITE_DREG: /* write debug register; parameter 8-bit register number to write & the 32-bit debug module register contents to be written */ bdmcf_tx_msg(BDMCF_CMD_WDMREG+command_buffer[2]); /* send the command */ if (bdmcf_tx_msg_half_rx(*((unsigned int *)(command_buffer+3)))) break; /* and the register value */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+5))); #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); case CMD_READ_REG: /* read address/data register; parameter 8-bit register number to read, returns 32-bit register contents */ bdmcf_tx_msg(BDMCF_CMD_RAREG+command_buffer[2]); /* send the command */ if (bdmcf_rx(2,command_buffer+1)) break; /* the 4 bytes of the register contents are received into command_buffer+1,+2,+3,+4 */ return(5); case CMD_WRITE_REG: /* write address/data register; parameter 8-bit register number to write & the 32-bit register contents to be written */ bdmcf_tx_msg(BDMCF_CMD_WAREG+command_buffer[2]); /* send the command */ if (bdmcf_tx_msg_half_rx(*((unsigned int *)(command_buffer+3)))) break; /* and the register value */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+5))); #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); case CMD_READ_MEM8: /* read a byte from memory; parameter 32bit address, returns 8bit value read from address */ bdmcf_tx_msg(BDMCF_CMD_READ8); /* send the command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* and the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); if (bdmcf_rx(1,command_buffer+1)) break; /* read the result into command_buffer+1 */ *(command_buffer+1)=*(command_buffer+2); /* the byte is LSB of the received word, copy it to the right place */ return(2); case CMD_READ_MEM16: /* read a word from memory; parameter 32bit address, returns 16bit value read from address */ bdmcf_tx_msg(BDMCF_CMD_READ16); /* send the command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* and the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); if (bdmcf_rx(1,command_buffer+1)) break; /* read the result into command_buffer+1,+2 */ return(3); case CMD_READ_MEM32: /* read a double-word from memory; parameter 32bit address, returns 32bit value read from address */ bdmcf_tx_msg(BDMCF_CMD_READ32); /* send the command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* and the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); if (bdmcf_rx(2,command_buffer+1)) break; /* read the result into command_buffer+1,+2,+3,+4 */ return(5); case CMD_WRITE_MEM8: /* write a byte to memory; parameter 32bit address & an 8-bit value to be written to the address */ bdmcf_tx_msg(BDMCF_CMD_WRITE8); /* send the command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); bdmcf_tx_msg(*(command_buffer+6)); /* and the data to be written */ #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); case CMD_WRITE_MEM16: /* write a word to memory; parameter 32bit address & a 16-bit value to be written to the address */ bdmcf_tx_msg(BDMCF_CMD_WRITE16); /* send the command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); bdmcf_tx_msg(*((unsigned int *)(command_buffer+6))); /* and the data to be written */ #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); case CMD_WRITE_MEM32: /* write a double-word to memory; parameter 32bit address & a 32-bit value to be written to the address */ bdmcf_tx_msg(BDMCF_CMD_WRITE32); /* send the command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); bdmcf_tx_msg(*((unsigned int *)(command_buffer+6))); /* and the data to be written */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+8))); #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); case CMD_READ_MEMBLOCK8: /* reads a block of bytes; parameter 32bit address; the number of bytes to read is given by command_size (the number of bytes requested by the host -1) */ { unsigned char i; unsigned char *ptr; bdmcf_tx_msg(BDMCF_CMD_READ8); /* send read byte command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* and the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); i=command_size; ptr=command_buffer+1; /* where first result should go */ do { i--; /* decrement the number of bytes to read */ if (i) { if (bdmcf_rxtx(1,ptr,BDMCF_CMD_DUMP8)) break; /* get the result & send in new DUMP command */ } else { if (bdmcf_rx(1,ptr)) { /* read the result (and send NOP) */ i=1; /* make i non-zero */ break; } } *(ptr)=*(ptr+1); /* the byte is LSB of the received word, copy it to the right place */ ptr++; } while(i); if (i) break; /* an error has occured */ return(command_size+1); } case CMD_READ_MEMBLOCK16: /* reads a block of words; parameter 32bit address; the number of bytes to read is given by command_size (the number of bytes requested by the host -1) */ { unsigned char i; unsigned char *ptr; bdmcf_tx_msg(BDMCF_CMD_READ16); /* send read byte command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* and the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); i=(command_size>>1); /* the number of words is the bytecount/2 */ ptr=command_buffer+1; /* where first result should go */ do { i--; /* decrement the number of bytes to read */ if (i) { if (bdmcf_rxtx(1,ptr,BDMCF_CMD_DUMP16)) break; /* get the result & send in new DUMP command */ } else { if (bdmcf_rx(1,ptr)) { /* read the result (and send NOP) */ i=1; /* make i non-zero */ break; } } ptr+=2; } while(i); if (i) break; /* an error has occured */ return(command_size+1); } case CMD_READ_MEMBLOCK32: /* reads a block of dwords; parameter 32bit address; the number of bytes to read is given by command_size (the number of bytes requested by the host -1) */ { unsigned char i; unsigned char *ptr; bdmcf_tx_msg(BDMCF_CMD_READ32); /* send read byte command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* and the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); i=(command_size>>2); /* the number of dwords is the bytecount/4 */ ptr=command_buffer+1; /* where first result should go */ do { i--; /* decrement the number of bytes to read */ if (i) { if (bdmcf_rxtx(2,ptr,BDMCF_CMD_DUMP32)) break; /* get the result & send in new DUMP command */ } else { if (bdmcf_rx(2,ptr)) { /* read the result (and send NOP) */ i=1; /* make i non-zero */ break; } } ptr+=4; } while(i); if (i) break; /* an error has occured */ return(command_size+1); } case CMD_WRITE_MEMBLOCK8: /* writes a block of words; parameters 32bit address & data to write; the number of bytes to write is given by command_size */ { unsigned char i; unsigned char *ptr; bdmcf_tx_msg(BDMCF_CMD_WRITE8); /* send write byte command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); bdmcf_tx_msg(*(command_buffer+6)); /* and the data */ i=command_size-4-1; /* the address has 4 bytes & done 1 byte already */ ptr=command_buffer+7; while(i) { if (bdmcf_complete_chk(BDMCF_CMD_FILL8)) break; /* send write byte command */ bdmcf_tx_msg(*ptr); /* and the data */ ptr++; i--; } if (i) break; /* an error has occured */ #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); } case CMD_WRITE_MEMBLOCK16: /* writes a block of words; parameters 32bit address & data to write; the number of bytes to write is given by command_size */ { unsigned char i; unsigned char *ptr; bdmcf_tx_msg(BDMCF_CMD_WRITE16); /* send write byte command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); bdmcf_tx_msg(*((unsigned int *)(command_buffer+6))); /* and the data */ i=(command_size-4-2)>>1; /* the address has 4 bytes & done 1 word already, every word has 2 bytes */ ptr=command_buffer+8; while(i) { if (bdmcf_complete_chk(BDMCF_CMD_FILL16)) break; /* send write word command */ bdmcf_tx_msg(*(unsigned int *)ptr); /* and the data */ ptr+=2; i--; } if (i) break; /* an error has occured */ #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); } case CMD_WRITE_MEMBLOCK32: /* writes a block of dwords; parameters 32bit address & data to write; the number of bytes to write is given by command_size */ { unsigned char i; unsigned char *ptr; bdmcf_tx_msg(BDMCF_CMD_WRITE32); /* send write byte command */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+2))); /* the address */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+4))); bdmcf_tx_msg(*((unsigned int *)(command_buffer+6))); /* and the data */ bdmcf_tx_msg(*((unsigned int *)(command_buffer+8))); i=(command_size-4-4)>>2; /* the address has 4 bytes & done 1 dword already, every dword has 4 bytes */ ptr=command_buffer+10; while(i) { if (bdmcf_complete_chk(BDMCF_CMD_FILL32)) break; /* send write dword command */ bdmcf_tx_msg(*(unsigned int *)(ptr+0)); /* and the data */ bdmcf_tx_msg(*(unsigned int *)(ptr+2)); ptr+=4; i--; } if (i) break; /* an error has occured */ #ifdef CMD_COMPLETE_CHECK if (bdmcf_complete_chk_rx()) break; #endif return(1); } case CMD_RESYNCHRONIZE: /* resync communication with the target MCU */ if (bdmcf_resync()) break; /* try to resynchronize */ return(1); case CMD_ASSERT_TA: /* assert the TA signal, parameter: 8-bit number of 10us ticks - duration of the TA assertion */ bdmcf_ta(command_buffer[2]); return(1); default: /* unknown command */ command_buffer[0] = CMD_UNKNOWN; return(1); } bdmcf_complete_chk_rx(); /* send at least 2 nops to purge the BDM of the offending command */ bdmcf_complete_chk_rx(); } else if (cable_status.target_type==JTAG) { switch (command_buffer[1]) { case CMD_JTAG_GOTORESET: /* no parameters, takes the TAP to TEST-LOGIC-RESET state, re-select the JTAG target to take TAP back to RUN-TEST/IDLE */ jtag_transition_reset(); return(1); case CMD_JTAG_GOTOSHIFT: /* parameters 8-bit path option; path option ==0 : go to SHIFT-DR, !=0 : go to SHIFT-IR (requires the tap to be in RUN-TEST/IDLE) */ jtag_transition_shift(command_buffer[2]); return(1); case CMD_JTAG_WRITE: /* parameters 8-bit exit option, 8-bit count of bits to shift in, and the data to be shifted in (shifted in LSB (last byte) first, unused bits (if any) are in the MSB (first) byte; exit option ==0 : stay in SHIFT-xx, !=0 : go to RUN-TEST/IDLE when finished */ jtag_write(command_buffer[2], command_buffer[3], command_buffer+4); return(1); case CMD_JTAG_READ: /* parameters 8-bit exit option, 8-bit count of bits to shift out; exit option ==0 : stay in SHIFT-xx, !=0 : go to RUN-TEST/IDLE when finished, returns the data read out of the device (first bit in LSB of the last byte in the buffer) */ { unsigned char i; i=command_buffer[3]>>3; /* calculate the number of bytes to return */ if ((command_buffer[3]&0x07)==0) i++; jtag_read(command_buffer[2], command_buffer[3], command_buffer+1); return(i+1); } default: /* unknown command */ command_buffer[0] = CMD_UNKNOWN; return(1); } } else {