flat assembler
Message board for the users of flat assembler.

flat assembler > Non-x86 architectures > [x51] Programming AT89S51 with another 8051 through ISP

Thread Post new topic Reply to topic

Joined: 25 Feb 2005
Posts: 1603
Location: Ukraine
The reason to do this is the trouble in usage of DIY or cheap programmers to program AT89S51 on modern computers. On the LPT era there was a cheapest and simpliest STK-200 programmer, which is supporting by all programmer's software and consists only of some wires at least, some resistors for more comprehensive, logical buffers and even led for most complete versions.
As the modern computers have poor IO capabilities reduced mostly to USB only, there is a problem appears. Some USB programmers made for Atmel supports AVR but not supports AT89S, other supports both but has only windows software.
So, when I met inexpectively that I can not program AT89S but I had to do this badly I decided to use my Olduino to solve this problem! So, it appeared not too complex as ISP protocol is described in each Atmel datasheet.

Here is a code to control MCU through ISP:
;======================================================================= ISP_SCK equ P3.5 ISP_MISO equ P3.4 ISP_MOSI equ P3.3 ISP_R equ P3.2 ;----------------------------------------------------------------------- macro ISP51 cmdl& iterate cmdb,cmdl mov A,#cmdb call isp51.xbyte end iterate end macro ;----------------------------------------------------------------------- isp51: .xbyte: push B mov B,#8 rlc A .xbyte_loop: mov ISP_MOSI,C mov R0,#50 ; SCK off delay djnz R0,$ setb ISP_SCK mov R0,#50 ; SCK on delay djnz R0,$ mov C,ISP_MISO clr ISP_SCK rlc A djnz B,.xbyte_loop pop B ret ;----------------------------------------------------------------------- .prog_enable: clr ISP_R clr ISP_SCK setb ISP_R mov R0,#30 call .delay_ms ISP51 10101100b,01010011b,0b,0b add A,#-01101001b ret .release: setb ISP_SCK clr ISP_R ret .read_sig: push ACC ISP51 00101000b pop ACC call .xbyte ISP51 0,0 ret .read_byte: ; R7:R6 - MCU addr ISP51 00100000b mov A,R7 call .xbyte mov A,R6 call .xbyte ISP51 0 ret .write_byte: ; R7:R6 - MCU addr xch A,B ISP51 01000000b mov A,R7 call .xbyte mov A,R6 call .xbyte xch A,B call .xbyte mov R0,#2 jmp .delay_ms .erase: ISP51 10101100b,10000000b,0b,0b mov R0,#100 jmp .delay_10ms .writex: ; R7:R6 - MCU addr, DPTR - mem addr, R5:R4 - block length mov A,R5 orl A,R4 jz .writex_done clr A movc A,@A+DPTR call .write_byte ;----------------------------------------------------------------------- call .read_byte xch A,B clr A movc A,@A+DPTR clr C subb A,B jnz .writex_done ;----------------------------------------------------------------------- inc DPTR mov A,R6 add A,#1 mov R6,A mov A,R7 addc A,#0 mov R7,A clr C mov A,R4 subb A,#1 mov R4,A mov A,R5 subb A,#0 mov R5,A jmp .writex .writex_done: ret ;======================================================================= ; delays with no timer usage ;----------------------------------------------------------------------- .delay_10ms: mov R1,#9 .delay_loop: call .delay_ms djnz R1,.delay_loop ;----------------------------------------------------------------------- .delay_ms: call .delay_x call .delay_x call .delay_x ;----------------------------------------------------------------------- .delay_x: mov R0,#0 djnz R0,$ ; 256 us ret ;=======================================================================

.xbyte - sends/recieves byte through ISP
.prog_enable - enters programming mode. this procedure substracts proper MCU responce, so, if success then accumulator contains zero value on return
.release - sets reset into inactive level (zero), so MCU may execute internal program without disconnection from programmer
.read_sig - reads signature byte
.read_byte - reads single byte from flash
.write_byte - writes single byte to flash
.erase - clears entire flash of MCU and lock bits
.writex - writes block into the flash byte by byte

As this code was made as quick solution, there is no subroutines for block reading, verifying flash or writing lock bits. If necessary their implementation is a bit trivial with this code.

Here is a part of code from s51uploader to write data from command memory (RAM for Olduino) into the AT89S51 flash:
mov DPTR,#buffer ;----------------------------------------------------------------------- call isp51.prog_enable jnz error call isp51.erase call isp51.writex jnz error ; jmp ok ;======================================================================= ok: ; led: long on & same long off mov A,#100 mov B,#100 jmp finish ;----------------------------------------------------------------------- error: ; led: short on & long off mov A,#5 mov B,#50 ;----------------------------------------------------------------------- finish: ; A:LED ON, B:LED OFF (1..256) x 10 ms ;----------------------------------------------------------------------- call isp51.release

NOTE: in-system programmer for AT89S51 must have strong pull-up to provide reset to target MCU as 8051 boards usually have capacitor and pull-down resistor for power-on reset, which may make reset impossible as internal pull-ups of x51 MCUs are weak (~40k). To be specific, my board has 10k pull-down resistor for RESET, thus I've been using 2k pull-up resistor on RESET wire for ISP programming.

UNICODE forever!
Post 07 Jul 2018, 19:02
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  

< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum

Copyright © 2004-2018, Tomasz Grysztar.

Powered by rwasa.