Full Version : Monitor Program for Memory & I/O (ASM)
avr >>PROJECTS (AVR) >>Monitor Program for Memory & I/O (ASM)


AVR_Admin- 04-28-2006
Memory and I/O monitor program for AVR Micro controllers by Dick Cappel


Works on AVR controllers with RAM and a hardware UART. This code is easily modified to integrate with ROM applications to provide the ability to monitor and interact with ROM applications via an terminal simulation program over an RS-232 port. It can also be used to stimulate and monitor I/O to aid in debugging hardware. It is very helpful to be able to look around at memory, I/O and peripherals, and change things inside a running controller


If you adapt this to a controller with a stack pointer that is more than 8 bits wide, be sure that both registers in the stack pointer, both spl and sph, are initialized.


The monitor's commands allow reading, monitoring, and byte-by-byte modification of memory locations $0000 through $00FF, which includes the register array and I/O space.

Link to Site: http://cappels.org/dproj/AVRMON/avrmon.htm

AVR_Admin- 04-28-2006
CODE


;*********************************
;2313 monitor program; should work on any AVR with UART
;*********************************

.include "2313def.inc"    

.equ     clock = 4000000         ;clock frequency
.equ     baudrate = 9600         ;choose a baudrate

.equ     baudconstant = (clock/(16*baudrate))-1

.def temp = r16;general purpose variable
.def inchar = r17    ;char destined to go out the uart
.def outchar = r18    ;char coming in from the uart
.def inbytel = r19    ;lower byte for asci-hex conversion
.def inbyteh = r20    ;higher byte for asci-hex conversion
.def currentadd = r21 ;pointer to write address for first page of memory
.org     $00
rjmp     reset         ;reset handle

reset:     rjmp     init         ;start init

init:    
ldi     temp,low(ramend)
out     spl,temp     ;set spl
ldi     temp,baudconstant    
out     ubrr,temp     ;load baudrate
rcall TypeGreeting
ldi currentadd,$00
;      rcall establish_address_send_data;estsablish current address

loop: ;*****command interpretation loop****
ldi outchar,$3A;send prompt (colon char) to terminal
rcall rs_send
ldi outchar,$20
rcall rs_send
ldi outchar,$20
rcall rs_send
rcall rs_rec ;get char from terminal and
  ;interpret char
   
cpi inchar,$2F;if / decrement current address and display
breq decrementanddisplay
cpi inchar,$3F;if ? then display meny
breq domenu
cpi inchar,$20;if <space>, increment current address and dispaly
breq incaddress
cpi inchar,$0D;if carriage return, read data at current address
breq readdata
cpi inchar,$21;if ! then use watchdog timer to reset the
breq pull_the_plug
cpi inchar,$25;if % (percent sign) monitor memory in binary
breq monitorbinary

andi inchar,$DF;make upper-case ascii

cpi inchar,$52;if R or r, read data at current address
breq readdata
cpi inchar,$57;if W or w, write data at current address
breq writedata
cpi inchar,$41;if A or a, set new current address
breq setaddress
cpi inchar,$51;if Q or q, restart monitor
breq reset
cpi inchar,$4D;if M or m, monitor memory location
breq monitormemory
rjmp loop ;keep going


decrementanddisplay:;decrement current address and display current memory contens
dec currentadd
rcall typeaddressdata
rjmp  loop        
   
monitorbinary:;send contents of memory as binary until char received from terminal

 
rcall crlf
rcall sendaddress; write adress and a space char
ldi     ZH,0  ; set Z register pair to point to current address
mov     ZL,currentadd    
ld inbytel,Z; get contents of (correntadd) into inbytel  
rcall  sendbinarybyte;send that byte to terminal
ldi outchar,$20;send space char to terminal
rcall rs_send
 
 
sbi     ucr,rxen    ;set reciver bit.
sbis     usr,rxc         ;repeat until char
     rjmp     monitorbinary
rjmp  loop      ;exit when char received


domenu:
rcall TypeGreeting
rjmp  loop

pull_the_plug:  ;enable watchdog timer and wait for hardware reset
ldi     ZH,high(2*resetmessage)    ; Load high part of byte address into ZH
ldi     ZL,low(2*resetmessage)    ; Load low part of byte address into ZL
rcall  sendstring
wdr
ldi temp,$08
out wdtcr,temp
wait_for_reset:
rjmp wait_for_reset


readdata:  ;read data from current location to terminal
rcall typeaddressdata
rjmp loop


writedata:
ldi     ZH,high(2*newdatamessage)    ; Load high part of byte address into ZH
ldi     ZL,low(2*newdatamessage)    ; Load low part of byte address into ZL
rcall  sendstring  ;ask for new datat to enter
rcall recbyte
ldi ZH,$00
mov ZL,currentadd
st Z,inbytel
rcall typeaddressdata
rjmp loop

incaddress:;increment current address and display current memory contens
inc currentadd
rcall typeaddressdata
rjmp  loop        
   

setaddress:;set current address
rcall establish_address_send_data
rjmp loop
     
monitormemory:;send contents of memory until char received from terminal

 
rcall crlf
rcall sendaddress; write adress and a space char
ldi     ZH,0  ; set Z register pair to point to current address
mov     ZL,currentadd    
ld inbytel,Z; get contents of (correntadd) into inbytel  
rcall  sendbyte;send that byte to terminal
ldi outchar,$20;send space char to terminal
rcall rs_send
sbi     ucr,rxen     ;set reciver bit.
sbis     usr,rxc  ;repeat until char
     rjmp     monitormemory
rjmp  loop      ;exit when char received


   
rs_send:
    sbi     ucr,txen    ;set sender bit
    sbis     usr,udre    ;wait till register is cleared
    rjmp     rs_send    
    out     udr,outchar    ;send the byte
    cbi     ucr,txen    ;clear sender bit
    ret              ;go back
   
   
   
rs_rec:    
sbi     ucr,rxen    ;set reciver bit...              
sbis     usr,rxc         ;wait for a byte
rjmp     rs_rec
in     inchar,udr    ;read valuable
cbi     ucr,rxen    ;clear register
ret              ;go back
   

rs_rec_echo:              ;receive and echo char
rcall  rs_rec
mov     outchar,inchar
     rcall   rs_send         ;send to comX              
     ret

crlf:                   ;send carriage return and line feed.
    ldi     ZH,high(2*crlfmessage)    ; Load high part of byte address into ZH
    ldi     ZL,low(2*crlfmessage)    ; Load low part of byte address into ZL
    rcall     sendstring
    ret



sendstring:         ;call with location of string in Z
    lpm                   ; Load byte from program memory into r0
    tst     r0              ; Check if we've reached the end of the message
    breq     finishsendstering    ; If so, return
    mov     outchar,r0
    rcall     rs_send
    adiw     ZL,1              ; Increment Z registers
    rjmp     sendstring
finishsendstering:
    ret



sendline:         ;send a string terminated in cariage return and line feed
             ;call with location of start of string in Z              
    rcall     sendstring
    rcall     crlf
    ret

sendaddress:;send address followed by space char
mov  inbytel,currentadd
rcall sendbyte
ldi outchar,$20
rcall  rs_send
ret

TypeGreeting:
rcall      crlf
rcall      crlf
ldi     ZH,high(2*hellomessage)    ; Load high part of byte address into ZH
ldi     ZL,low(2*hellomessage)    ; Load low part of byte address into ZL
rcall     sendline         ; sent it.
ret


askforaddress:
    ldi     ZH,high(2*askaddressmessage)    ; Load high part of byte address into ZH
    ldi     ZL,low(2*askaddressmessage)    ; Load low part of byte address into ZL
    rcall     sendstring         ; sent it.
    ret




byte_to_asciihex:    ;convert byte in inbytel to ascii in inbyteh,nbytel
mov     inbyteh,inbytel
lsr     inbyteh         ;convert the high nybble to ascii byte
lsr     inbyteh
lsr     inbyteh
lsr      inbyteh
subi     inbyteh,$D0    ;add $30
cpi      inbyteh,$3A    
brlo     PC+2         ;If less than 9 skip next instruction
subi     inbyteh,$F9    ;add 8 to ASCII (if data greater than 9)
   ; byte in inbyteh represents upper nybble that was in inbytel at start

andi     inbytel,0b00001111    ;convert the lower nybble to ascii byte
subi      inbytel,$D0    ;add $30
cpi      inbytel,$3A    
brlo     PC+2         ;If less than 9 skip next instruction
subi     inbytel,$F9    ;add 8 to ASCII (if data greater than 9)
   ; byte in inbyteh represents upper nybble that was in inbytel at start
ret


asciihex_to_byte:     ;convert ascii in inbyteh,inbytel to byte in inbytel
sbrc     inbyteh,6     ;convert high byte
subi     inbyteh,$f7    ;add     inbyte,temp    ;if bit 6 is set, add $09
andi     inbyteh,$0F

sbrc     inbytel,6 ;convert low byte
subi     inbytel,$f7    ;add     inbyte,temp    ;if bit 6 is set, add $09
andi     inbytel,$0F

lsl     inbyteh     ;combine them
lsl     inbyteh
lsl     inbyteh
lsl     inbyteh    
or     inbytel,inbyteh
ret

sendbyte:     ;send byte contained in inbytel to terminal

rcall  byte_to_asciihex
     mov     outchar,inbyteh
     rcall  rs_send
     mov     outchar,inbytel
     rcall   rs_send
ret

sendbinarybyte:
ldi temp,$08
stillsendingbinary:
ldi outchar,$30
rol inbytel
brcc dontsendone
ldi outchar,$31
dontsendone:
     rcall   rs_send
     dec  temp
     brne stillsendingbinary    
ret



recbyte:    ; get ascii hex byte from terminal. Result in inbytel
rcall  rs_rec_echo           ;read from comX
mov     inbyteh,inchar      ;put 1st char from uart into inbyteh for hex conversion    
rcall   rs_rec_echo
mov     inbytel,inchar      ;put 2nd char from uart into inbytel for hex conversion
rcall  asciihex_to_byte;convert ASCII to byte in inbytel
ret


typeaddressdata:
rcall crlf ;send carriage return and life feed
rcall sendaddress; write adress and a space char
ldi     ZH,0  ; set Z register pair to point to current address
mov     ZL,currentadd    
ld inbytel,Z; get contents of (correntadd) into inbytel  
rcall  sendbyte;send that byte to terminal
ldi outchar,$20;send space char to terminal
rcall rs_send
ret


establish_address_send_data:
rcall askforaddress;ask for memory address
rcall recbyte  ;get a byte from terminal
mov currentadd,inbytel;save received byte as current address
rcall typeaddressdata
ret



hellomessage:
.db     "2313 monitor  2002.02.01 V              Dick Cappels"
.db $0A,$0D
.db "A = set address "
.db $0A,$0D
.db "W = write "
.db $0A,$0D
.db   "R or <CR> = show memory contents at current address "
.db $0A,$0D
.db "<space> = increment current address and display "
.db $0A,$0D
.db "/ = decrement current address and display "
.db $0A,$0D
.db "M = monitor data until key pressed"
.db $0A,$0D
.db "% = monitor data and show in binary "
.db $0A,$0D
.db "? = type opening screen."
.db $0A,$0D
.db "Q = restart firmware"
.db $0A,$0D
.db "! = reset chip"
.db $0A,$0D
.db "All address and data values are hexadecimal and are byte wide."
.db $0A,$0D
.db      00,00

askaddressmessage:
.db "Address:  "
.db $00,00

crlfmessage:
.db     $0A,$0D
.db     00,00


newdatamessage:
.db "new data: "
.db $00,$00

resetmessage:
.db "Hardware reset via watchdog initiated."
.db $00,$00


Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.