/* Easy-Downloader V3.0 for ATMEL 89C51/52/55WD Copyright(c) 2002 By Wichit Sirichote kswichit@kmitl.ac.th The source code was compiled with Dunfiled Micro-C V3.2 for 8051, TINY model. */ #include <8051io.h> #include <8051reg.h> #include <8051bit.h> #define xon 0x11 #define xoff 0x13 #define Vpp P3.3 // set Vpp = +5V clear Vpp = +12.5V #define prog P2.7 // map materchip i/o port to the mode selection on ZIF #define p26 P3.4 #define p27 P3.5 #define p33 P3.2 #define p36 P3.6 #define p37 P3.7 #define Vtarget P1.5 // Vtarget set = +5V, clr = +6.5V #define RDY P1.6 #define ALE P1.7 #define RTS P1.3 #define CTS P1.4 #define power P1.2 // power set = power down, clear = power up register int i; unsigned register char ACCU,temp,blank,chip,VPP; register char command; register unsigned int address,chksum; char title[] = "\n Easy-Downloader V3.0 for ATMEL 89C51/52/55WD" char prompt[] = "\n >" char ok[] = "\n ok" unsigned register int count,bytes,nonblank; main() { i = 0; count = 0; serinit(9600); getch(); putstr(title); sendprompt(); // clrbit(power); for(;;) { getcommand(); prompting(); setcounter(); erase(); write(); read(); lock(); read_lock_bit(); printchksum(); getinfo(); PGMparameters(); } } getnum() { char s[6]; /* five characters plus terminator */ char c; int i; c = 0; for (i = 0; c != 10; i++) { putch(xon); c = putchr(getch()); s[i] = c; } s[i] = '\0'; /* put end-of-string to the last byte */ if (i==0) return (-1); else return (_atoi(s)); } getcommand() { if ((SCON & 0x01) != 0) command = putchr(getch()); else command = -1; /* no cammand has entered */ } getconsole() { if ((SCON & 0x01) != 0) command = getchr(); else command = -1; } putok() { powerdown(); putstr(ok); sendprompt(); } sendprompt() { putstr(prompt); } prompting() { if (command == '\n') { putstr(title); sendprompt(); } } powerup() { clrbit(power); delay(100); } powerdown() { setbit(power); delay(100); } erase() { if (command == 'e') { powerup(); setbit(Vpp) setbit(p26) clrbit(p27) setbit(p33) clrbit(p36) clrbit(p37) delay10us(); clrbit(Vpp) delay(100); // raise Vpp from +5V to +12.5V if(chip == 0x55) { clrbit(Vtarget) // raise Vtarget from +5V to +6.5V delay(100); clrbit(prog) asm" NOP"; // actual erase pulse was 200ns-500ns setbit(prog) delay(150); setbit(power) // turn power down delay(100); clrbit(power) delay(100); clrbit(prog) asm" NOP"; // actual erase pulse was 200ns-500ns setbit(prog) delay(150); setbit(power); delay(100); clrbit(power); setbit(Vtarget) // bring back to +5V } else { clrbit(prog) delay(10); /* 10 ms prog pulse */ setbit(prog) } delay(10); setbit(Vpp) delay(100); putok(); } } char low_level_read() { asm{ mov P0,address setb ALE nop nop nop nop clr ALE nop nop nop nop mov A,address+1 orl A,#$80 mov P2,A } clrbit(p27) P0 = 0xFF; /* put FF before read back */ return(P0); } write() /* call sequence before write: 's', 't','e','w' */ { if (command == 'w') { powerup(); setbit(Vtarget) clrbit(ALE) setbit(Vpp) clrbit(p26) setbit(p27) setbit(p33) setbit(p36) setbit(p37) setbit(prog) delay10us(); // if (VPP == 0xff) /* skip if VPP != 0xff,i.e., need 5Vpp for programming */ clrbit(Vpp) delay(100); /* raise programming voltage to 12V */ chksum = 0; for (i = 0; i < count; i++) { /* use XON & XOFF flow control */ putch(xon); /* send XON */ address = i; asm{ mov P0,address setb ALE nop nop nop nop clr ALE nop nop nop nop mov A,address+1 orl A,#$80 mov P2,A } delay10us(); P0 = getchr(); /* read raw bytes from console */ putch(xoff); /* send XOFF */ chksum += P0; /* summing chksum */ pulseProg(); if(chip == 0x55) asm " jnb P1.6,*"; // for 89C55WD else { asm " setb P2.6"; // switch P2.6 to input bit for RDY/BSY status of asm " jnb P2.6,*"; // 89C51 and 89C52 } } setbit(Vpp) /* bring Vpp back to 5V */ delay(100); putok(); } } read() /* read according to number of bytes by 'c' command */ { unsigned int i; if (command=='r') { chksum = 0; /* reset check sum word */ powerup(); setbit(Vtarget) clrbit(ALE) setbit(Vpp) setbit(prog) clrbit(p26) setbit(p27) clrbit(p33) setbit(p36) setbit(p37) blank = '1'; for(i = 0; i < count; i++) { address = i; temp = low_level_read(); chksum += temp; printA(temp); /* read in HEX */ setbit(p27) chkXOFF(); } putok(); } } printA(char n) //char n; { ACCU = n; ACCU >>= 4; /* shift right 4 bits */ putHEX(); ACCU = n&15; putHEX(); } chkXOFF() /* use XON and XOFF for controlling flow with host */ { if(getconsole() == xoff) { do ; while(getconsole() != xon); } } putHEX() { if (ACCU > 9) putch(ACCU+55); else putch(ACCU+48); } blanktest() /* if all bytes are 0FFH then blank =FF, else blank = 0 */ { if (P0 != 0xff) { blank = '0'; /* full */ nonblank++; } } read_lock_bit() { if(command == 'b') { powerup(); setbit(p26) setbit(p27) clrbit(p33) setbit(p36) clrbit(p37) P0= 0xFF; temp = P0; temp &= 0x1C; printf("\n lock bit 1,2,3 = %03b",temp>>2); putok(); } } lock() /* only protection mode 4 can be programmed,i.e., disabled further program, verify, and external execution */ { if (command == 'l') { powerup(); clrbit(Vpp) if(chip==0x55) clrbit(Vtarget) // if chip = 89C55WD, raise Vtarget from +5V to +6.5V setbit(prog) setbit(p26) setbit(p27) setbit(p33) setbit(p36) setbit(p37) delay(100); lock_pulse(); // write lock bit 1 delay(5); clrbit(p36) clrbit(p37) delay10us(); lock_pulse(); // write lock bit 2 delay(5); clrbit(p27) setbit(p36) clrbit(p37) // write lock bit 3 delay10us(); lock_pulse(); delay(5); setbit(power); delay(100); clrbit(power); setbit(Vtarget) // bring back Vtraget to +5V setbit(p27) // float data bus putok(); } } printchksum() { if (command == 'c') { printf("\n CHKSUM = %04x",~chksum+1); putok(); } } signature() /* read signature ATMEL chip 51/52/55 12V or 5V Vpp */ { powerup(); clrbit(ALE) setbit(Vtarget) setbit(Vpp) setbit(prog) clrbit(p26) setbit(p27) clrbit(p33) clrbit(p36) clrbit(p37) address = 0x31; // location stores ATMEL ID for 89C51 and 89C52 chip = low_level_read(); delay10us(); // if chip = 0xFF, try with address 0x100 for 89C55WD also if(chip ==0xFF) { address = 0x100; // stores ATMEL device ID 0x55 for 89C55WD chip = low_level_read(); // printf("\n %04x = %02x ",address,chip); } // address++; VPP = 0xFF; /* save Vpp 12V (FF) or 5V (5) into VPP */ // printf("\n VPP = %02x ",VPP); setbit(p27) } testblank() /* need to call signature function pior calling testblank */ { signature(); switch(chip){ case (0x51): /* 89C51 */ bytes = 4096; /* if chip == 0x51 or 0x61 then bytes = 4kB */ break; case (0x61): /* 89LV51 */ bytes = 4096; break; case (0x52): /* 89C52 */ bytes = 8192; /* if chip == 0x52 or 0x62 then bytes = 8kB */ break; case (0x62): /* 89LV52 */ bytes = 8192; break; case (0x55): /* 89C55 */ bytes = 20480; /* if chip == 0x55 or 0x65 then bytes = 20kB */ break; case (0x65): /* 89LV55 */ bytes = 20480; break; case 0xff: bytes = 0; } chksum = 0; /* reset check sum word */ nonblank = 0; /* reset nonblank bytes counter */ setbit(Vpp) setbit(prog) clrbit(p26) setbit(p27) clrbit(p33) setbit(p36) setbit(p37) blank = '1'; for(i = 0; i < bytes; i++) { address = i; temp = low_level_read(); chksum += temp; blanktest(); setbit(p27) /* next address */ } } setcounter() { if (command == 's') { count = getnum(); putok(); } } getinfo() { if (command =='g') { testblank(); if(chip!=0xff) { printf("\n found 89C%2x",chip); if (VPP==0xff) putstr("-12V"); if (VPP==5) putstr("-5V"); printf("\n nonblank %u bytes",nonblank); printf("\n bytes counter %u",count); } else(putstr("\n Not found 89Cxx")); putok(); } } PGMparameters() /* for simple host interfacing */ { if (command=='p') { testblank(); printf("%x,%u,%u",chip,nonblank,count); putok(); } } /* printhelp() { if (command == '?') { putstr("\n e erase"); putstr("\n rb read BIN"); putstr("\n rh read HEX"); putstr("\n w write"); putstr("\n l lock"); } putok(); } */ pulseProg() { if(chip ==0x55) { clrbit(prog) asm" nop"; setbit(prog) } else { clrbit(prog) asm " nop"; asm " nop"; asm " nop"; setbit(prog) } } lock_pulse() { clrbit(prog) delay100us(); setbit(prog) } delay10us() { int i; for (i=0;i<1;i++); } delay100us() { int i; for (i=0; i<20;i++); }