Files
jataricart/lib/flashwritelib.asx
Jakub Husak e6dc1ff925 rewritten flash recognition procedure
updated flasher to handle all chip configuration.
2025-01-26 17:59:21 +01:00

530 lines
9.4 KiB
Plaintext

; flash eeprom library
; by JHusak , 04.01.2020
; free to use.
FRAME_FEEDBACK=1
icl "lib_28sf0x0.asm"
icl "lib_29f0x0.asm"
icl "lib_39sf0x0.asm"
num_mems = 3
; CONSTANTS
m_offsets
; jump table
softid_entry = 0
softid_exit = 3
flash_formatchip = 6
flash_formatsector = 9
flash_writebyte = 12
flash_lockchip = 15
flash_unlockchip = 18
flash_wait_unit = 21
; data table
; 1 byte
flash_sectorsizeMSB = 24
; var bytes 0 terminated
flash_idstr = 25
; rw section, may be moved to ZP if needed
M_VECTOR .word 0
m_vendor .byte 0
m_kind .byte 0
; ro section again
; Protocols for known kinds of memory:
; 28sf0x0 protokol unlock/write
; 39sf0x0 protokol 5555/AA;2aaa/55
; 29f0x0 protokol 555/AA;2aa/55
; Working scan order; scanning from the end;
M_CHECK_VECS .word M_VECTORS_39SF, M_VECTORS_29F, M_VECTORS_28SF
; --------------------------------------------------------------------
;Problems to solve with writing:
; - check flash presence
; - flash protocol
; - size of flash 1,2
; - size of sector in some cases
; - number of flashes (easy, they do not overlap)
; All can be read by erasing memory, writing several bytes and reading them;
; But we will rely rather on user's choice not to wear memory
; First detection is to read raw memory and id and compare results. However, we do not want to keep all those ids to recognise.
; Second detection is to compare contents. But not very reliable as contents may repeat.
; And ome issues may occur when no memory inserted.
; Eventually, for flash recognition
; - format,
; - write 128k-1 byte, read 2*128k-1 -> if not ff flash is 128k
; - write 256k-1 byte, read 2*256k-1 -> if not ff flash is 256kB, else is 512kb
;
; ??? c parameter as format/writebyte
; ??? for compatibility, 5555_2aaa only
; ------------------------------------------------------------------------
; --------------------------
; PROCEDURE
; x = 0 or 0x40 - flash chip address.
; stores proper vector table pointer
; this fails only when somebody stores vendor and product bytes
; at the proper cells.
; The second case is that there is no mem at all.
; Then two cases are possible: random number OR fixed ff.
;
; then in the code we call lda #offset/jsr jsrtovectorproc
.if 0
check_type
ldy #(2*(num_mems-1))
?again
sty m_iter
?again_loop
; store default values
jsr flashsetbank0
; load real values, may be random if no chip.
lda $a000
sta m_vendor
lda $a001
sta m_kind
jsr jsrtosoftidentry
jsr flashsetbank0
lda $a000 ; vendor
cmp m_vendor
sta m_vendor
beq ?next
lda $a001 ; id
cmp m_kind
sta m_kind
beq ?next
bne ?OK
?next
ldy m_iter
dey
dey
bpl ?again
; error
sec ; failed, no chip
rts
?check_again
; if zero, decrement check_bad_counter
sne
dec check_bad_counter
dec check_counter
bne ?again_loop
lda check_bad_counter
cmp #CNTINIT
; if check_counter is 0 and check_bad_counter is CNTINIT then ok, else
; go to ?next
bne ?next
.endif
check_type
ldy #(2*(num_mems-1))
?again
sty ?m_iter
lda #0
sta ?or_val
sta ?or_val+1
sta ?c_iter
lda #$ff
sta ?and_val
sta ?and_val+1
?repeat
jsr flashsetbank0
jsr jsrtosoftidentry
lda $A000
sta ?_id_m
lda $A001
sta ?_id_m+1
jsr jsrtosoftidexit
lda $A000
sta ?_no_m
lda $A001
sta ?_no_m+1
lda ?_id_m
and:sta ?and_val
lda ?_id_m+1
and:sta ?and_val+1
lda ?_id_m
ora:sta ?or_val
lda ?_id_m+1
ora:sta ?or_val+1
dec ?c_iter
bne ?repeat
;@
; lda #$ff
; sta $d01a
; lda #0
; sta $d01a
; jmp @-
cpw ?and_val ?or_val
bne ?next_chip ; empty slot, random values, no chip, check next chip
cpw ?and_val ?_no_m
beq ?next_chip ; the came content, stable values, no response so no chip, check next chip
?OK
lda ?_id_m
sta m_vendor
lda ?_id_m+1
sta m_vendor+1
lda M_CHECK_VECS+1,y
sta M_VECTOR+1
lda M_CHECK_VECS,y
sta M_VECTOR
clc
rts
?next_chip
php ; store zero flag
pla
ldy ?m_iter
dey
dey
jpl ?again
pha ; restored zero flag
plp
sec
rts
?or_val dta 0,0
?and_val dta 0,0
?_id_m dta 0,0
?_no_m dta 0,0
?c_iter .byte 0
?m_iter .byte 0
jsrtosoftidexit
lda #softid_exit
jsr jsrtovectorproc
lda $d013
sta $3fa
clc
rts
jsrtosoftidentry
lda M_CHECK_VECS+1,y ; first is softid entry
sta M_VECTOR+1
pha
lda M_CHECK_VECS,y ; first is softid entry
sta M_VECTOR
pha
php
rti ; jsr to tabled func
; PROCEDURE
; performs jump to vector table at offset in A provided
; y passed to the procedure called
jsrtovectorproc
php ; preserve C
clc
adc M_VECTOR
sta tmpa
lda M_VECTOR+1
adc #0
plp ; restore C
pha
lda tmpa:#0
pha
php
rti
; a - vector value offset
; returns y-LSB A-MSB
getvectorvalue
clc
adc M_VECTOR
tay
lda M_VECTOR+1
adc #0
rts
; --------------------------
flashformatchip2
ldx #$40
dta { bit.w }
flashformatchip1
ldx #$0
; --------------------------
; PROCEDURE
; x = 0 or 0x40 - flash chip address.
flashformatchip
; first check if not formatted
stx store_x
jsr flashcheckempty
bcc flashformatexit
sei
ldx store_x
lda #flash_formatchip
jsr jsrtovectorproc ; preserves A
; not needed to mva $ff flashcmp
jsr wait4flashcheckresult ; waits for format finished
; then check number of banks for FFs
flashcheckempty
lda #$3f ; this depends on flash size, $0f, $1f, $3f
sta flashformatcounter
flashbankloop sei
ldx store_x
sta flashformatcounter:$d5FF,x ; set chip (x) and bank
; set pages count, 8kB
ldy #$20
; reset address
lda #$a0
sta flashformataddrcheck + 2
; check whole sector against 0xff
jsr flashchecksectorformatted_bare ; destroys x
bcs flashformatexit ; format error if c set
dec flashformatcounter
bpl flashbankloop
flashformatexit
flashcartoff ; preserves C
pha
sta $d580
lda $d013
sta $3fa
cli
pla
rts
flashchecksectorformatted
ldy #$10
flashchecksectorformatted_bare
lda #$ff
ldx #0
flashformataddrcheck
cmp $a000,x
bne flashsectorformaterror
inx
bne flashformataddrcheck
FEEDBACK
inc flashformataddrcheck + 2
dey
bne flashformataddrcheck
FEEDBACKEND
clc
rts
flashsectorformaterror
jsr flashcartoff
sec
rts
; --------------------------
store_x dta 0
; --------------------------
; PROCEDURE
flashformatsector
; x - bank number 00 - 7f (even sector>>1)
; a - page number in 128byte units $0-$3f
; erase sector containing address bank number * $2000 + page number * 128
stx flashformatstorex
sei
; calculate lower 13 bits of sector
; (address in 8kb bank)
ldx #0
; convert page in A to cartridge a000-bfff address flashtmpaddr
; 0,1 -> 0 ; 2,3 -> 256 ; 4,5 -> 512 etc
lsr
ora #$A0
tay
jsr flashsetaddr ;(x/y) store address for write byte to format sector
;
ldx flashformatstorex:#0 ; filled before, 8k bank number
lda #flash_formatsector ; does not touch A,X?
jsr jsrtovectorproc
ldy #{ sta.w }
jsr flashprocessbyte ; format sector INVOKED !
jsr wait4flashcheckresult ;
;sei
ldx flashformatstorex
jsr flashsetbank0
cli
; check if all data in sector is $ff
flashsectorformatgood
;jsr flashcartoff
clc
rts
.macro FEEDBACK
.if (FRAME_FEEDBACK)>=1
php
pha
.if (FRAME_FEEDBACK&1)==1
inc colbaks
lda colbaks
sta colbak
.endif
.if (FRAME_FEEDBACK&2)==2
lda #0
sta dmactl
sta sdmctl
.endif
pla
plp
.endif
.endm
.macro FEEDBACKEND
.if FRAME_FEEDBACK>=1
php
pha
lda #0
sta colbaks
sta colbak
.if (FRAME_FEEDBACK&2)==2
lda #34 ; ???
sta sdmctl
sta dmactl
.endif
pla
plp
.endif
.endm
; ---------------------
; PROCEDURE
flashwritebyte
; a - byte to write
; x - 8kb bank to switch, $00 to $7f, also chip select
; flashaddr - addres in flash - must be a000-offset
; do not programm byte if already good
sei
sta $D500,x ; select bank, chip
ldy #{ cmp.w }
jsr flashprocessbyte
bne byte_differs
sta $D580
cli
clc
rts
byte_differs
sta flashcmp
sei
pha
lda #flash_writebyte ; preserves A,X
jsr jsrtovectorproc
pla
; set right bank
sta $D500,x
ldy #{ sta.w }
jsr flashprocessbyte ; WRITE BYTE INVOKED !
wait4flashcheckresult ; sei mode
mva #0 flashcnt ; reset counter
sta flashcnt+1
; ldy #1 ; first time wait short first turn to speed up byte write.
beq skipwsync
flashwaitfordone
; WARNING! 29f040 erases even 10 seconds!
; approx 100ms in overall for chip erase:
; as many cycles needed, as 256*cycles >100ms * (1+epsilon)
; 100 ms is 180000 cycles
; so max 256 rough loops must last longer
; 180000 / 256 = 703
; 700 cycles by 6 cycles loop lasts = 116.
; so flipipng values, and adding margin,
; we count 128*6 cycles in inner loop.
; max sector erase by datasheet: 25 ms
; max chip erase by datasheet: 100 ms 39sf040
; max chip erase by datasheet: 20 ms 28sf040
; max chip erase by datasheet: 10000 ms 29f040
;ldy#250
sta WSYNC
skipwsync
;lda #flash_wait_unit
;jsr jsrtovectorproc
FEEDBACK
;dey
;bne @-
ldy #{ lda.w }
jsr flashprocessbyte
sta flashval
ldy #{ eor.w }
jsr flashprocessbyte
inc flashcnt
bne cont
inc flashcnt+1
bne cont
jsr flashcartoff
FEEDBACKEND
lda #$ff ; status
rts
cont
and #$40
bne flashwaitfordone
jsr flashcartoff
FEEDBACKEND
lda flashval:#0
cmp flashcmp:#0
; when byte compare non zero = error
rts
flashcnt
dta 0,0
; ----------------------
; PROCEDURE
flashprocessbyte
; y - byteop for cpu to do with byte
; flashaddr - stored address
sty flashbyteop
flashbyteop
sta flashaddr:$aaaa
rts
flashend
FEEDBACKEND
rts
flashincaddr
inw flashaddr
rts
flashsetaddr
stx flashaddr
sty flashaddr+1
rts
flashunlockchip
lda #flash_unlockchip
jmp jsrtovectorproc
flashlockchip
lda #flash_lockchip
jmp jsrtovectorproc
flashsetbank0
sta $d500,x
pha
lda $d013
sta $3fa
pla
rts