Files
m68k-bdm/m68k/tblcf/tblcf_bt.c
Bernd Mueller adfd70813f initial push
2026-06-17 13:44:30 +02:00

289 lines
11 KiB
C

/*
Turbo BDM Light ColdFire
Copyright (C) 2006 Daniel Malik
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 <stdio.h>
#include <string.h>
#include "tblcf_hwdesc.h"
#include "tblcf_usb.h"
#include "version.h"
#include "tblcf_bt.h"
#include "log_cmdline.h"
#include "srec.h"
#include "commands.h"
/*
Changes:
1.0 Initial coding
*/
function_descriptor_t function_descriptor; /* this structure describes what the program should do */
/* returns number of parameters or a negative number in case of error */
char handleoptions(int argc,char *argv[]) {
int i,notoption=0;
for (i=1; i< argc;i++) {
if (argv[i][0] == '/' || argv[i][0] == '-') {
switch (argv[i][1]) {
case 'b':
case 'B':
/* replace boot sector */
function_descriptor.replace_boot=1;
break;
case 'd':
case 'D':
/* USB device number */
{
strcpy (function_descriptor.device_name, argv[i]+2);
print_screen("Device #: %s\n",function_descriptor.device_name);
break;
}
case 'U':
case 'u':
/* request firmware upgrade */
function_descriptor.request_upgrade=1;
break;
case 'l':
case 'L':
/* -l<log file> */
open_log(argv[i]+2);
break;
default:
print_screen("Unknown option %s\n",argv[i]);
return(-1);
}
} else {
if (notoption==0) { /* the first parameter which is not an option is the S-record file */
strncpy(function_descriptor.s_rec_filename,argv[i],MAX_PATH);
}
if (notoption>=1) {
print_screen("Too many parameters!\n");
}
notoption++;
}
}
return(notoption);
}
void usage(void) {
print_screen("\nUsage:\n\nTBLCF_BT <S-record file> [<options>]\n\n");
print_screen("Options:\n\n");
print_screen("-B\t\tReplace BOOT sector\n");
print_screen("-D<n>\t\tSpecify which USB device to work with\n");
print_screen("-L<log file>\tWrite messages into a log file\n");
print_screen("-U\t\tRequest Firmware upgrade\n");
print_screen("\n");
}
int main(int argc, char *argv[]) {
int i;
unsigned int start,end; /* indexes into the array delimiting block of data to be programmed into flash */
print_screen("Turbo BDM Light ColdFire Bootloader ver %01X.%01X. Compiled on %s, %s.\n",TBLCF_BOOTLOADER_VERSION>>4,TBLCF_BOOTLOADER_VERSION&0x0f,__DATE__,__TIME__);
/* initialise function_descriptor */
function_descriptor.replace_boot=0;
function_descriptor.device_no=0;
function_descriptor.request_upgrade=0;
for (i=0;i<sizeof(function_descriptor.boot_sector_data);i++) function_descriptor.boot_sector_data[i]=0xff;
for (i=0;i<sizeof(function_descriptor.flash_data);i++) function_descriptor.flash_data[i]=0xff;
/* now handle user supplied options */
i=handleoptions(argc,argv);
if ((i != 1)&&(function_descriptor.request_upgrade==0)) { /* number of parameters is incorrect */
print_screen("Number of parameters incorrect or other error\n");
usage();
return(1);
}
tblcf_usb_init();
/* request firmware upgrade on next power up (if required by the user) */
if (function_descriptor.request_upgrade) {
unsigned char data[6];
tblcf_usb_find_devices(TBLCF_PID);
print_screen("found %d Turbo BDM Light ColdFire device(s)\n",i=tblcf_usb_cnt());
if (function_descriptor.device_no>=i) {
print_screen("Not enough devices connected to work with device #%d\n",
function_descriptor.device_no);
return(1);
}
function_descriptor.device_no = tblcf_usb_open(function_descriptor.device_name);
/* request bootloader action op next power-up */
data[0]=1; /* return 1 byte */
data[1]=CMD_SET_BOOT;
data[2]='B';
data[3]='O';
data[4]='O';
data[5]='T';
i=tblcf_usb_recv_ep0(function_descriptor.device_no, data);
tblcf_usb_close(function_descriptor.device_no);
if ((i)||(data[0]!=CMD_SET_BOOT)) {
print_screen("USB communication problem or CMD_SET_BOOT command failure\n");
return(1);
}
print_screen("HC08JB16 ICP will execute on next power-up. Disconnect and reconnect the device.\n");
return(0);
}
if (s_rec_process()) return(1); /* process the S-record file, exit in case of error */
/* now open communication with the device */
tblcf_usb_find_devices(JB16ICP_PID);
print_screen("found %d HC08JB16 ICP device(s)\n",i=tblcf_usb_cnt());
if (function_descriptor.device_no>=i) {
print_screen("Not enough devices connected to work with device #%d\n",
function_descriptor.device_no);
return(1);
}
function_descriptor.device_no = tblcf_usb_open(function_descriptor.device_name);
/* boot sector reprogramming (if requested by user) */
i=icp_verify(function_descriptor.device_no,
function_descriptor.boot_sector_data,
TBLCF_FLASH_BOOT_START, TBLCF_FLASH_BOOT_END-TBLCF_FLASH_BOOT_START+1);
if (i<0) {
print_screen("USB communication problem\n");
tblcf_usb_close(function_descriptor.device_no);
return(1);
}
if (function_descriptor.replace_boot) {
/* user wants to overwrite the boot sector, first check, whether it is really needed */
if (i) {
print_screen("Boot sector contents different, performing mass erase\n");
/* erase flash of the device */
i=icp_mass_erase(function_descriptor.device_no);
if (i) {
print_screen("USB communication problem or mass erase failure\n");
tblcf_usb_close(function_descriptor.device_no);
return(1);
}
print_screen("Mass erase done, programming boot sector\n");
/* program the boot sector contents */
i=icp_program(function_descriptor.device_no,
function_descriptor.boot_sector_data,
TBLCF_FLASH_BOOT_START, TBLCF_FLASH_BOOT_END-TBLCF_FLASH_BOOT_START+1);
if (i) {
print_screen("USB communication problem or programming failure\n");
tblcf_usb_close(function_descriptor.device_no);
return(1);
}
print_screen("Programming done, verifying boot sector\n");
/* verify that the contents is now correct */
i=icp_verify(function_descriptor.device_no,
function_descriptor.boot_sector_data,
TBLCF_FLASH_BOOT_START, TBLCF_FLASH_BOOT_END-TBLCF_FLASH_BOOT_START+1);
if (i) {
print_screen("USB communication problem or verification failure\n");
tblcf_usb_close(function_descriptor.device_no);
return(1);
}
print_screen("Verification done, boot sector OK. You can start breathing again.\n");
} else {
print_screen("Boot sector contents identical, -B option ignored\n");
}
} else {
/* user does not want to reprogram the boot sector */
if (i) {
print_screen("Boot sector contents differs from S-record, update required\n");
tblcf_usb_close(function_descriptor.device_no);
return(1);
}
}
/* flash programming */
for (i=TBLCF_FLASH_START;i<TBLCF_FLASH_END;i+=ICP_FLASH_BLOCK_SIZE) {
/* erase all flash blocks one by one */
print_screen("Erasing block at address: 0x%04X\r",i);
if (icp_block_erase(function_descriptor.device_no, i)) {
print_screen("\nUSB communication problem or block erase failure\n");
tblcf_usb_close(function_descriptor.device_no);
return(1);
}
}
print_screen("\n");
/* set the boot_state variable to erased state (0xFF 0xFF) before programming */
function_descriptor.flash_data[TBLCF_BOOT_STATE-TBLCF_FLASH_START]=TBLCF_BOOT_STATE_BLANK>>8;
function_descriptor.flash_data[TBLCF_BOOT_STATE-TBLCF_FLASH_START+1]=TBLCF_BOOT_STATE_BLANK&&0xff;
/* now do the actual programming */
/* the algorithm below will split the flash into several sections if there is at least 8 unprogrammed bytes beetwen two sections */
/* for TBLCF firmware there will typically be only 2 sections: code of the application at the beginning of flash and secondary vectors at the end */
end=TBLCF_FLASH_START;
while (1) {
/* look for first byte in non-erased state */
start=end;
while ((function_descriptor.flash_data[start-TBLCF_FLASH_START]==0xff) &&
(start<=TBLCF_FLASH_END)) start++; /* find first byte != 0xff */
if (start>TBLCF_FLASH_END) break; /* end of array */
/* now look for block of 8 bytes in erased state */
end=start;
do {
while ((function_descriptor.flash_data[end-TBLCF_FLASH_START]!=0xff) &&
(end<TBLCF_FLASH_END)) end++; /* find first byte == 0xff */
if (end<TBLCF_FLASH_END) {
i=1;
while ((function_descriptor.flash_data[end+i-TBLCF_FLASH_START]==0xff) &&
((end+i)<TBLCF_FLASH_END)&&(i<8)) i++; /* keep going for 7 more bytes (max) */
if (i<8) end+=i;
}
} while ((i<8)&&(end<TBLCF_FLASH_END));
if (end<TBLCF_FLASH_END) end--; /* go back 1 byte (it is blank anyway) */
/* program the block */
print_screen("Programming block from 0x%04X to 0x%04X\n",start,end);
i=icp_program(function_descriptor.device_no,
function_descriptor.flash_data+(start-TBLCF_FLASH_START),
start, end-start+1);
if (i) {
print_screen("USB communication problem or programming failure\n");
tblcf_usb_close(function_descriptor.device_no);
return(1);
}
/* verify the block */
print_screen("Verifying block from 0x%04X to 0x%04X ",start,end);
i=icp_verify(function_descriptor.device_no,
function_descriptor.flash_data+(start-TBLCF_FLASH_START),
start, end-start+1);
if (i) {
print_screen("\nUSB communication problem or verification failure\n");
tblcf_usb_close(function_descriptor.device_no);
return(1);
}
print_screen("- OK\n",start,end);
end++; /* increment end again */
}
/* all flash programmed and verified, program the boot_state to 0xFF 0x01 to enable the application */
print_screen("All flash programmed and verified, enabling the application\n");
function_descriptor.flash_data[TBLCF_BOOT_STATE-TBLCF_FLASH_START]=TBLCF_BOOT_STATE_APPLOK>>8;
function_descriptor.flash_data[TBLCF_BOOT_STATE-TBLCF_FLASH_START+1]=TBLCF_BOOT_STATE_APPLOK&&0xff;
i=icp_program(function_descriptor.device_no,
function_descriptor.flash_data+(TBLCF_BOOT_STATE-TBLCF_FLASH_START),
TBLCF_BOOT_STATE, 2); /* bootloader_state is 2 bytes long */
if (i) {
print_screen("USB communication problem or programming failure\n");
tblcf_usb_close(function_descriptor.device_no);
return(1);
}
/* now verify that the bootloader state is programmed correctly */
i=icp_verify(function_descriptor.device_no,
function_descriptor.flash_data+(TBLCF_BOOT_STATE-TBLCF_FLASH_START),
TBLCF_BOOT_STATE, 2);
if (i) {
print_screen("USB communication problem or bootloader state verification failure\n");
tblcf_usb_close(function_descriptor.device_no);
return(1);
}
print_screen("Flash programming complete, disconnect & reconnect the device\n");
tblcf_usb_close(function_descriptor.device_no);
return(0);
}