?? mypaulm2.asm
字號:
; PAULMON2, a user-friendly 8051 monitor, by Paul Stoffregen; Please email comments, suggestions, bugs to paul@ece.orst.edu; It's free. PAULMON2 is in the public domain. You may copy; sections of code from PAULMON2 into your own programs, even; for commercial purposes. PAULMON2 should only be distributed; free of charge, but may be bundled as 'value-added' with other; products, such as development boards, CDROMs, etc. Please; distribute the PAULMON2.DOC file and other files, not just; the object code!; The PAULMON2.EQU and PAULMON2.HDR files contain valuable; information that could help you to write programs for use; with PAULMON2.; PAULMON2 is in the public domain. PAULMON2 is distributed in; the hope that it will be useful, but without any warranty;; without even the implied warranty of merchantability or fitness; for a particular purpose. ; You are probably reading this code to see what it looks like; and possibly learn something, or to modify it for some reason.; Either is ok, but please remember that this code uses a number; of tricks to cram all the functionality into just 4k. As a; result, the code can be difficult to read, and adding new; features can be very difficult without growing beyond 4k. To; add or modify commands in PAULMON2, please consider using the; "external command" functionality. It is easier to develop; new commands this way, and you can distribute them to other; users. Email paul@ece.orst.edu if you have new PAULMON2; commands to contribute to others. Details about adding new; commands to PAULMON2 (with examples) can be found at:; http://www.ece.orst.edu/~paul/8051-goodies/pm2_docs/addons.html;---------------------------------------------------------;; ;; PAULMON2's default configuration ;; ;;---------------------------------------------------------;; PAULMON2 should be assembled using the modified AS31 assembler,; originally written by Ken Stauffer, many small changes by Paul; Stoffregen. This free assembler is available on the web at; http://www.ece.orst.edu/~paul/8051-goodies/goodies-index.html; As well, these web pages have a fill-out form which makes it; very easy to custom configure PAULMON2. Using this form will; edit the code for you, run the AS31 assmebler, and send you the; object code to program into your chip.; These two parameters control where PAULMON2 will be assembled,; and where it will attempt to LJMP at the interrupt vector locations..equ base, 0x0000 ;location for PAULMON2.equ vector, 0x8000 ;location to LJMP interrupt vectors change to 8000h; These three parameters tell PAULMON2 where the user's memory is; installed. "bmem" and "emem" define the space that will be searched; for program headers, user installed commands, start-up programs, etc.; "bmem" and "emem" should be use so they exclude memory areas where; perphreal devices may be mapped, as reading memory from an io chip; may reconfigure it unexpectedly. If flash rom is used, "bmem" and "emem"; should also include the space where the flash rom is mapped..equ pgm, 0x8000 ;default location for the user program.equ bmem, 0x1000 ;where is the beginning of memory.equ emem, 0xFFFF ;end of the memory; Flash ROM parameters. If "has_flash" is set to zero, all flash rom; features are turned off, otherwise "bflash" and "eflash" should specify; the memory range which is flash rom. Though AMD doesn't suggest it,; you may be able to map only a part of the flash rom with your address; decoder logic (and not use the rest), but you should be careful that; "bflash" and "eflash" don't include and memory which is NOT flash rom; so that the erase algorithm won't keep applying erase pulses until it; finally gives up (which will stress the thin oxide and degrade the; flash rom's life and reliability). "erase_pin" allows you to specify; the bit address for a pin which (if held low) will tell PAULMON2 to; erase the flash rom chip when it starts up. This is useful if you; download programs with the "start-up" headers on them and the code you've; put in the flash rom crashes!.equ has_flash, 0 ;set to non-zero value if flash installed.equ bflash, 0x8000 ;first memory location of Flash ROM.equ eflash, 0xFFFF ;last memory location of Flash ROM;.equ erase_pin, 0 ;00 = disable erase pin feature.equ erase_pin, 0xB5 ;B5 = pin 15, P3.5 (T1); Please note... much of the memory management code only looks at the; upper 8 bits of an address, so it's not a good idea to somehow map; your memory chips (with complex address decoding logic) into chunks; less than 256 bytes. In other words, only using a piece of a flash; rom chip and mapping it between C43A to F91B would confuse PAULMON2; (as well as require quit a bit of address decoding logic circuitry); To set the baud rate, use this formula or set to 0 for auto detection; baud_const = 256 - (crystal / (12 * 16 * baud));.equ baud_const, 0 ;automatic baud rate detection;.equ baud_const, 255 ;57600 baud w/ 11.0592 MHz;.equ baud_const, 253 ;19200 baud w/ 11.0592 MHz;.equ baud_const, 252 ;19200 baud w/ 14.7456 MHz;.equ baud_const, 243 ;4808 baud w/ 12 MHz.equ baud_const, 244 ;9600 baud w/ 22.1184 MHz.equ line_delay, 6 ;num of char times to pause during uploads; About download speed: when writing to ram, PAULMON2 can accept data; at the maximum baud rate (baud_const=255 or 57600 baud w/ 11.0592 MHz).; Most terminal emulation programs introduce intentional delays when; sending ascii data, which you would want to turn off for downloading; larger programs into ram. For Flash ROM, the maximum speed is set by; the time it takes to program each location... 9600 baud seems to work; nicely for the AMD 28F256 chip. The "character pacing" delay in a; terminal emulation program should be sufficient to download to flash; rom and any baud rate. Some flash rom chips can write very quickly,; allowing high speed baud rates, but other chips can not. You milage; will vary...; Several people didn't like the key definations in PAULMON1.; Actually, I didn't like 'em either, but I never took the time; to change it. Eventually I got used to them, but now it's; really easy to change which keys do what in PAULMON2. You; can guess what to do below, but don't use lowercase..equ help_key, '?' ;help screen.equ dir_key, 'M' ;directory.equ run_key, 'R' ;run program.equ dnld_key, 'D' ;download.equ upld_key, 'U' ;upload.equ nloc_key, 'N' ;new memory location.equ jump_key, 'J' ;jump to memory location.equ dump_key, 'H' ;hex dump memory.equ intm_key, 'I' ;hex dump internal memory.equ edit_key, 'E' ;edit memory.equ clrm_key, 'C' ;clear memory.equ erfr_key, 'Z' ;erase flash rom; timing parameters for AMD Flash ROM 28F256. These parameters; and pretty conservative and they seem to work with crystals; between 6 MHz to 24 MHz... (tested with AMD 28F256 chips only); unless you know this is a problem, it is probably not a good; idea to fiddle with these..equ pgmwait, 10 ;22.1184 MHz crystal assumed;.equ pgmwait, 19 ;11.0592 MHz.equ verwait, 5.equ erwait1, 40 ;fourty delays @22.1184;.equ erwait1, 20 ;twenty delays for 11.0592 MHz.equ erwait2, 229 ;each delay .5 ms @22.1184MHz; These symbols configure paulmon2's internal memory usage.; It is usually not a good idea to change these unless you; know that you really have to..equ psw_init, 0 ;value for psw (which reg bank to use).equ dnld_parm, 0x10 ;block of 16 bytes for download.equ stack, 0x30 ;location of the stack.equ baud_save, 0x78 ;save baud for warm boot, 4 bytes;---------------------------------------------------------;; ;; Interrupt Vectors ;; (and little bits of code crammed in the empty spaces) ;; ;;---------------------------------------------------------; .org base ljmp poweron ;reset vector .org base+3 ljmp vector+3 ;ext int0 vectorr6r7todptr: mov dpl, r6 mov dph, r7 ret .org base+11 ljmp vector+11 ;timer0 vectordptrtor6r7: mov r6, dpl mov r7, dph ret .org base+19 ljmp vector+19 ;ext int1 vectordash: mov a, #'-' ;seems kinda trivial, but each time ajmp cout ;this appears in code, it takes 4 nop ;bytes, but an acall takes only 2 .org base+27 ljmp vector+27 ;timer1 vectorcout_sp:acall cout ajmp space nop .org base+35 ljmp vector+35 ;uart vectordash_sp:acall dash ajmp space nop .org base+43 ljmp vector+43 ;timer2 vector (8052);---------------------------------------------------------;; ;; The jump table for user programs to call ;; subroutines within PAULMON ;; ;;---------------------------------------------------------;.org base+46 ;never change this line!! Other ;programs depend on these locations ;to access paulmon2 functions ajmp phex1 ;2E ajmp cout ;30 ajmp cin ;32 ajmp phex ;34 ajmp phex16 ;36 ajmp pstr ;38 ajmp ghex ;3A ajmp ghex16 ;3C ajmp esc ;4E ajmp upper ;40 ljmp autobaud ;42pcstr_h:ljmp pcstr ;45 ajmp newline ;48 ljmp lenstr ;4A ljmp pint8u ;4D ljmp pint8 ;50 ljmp pint16u ;53 ljmp smart_wr ;56 ljmp prgm ;59 ljmp erall ;5C ljmp find ;5Fcin_filter_h: ljmp cin_filter ;62 ajmp asc2hex ;64;---------------------------------------------------------;; ;; Subroutines for serial I/O ;; ;;---------------------------------------------------------;cin: jnb ri, cin clr ri mov a, sbuf retdspace: acall spacespace: mov a, #' 'cout: jnb ti, cout clr ti ;clr ti before the mov to sbuf! mov sbuf, a ret;clearing ti before reading sbuf takes care of the case where;interrupts may be enabled... if an interrupt were to happen;between those two instructions, the serial port will just;wait a while, but in the other order and the character could;finish transmitting (during the interrupt routine) and then;ti would be cleared and never set again by the hardware, causing;the next call to cout to hang forever!newline2: ;print two newlines acall newlinenewline:push acc ;print one newline mov a, #13 acall cout mov a, #10 acall cout pop acc ret ;get 2 digit hex number from serial port ; c = set if ESC pressed, clear otherwise ; psw.5 = set if return w/ no input, clear otherwiseghex:ghex8: clr psw.5ghex8c: acall cin_filter_h ;get first digit acall upper cjne a, #27, ghex8fghex8d: setb c clr a retghex8f: cjne a, #13, ghex8h setb psw.5 clr c clr a retghex8h: mov r2, a acall asc2hex jc ghex8c xch a, r2 ;r2 will hold hex value of 1st digit acall coutghex8j: acall cin_filter_h ;get second digit acall upper cjne a, #27, ghex8k sjmp ghex8dghex8k: cjne a, #13, ghex8m mov a, r2 clr c retghex8m: cjne a, #8, ghex8pghex8n: acall cout sjmp ghex8cghex8p: cjne a, #21, ghex8q sjmp ghex8nghex8q: mov r3, a acall asc2hex jc ghex8j xch a, r3 acall cout mov a, r2 swap a orl a, r3 clr c ret ;carry set if esc pressed ;psw.5 set if return pressed w/ no inputghex16: mov r2, #0 ;start out with 0 mov r3, #0 mov r4, #4 ;number of digits left clr psw.5ghex16c: acall cin_filter_h acall upper cjne a, #27, ghex16d setb c ;handle esc key clr a mov dph, a mov dpl, a retghex16d:cjne a, #8, ghex16f sjmp ghex16kghex16f:cjne a, #127, ghex16g ;handle backspaceghex16k:cjne r4, #4, ghex16e ;have they entered anything yet? sjmp ghex16cghex16e:acall cout acall ghex16y inc r4 sjmp ghex16cghex16g:cjne a, #13, ghex16i ;return key mov dph, r3 mov dpl, r2 cjne r4, #4, ghex16h clr a mov dph, a mov dpl, a setb psw.5ghex16h:clr c retghex16i:mov r5, a ;keep copy of original keystroke acall asc2hex jc ghex16c xch a, r5 lcall cout mov a, r5 push acc acall ghex16x pop acc add a, r2 mov r2, a clr a addc a, r3 mov r3, a djnz r4, ghex16c clr c mov dpl, r2 mov dph, r3 retghex16x: ;multiply r3-r2 by 16 (shift left by 4) mov a, r3 swap a anl a, #11110000b mov r3, a mov a, r2 swap a anl a, #00001111b orl a, r3 mov r3, a mov a, r2 swap a anl a, #11110000b mov r2, a retghex16y: ;divide r3-r2 by 16 (shift right by 4) mov a, r2 swap a anl a, #00001111b mov r2, a mov a, r3 swap a anl a, #11110000b orl a, r2 mov r2, a mov a, r3 swap a anl a, #00001111b mov r3, a ret ;carry set if invalid inputasc2hex: clr c add a, #208 jnc hex_not add a, #246 jc hex_maybe add a, #10 clr c rethex_maybe: add a, #249 jnc hex_not add a, #250 jc hex_not add a, #16 clr c rethex_not:setb c retphex:phex8: push acc swap a anl a, #15 add a, #246 jnc phex_b add a, #7phex_b: add a, #58 acall cout pop accphex1: push acc anl a, #15 add a, #246 jnc phex_c add a, #7phex_c: add a, #58 acall cout pop acc retphex16: push acc mov a, dph acall phex mov a, dpl acall phex pop acc ret;a not so well documented feature of pstr is that you can print;multiple consecutive strings without needing to reload dptr;(which takes 3 bytes of code!)... this is useful for inserting;numbers or spaces between strings.pstr: push accpstr1: clr a movc a, @a+dptr inc dptr jz pstr2 mov c, acc.7 anl a, #0x7F acall cout jc pstr2 sjmp pstr1pstr2: pop acc retupper: ;converts the ascii code in Acc to uppercase, if it is lowercase push acc clr c subb a, #97 jc upper2 ;is it a lowercase character subb a, #26 jnc upper2 pop acc add a, #224 ;convert to uppercase retupper2: pop acc ;don't change anything retlenstr: mov r0, #0 ;returns length of a string in r0 push acclenstr1:clr a movc a,@a+dptr jz lenstr2 mov c,acc.7 inc r0 Jc lenstr2 inc dptr sjmp lenstr1lenstr2:pop acc retesc: ;checks to see if <ESC> is waiting on serial port ;C=clear if no <ESC>, C=set if <ESC> pressed ;buffer is flushed push acc clr c jnb ri,esc2 mov a,sbuf cjne a,#27,esc1 setb cesc1: clr riesc2: pop acc ret;---------------------------------------------------------;; ;; The 'high-level' stuff to interact with the user ;; ;;---------------------------------------------------------;menu: ;first we print out the prompt, which isn't as simple ;as it may seem, since external code can add to the ;prompt, so we've got to find and execute all of 'em. mov dptr, #prompt1 ;give 'em the first part of prompt acall pcstr_h mov a, r7 acall phex mov a, r6 acall phex ;mov dptr, #prompt2 acall pstr;now we're finally past the prompt, so let's get some input acall cin_filter_h ;get the input, finally acall upper;push return address onto stack so we can just jump to the program mov b, #(menu & 255) ;we push the return address now, push b ;to save code later... mov b, #(menu >> 8) ;if bogus input, just ret for push b ;another prompt.;first we'll look through memory for a program header that says;it's a user installed command which matches what the user pressed;user installed commands need to avoid changing R6/R7, which holds;the memory pointer. The stack pointer can't be changed obviously.;all the other general purpose registers should be available for;user commands to alter as they wish.menux: mov b, a ;now search for external commands... mov dptr, #bmemmenux1: acall find jnc menuxend ;searched all the commands? mov dpl, #4 clr a movc a,@a+dptr cjne a, #254, menux2 ;only FE is an ext command inc dpl clr a movc a,@a+dptr cjne a, b, menux2 ;only run if they want it acall space mov dpl, #32 acall pstr ;print command name acall newline mov dpl, #64 clr a jmp @a+dptr ;take a leap of faith and jump to it!menux2: inc dph mov a, dph cjne a, #((emem+1) >> 8) & 255, menux1menuxend: mov a, b;since we didn't find a user installed command, use the builtin onesmenu1a: cjne a, #help_key, menu1b mov dptr, #help_cmd2 acall pcstr_h ajmp helpmenu1b: cjne a, #dir_key, menu1c mov dptr, #dir_cmd acall pcstr_h ajmp dirmenu1c: cjne a, #run_key, menu1d mov dptr, #run_cmd acall pcstr_h ajmp runmenu1d: cjne a, #dnld_key, menu1e mov dptr, #dnld_cmd acall pcstr_h ajmp dnldmenu1e: cjne a, #upld_key, menu1f mov dptr, #upld_cmd
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -