123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; 8051dumper.asm: Dump internal ROM contents of 8051 to serial port.
- ;;
- ;;
- PROCESSOR 8051
- INCLUDE "SFR.asm"
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; GPIOs
- ;;
- OUT_EA ALIAS "P1.0" ; Inverted and connected to EAn pin
- OUT_REDLEDn ALIAS "P1.1" ; Red LED in RESET button
- OUT_GRNLEDn ALIAS "P1.2" ; Green LED in START button
- IN_GRNBTNn ALIAS "P1.3" ; Green START button
- IN_R32Kn ALIAS "P1.4" ; Dump size knob: 8058 (32k)
- IN_R16Kn ALIAS "P1.5" ; Dump size knob: 8054 (16k)
- IN_R8Kn ALIAS "P1.6" ; Dump size knob: 8052 (8k)
- IN_R4Kn ALIAS "P1.7" ; Dump size knob: 8051 (4k)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Internal RAM (uninitialized data segment)
- ;;
- SEGU "IRAM"
- ; 0x00..0x1F contains the four register banks.
- ; 0x20..0x2F is the bit addressable area.
- ; 0x30..0x7F is the scratch pad area.
- ORG 0x0030
- IROMSIZE: DS 1 ; High byte of internal ROM size
- CKSUM: DS 1 ; Checksum accumulator for line
- HINYBBLE: DS 1 ; Temp buffer for HEXBYTE
- LONYBBLE: DS 1 ; Temp buffer for HEXBYTE
- ; Intel Hex line buffer for 16 byte record
- BUF_START: DS 1 ; Start code ":"
- BUF_BYTECOUNT: DS 2 ; Byte count "10"
- BUF_ADDR: DS 4 ; Start address of record
- BUF_RECTYPE: DS 1 ; Record type
- BUF_DATA: DS 32 ; Record data
- BUF_CKSUM: DS 2 ; Checksum
- BUF_EOL: DS 3 ; CRLF and terminating NUL
- ; Rest of RAM is stack. Initial stack pointer should be 1 byte before
- ; beginning of stack because PUSH operations pre-increment the stack pointer.
- STACK: DS 0x0080-$
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Code segment starting at base of external program memory EEPROM
- ;;
- SEG "code"
- ; Reset vector (3 bytes)
- ORG 0x0000
- RESET: LJMP MAIN
- ; External Request 0 Interrupt Service Routine (8 bytes)
- ORG 0x0003
- ER0_ISR: LJMP ERROR
- ; Internal Timer/Counter 0 Interrupt Service Routine (8 bytes)
- ORG 0x000B
- ITC0_ISR: LJMP ERROR
- ; External Request 1 Interrupt Service Routine (8 bytes)
- ORG 0x0013
- ER1_ISR: LJMP ERROR
- ; Internal Timer/Counter 1 Interrupt Service Routine (8 bytes)
- ORG 0x001B
- ITC1_ISR: LJMP ERROR
- ; Internal Serial Port Interrupt Service Routine (8 bytes)
- ORG 0x0023
- ISP_ISR: LJMP ERROR
- ; 8052 TF2 and EXF2 Interrupt Service Routine (8 bytes)
- ORG 0x002B
- TF2_ISR: LJMP ERROR
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Following code/data will be accessed in a mirror image of the 32k EEPROM
- ;; at 0x8000. We will raise the EAn pin with a GPIO in order to overlay
- ;; internal ROM at address 0x0000. We will not use any interrupts because
- ;; interrupt vectors will contain unpredictable code from internal ROM.
- ;;
- ORG 0x0032
- RORG 0x8032
- IDSTR: DB "8051dumper v1.0 by NF6X", 0x0D, 0x0A, 0x00
- KNOBSTR: DB "ERROR: Could not read ROM size knob!", 0x0D, 0x0A, 0x00
- ENDSTR: DB ":00000001FF", 0x0D, 0x0A, 0x00
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Main entry point
- ;;
- MAIN:
- MOV IE, #0x00 ; Disable all interrupts
- MOV P1, #0xFF ; GPIOs all input/high
- MOV SP, #STACK-1 ; Initialize stack pointer
- CLR OUT_EA ; Select INTERNAL ROM at 0x0000
- ; Configure serial port for Mode 1, 9600 8n1
- ; SMOD = 0 ==> K = 1
- ; Oscillator frequency = 11.0592 MHz
- ; TH1 = 256 - (K * Fosc)/(32 * 12 * Baud)
- ; TH1 = 256 - (1 * 11059200)/(32 * 12 * 9600) = 253 = 0xFD
- MOV PCON, #0x00 ; SMOD = 0
- MOV SCON, #0x50 ; Mode 1
- MOV TMOD, #0x21 ; T1: Mode 2, T0: Mode 1
- MOV TH1, #0xFD ; 9600 baud
- MOV TL1, #0xFD ; 9600 baud
- SETB TCON_TR1 ; Enable timer
- ; Send ID string
- MOV DPTR, #IDSTR
- ACALL SENDROM
- ; Blink green LED until green START button pressed.
- ; Flash LED 2x per second at 20% duty cycle, checking
- ; button every 100ms.
- WAITSTART: CLR OUT_GRNLEDn ; On for 100ms
- ACALL DELAY100ms
- JNB IN_GRNBTNn, READKNOB ; Button pressed?
- SETB OUT_GRNLEDn ; Off for 400ms
- ACALL DELAY100ms
- JNB IN_GRNBTNn, READKNOB ; Button pressed?
- ACALL DELAY100ms
- JNB IN_GRNBTNn, READKNOB ; Button pressed?
- ACALL DELAY100ms
- JNB IN_GRNBTNn, READKNOB ; Button pressed?
- ACALL DELAY100ms
- JNB IN_GRNBTNn, READKNOB ; Button pressed?
- SJMP WAITSTART
- ; Read dump size knob and begin dumping code.
- READKNOB: SETB OUT_GRNLEDn ; Green LED off
-
- .TST32K: JB IN_R32Kn, .TST16K ; Knob set to 32k?
- MOV IROMSIZE, #0x80 ; Yes, 32k
- SJMP INITBUF
- .TST16K: JB IN_R16Kn, .TST8K ; Knob set to 16k?
- MOV IROMSIZE, #0x40 ; Yes, 16k
- SJMP INITBUF
- .TST8K: JB IN_R8Kn, .TST4K ; Knob set to 8k?
- MOV IROMSIZE, #0x20 ; Yes, 8k
- SJMP INITBUF
- .TST4K: JB IN_R4Kn, .TSTFAIL ; Knob set to 4k?
- MOV IROMSIZE, #0x10 ; Yes, 4k
- SJMP INITBUF
- .TSTFAIL: MOV DPTR, #KNOBSTR ; Cannot read knob!
- ACALL SENDROM
- LJMP ERROR
- ; Initialize the line buffer and ROM data pointer
- INITBUF: MOV BUF_START, #':'
- MOV BUF_BYTECOUNT, #'1'
- MOV BUF_BYTECOUNT+1, #'0'
- MOV BUF_EOL, #0x0D
- MOV BUF_EOL+1, #0x0A
- MOV BUF_EOL+2, #0x00
- MOV DPTR, #0000
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Dump one Intel Hex record of 16 bytes at a time until done.
- ;; Toggle red LED for each line to show activity.
- ;;
- DUMPLOOP: MOV A, DPH ; Has DPTR hit end of IROM?
- CJNE A, IROMSIZE, DUMPRECORD
- SJMP EOF ; Finished with IROM
- ; Dump one 16-byte record
- DUMPRECORD:
- CPL OUT_REDLEDn
- MOV CKSUM, #0x10 ; Init checksum w/ record length
- MOV R0, #BUF_ADDR ; Point to address field
- MOV A, DPH ; High address byte
- ACALL HEXBYTE
- MOV A, DPL ; Low address byte
- ACALL HEXBYTE
- CLR A ; Record type
- ACALL HEXBYTE
- DUMPBYTE: CLR A ; Read byte from IROM
- MOVC A, @A+DPTR
- ACALL HEXBYTE ; Add it to line buffer
- MOV A, DPL ; End of record?
- ANL A, #0x0F
- CLR C
- SUBB A, #0x0F
- JZ EOR ; Yes, at end of 16-byte record
- INC DPTR ; No, increment IROM pointer
- SJMP DUMPBYTE ; Add next byte
- EOR: MOV A, CKSUM ; Add checksum to record
- CPL A
- ADD A, #1
- ACALL HEXBYTE
- ACALL SENDRECORD ; Send out this record
- INC DPTR
- SJMP DUMPLOOP
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Send out end of file record, turn green LED on and red LED off,
- ;; and loop forever.
- ;;
- EOF: MOV DPTR, #ENDSTR
- ACALL SENDROM
- CLR OUT_GRNLEDn ; Green LED on
- SETB OUT_REDLEDn ; Red LED off
- SJMP $
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Add hex representation of A to buffer at R0 and accumulate checksum.
- ;;
- HEXBYTE: MOV HINYBBLE, A ; Add byte to checksum
- MOV LONYBBLE, A
- ADD A, CKSUM
- MOV CKSUM, A
- MOV A, HINYBBLE ; Isolate high nybble
- SWAP A
- ANL A, #0x0F
- ADD A, #'0'
- MOV HINYBBLE, A
- CLR C
- SUBB A, #':'
- JC .LO
- MOV A, HINYBBLE
- ADD A, #7
- MOV HINYBBLE, A
- .LO: MOV A, LONYBBLE ; Isolate low nybble
- ANL A, #0x0F
- ADD A, #'0'
- MOV LONYBBLE, A
- CLR C
- SUBB A, #':'
- JC .STHI
- MOV A, LONYBBLE
- ADD A, #7
- MOV LONYBBLE, A
- .STHI: MOV A, HINYBBLE ; Store high nybble hex char
- MOV @R0, A
- INC R0
- MOV A, LONYBBLE ; Store low nybble hex char
- MOV @R0, A
- INC R0
- RET
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Send out the current record.
- ;;
- SENDRECORD: MOV R0, #BUF_START ; Init pointer
- .SENDCHAR: MOV A, @R0 ; Get next char
- JZ .DONE ; Done if it is NUL
- CLR SCON_TI ; Send byte
- MOV SBUF, A
- JNB SCON_TI, $ ; Loop until character sent
- INC R0
- SJMP .SENDCHAR
- .DONE: RET
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Error handler
- ;; Turn on red LED and loop forever.
- ;;
- ERROR: SETB OUT_GRNLEDn ; Green LED off
- CLR OUT_REDLEDn ; Red LED on
- SJMP $
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Delay 100ms
- ;; Uses Timer 0, delaying 50ms twice
- ;; Oscillator frequency = 11.0592 MHz
- ;; ==> 50ms = 11059200 / (12 * 20) = 46080 = 0xB400 counts
- ;; ==> (TH0,TL0) = 0x10000 - 0xB400 = 0x4C00
- ;; This all ignores subroutine call overhead and so forth.
- ;;
- DELAY100ms: CLR TCON_TR0 ; Timer off
- MOV TH0, #0x4C ; 50ms delay
- MOV TL0, #0x00
- CLR TCON_TF0 ; Clear overflow
- SETB TCON_TR0 ; Timer on
- JNB TCON_TF0, $ ; Wait for overflow
- CLR TCON_TR0 ; Timer off
- MOV TH0, #0x4C ; 50ms delay
- MOV TL0, #0x00
- CLR TCON_TF0 ; Clear overflow
- SETB TCON_TR0 ; Timer on
- JNB TCON_TF0, $ ; Wait for overflow
- CLR TCON_TR0 ; Timer off
- RET
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Send NUL-terminated string in ROM pointed to by DPTR.
- ;; Trashes A, DPTR
- ;;
- SENDROM: CLR A ; Get byte from ROM
- MOVC A, @A+DPTR
- JZ .DONE ; Done if it is NUL
- CLR SCON_TI ; Send byte
- MOV SBUF, A
- JNB SCON_TI, $ ; Loop until character sent
- INC DPTR ; Send next byte
- SJMP SENDROM
- .DONE: RET
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- END
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|