📄 slfprgr-trim-qc.asm
字号:
STA OSCTRIM ;[2] trim ICG now
JMP VEC0 ;[3] jump to real application
FL0_PROT_ROM: SECTION
; 14 bytes
slfprg:
MOV #%10000001,CONFIG1 ;[3] COP disable,
;ESCI clock = CGMCLK by default (via CONFIG2)
IFDEF HICLOCK
MOV #%00110000,OSCSC ;[3] 25.6MHz Internal clock select
ELSE
MOV #%00100000,OSCSC ;[3] 12.8MHz Internal clock select
ENDIF
BSET 6,SCC1 ;[2] SCI enable
MOV #%00001100,SCC2 ;[3] transmit & receive enable
JMP page0 ;[3]
CODE_ROM: SECTION
page0:
IFDEF LIN
MOV #%00000001,CONFIG2 ; RST pin enabled
ENDIF
IFDEF HICLOCK
MOV #%00010001,SCBR ;[3] 9600Bd @ 25.6MHz CGMXCLK (:3 :2)
ELSE
MOV #%00010000,SCBR ;[3] 9600Bd @ 12.8MHz CGMXCLK (:3)
ENDIF
MOV #%10111110,SCPSC ;[3] 9600Bd @ 12.8 or 25.6MHz CGMXCLK (:(6+30/32))
IFDEF LIN
; OPTIONAL DELAY - if your RS232 hardware is lazy, uncomment following delay
CLRX
DLY2: CLRA
DLY1: NOP
DBNZA DLY1
DBNZX DLY2
; End delay
ENDIF
CLR SCC3 ;[2] ctrl. reg
LDA SCS1 ;[2] Read Status Register before SCDR
MOV #ACK,SCDR ;[2] present ACK (we're here)
IFDEF LIN
BSR READ ;Read the SCDR buffer to clear the loopback due to LIN Driver.
ENDIF
LDX #T100MS
L2: CLRA
L1: BRSET 5,SCS1,CAUGHT
DBNZA L1
DBNZX L2
; timeout
ILOP ; generate RESET by doing illegal operation
;*******************************************************************************************
CAUGHT: ; CAUGHT IN SELF-PROGRAMMING?
BSR READ
BCLR 6,SCC1 ; disable SCI
JSR ICGTRIM ; go & trim
BSET 6,SCC1 ; SCI enable
MOV #%00001100,SCC2 ; transmit & receive enable
MOV #SPEED,CPUSPD ; feed the speed
CLR CTRLBYT ; no mass erase (QB will probably neeed this byte cleared
; competely as well as QC family)
;*******************************************************************************************
; successful return from all write routines
SUCC:
LDA #ACK
BSR WRITE
;fall thru to background
;*******************************************************************************************
; BEGIN OF BACKGROUND COMMAND LOOP
BCKGND:
BSR READ
CBEQA #ERASE, ERASE_COM ; Erase command
CBEQA #WR_DATA, WR_DATA_COM ; Write (program) command
CBEQA #IDENT, IDENT_COM ; Ident command
IF RCS_ENA = 1
CBEQA #RD_DATA, RD_DATA_COM ; Read command
ENDIF
; if no valid command found (including Quit)
; generate reset too!
ILOP ; generate RESET by doing illegal operation
;*******************************************************************************************
IDENT_COM: ; TRANSFER OF IDENTIFICATION STRING
MOV #ID_STRING1_END-ID_STRING1, LEN
LDHX #ID_STRING1
BSR WRITE_LOOP
LDA OSCTRIM
BSR WRITE ; next byte would be ICGTR, needed when no boot done!
LDHX #PRIV+1 ; next 7 are from private area
MOV #7,LEN
BSR WRITE_LOOP
MOV #ID_STRING2_END-ID_STRING2, LEN
LDHX #ID_STRING2
BSR WRITE_LOOP
BRA BCKGND ; finish without ACK
;*******************************************************************************************
WRITE_LOOP: ; start address in HX, length in LEN
LDA ,X
BSR WRITE
AIX #1
DBNZ LEN, WRITE_LOOP
RTS
;*******************************************************************************************
IF RCS_ENA = 1
RD_DATA_COM:
BSR READ
STA ADRS
BSR READ
STA ADRS+1
BSR READ
STA LEN
LDHX ADRS
BSR WRITE_LOOP
BRA BCKGND ; finish without ACK
ENDIF
;*******************************************************************************************
GETADDR:
BSR READ
PSHA
PULH ; store to H:x
BSR READ
TAX ; store to h:X
RTS ; low in A as well
;*******************************************************************************************
WRITE:
BRCLR 6,SCS1,WRITE
STA SCDR
IFNDEF LIN
RTS ; in case of LIN version, fall through to READ to clear
ENDIF
READ:
BRCLR 5,SCS1,READ
LDA SCDR
RTS
;*******************************************************************************************
ERASE_COM:
BSR GETADDR ; read adr. and return in H:X
IF SIZE = 16 ; QC16
CPHX #(FLS_END+2*ERBLK_LEN) ; self-protection since FLBPR is unusable
BGE SUCCERRER ; on QC16
ENDIF
JSR ERARNGE ; call ROM erase routine
SUCCERRER:
BRA SUCC ; refer status back to PC
;*******************************************************************************************
WR_DATA_COM:
BSR GETADDR ; read adr. and return in H:X
STHX ADRS
BSR READ
STA STAT
DECA
STA LEN
LDHX #DATA
WR_DATA_L1:
BSR READ
STA ,X
AIX #1
DBNZ STAT,WR_DATA_L1
; START OF SELF-PROGRAMMING
LDA ADRS+1
ADD LEN
STA LADDR+1
LDA ADRS
ADC #0
STA LADDR
LDHX ADRS
IF SIZE = 16 ; QC16
CPHX #(FLS_END+2*ERBLK_LEN) ; self-protection since FLBPR is unusable
BGE SUCCERRWR ; on QC16
ENDIF
JSR PRGRNGE ; call ROM erase routine
SUCCERRWR:
JMP SUCC ; refer status back to PC
;*******************************************************************************************
ICGTRIM:
CLRX
CLRH
MONRXD:
BRSET RXDBIT,RXDPORT,MONRXD ; WAIT FOR BREAK SIGNAL TO START
CHKRXD:
BRSET RXDBIT,RXDPORT,BRKDONE ; (5) GET OUT OF LOOP IF BREAK IS OVER
AIX #1 ; (2) INCREMENT THE COUNTER
NOP ; (1)
NOP ; (1)
NOP ; (1)
BRA CHKRXD ; (3) GO BACK AND CHECK SIGNAL AGAIN
BRKDONE:
PSHH
PULA ; PUT HIGH BYTE IN ACC AND WORK WITH A:X
IFDEF HICLOCK
LSRA
RORX ; divide by 2 (12.8 vs. 25.6 MHz version)
ENDIF
TSTA ; IF MSB OF LOOP CYCLES = 0, THEN BREAK TAKES TOO
TXA ; FEW CYCLES THAN EXPECTED, SO TRIM BY SPEEDING
BEQ SLOW ; UP f OP .
FAST: CMP #$40 ; SEE IF BREAK IS WITHIN TOLERANCE
BGE OOR ; DON'T TRIM IF OUT OF RANGE
ASLA ; multiply by two to get right range
ADD #$80 ; BREAK LONGER THAN EXPECTED, SO SLOW DOWN f OP
BRA ICGDONE
SLOW: CMP #$C0 ; SEE IF BREAK IS WITHIN TOLERANCE
BLT OOR ; DON'T TRIM IF OUT OF RANGE
ASLA ; multiply by two to get right range
SUB #$80
ICGDONE:
STA OSCTRIM
OOR:
RTS
;*******************************************************************************************
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -