/* Turbo BDM Light ColdFire - interface DLL Copyright (C) 2006 Daniel Malik Changed to support the BDM project. Chris Johns (cjohns@user.sourgeforge.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "log.h" #include "version.h" #include "tblcf.h" #include "tblcf_usb.h" #include "tblcf_hwdesc.h" #include "commands.h" /* define symbol "LOG" during compilation to produce a log file tblcf_dll.log */ static unsigned char usb_data[MAX_DATA_SIZE+2]; /* returns version of the DLL in BCD format */ unsigned char tblcf_version(void) { return(TBLCF_DLL_VERSION); } /* initialises USB and returns number of devices found */ unsigned char tblcf_init(void) { unsigned char i; tblcf_usb_init(); tblcf_usb_find_devices(TBLCF_PID); /* look for devices on all USB busses */ i=tblcf_usb_cnt(); tblcf_print("TBDML_INIT: Usb initialised, found %d device(s)\r\n",i); return(i); /* count the devices found and return the number */ } /* opens a device with given number name */ /* returns device number on success and -1 on error */ int tblcf_open(const char *device) { tblcf_print("TBLCF_OPEN: Trying to open device %s\r\n", device); return(tblcf_usb_open(device)); } /* closes currently open device */ void tblcf_close(int dev) { tblcf_print("TBLCF_CLOSE: Trying to close the device\r\n"); tblcf_usb_close(dev); } /* gets version of the interface (HW and SW) in BCD format */ unsigned int tblcf_get_version(int dev) { usb_data[0]=3; /* get 3 bytes */ usb_data[1]=CMD_GET_VER; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_GET_VERSION: Reported cable version (0x%02X) - %02X.%02X (HW.SW)\r\n", usb_data[0],usb_data[2],usb_data[1]); return((*((unsigned int *)(usb_data+1)))&0xffff); } /* returns status of the last command: 0 on sucess and non-zero on failure */ unsigned char tblcf_get_last_sts_value(int dev) { usb_data[0]=1; /* get 1 byte */ usb_data[1]=CMD_GET_LAST_STATUS; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_GET_LAST_STATUS: Reported last command status 0x%02X\r\n",usb_data[0]); return usb_data[0]; } /* returns status of the last command: 0 on sucess and non-zero on failure */ unsigned char tblcf_get_last_sts(int dev) { unsigned char status = tblcf_get_last_sts_value(dev); if ((status==CMD_FAILED)||(status==CMD_UNKNOWN)) return(1); else return(0); } /* requests bootloader execution on next power-up */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_request_boot(int dev) { usb_data[0]=1; /* return 1 byte */ usb_data[1]=CMD_SET_BOOT; usb_data[2]='B'; usb_data[3]='O'; usb_data[4]='O'; usb_data[5]='T'; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_REQUEST_BOOT: Requested bootloader on next power-up (0x%02X)\r\n",usb_data[0]); return(!(usb_data[0]==CMD_SET_BOOT)); } /* sets target MCU type */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_set_target_type(int dev, target_type_e target_type) { usb_data[0]=1; /* get 1 byte */ usb_data[1]=CMD_SET_TARGET; usb_data[2]=target_type; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_SET_TARGET_TYPE: Set target type 0x%02X (0x%02X)\r\n",usb_data[2],usb_data[0]); return(!(usb_data[0]==CMD_SET_TARGET)); } /* resets the target to normal or BDM mode */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_target_reset(int dev, target_mode_e target_mode) { usb_data[0]=1; /* get 1 byte */ usb_data[1]=CMD_RESET; usb_data[2]=target_mode; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_TARGET_RESET: Target reset into mode 0x%02X (0x%02X)\r\n",usb_data[2],usb_data[0]); return(!(usb_data[0]==CMD_RESET)); } /* fills user supplied structure with current state of the BDM communication channel */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_bdm_sts(int dev, bdmcf_status_t *bdmcf_status) { usb_data[0]=3; /* get 3 bytes */ usb_data[1]=CMD_GET_STATUS; tblcf_usb_recv_ep0(dev, usb_data); if (usb_data[0]!=CMD_GET_STATUS) return(1); bdmcf_status->reset_state = ((usb_data[1]*256+usb_data[2])&RSTO_STATE_MASK)?RSTO_INACTIVE:RSTO_ACTIVE; bdmcf_status->reset_detection = ((usb_data[1]*256+usb_data[2])&RESET_DETECTED_MASK)?RESET_DETECTED:RESET_NOT_DETECTED; tblcf_print("TBLCF_BDM_STATUS: Reported communication status 0x%04X (0x%02X)\r\n", (usb_data[1]*256+usb_data[2]),usb_data[0]); return(0); } /* brings the target into BDM mode */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_target_halt(int dev) { usb_data[0]=1; /* get 1 byte */ usb_data[1]=CMD_HALT; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_TARGET_HALT: (0x%02X)\r\n",usb_data[0]); return(!(usb_data[0]==CMD_HALT)); } /* starts target execution from current PC address */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_target_go(int dev) { usb_data[0]=1; /* get 1 byte */ usb_data[1]=CMD_GO; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_TARGET_GO: (0x%02X)\r\n",usb_data[0]); return(!(usb_data[0]==CMD_GO)); } /* steps over a single target instruction */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_target_step(int dev) { usb_data[0]=1; /* get 1 byte */ usb_data[1]=CMD_STEP; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_TARGET_STEP: (0x%02X)\r\n",usb_data[0]); return(!(usb_data[0]==CMD_STEP)); } /* resynchronizes communication with the target (in case of noise, etc.) */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_resynchronize(int dev) { usb_data[0]=1; /* get 1 byte */ usb_data[1]=CMD_RESYNCHRONIZE; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_RESYNCHRONIZE: (0x%02X)\r\n",usb_data[0]); return(!(usb_data[0]==CMD_RESYNCHRONIZE)); } /* asserts the TA signal for the specified time (in 10us ticks) */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_assert_ta(int dev, unsigned char duration_10us) { usb_data[0]=1; /* get 1 byte */ usb_data[1]=CMD_ASSERT_TA; usb_data[2]=duration_10us; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_ASSERT_TA: duration %d us (0x%02X)\r\n",(int)10*usb_data[2],usb_data[0]); return(!(usb_data[0]==CMD_ASSERT_TA)); } /* reads control register at the specified address and writes its contents into the supplied buffer */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_read_creg(int dev, unsigned int address, unsigned long int * result) { usb_data[0]=5; /* get 5 bytes */ usb_data[1]=CMD_READ_CREG; usb_data[2]=(address>>8)&0xff; /* address in big endian */ usb_data[3]=address&0xff; tblcf_usb_recv_ep0(dev, usb_data); *result = (((unsigned long int)usb_data[1])<<24)+(usb_data[2]<<16)+(usb_data[3]<<8)+usb_data[4]; /* result is in big endian */ tblcf_print("TBLCF_READ_CREG: Read control register from address 0x%04X, result: 0x%08lX (0x%02X)\r\n",address,*result,usb_data[0]); return(!(usb_data[0]==CMD_READ_CREG)); } /* writes control register at the specified address */ void tblcf_write_creg(int dev, unsigned int address, unsigned long int value) { usb_data[0]=7; /* send 7 bytes */ usb_data[1]=CMD_WRITE_CREG; usb_data[2]=(address>>8)&0xff; /* address in big endian */ usb_data[3]=address&0xff; usb_data[4]=(value>>24)&0xff; usb_data[5]=(value>>16)&0xff; usb_data[6]=(value>>8)&0xff; usb_data[7]=(value)&0xff; tblcf_print("TBLCF_WRITE_CREG: Write control register at address 0x%04X with 0x%08lX\r\n",address,value); tblcf_usb_send_ep0(dev, usb_data); } /* reads the specified debug register and writes its contents into the supplied buffer */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_read_dreg(int dev, unsigned char dreg_index, unsigned long int * result) { usb_data[0]=5; /* get 5 bytes */ usb_data[1]=CMD_READ_DREG; usb_data[2]=dreg_index; tblcf_usb_recv_ep0(dev, usb_data); *result = (((unsigned long int)usb_data[1])<<24)+(usb_data[2]<<16)+(usb_data[3]<<8)+usb_data[4]; /* result is in big endian */ tblcf_print("TBLCF_READ_DREG: Read debug register #0x%02X, result: 0x%08lX (0x%02X)\r\n", dreg_index,*result,usb_data[0]); return(!(usb_data[0]==CMD_READ_DREG)); } /* writes specified debug register */ void tblcf_write_dreg(int dev, unsigned char dreg_index, unsigned long int value) { usb_data[0]=6; /* send 6 bytes */ usb_data[1]=CMD_WRITE_DREG; usb_data[2]=dreg_index&0xff; usb_data[3]=(value>>24)&0xff; usb_data[4]=(value>>16)&0xff; usb_data[5]=(value>>8)&0xff; usb_data[6]=(value)&0xff; tblcf_print("TBLCF_WRITE_DREG: Write debug register #0x%02X with 0x%08lX\r\n",dreg_index,value); tblcf_usb_send_ep0(dev, usb_data); } /* reads the specified register and writes its contents into the supplied buffer */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_read_reg(int dev, unsigned char reg_index, unsigned long int * result) { usb_data[0]=5; /* get 5 bytes */ usb_data[1]=CMD_READ_REG; usb_data[2]=reg_index; tblcf_usb_recv_ep0(dev, usb_data); *result = (((unsigned long int)usb_data[1])<<24)+(usb_data[2]<<16)+(usb_data[3]<<8)+usb_data[4]; /* result is in big endian */ tblcf_print("TBLCF_READ_REG: Read register #0x%02X, result: 0x%08lX (0x%02X)\r\n", reg_index,*result,usb_data[0]); return(!(usb_data[0]==CMD_READ_REG)); } /* writes specified register */ void tblcf_write_reg(int dev, unsigned char reg_index, unsigned long int value) { usb_data[0]=6; /* send 6 bytes */ usb_data[1]=CMD_WRITE_REG; usb_data[2]=reg_index&0xff; usb_data[3]=(value>>24)&0xff; usb_data[4]=(value>>16)&0xff; usb_data[5]=(value>>8)&0xff; usb_data[6]=(value)&0xff; tblcf_print("TBLCF_WRITE_REG: Write register #0x%02X with 0x%08lX\r\n",reg_index,value); tblcf_usb_send_ep0(dev, usb_data); } /* reads byte from the specified address */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_read_mem8(int dev, unsigned long int address, unsigned char * result) { usb_data[0]=2; /* get 2 bytes */ usb_data[1]=CMD_READ_MEM8; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; tblcf_usb_recv_ep0(dev, usb_data); *result = usb_data[1]; tblcf_print("TBLCF_READ_MEM8: Read byte from address 0x%08lX, result: 0x%02X (0x%02X)\r\n", address,*result,usb_data[0]); return(!(usb_data[0]==CMD_READ_MEM8)); } /* reads word from the specified address */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_read_mem16(int dev, unsigned long int address, unsigned int * result) { usb_data[0]=3; /* get 3 bytes */ usb_data[1]=CMD_READ_MEM16; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; tblcf_usb_recv_ep0(dev, usb_data); *result = ((unsigned int)usb_data[1]<<8)+usb_data[2]; tblcf_print("TBLCF_READ_MEM16: Read word from address 0x%08lX, result: 0x%04X (0x%02X)\r\n", address,*result,usb_data[0]); return(!(usb_data[0]==CMD_READ_MEM16)); } /* reads long word from the specified address */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_read_mem32(int dev, unsigned long int address, unsigned long int * result) { usb_data[0]=5; /* get 5 bytes */ usb_data[1]=CMD_READ_MEM32; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; tblcf_usb_recv_ep0(dev, usb_data); *result = (((unsigned long int)usb_data[1])<<24)+(usb_data[2]<<16)+(usb_data[3]<<8)+usb_data[4]; tblcf_print("TBLCF_READ_MEM32: Read long word from address 0x%08lX, result: 0x%08lX (0x%02X)\r\n",address,*result,usb_data[0]); return(!(usb_data[0]==CMD_READ_MEM32)); } /* writes byte at the specified address */ void tblcf_write_mem8(int dev, unsigned long int address, unsigned char value) { usb_data[0]=6; /* send 6 bytes */ usb_data[1]=CMD_WRITE_MEM8; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; usb_data[6]=(value)&0xff; tblcf_print("TBLCF_WRITE_MEM8: Write byte 0x%02X to address 0x%08lX\r\n",value,address); tblcf_usb_send_ep0(dev, usb_data); } /* writes word at the specified address */ void tblcf_write_mem16(int dev, unsigned long int address, unsigned int value) { usb_data[0]=7; /* send 7 bytes */ usb_data[1]=CMD_WRITE_MEM16; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; usb_data[6]=(value>>8)&0xff; usb_data[7]=(value)&0xff; tblcf_print("TBLCF_WRITE_MEM16: Write word 0x%04X to address 0x%08lX\r\n",value,address); tblcf_usb_send_ep0(dev, usb_data); } /* writes long word at the specified address */ void tblcf_write_mem32(int dev, unsigned long int address, unsigned long int value) { usb_data[0]=9; /* send 9 bytes */ usb_data[1]=CMD_WRITE_MEM32; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; usb_data[6]=(value>>24)&0xff; usb_data[7]=(value>>16)&0xff; usb_data[8]=(value>>8)&0xff; usb_data[9]=(value)&0xff; tblcf_print("TBLCF_WRITE_MEM32: Write long word 0x%08lX to address 0x%08lX\r\n",value,address); tblcf_usb_send_ep0(dev, usb_data); } /* reads the requested number of bytes from target memory from the supplied address and stores results into the user supplied buffer */ /* uses byte accesses only */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_read_block8(int dev, unsigned long int address, unsigned long int bytecount, unsigned char *buffer) { int i; tblcf_print("TBLCF_READ_BLOCK8: Read 0x%08lX byte(s) from address 0x%08lX:\r\n",bytecount,address); while (bytecount>=MAX_DATA_SIZE) { usb_data[0]=MAX_DATA_SIZE+1; /* receive block of maximum size */ usb_data[1]=CMD_READ_MEMBLOCK8; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_READ_BLOCK8: Block read, size 0x%02X (0x%02X):\r\n",MAX_DATA_SIZE,usb_data[0]); tblcf_print_dump(usb_data+1, MAX_DATA_SIZE); if (usb_data[0]!=CMD_READ_MEMBLOCK8) return(1); for (i=0;i>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_READ_BLOCK8: Block read, size 0x%02X (0x%02X):\r\n",bytecount,usb_data[0]); tblcf_print_dump(usb_data+1, bytecount); if (usb_data[0]!=CMD_READ_MEMBLOCK8) return(1); for (i=0;i=(MAX_DATA_SIZE&0xfffe)) { usb_data[0]=(MAX_DATA_SIZE&0xfffe)+1; /* receive block of maximum size */ usb_data[1]=CMD_READ_MEMBLOCK16; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_READ_BLOCK16: Block read, size 0x%02X (0x%02X):\r\n",MAX_DATA_SIZE&0xfffe,usb_data[0]); tblcf_print_dump(usb_data+1, MAX_DATA_SIZE&0xfffe); for (i=0;i<(MAX_DATA_SIZE&0xfffe);i++) *(buffer++)=usb_data[1+i]; /* copy results */ bytecount-=(MAX_DATA_SIZE&0xfffe); address+=(MAX_DATA_SIZE&0xfffe); if (usb_data[0]!=CMD_READ_MEMBLOCK16) return(1); } if (bytecount) { usb_data[0]=bytecount+1; if ((bytecount&0x01)==1) usb_data[0]++; /* increase the number of bytes to return to a whole number of words */ usb_data[1]=CMD_READ_MEMBLOCK16; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_READ_BLOCK16: Block read, size 0x%02X (0x%02X):\r\n",bytecount,usb_data[0]); tblcf_print_dump(usb_data+1, bytecount); if (usb_data[0]!=CMD_READ_MEMBLOCK16) return(1); for (i=0;i=(MAX_DATA_SIZE&0xfffc)) { usb_data[0]=(MAX_DATA_SIZE&0xfffc)+1; /* receive block of maximum size */ usb_data[1]=CMD_READ_MEMBLOCK32; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_READ_BLOCK32: Block read, size 0x%02X (0x%02X):\r\n",MAX_DATA_SIZE&0xfffc,usb_data[0]); tblcf_print_dump(usb_data+1, MAX_DATA_SIZE&0xfffc); for (i=0;i<(MAX_DATA_SIZE&0xfffc);i++) *(buffer++)=usb_data[1+i]; /* copy results */ bytecount-=(MAX_DATA_SIZE&0xfffc); address+=(MAX_DATA_SIZE&0xfffc); if (usb_data[0]!=CMD_READ_MEMBLOCK32) return(1); } if (bytecount) { usb_data[0]=bytecount+1; usb_data[0]+=((4-(bytecount&0x03))&0x03); /* increase the number of bytes to make it a multiple of 4 */ usb_data[1]=CMD_READ_MEMBLOCK32; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_READ_BLOCK32: Block read, size 0x%02X (0x%02X):\r\n",bytecount,usb_data[0]); tblcf_print_dump(usb_data+1, bytecount); if (usb_data[0]!=CMD_READ_MEMBLOCK32) return(1); for (i=0;i=MAX_DATA_SIZE) { usb_data[0]=MAX_DATA_SIZE+5; /* write block of maximum size */ usb_data[1]=CMD_WRITE_MEMBLOCK8; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; for (i=0;i>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; for (i=0;i=(MAX_DATA_SIZE&0xfffe)) { usb_data[0]=(MAX_DATA_SIZE&0xfffe)+5; /* send block of maximum size */ usb_data[1]=CMD_WRITE_MEMBLOCK16; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; for (i=0;i<(MAX_DATA_SIZE&0xfffe);i++) usb_data[6+i]=*(buffer++); /* copy data */ tblcf_print("TBLCF_WRITE_BLOCK16: Block write, size 0x%02X:\r\n",MAX_DATA_SIZE&0xfffe); tblcf_print_dump(usb_data+6, MAX_DATA_SIZE&0xfffe); tblcf_usb_send_ep0(dev, usb_data); bytecount-=(MAX_DATA_SIZE&0xfffe); address+=(MAX_DATA_SIZE&0xfffe); #ifdef WRITE_BLOCK_CHECK if (tblcf_get_last_sts(dev)) return(1); #endif } if (bytecount>=2) { usb_data[0]=bytecount+5; if ((bytecount&0x01)==1) usb_data[0]--; /* decrease the number of bytes to write a whole number of words */ usb_data[1]=CMD_WRITE_MEMBLOCK16; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; for (i=0;i<(bytecount&0xfffe);i++) usb_data[6+i]=*(buffer++); /* copy data */ tblcf_print("TBLCF_WRITE_BLOCK16: Block write, size 0x%02X:\r\n",(bytecount&0xfffe)); tblcf_print_dump(usb_data+6, (bytecount&0xfffe)); tblcf_usb_send_ep0(dev, usb_data); #ifdef WRITE_BLOCK_CHECK if (tblcf_get_last_sts(dev)) return(1); #endif address+=(bytecount&0xfffe); bytecount&=0x01; } if (bytecount) { /* leftover byte */ tblcf_print("TBLCF_WRITE_BLOCK16: Misaligned byte at the end of the block, performing 1 byte write\r\n"); tblcf_write_mem8(dev, address, *buffer); #ifdef WRITE_BLOCK_CHECK if (tblcf_get_last_sts(dev)) return(1); #endif } return(0); } /* writes the requested number of bytes to target memory at the supplied address */ /* uses long word accesses */ /* if the address is not aligned byte/word writes are performed */ /* if there are odd bytes at the end of the block they is written using byte/word writes */ /* returns 0 on success and non-zero on failure (must be compiled with WRITE_BLOCK_CHECK, otherwise always returns 0) */ unsigned char tblcf_write_block32(int dev, unsigned long int address, unsigned long int bytecount, unsigned char *buffer) { int i; tblcf_print("TBLCF_WRITE_BLOCK32: Write 0x%08lX byte(s) at address 0x%08lX:\r\n",bytecount,address); if (address&0x01) { tblcf_print("TBLCF_WRITE_BLOCK32: Address is odd, performing 1 byte write\r\n"); tblcf_write_mem8(dev, address, *buffer); #ifdef WRITE_BLOCK_CHECK if (tblcf_get_last_sts(dev)) return(1); #endif bytecount--; address++; buffer++; } if (address&0x02) { tblcf_print("TBLCF_WRITE_BLOCK32: Address is not aligned, performing 1 word write\r\n"); tblcf_write_mem16(dev, address, (*(buffer+0))*256+*(buffer+1)); #ifdef WRITE_BLOCK_CHECK if (tblcf_get_last_sts(dev)) return(1); #endif bytecount-=2; address+=2; buffer+=2; } while (bytecount>=(MAX_DATA_SIZE&0xfffc)) { usb_data[0]=(MAX_DATA_SIZE&0xfffc)+5; /* send block of maximum size */ usb_data[1]=CMD_WRITE_MEMBLOCK32; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; for (i=0;i<(MAX_DATA_SIZE&0xfffc);i++) usb_data[6+i]=*(buffer++); /* copy data */ tblcf_print("TBLCF_WRITE_BLOCK32: Block write, size 0x%02X:\r\n",MAX_DATA_SIZE&0xfffc); tblcf_print_dump(usb_data+6, MAX_DATA_SIZE&0xfffc); tblcf_usb_send_ep0(dev, usb_data); bytecount-=(MAX_DATA_SIZE&0xfffc); address+=(MAX_DATA_SIZE&0xfffc); #ifdef WRITE_BLOCK_CHECK if (tblcf_get_last_sts(dev)) return(1); #endif } if (bytecount>=4) { usb_data[0]=bytecount+5; usb_data[0]-=(bytecount&0x03); /* decrease the number of bytes to write a whole number of long words */ usb_data[1]=CMD_WRITE_MEMBLOCK32; usb_data[2]=(address>>24)&0xff; usb_data[3]=(address>>16)&0xff; usb_data[4]=(address>>8)&0xff; usb_data[5]=(address)&0xff; for (i=0;i<(bytecount&0xfffc);i++) usb_data[6+i]=*(buffer++); /* copy data */ tblcf_print("TBLCF_WRITE_BLOCK32: Block write, size 0x%02X:\r\n",(bytecount&0xfffc)); tblcf_print_dump(usb_data+6, (bytecount&0xfffc)); tblcf_usb_send_ep0(dev, usb_data); #ifdef WRITE_BLOCK_CHECK if (tblcf_get_last_sts(dev)) return(1); #endif address+=(bytecount&0xfffc); bytecount&=0x03; } if (bytecount>=2) { /* leftover word */ tblcf_print("TBLCF_WRITE_BLOCK32: Misaligned word at the end of the block, performing 1 word write\r\n"); tblcf_write_mem16(dev, address, (*(buffer+0))*256+*(buffer+1)); #ifdef WRITE_BLOCK_CHECK if (tblcf_get_last_sts(dev)) return(1); #endif address+=2; bytecount-=2; buffer+=2; } if (bytecount) { /* leftover byte */ tblcf_print("TBLCF_WRITE_BLOCK32: Misaligned byte at the end of the block, performing 1 byte write\r\n"); tblcf_write_mem8(dev, address, *(buffer)); #ifdef WRITE_BLOCK_CHECK if (tblcf_get_last_sts(dev)) return(1); #endif } return(0); } /* JTAG - go from RUN-TEST/IDLE to SHIFT-DR or SHIFT-IR state */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_jtag_sel_shift(int dev, unsigned char mode) { usb_data[0]=1; /* get 1 byte */ usb_data[1]=CMD_JTAG_GOTOSHIFT; usb_data[2]=mode; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_JTAG_SEL_SHIFT: SHIFT-%cR\r\n",mode?'I':'D'); return(!(usb_data[0]==CMD_JTAG_GOTOSHIFT)); } /* JTAG - go from RUN-TEST/IDLE to TEST-LOGIC-RESET state */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_jtag_sel_reset(int dev) { usb_data[0]=1; /* get 1 byte */ usb_data[1]=CMD_JTAG_GOTORESET; tblcf_usb_recv_ep0(dev, usb_data); tblcf_print("TBLCF_JTAG_SEL_RESET\r\n"); return(!(usb_data[0]==CMD_JTAG_GOTORESET)); } /* JTAG - write data */ /* parameter exit: ==0 : stay in SHIFT-xx, !=0 : go to RUN-TEST/IDLE when done */ /* data: shifted in LSB (last byte) first, unused bits (if any) are in the MSB (first) byte */ void tblcf_jtag_write(int dev, unsigned char bit_count, unsigned char exit, unsigned char *buffer) { int i; usb_data[0]=(bit_count>>3)+((bit_count&0x07)!=0)+3; /* send all data bits & 3 more bytes */ usb_data[1]=CMD_JTAG_WRITE; usb_data[2]=exit; usb_data[3]=bit_count; for (i=0;i<((bit_count>>3)+1);i++) usb_data[4+i]=*(buffer+i); /* copy data */ tblcf_usb_send_ep0(dev, usb_data); tblcf_print("TBLCF_JTAG_WRITE: %d bits (%sexit to RUN-TEST/IDLE)\r\n",bit_count,exit?"":"NO "); tblcf_print_dump(usb_data+4,(bit_count>>3)+((bit_count&0x07)!=0)); } /* JTAG - read data */ /* parameter exit: ==0 : stay in SHIFT-xx, !=0 : go to RUN-TEST/IDLE when done */ /* data: shifted in LSB (last byte) first, unused bits (if any) are in the MSB (first) byte */ /* returns 0 on success and non-zero on failure */ unsigned char tblcf_jtag_read(int dev, unsigned char bit_count, unsigned char exit, unsigned char *buffer) { int i; usb_data[0]=(bit_count>>3)+((bit_count&0x07)!=0)+1; /* get all data bits & the status byte */ usb_data[1]=CMD_JTAG_READ; usb_data[2]=exit; usb_data[3]=bit_count; tblcf_usb_recv_ep0(dev, usb_data); for (i=0;i<((bit_count>>3)+((bit_count&0x07)!=0));i++) *(buffer+i)=usb_data[1+i]; /* copy data */ tblcf_print("TBLCF_JTAG_READ: %d bits (%sexit to RUN-TEST/IDLE)\r\n",bit_count,exit?"":"NO "); tblcf_print_dump(usb_data+1,(bit_count>>3)+((bit_count&0x07)!=0)); return(!(usb_data[0]==CMD_JTAG_READ)); } #if 0 BOOL LibMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) { char path[MAX_PATH]; char *charp; time_t time_now; switch (fdwReason) { case DLL_PROCESS_ATTACH: tblcf_usb_init(); /* initialise USB */ #ifdef LOG GetModuleFileName(NULL,path,sizeof(path)); charp=strchr(path,'\\'); if (charp!=NULL) { while (strchr(charp+1,'\\')) charp=strchr(charp+1,'\\'); /* find the last backslash */ strcpy(charp+1,"tblcf_dll.log"); log_file=fopen(path,"wb"); } tblcf_print("Log file path: %s\r\n",path); tblcf_print("Turbo BDM Light DLL v%1d.%1d. Compiled on %s, %s.\r\n", TBLCF_DLL_VERSION/16,TBLCF_DLL_VERSION&0x0f,__DATE__,__TIME__); time(&time_now); tblcf_print("Log file created on: %s\r", ctime(&time_now)); #endif break; case DLL_PROCESS_DETACH: #ifdef LOG time(&time_now); tblcf_print("End of log file: %s\r", ctime(&time_now)); fclose(log_file); #endif break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return TRUE; } #endif