📄 flash_monitor.s43
字号:
bit.w #MC_2, &TACTL ; is Timer_A running?
jz GetChar
bit.w #TAIFG, &TACTL ; did Timer_A overflow?
jz GetChar; ; otherwise, keep waiting
mov.w #APP_START, R10
cmp.w #-1, 0(R10) ; check application reset vector
jz GetChar ; stay in monitor if blank
mov.w 0(R10), PC ; jmp APP_START
#endif
jmp GetChar; ; otherwise, wait longer
ReadChar:
#ifdef DELAY_START
bic.w #MC_2, &TACTL ; if char received, stop Timer_A
bic.w #TAIFG,&TACTL ; clear timer interrupt flag
#endif
mov.b &U_RXBUF, R12 ; read RX character
IF ECHO
call R9 ;#SendChar
ENDIF
ret
CmdFunctions: DW Checksum
DW DumpMem
DW EraseFlash
DW RunUserApp
DW InfoMem
DW UpdateFlash
InfoMem: mov.w #0x1080, R13
mov.w R13, R15
call #GetChar
cmp.b #'A', R12
jne InfoB
call #EraseLoop
InfoB: cmp.b #'B', R12
jne InfoDone
sub.w #1, R15
call #EraseLoop
InfoDone: ret
Checksum: mov.w #UMEM_START, R4 ;R4 points to start of user flash
mov.w #UMEM_SIZE, R5 ;R5 points to end of user flash
clr R12 ;0->R6
ChecksumCont: add.w @R4+, R12 ;XOR in the next word
cmp.w R5, R4 ;test R4-R5
jge ChecksumCont ;if R4<=R5, not done
;Checksum is in R12
mov.w #OutString, R14 ;Destination is OutString in R14
call #ToString ;convert R12 to ASCII HEX string
call #SendSpace
mov.w #OutString, R12
call R8 ;#SendString
ret
DumpMem:
#if MEMDUMP ;assemble this if MEMDUMP is non-zero
call #SendSpace
call R7 ; #GetWord, get start address
tst.w R13
jnz DumpStart ;no address, use default
mov.w R12, &Address ;save the address
call #SendSpace
mov.w #-1, &Count ;0xFFFF ->Count
mov.b #1, &Pace
call #SendSpace
call R7 ; #GetWord, get word count
tst.w R13 ;was a count entered?
jnz NoCount ;if no, use default
cmp.w #0, R12 ;was the count zero
jeq NoCount ;if zero, use the default
mov.w R12, &Count ;if yes, save the count
mov.b #0, &Pace ;no pacing if count entered
NoCount: mov.w &Address, R4 ;User specified the address
cmp.w #0x200, R4 ;valid memory address?
jc DumpAddr
mov.w #0x200, R4 ;if not, set to start of RAM
jmp DumpAddr ;Dump from specified address
DumpStart: mov.w #UMEM_START, R4 ;Default is start of flash
DumpAddr: mov.w #UMEM_END, R5
NextLine: mov.w #CRLF, R12
call R8 ;#SendString
mov.w #OutString, R14
mov.w R4, R12
call #ToString ;convert address to string
mov.b #8, R6 ;write 8 words/line
SameLine: mov.b #' ', 0(R14) ;insert a space
inc.w R14 ;point to the next char
mov.w @R4+, R12 ;get the next word
call #ToString ;convert mem value to string
dec.w &Count ;decrement word count
jz DumpDone ;done?
cmp.w R4, R5 ;check for end of memory
jnc DumpDone
dec.w R6 ;decrement the word/line counter
jnz SameLine ;Stay on the same line
mov.w #OutString, R12
call R8 ;#SendString, write out the line
tst.b &Pace ;Is the dump paced?
jz NextLine ;if not, continue
call #GetChar ;get a character from USART1
cmp.b #'Q', R12 ;was it a 'Q' (QUIT)
jz DumpQuit ;quit when told
jmp NextLine ;do another line
DumpDone: mov.w #OutString, R12
call R8 ;#SendString
#endif ;End conditional assembly
DumpQuit: ret
EraseFlash: mov.w #Pass, R12
#ifdef PASSWORD ; don't assemble this if no password protection is desired
call R8 ;#SendString, send PW prompt
call R7 ;#GetWord,get a PW in R12
cmp.w &Password, R12 ;Compare to stored password
jne EraseDone ; Return if no match
#endif
call #SendSpace
call R7 ; #GetWord, get start address
tst.b R13 ;was a number entered?
jnz EraseDone ;if not, use defaults
cmp.w #UMEM_START, R12 ;check memory bounds
jnc EraseDone
CheckEnd: mov.w #UMEM_END, R14
cmp.w R12, R14 ;check against user memory end
jnc EraseDone ;jump if past upper bound
mov.w R12, R10 ;otherwise, save in R10
call #SendSpace
push.w R14 ;save the upper memory bound
call R7 ; #GetWord, next, get end address
tst.b R13 ;was an end address entered?
jnz EraseDone ;if not, erase to end of flash
pop.w R14 ;restore the upper memory bound
cmp.w R12, R14 ;check against user memory end
jnc EraseDone ;ignore if past end address
cmp.w #UMEM_START,R12 ;is it before start of user memory?
jnc EraseDone
mov.w R10, R13 ;put start address in R13
mov.w R12, R15 ;end address in R15
cmp.w R13, R15 ;end address > start address?
jc DoErase
jz DoErase
jmp EraseDone ;no end specified, erase to end
DoErase mov.b #'.', R12 ; Use '.' as a progress marker
EraseLoop: mov.w #FWKEY,&FCTL3 ; Lock = 0
mov.w #FWKEY+ERASE,&FCTL1 ; Erase bit = 1
clr.w 0(R13) ; Dummy write to erase segment
FlashWait: bit.w #WAIT, &FCTL3 ; Test flash WAIT bit
jz FlashWait ; Wait for fl
FlashBusy: bit.w #BUSY, &FCTL3
jnz FlashBusy
call R9 ;#SendChar Send a progress marker
add.w #0x200, R13 ; point to next segment
and.w #0xFE00, R13 ; force to the start of the segment
cmp.w R13, R15 ; past end of range
jc EraseLoop
LockFlash: mov #FWKEY+LOCK,&FCTL3 ; Done, set LOCK
EraseDone ret
RunUserApp: mov.w #APP_START, R10
cmp.w #-1, R10
jz Ready ; stay in monitor if blank
mov.w @R10, PC ; jmp APP_START
UpdateFlash: mov.w #FilePrompt, R12
call R8 ;#SendString
call #GetChar
cmp #'@', R12 ;Check for address header
jne UpdateDone ;If no address, skip it
mov #0, &ByteCount
NewAddr: call R7 ; #GetWord, get start address
tst.w R13 ;check ASCII flag
jnz NewAddr ;Skip if flagged as char
cmp.w #UMEM_START,R12 ;Check lower flash boundary
jnc UpdateDone ;Jump if too low
cmp.w #UMEM_END, R12 ;Check upper boundary
jc UpdateDone ;Jump if too high
mov.w R12, R4 ;R4 is the update address
;Unlock the flash for writing
mov.w #FWKEY,&FCTL3 ; Lock = 0
mov.w #FWKEY+WRT,&FCTL1 ; Write bit = 1
mov.w #1, R5 ;R5=1 if byte is high byte
NextByte: call R7 ; #GetWord, get a byte in R12
tst.w R13 ;was it data or whitespace?
jz SaveByte ;jump if it was data
cmp.b #'@', R12
jeq NewAddr ;Got a new start address
cmp.b #'\n',R12 ;check for CR
jeq WriteBytes ;copy buffer to RAM
cmp.b #'q', R12 ;Check for 'q'(uit)
jeq UpdateDone ;No more data
jmp NextByte ;Skip any other characters
SaveByte mov.w &ByteCount, R15
mov.b R12, FlashBuf(R15) ;save byte in RAM
inc.w R15 ;point to next location in RAM
mov.w R15, &ByteCount
jmp NextByte ;get another byte
WriteBytes: mov.w &ByteCount, R15
cmp.w #0, R15
jeq NoBytes
clr.w R14 ;clear R14
MoreBytes: mov.b FlashBuf(R14), R12 ;load byte into R12
inc.w R14 ;bump R14 to next byte
cmp.b #0xFF, 0(R4) ;Is the target byte erased?
jz BlankByte ;If it is, write it
mov.w #NotBlank, R12 ;otherwise send error message
call R8 ;#SendString
jmp BadWrite ;Terminate programming
BlankByte mov.b R12, 0(R4) ;Write byte to flash
cmp.b R12, 0(R4) ;Check write
jnz BadWrite
inc.w R4 ;point to next byte
cmp.w R15, R14 ;buffer emptied?
jnz MoreBytes ;jump if not
NoBytes: mov.w #0, ByteCount ;clear byte counter
jmp NextByte ;go get some more
BadWrite mov.w #ProgErr, R12
call R8 ;#SendString, send error message
FlushProg: call #GetChar ;more data
cmp.b #'q', R12
jne FlushProg ;flush till clear
UpdateDone: mov.w #FWKEY+LOCK,&FCTL3 ; Lock = 1
ret
SendSpace: mov.b #' ', R12
call R9 ;#SendChar
ret
CmdTable: DB "CDEGIU"
Prompt: DB "\r\n?"
Pass: DB "PW?"
CRLF DB "\r\n"
ProgErr DB "ERR\r\n"
NotBlank DB "NB\r\n"
FilePrompt DB "@?"
;------------------------------------------------------------------------------
; Interrupt Vector Definitions
;------------------------------------------------------------------------------
#ifndef DIRECT_INTERRUPTS
; Interrupt vectors
;
ASEGN INTVEC: CODE, 0xFFE0
DW Int_Priority_0 ;FFE0
DW Int_Priority_1 ;FFE2
DW Int_Priority_2 ;FFE4
DW Int_Priority_3 ;FFE6
DW Int_Priority_4 ;FFE8
DW Int_Priority_5 ;FFEA
DW Int_Priority_6 ;FFEC
DW Int_Priority_7 ;FFEE
DW Int_Priority_8 ;FFF0
DW Int_Priority_9 ;FFF2
DW Int_Priority_A ;FFF4
DW Int_Priority_B ;FFF6
DW Int_Priority_C ;FFF8
DW Int_Priority_D ;FFFA
DW Int_Priority_E ;FFFC
ASEGN RESET: CODE, 0xFFFE
DW Reset
#endif
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -