📄 paulmon.txt
字号:
;---------------------------------------------------------;
nloc:
mov dptr, #prompt6
acall pcstr_h
acall ghex16
jc abort2
jb psw.5, abort2
acall dptrtor6r7
ajmp newline2
;---------------------------------------------------------;
erfr:
acall newline2
mov dptr, #erfr_cmd
acall pcstr_h
mov a, #','
acall cout_sp
mov dptr, #sure
acall pcstr_h
acall cin_filter_h
acall upper
cjne a, #'Y', abort_it
acall newline2
lcall erall
mov dptr, #erfr_ok
jnc erfr_end
mov dptr, #erfr_err
erfr_end:
ajmp pcstr_h
;---------------------------------------------------------;
intm: acall newline
mov r0, #0
intm2: acall newline
cjne r0, #0x80, intm3
ajmp newline
intm3: mov a, r0
acall phex
mov a, #':'
acall cout
intm4: acall space
mov a, @r0
acall phex
inc r0
mov a, r0
anl a, #00001111b
jnz intm4
sjmp intm2
;**************************************************************
;**************************************************************
;***** *****
;***** 2k page boundry is somewhere near here *****
;***** (no ajmp or acall past this point) *****
;***** *****
;**************************************************************
;**************************************************************
;---------------------------------------------------------;
; ;
; Subroutines for memory managment and non-serial I/O ;
; ;
;---------------------------------------------------------;
; poll the flash rom using it's toggle bit feature
; on D6... and wait until the flash rom is not busy
; dptr must be initialized with the address to read
flash_wait:
push b
clr a
movc a, @a+dptr
flwt2: mov b, a
inc r5
clr a
movc a, @a+dptr
cjne a, b, flwt2
pop b
ret
;send the flash enable codes
flash_en:
mov dptr, #flash_en1_addr
mov a, #flash_en1_data
movx @dptr, a
mov dptr, #flash_en2_addr
mov a, #flash_en2_data
movx @dptr, a
ret
;a routine that writes ACC to into flash memory at DPTR
; C is set if error occurs, C is clear if it worked
prgm: xch a, r0
push acc
push dpl
push dph
acall flash_en ;do first step, enable writing
mov dptr, #flash_wr_addr
mov a, #flash_wr_data
movx @dptr, a ;send flash write command
pop dph
pop dpl
mov a, r0
movx @dptr, a ;write the data
acall flash_wait ;wait until it's done
clr a
movc a, @a+dptr ;read it back
clr c
xrl a, r0
jz prgmend ;check if data written ok
setb c
prgmend:pop acc
xch a, r0
ret
; erase the entire flash rom
; C=1 if failure, C=0 if ok
erall:
mov dptr, #flash_er2_addr
mov a, #flash_er2_data
acall erblock ;use erblock to send erase all
mov dptr, #bflash
erall2: clr a
movc a, @a+dptr ;read back flash memory
cpl a
jnz erall_err ;check if it's really erased
inc dptr
mov a, #((eflash+1) & 255)
cjne a, dpl, erall2
mov a, #(((eflash+1) >> 8) & 255)
cjne a, dph, erall2
clr c
ret
erall_err:
setb c
ret
;send a custom erase command. This is used by erall,
;and it's intended to be callable from the flash memory
;so that custom block erase code can be implemented
erblock:
push acc
push dpl
push dph
acall flash_en ;send flash enable stuff
mov dptr, #flash_er1_addr
mov a, #flash_er1_data
movx @dptr, a ;send erase enable
acall flash_en ;send flash enable stuff
pop dph
pop dpl
pop acc
movx @dptr, a ;send erase command
ajmp flash_wait
;finds the next header in the external memory.
; Input DPTR=point to start search (only MSB used)
; Output DPTR=location of next module
; C=set if a header found, C=clear if no more headers
find: mov dpl, #0
clr a
movc a, @a+dptr
cjne a, #0xA5, find3
inc dptr
clr a
movc a, @a+dptr
cjne a, #0xE5, find3
inc dptr
clr a
movc a, @a+dptr
cjne a, #0xE0, find3
inc dptr
clr a
movc a, @a+dptr
cjne a, #0xA5, find3
mov dpl, #0 ;found one here!
setb c
ret
find3: mov a, #(emem >> 8)
cjne a, dph, find4 ;did we just check the end
clr c
ret
find4: inc dph ;keep on searching
sjmp find
;************************************
;To make PAULMON2 able to write to other
;types of memory than RAM and flash rom,
;modify this "smart_wr" routine. This
;code doesn't accept any inputs other
;that the address (dptr) and value (acc),
;so this routine must know which types
;of memory are in what address ranges
;************************************
;Write to Flash ROM or ordinary RAM. Carry bit will indicate
;if the value was successfully written, C=1 if not written.
smart_wr:
push acc
push b
mov b, a
;do we even have a flash rom?
mov a, #has_flash
jz wr_ram
;there is a flash rom, but is this address in it?
mov a, dph
cjne a, #(eflash >> 8), isfl3
sjmp wr_flash
isfl3: jnc wr_ram
cjne a, #(bflash >> 8), isfl4
sjmp wr_flash
isfl4: jnc wr_flash
;sjmp wr_ram
wr_ram: mov a, b
movx @dptr, a ;write the value to memory
clr a
movc a, @a+dptr ;read it back from code memory
clr c
subb a, b
jz smwrok
movx a, @dptr ;read it back from data memory
clr c
subb a, b
jz smwrok
smwrbad:setb c
sjmp smwrxit
smwrok: clr c
smwrxit:pop b
pop acc
ret
wr_flash:
mov a, b
lcall prgm
pop b
pop acc
ret
;---------------------------------------------------------;
; ;
; Power-On initialization code and such... ;
; ;
;---------------------------------------------------------;
;first the hardware has to get initialized.
intr_return:
reti
poweron:
clr a
mov ie, a ;all interrupts off
mov ip, a
mov psw, #psw_init
;clear any interrupt status, just in case the user put
;"ljmp 0" inside their interrupt service code.
acall intr_return
acall intr_return
cpl a
mov p0, a
mov p1, a
mov p2, a
mov p3, a
mov sp, #stack
;Before we start doing any I/O, a short delay is required so
;that any external hardware which may be in "reset mode" can
;initialize. This is typically a problem when a 82C55 chip
;is used and its reset line is driven from the R-C reset
;circuit used for the 8051. Because the 82C55 reset pin
;switches from zero to one at a higher voltage than the 8051,
;any 82C55 chips would still be in reset mode right now...
rst_dly:
mov r1, #200 ;approx 100000 cycles
rdly2: mov r2, #249 ;500 cycles
djnz r2, *
djnz r1, rdly2
;Check for the Erase-on-startup signal and erase Flash ROM
;if it's there.
mov a, #has_flash
jz skip_erase
mov a, #erase_pin
jz skip_erase
mov r0, #250 ;check it 250 times, just to be sure
chk_erase:
mov c, erase_pin
mov r1, #200
djnz r1, * ;short delay
jc skip_erase ;skip erase if this bit is not low
djnz r0, chk_erase
lcall erall ;and this'll delete the flash rom
skip_erase:
;run any user initialization programs in external memory
mov b, #249
acall stcode
;initialize the serial port, auto baud detect if necessary
acall autobaud ;set up the serial port
;mov a, th1
;lcall phex
;run the start-up programs in external memory.
mov b, #253
acall stcode
;now print out the nice welcome message
welcome:
mov r0, #24
welcm2: lcall newline
djnz r0, welcm2
mov r0, #15
mov a, #' '
welcm4: lcall cout
djnz r0, welcm4
mov dptr, #logon1
lcall pcstr
mov dptr, #logon2
lcall pcstr
lcall dir
mov r6, #(pgm & 255)
mov r7, #(pgm >> 8)
ljmp menu
stcode: mov dptr, #bmem ;search for startup routines
stcode2:lcall find
jnc stcode5
mov dpl, #4
clr a
movc a, @a+dptr
cjne a, b, stcode4 ;only startup code if matches B
push b
push dph
mov a, #(stcode3 & 255)
push acc
mov a, #(stcode3 >> 8)
push acc
mov dpl, #64
clr a
jmp @a+dptr ;jump to the startup code
stcode3:pop dph ;hopefully it'll return to here
pop b
stcode4:inc dph
mov a, dph
cjne a, #((emem+1) >> 8) & 255, stcode2
stcode5:ret ;now we've executed all of 'em
;to do automatic baud rate detection, we assume the user will
;press the carriage return, which will cause this bit pattern
;to appear on port 3 pin 0 (CR = ascii code 13, assume 8N1 format)
;
; 0 1 0 1 1 0 0 0 0 1
; | | | |
; start bit----+ +--lsb msb--+ +----stop bit
;
;we'll start timer #1 in 16 bit mode at the transition between the
;start bit and the LSB and stop it between the MBS and stop bit.
;That will give approx the number of cpu cycles for 8 bits. Divide
;by 8 for one bit and by 16 since the built-in UART takes 16 timer
;overflows for each bit. We need to be careful about roundoff during
;division and the result has to be inverted since timer #1 counts up. Of
;course, timer #1 gets used in 8-bit auto reload mode for generating the
;built-in UART's baud rate once we know what the reload value should be.
autobaud:
mov a, #baud_const ;skip if user supplied baud rate constant
jnz autoend_jmp
mov a, baud_save+3 ;is there a value from a previous boot?
xrl baud_save+2, #01010101b
xrl baud_save+1, #11001100b
xrl baud_save+0, #00011101b
cjne a, baud_save+2, autob1
cjne a, baud_save+1, autob1
cjne a, baud_save+0, autob1
autoend_jmp:
ajmp autoend
autob1: ;wait for inactivity
mov pcon, #0x80 ;configure uart, fast baud
mov scon, #0x42 ;configure uart, but receive disabled
mov tmod, #0x11 ;get timers ready for action (16 bit mode)
clr a
mov tcon, a
mov tl0, a
mov th0, a
mov tl1, a
mov th1, a
;make sure there is no activity on the line
;before we actually begin looking for the carriage return
mov r0, #200
autob1b:mov r1, #30
autob1c:jnb p3.0, autob1
djnz r1, autob1c
djnz r0, autob1b
autob2: ;look for the bits of the carriage return
jb p3.0, autob2 ;wait for start bit
jb p3.0, autob2
jb p3.0, autob2 ; check it a few more times to make
jb p3.0, autob2 ; sure we don't trigger on some noise
jb p3.0, autob2
autob2b:jnb p3.0, autob2b ;wait for bit #0 to begin
setb tr1 ;and now we're timing it
autob2c:jb tf1, autob1 ;check for timeout while waiting
jb p3.0, autob2c ;wait for bit #1 to begin
autob2d:jb tf1, autob1 ;check for timeout while waiting
jnb p3.0, autob2d ;wait for bit #2 to begin
autob2e:jb tf1, autob1 ;check for timeout while waiting
jb p3.0, autob2e ;wait for bit #4 to begin
setb tr0 ;start timing last 4 bits
autob2f:jb tf1, autob1 ;check for timeout while waiting
jnb p3.0, autob2f ;wait for stop bit to begin
clr tr1 ;stop timing (both timers)
clr tr0
jb tf1, autob1 ;check for timeout one last time
;compute the baud rate based on timer1
mov a, tl1
rlc a
mov b, a
mov a, th1
rlc a
jc autob1 ;error if timer0 > 32767
mov c, b.7
addc a, #0
cpl a
inc a ;now a has the value to load into th1
jz autob1 ;error if baud rate too fast
;after we get the carriage return, we need to make sure there
;isn't any "crap" on the serial line, as there is in the case
;were we get the letter E (and conclude the wrong baud rate).
;unfortunately the simple approach of just looking at the line
;for silence doesn't work, because we have to accept the case
;where the user's terminal emulation is configured to send a
;line feed after the carriage return. The best thing to do is
;use the uart and look see if it receives anything
autob3: mov th1, a ;config timer1
mov tl1, #255 ;start asap!
mov tmod, #0x21 ;autoreload mode
setb ren ;turn on the uart
setb tr1 ;turn on timer1 for its clock
mov a, th1
cpl a
inc a
mov r1, a
autob3b:mov r0, #255
autob3c:djnz r0, autob3c
djnz r1, autob3b
jnb ri, autob4
;if we got here, there was some stuff after the carriage
;return, so we'll read it and see if it was the line feed
clr ri
mov a, sbuf
anl a, #01111111b
add a, #246
jz autob4 ;ok if 0A, the line feed character
add a, #5
jz autob4 ;of if 05, since we may have missed start bit
autob1_jmp:
ljmp autob1
autob4:
;compute the baud rate based on timer0, check against timer1 value
mov a, tl0
rlc a
mov r0, a
mov a, th0
rlc a
mov r1, a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -