Binary input file is needed for programmer. SDCC has tool called makebin that does HEX to BIN conversion. There is no posibility (hardware limitation) to do programming verification. If programmer says "We are finished" Programming should be OK, otherwise error is issued on missing device or timeout.
#include "microdelay.h" #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <ctype.h> #include <sys/io.h> #include <sys/types.h> #include <fcntl.h> #define inc_bit 0x01 #define vpp_bit 0x02 #define prog_bit 0x04 /* not inverse */ #define erase_bit 0x08 #define prog_mode 0x0F #define erase_mode 0x07 #define idle 0x09 /* Idle, rst = 0 */ #define MEM_SIZE 2048 int main(int argc, char **argv) { // parallel programmer variables unsigned int port=0x378; unsigned char mem[MEM_SIZE]; int i, j, k, l, fd; /* check root privileges */ if (geteuid()!=0) { fprintf(stderr,"ERROR: this programs needs root permisions to access " "parallel port. Please use root user to run or setuid bit.\n"); abort(); } ioperm(port,3,1); microdelay_init(); //initialize microdelay function for (i = 0; i < MEM_SIZE; i++) mem[i] = 0xFF; fd = open(argv[1], O_RDONLY); if (!fd) { perror(argv[1]); outb(idle, port+2); outb(0x00, port); exit(2); } read(fd, mem, MEM_SIZE); close(fd); #define nms(x) microdelay((x)*1000) /* Erase */ outb(0xFF, port); outb(0x01, port+2); nms(10); outb(0x03, port+2); /* RST = 12 */ nms(1); outb(erase_mode, port+2); nms(1); outb(erase_mode^prog_bit, port+2); /* P3.2 = 0 */ nms(12); outb(erase_mode, port+2); /* P3.2 = 1 */ nms(12); outb(erase_mode ^ vpp_bit, port+2); /* RST = 0 */ nms(20); /* Program FLASH */ outb(idle, port+2); nms(10); outb(idle | vpp_bit, port+2); nms(10); outb(prog_mode, port+2); /* RST = 12, PROG = H */ nms(1); printf("Blowing"); k = 0; l = 0; for(j = 0; j < MEM_SIZE; j++) { outb(mem[j], port); if (mem[j] != 0xFF) { microdelay(2); /* PROG pulse */ outb(prog_mode ^ prog_bit, port+2); /* P3.2 = 0 */ microdelay(5); outb(prog_mode, port+2); /* P3.2 = 1 */ i = 0; while ( (inb(port+1) & 64) == 0) { microdelay(20); if (i > 200) { printf("Error, never ready?\n"); outb(idle, port+2); outb(0x00, port); exit(3); } if (i > k) k = i; i++; } if (l > 30) { printf("Error, no device?\n"); outb(idle, port+2); outb(0x00, port); exit(4); } if (i == 0) l++; microdelay(2); } outb(prog_mode ^ inc_bit, port+2); /* XT1 = 1 */ microdelay(5); outb(prog_mode, port+2); /* XT1 = 1 */ microdelay(2); if (j % 64 == 0) printf("."); } outb(0xFF, port); nms(1); outb(prog_mode ^ vpp_bit, port+2); /* P3.2 = 0 !! */ nms(1); outb(idle, port+2); outb(0x00, port); printf("\nWe are finished\n"); exit(0); }
/* Copyright (C) 2000-2001 José Roberto B. de A. Monteiro <jrm@autsens.com> and Pedro Zorzenon Neto <pzn@autsens.com> 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. */ #ifndef _MICRODELAY_H #define _MICRODELAY_H void microdelay_init(); void microdelay(unsigned int microsec); #endif
/* Copyright (C) 2000-2001 José Roberto B. de A. Monteiro <jrm@autsens.com> and Pedro Zorzenon Neto <pzn@autsens.com> 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. */ /* From http://www.linuxdoc.org/HOWTO/mini/IO-Port-Programming.html an outb to port 0x80 gives a delay of aprox 1microsec independent of your machine type/clock. See also documentation in asm/io.h */ #include "microdelay.h" #include <unistd.h> #include <sys/io.h> int old_port_value; void microdelay_init() { // permition to write in port 0x80 // nothing is suposed to use this port // however, we will write the same value we read... ioperm(0x80,1,1); old_port_value=inb(0x80); } void microdelay(unsigned int microsec) { while (microsec) { outb(old_port_value,0x80); microsec--; } }
Grzegorz Jaskiewicz suggested the following amendments (verification?) and flush of dotted output.:
--- bi2051.c 2003-04-29 17:01:35.000000000 +0200 +++ /tmp/bi2051.c 2006-06-08 13:43:05.000000000 +0200 @@ -23,7 +23,7 @@ unsigned int port=0x378; unsigned char mem[MEM_SIZE]; - int i, j, k, l, fd; + int i, j, k, l, fd, v; /* check root privileges */ @@ -117,14 +117,24 @@ if (i == 0) l++; + + v = inb(port); + if ( mem[j] != v ) { + printf("verification failed\n"); + exit(5); + } microdelay(2); } + + outb(prog_mode ^ inc_bit, port+2); /* XT1 = 1 */ microdelay(5); outb(prog_mode, port+2); /* XT1 = 1 */ microdelay(2); - if (j % 64 == 0) + if (j % 64 == 0) { + fflush(stdout); printf("."); + } } outb(0xFF, port); nms(1);