$MOD550 ; MMU-controlling pins, after RESET MODE0=1 and MODE1=1 MODE0 equ P3.4 MODE1 equ P3.3 ; Memory pointer POINTER equ R0 ; Record type RECORD_TYPE equ R2 ; Counter for different routines COUNTER equ R3 ; Checksum calculated for received data CHKSUM equ R4 ; Flag used by memory test MEMTEST equ R5 ; Number of bytes in received record NUM_OF_BYTES data 40h ; Received checksum CHKSUM2 data 41H ; Temporary variable TEMP data 42h ; Higher and lower bytes of target address of received record ADRL data 43H ADRH data 44H ; Stack location STACKADR equ 08h ; Data buffer (here are placed received by serial interface data) BUFOR data 46h org 0 ;After memory is switched over ajmp INIT ;these vectors are available above 8000h org 3 ;And provide access to: ajmp WAIT_FOR_NEW_RECORD ; Downloading procedure org 6 setb MODE0 ; "Warm" restart ljmp 0H org 100h ;Prepare hardware for work INIT: ; Clear registers clr A mov PSW,A mov TCON,A mov IE,A mov SCON,A ; Set stack pointer mov SP,#STACKADR ; Set SFR registers mov TMOD,#20H ; Timer 1: 8-bit auto-reload timer mov TH1,#0FAH ; Set transmission rate to 10417 bit/s mov TL1,TH1 ; (this value is the best suited to IBM RS232, orl PCON,#80H ; from all high speeds available in 8051 for 12 MHz XTAL) setb TR1 ; Switch on timer 1 mov SCON,#40H ; 8-bit UART setb REN clr RI clr TI ;The hardware is ready - send the prompt character and receive program call SEND_PROMPT sjmp WAIT_FOR_NEW_RECORD ;Following procedures send to the host computer error messages ;Error "Transmitted data couldn't be downloaded to the RAM" MEMORY_WRITE_ERROR: jnb TI,$ clr TI mov SBUF,#'#' sjmp WAIT_FOR_NEW_RECORD ;Error "Transmission or protocol error" RECEIVE_ERROR: jnb TI,$ clr TI mov SBUF,#'?' ;This procedure receives new hex-record WAIT_FOR_NEW_RECORD: jnb RI,$ mov A,SBUF clr RI cjne A,#':',RECEIVE_ERROR NEW_HEX_RECORD: ;Because sometimes, after an error, processor jumps here from inside ; of other procedures, at first we have to clean up the stack mov SP,#STACKADR mov CHKSUM,#0 acall GETBYTE_CHK mov NUM_OF_BYTES,A ;Number of bytes in record received acall GETBYTE_CHK mov ADRH,A acall GETBYTE_CHK mov ADRL,A ;Target address of record data received acall GETBYTE_CHK mov RECORD_TYPE,A mov COUNTER,NUM_OF_BYTES mov POINTER,#BUFOR NEXT_BYTE: cjne COUNTER,#0,NEXT_BYTE_TO_BUFFER ;If jump is not performed - the last byte is received, ;so we have to receive and check the checksum. acall GETBYTE_CHK mov CHKSUM2,A cjne CHKSUM,#0,RECEIVE_ERROR cjne RECORD_TYPE,#0,PROBABLY_END_RECORD acall TRANSFER_BUFFER_DATA cjne MEMTEST,#0ffh,BUFOR_OK ;Check if data are correctly written to RAM ajmp MEMORY_WRITE_ERROR BUFOR_OK: acall SEND_ACK sjmp WAIT_FOR_NEW_RECORD ;Prepare for reception of next record NEXT_BYTE_TO_BUFFER: acall GETBYTE_CHK mov @POINTER,A inc POINTER dec COUNTER sjmp NEXT_BYTE PROBABLY_END_RECORD: cjne RECORD_TYPE,#1,RECEIVE_ERROR acall SEND_ACK jnb TI,$ ;After acknowledge has been sent, jump to the program start procedure ;found in the higher half of code memory (because the lower part of ;code memory is to be switched over). ljmp 8000h+PROGRAM_RUN ; This procedure transfers the received record to the target address in RAM ; TRANSFER_BUFFER_DATA: mov A,ADRH orl A,#80h ;Add 80h, because RAM found in the higher half of data space ;will be seen in the lower half of code space, after memory ;is switched over mov DPH,A mov DPL,ADRL mov POINTER,#BUFOR mov COUNTER,NUM_OF_BYTES TRANSFER_LOOP: cjne COUNTER,#0,TRANSFER_NEXT sjmp CHECK_BUFFER TRANSFER_NEXT: mov A,@POINTER movx @DPTR,A inc POINTER inc DPTR dec COUNTER sjmp TRANSFER_LOOP CHECK_BUFFER: mov MEMTEST,#0ffh mov A,ADRH orl A,#80h mov DPH,A mov DPL,ADRL mov POINTER,#BUFOR mov COUNTER,NUM_OF_BYTES CHECK_LOOP: cjne COUNTER,#0,CHECK_NEXT mov MEMTEST,#0 CHECK_RET: ret CHECK_NEXT: movx A,@DPTR mov TEMP,@POINTER cjne A,TEMP,CHECK_RET inc POINTER inc DPTR dec COUNTER sjmp CHECK_LOOP ; ; This procedure starts execution of loaded program ; PROGRAM_RUN: clr MODE0 mov r0,#0ffh START_DELAY: mov r1,#0ffh djnz r1,$ djnz r0,START_DELAY push ADRL push ADRH ret ; This procedure receives hex-byte and modifies checksum ; In the case of error this procedure does not return but ; jumps to the RECEIVE_ERROR GETBYTE_CHK: acall GETBYTE push ACC add A,CHKSUM mov CHKSUM,A pop ACC ret ; This procedure sends positive acknowledge to the host SEND_ACK: jnb TI,$ clr TI mov SBUF,#'!' ; This char is acknowlegment's header jnb TI,$ clr TI mov SBUF,ADRH ; Send address of downloaded data jnb TI,$ clr TI mov SBUF,ADRL jnb TI,$ clr TI mov SBUF,CHKSUM2 ; Send received chksum ret ;This procedure receives hex-byte GETBYTE: acall GETTETR cjne A,#0ffh,GB_NEXT1 ajmp RECEIVE_ERROR GB_NEXT1: swap A mov TEMP,A acall GETTETR cjne A,#0ffh,GB_NEXT2 ajmp RECEIVE_ERROR GB_NEXT2: orl A,TEMP ret ;This procedure receives one nibble of byte ; If an ':' character is received, this procedure does not return, ; but jumps directly to the NEW_HEX_RECORD label GETTETR: jnb RI,$ mov A,SBUF clr RI cjne A,#':',GT_NEXT ajmp NEW_HEX_RECORD GT_NEXT: cjne A,#'0',$+3 jc GT_ERROR cjne A,#'9'+1,$+3 jnc GT_IS_A_TO_F? subb A,#'0'-1 ;(Carry is already set) ret GT_IS_A_TO_F?: cjne A,#'A',$+3 jc GT_ERROR cjne A,#'F'+1,$+3 jnc GT_ERROR subb A,#'A'-11 ;(Carry is already set) ret GT_ERROR: mov A,#0ffh ret ; This procedure sends prompt to the host computer SEND_PROMPT: mov DPTR,#PROMPT clr A movc A,@A+DPTR mov SBUF,A ; Send always at least one char SP_LOOP: inc DPTR clr A movc A,@A+DPTR jz SP_RET jnb TI,$ clr TI mov SBUF,A sjmp SP_LOOP SP_RET: ret ; This is the prompt message, sent to the host after EV51WZ1 is switched on PROMPT: DB 'EV550WZ1 (c) W.M.Zabolotny 09.1999' DB 10,13 DB 'This loader is available under the "Artistic Licence"' DB 10,13 DB 'see http://language.perl.com/misc/Artistic.html for details' DB 10,13 DB 'Ready' DB 10,13,0 END