Spare Time Labs 2.0 | |
Welcome EazyCNC jDraft 2.0 PureJavaComm PIC CDC ACM Weather Ten-Buck Furnace
H8S Bootloader
Camera Calibration
Multitouch
Myford VFD Fun with HC08 bl08 printf II Java Goes Native
Densitometer printf jApp Igloo New Furnace New Furnace Part II Linux 101 H8S/gcc Quickie Gas Fired Furnace Down Memory Lane Exlibris Wheel Patterns Glitches CHIP-8 eDice Animato jDraft JNA Benchmark Contact Info |
Created 15.4.2009
A Bootloader for Renesas H8SA few years ago I wrote a simple bootloader with built in terminal emulator for Renesas H8S processor that I was working with at the time. It is not a big deal, just a simple commmand line tool to get the job done. It reads an S-record file and downloads it via serial port to the target CPU. Just something I wrote in about an hour. However, it has one big merit in my eyes, it is a single file that you should be able to compile and build by just typing the following in your shell (in any reasonable operating system that is):
You can download the code from here or browse it at the end of this page.
If you are into Renesas H8S processors you might be interested in the following pages:
and That's all folks, cheers Kusti /* File: bload.c Copyright (C) 2004 Kustaa Nyholm 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.0 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 Lesser 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 <fcntl.h> #include <termios.h> #include <stdio.h> #include <unistd.h> #include <sys/time.h> #include <sys/types.h> #include <time.h> #include <string.h> #include <stdlib.h> #define DEFAULT_COM "/dev/ttyS0" #define DEFAULT_FILENAME "boot.sr" #define DEFAULT_BASE 0xFFE400 int outcnt=0; char verbose=0; char quiet=0; void putChar(int com,unsigned char ch) { if (verbose) printf("%02X ",ch); else if (!quiet) printf("."); write(com, &ch, 1); if (++outcnt>=16) { outcnt=0; if (verbose || !quiet) printf("\n"); } } void setCommPort(char* comname,int com) { static struct termios pts; int pfda; tcgetattr(com, &pts); pts.c_lflag &= ~ICANON; pts.c_lflag &= ~(ECHO | ECHOCTL | ECHONL); pts.c_cflag |= HUPCL | CLOCAL | CREAD; pts.c_cflag &= ~PARENB; pts.c_cflag &= ~PARODD; pts.c_cflag &= ~CSIZE; pts.c_cflag |= CS8; pts.c_cc[VMIN] = 1; pts.c_cc[VTIME] = 0; pts.c_oflag &= ~ONLCR; pts.c_iflag &= ~ICRNL; cfsetospeed(&pts, B9600); cfsetispeed(&pts, B9600); if (tcsetattr(com,TCSANOW,&pts)!=0) { perror(comname); exit(-1); } } char* getArg(int argc, char *argv[],char chr) { int i; for (i=1; i<argc; ++i) if ((argv[i][0]=='-') && (argv[i][1]==chr)) return &(argv[i][2]); return NULL; } void termEmu(int com, char* args) { // get rid of stuff that has been echoed to us tcflush(com,TCIFLUSH ); // .. then get rid of the echoes and what ever... int con= open("/dev/console", O_RDWR ); if (con <0) {perror("/dev/console"); exit(-1); } printf("\nTerminal mode, press CTRL-C to exit.\n"); struct termios newtio,oldtio; tcgetattr(con,&oldtio); // we do not want to change the console setting forever, so keep the old tcgetattr(con,&newtio); // configure the console to return as soon as it a key is pressed newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 1; tcsetattr(con,TCSANOW,&newtio); fd_set readfs; int maxfd; int res; char buf[2]; maxfd = (con>com ? con : com)+1; while (1) { // wait for something from console or serial port FD_SET(con, &readfs); FD_SET(com, &readfs); struct timeval tout; tout.tv_usec = 10; tout.tv_sec = 0; select(maxfd, &readfs, NULL, NULL, &tout); // copy console stuff to the serial port if (FD_ISSET(con,&readfs)) { res=read(con,buf,1); if (buf[0]==3) break; // CTRL-C terminates terminal mode write(com,buf,res); } // copy serial port stuff to console if (FD_ISSET(com,&readfs)){ res=read(com,buf,1); write(con,buf,res); } } tcsetattr(con,TCSANOW,&oldtio); // restore console settings close(con); } void delay(int delay) { time_t t0=clock(); while (clock()-t0<CLOCKS_PER_SEC*delay/1000) ; } int main(int argc, char *argv[]) { unsigned char bcode[0x20000]; // 128kB char* comname=DEFAULT_COM; char* filename=DEFAULT_FILENAME; int base=DEFAULT_BASE; int size=0x1780; char * arg; char * termargs; int termMode=0; int dly=0; int sum; arg=getArg(argc,argv,'-'); if (arg && strcmp(arg,"help")==0) { printf("Usage: \n"); printf(" bload [-b address] [-s size] [-c comport] [-q] [-n] [srecord filename]\n"); printf(" -b address to rip from \n"); printf(" -s max rip size\n"); printf(" -c comm port/device to dump to\n"); printf(" -C send check sum (sum of all data bytes sent)\n"); printf(" -n do not set commport baud, char size, parity, use comm port 'as is' \n"); printf(" -v verbose operation\n"); printf(" -q quiet operation\n"); printf(" -d delay n msec after download (before exit or terminal mode (\n"); printf(" -t enter terminal mode after download\n"); printf(" -T enter terminal mode without download\n"); printf(" Commport is set, if '-n' option NOT used, to 9600 baud, 8 bit char size, no parity, one stop bit, no handshake\n"); printf(" No space between option and value, for example -b10000, not -b 10000\n"); printf(" Address and size must be in hexadecimal\n"); printf(" If no arguments given, then a default file name used, otherwise filename required\n"); printf("Example (same as using all defaults):\n"); printf(" bload -b%X -s%X -c%s %s\n",base,size,comname,filename); return 0; } int i; for (i=1; i<argc; i++) { if (argc>1 && (argv[i][0]!='-')) filename=argv[i]; } arg=getArg(argc,argv,'b'); if (arg) sscanf(arg,"%x",&base); arg=getArg(argc,argv,'s'); if (arg) sscanf(arg,"%x",&size); arg=getArg(argc,argv,'c'); if (arg) comname=arg; arg=getArg(argc,argv,'d'); if (arg) sscanf(arg,"%d",&dly); arg=getArg(argc,argv,'t'); if (arg) { termMode=1; termargs=arg; } arg=getArg(argc,argv,'T'); if (arg) { termMode=2; termargs=arg; } verbose=getArg(argc,argv,'v')!=NULL; quiet=getArg(argc,argv,'q')!=NULL; if (quiet) verbose=0; if (verbose) { printf("This program reads in a S-record froms file '%s' and \n",filename); printf("rips code from address range %06X..%06X and \n",base,base+size-1); printf("dumps it to '%s' in the H8S2357 boot mode compatible format.\n",comname); printf("This is a blind dump, this does not wait for the H8S to respond.\n"); printf("\n"); printf("Reading in boot code...\n"); } int c, n; struct termios options; char ob[]={0,0,0,0,0}; char ib[1]; int com= open(comname, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); if (com <0) {perror(comname); exit(-1); } if (!getArg(argc,argv,'n')) setCommPort(comname,com); if (termMode==2) { termEmu(com,termargs); exit(0); } FILE* sf=fopen(filename,"r"); if (sf==NULL) { printf("Failed to open '%s'\n",filename); exit(-1); } memset(bcode,0xff,sizeof(bcode)); char line[80]; int amax=0; while (fgets(line,255,sf)!=NULL) { if (verbose) printf("%s",line); if (line[0]=='S') { int n,a,o=0; sscanf(line+2,"%2x",&n); n--; if (line[1]=='1') { sscanf(line+4,"%4x",&a); n=n-2; o=8; } if (line[1]=='2') { sscanf(line+4,"%6x",&a); n=n-4; o=10; } if (o!=0) { int i; for (i=0; i<n; ++i) { int d; sscanf(line+o+i*2,"%2x",&d); if ( (a>=base) && (a<base+size)) { bcode[a-base]=d; a++; amax= a>amax ? a : amax; } } } else if (!quiet) printf("Ignored S-record: %s\n",line); } } fclose(sf); if (verbose) printf("\n"); int dlen=amax-base; if (dlen<0) { printf("Nothing to download, no S-records in address range %06X..%06X\n",base,base+size-1); exit(-1); } if (verbose) printf("Sending boot mode bitrate adjustment and acknowledge bytes...\n"); putChar(com,0x00); putChar(com,0x00); putChar(com,0x00); putChar(com,0x00); putChar(com,0x00); putChar(com,0x55); if (verbose) printf("\n"); if (verbose) printf("\n"); outcnt=0; if (verbose) printf("Sending boot code length bytes...\n"); putChar(com,dlen/256); putChar(com,dlen%256); if (verbose) printf("\n"); if (verbose) printf("\n"); outcnt=0; if (verbose) printf("Downloading %d bytes of boot code...\n",dlen); for (i=0; i<dlen; ++i) { putChar(com,bcode[i]); sum+=bcode[i]; } if (getArg(argc,argv,'C')) { sum=sum&0xFF; if (verbose) printf("\nSending check sum ...\n"); putChar(com,sum); } if (!quiet || verbose) printf("\n\n"); if (verbose) printf("Done downloading %d bytes, the H8S should be executing the code by now!\n",dlen); tcdrain(com); // wait until we have transmitted all... if (dly) delay(dly); if (termMode) termEmu(com,termargs); close(com); } syntax highlighted by Code2HTML, v. 0.9.1 |