mirror of
https://github.com/Pecusx/jataricart.git
synced 2026-05-21 06:39:37 +02:00
328 lines
6.5 KiB
Plaintext
328 lines
6.5 KiB
Plaintext
; flash eeprom library
|
|
; by JHusak , 04.01.2020
|
|
; free to use.
|
|
|
|
; Nice to have procedures, because mads may exclude unused procedures (-x in cmdl)
|
|
;.def STRIPPED
|
|
|
|
icl "lib_28sf0x0.asm"
|
|
icl "lib_29f0x0.asm"
|
|
icl "lib_29sf0x0.asm"
|
|
icl "lib_39sf0x0.asm"
|
|
|
|
; x - 0x0 or 0x40 - chip select;
|
|
; a - $80 - format, $90 - enter id mode, $a0 - writebyte
|
|
C_ID_MODE equ $90
|
|
|
|
M_SECTOR_SIZES
|
|
.word M_SSIZE_28SF, M_SSIZE_29F, M_SSIZE_29SF, M_SSIZE_39SF
|
|
M_PREAMBLE_VECS
|
|
.word flashoppreamble_28SF, flashoppreamble_29F, flashoppreamble_29SF, flashoppreamble_39SF
|
|
M_PREAMBLES_ACC_VECS
|
|
.word flashoppreamble_acc_28SF, flashoppreamble_acc_29F, flashoppreamble_acc_29SF, flashoppreamble_acc_39SF
|
|
M_UNLOCKMEM_VECS
|
|
.word flash_unlockchip_28SF, flash_unlockchip_29F, flash_unlockchip_29SF, flash_unlockchip_39SF
|
|
|
|
|
|
;Problems 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
|
|
; For flash recognition
|
|
; - format,
|
|
; - write 128 kbytes, read more -> if not ff, flash is 128k
|
|
; - write additional 128KB, read more ->if not ff flash is 256kB, else is 512kb
|
|
;
|
|
; First detection is to read raw memory and id and compare results. Some issues may occur when no memory inserted.
|
|
|
|
;flash_detect_protocol:
|
|
; lda #ID_MODE
|
|
; jsr flashoppreamble_5555_2aaa
|
|
|
|
; c parameter as format/writebyte
|
|
; for compatibility, 5555_2aaa only
|
|
|
|
.ifndef STRIPPED
|
|
; flash size only needed in not stripped version for format result check.
|
|
flash_size dta 0
|
|
; as well as check_vendor procedure
|
|
;
|
|
; --------------------------
|
|
; PROCEDURE
|
|
; x = 0 or 0x40 - flash chip address.
|
|
; returns c set -> failed
|
|
; if c cleared, x=vendor, y=product code
|
|
; there are some memories which need multiple read, but we do not abuse them.
|
|
check_vendor
|
|
lda #C_ID_MODE
|
|
jsr flashoppreamble_acc
|
|
ldx $a000 ; vendor
|
|
ldy $a001 ; id
|
|
mva #$f0 $a000 ; exit read_id
|
|
mva #0 flash_size
|
|
|
|
cpx #$BF; SST
|
|
bne next1
|
|
; nice to store that this is SST
|
|
cpy #$B5
|
|
bne @+
|
|
lda #$0f
|
|
@ cpy #$B6
|
|
bne @+
|
|
lda #$1f
|
|
@ cpy #$B7
|
|
bne @+
|
|
lda #$3f
|
|
@ sta flash_size
|
|
clc
|
|
rts
|
|
next1
|
|
.if 0
|
|
lda #C_ID_MODE
|
|
jsr flashoppreamble_acc
|
|
ldx $a000 ; vendor
|
|
ldy $a001 ; id
|
|
mva #$f0 $a000 ; exit read_id
|
|
mva #0 flash_size
|
|
|
|
cpx #$BF; SST
|
|
bne cvexit
|
|
; nice to store that this is SST
|
|
cpy #$24
|
|
bne @+
|
|
lda #$1f
|
|
@ cpy #$13
|
|
bne @+
|
|
lda #$3f
|
|
@ sta flash_size
|
|
clc
|
|
rts
|
|
.endif
|
|
cvexit
|
|
sec
|
|
rts
|
|
.endif
|
|
|
|
|
|
|
|
; --------------------------
|
|
flashformatchip2
|
|
ldx #$40
|
|
dta { bit.w }
|
|
flashformatchip1
|
|
ldx #$0
|
|
; --------------------------
|
|
; PROCEDURE
|
|
; x = 0 or 0x40 - flash chip address.
|
|
flashformatchip
|
|
|
|
sei
|
|
stx store_x
|
|
lda #C_FORMAT
|
|
jsr flashoppreamble_acc ; does not touch A
|
|
sta $d502,x
|
|
lda #TRIGGER_FORMAT
|
|
sta $b555 ; FORMAT HERE TRIGGERED!
|
|
; not needed to mva $ff flashcmp
|
|
jsr wait4flashcheckresult ; waits for format finished
|
|
; then check number of banks for FFs
|
|
lda #$3f ; this depends on flash size, $0f, $1f, $3f
|
|
sta flashformatcounter
|
|
flashbankloop sei
|
|
ldx store_x
|
|
flashformatcounter equ*+1
|
|
sta $d5FF,x ; set chip (x) and bank
|
|
; set pages count
|
|
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 jmp flashcartoff ; preserves C
|
|
store_x dta 0
|
|
|
|
; --------------------------
|
|
; PROCEDURE
|
|
flashformatsector
|
|
; x - bank number 00 - 7f (even sector>>1)
|
|
; a - erase 4KB from $B000 if A=$B0, FROM $A000 IF A=$A0
|
|
; format 4kb evensector
|
|
; strange form - easily maps to cartridge banks
|
|
; to format bank, must format sector (x<<1) and (x<<1) +1
|
|
; IT IS LONG because it has to be save, ie not format if formatted etc.
|
|
|
|
; first check if all ff
|
|
; this is to avoid wear
|
|
stx flashformatstorex
|
|
sta flashformatstorea
|
|
sei
|
|
sta $d500,x
|
|
; store #$a0 or #$b0
|
|
sta flashformataddrcheck + 2
|
|
jsr flashchecksectorformatted
|
|
bcc flashsectorformatgood
|
|
sei
|
|
flashformatstorex equ * + 1
|
|
ldx #0 ; filled before
|
|
; check least sector bit
|
|
|
|
lda #C_FORMAT
|
|
jsr flashoppreamble_acc ; does not touch A,X
|
|
sta $D500,x
|
|
; A must be either $A0 or $B0
|
|
flashformatstorea equ * + 1
|
|
lda #0 ; filled before
|
|
sta flashtmpaddr+1
|
|
sta flashformataddrcheck + 2
|
|
|
|
lda #$30
|
|
flashtmpaddr equ *+1
|
|
sta $a000 ; SECTOR FORMAT INVOKED HERE!
|
|
jsr wait4flashcheckresult ;
|
|
sei
|
|
|
|
lda flashformatstorea
|
|
sta flashformataddrcheck+2
|
|
|
|
ldx flashformatstorex
|
|
sta $d500,x
|
|
|
|
; check if all data in sector is $ff
|
|
flashchecksectorformatted
|
|
ldy #$10
|
|
flashchecksectorformatted_bare
|
|
lda #$ff
|
|
ldx #0
|
|
flashformataddrcheck
|
|
cmp $a000,x
|
|
bne flashsectorformaterror
|
|
inx
|
|
bne flashformataddrcheck
|
|
inc flashformataddrcheck + 2
|
|
dey
|
|
bne flashformataddrcheck
|
|
|
|
flashsectorformatgood
|
|
jsr flashcartoff
|
|
clc
|
|
rts
|
|
|
|
flashsectorformaterror
|
|
jsr flashcartoff
|
|
sec
|
|
rts
|
|
|
|
|
|
; ---------------------
|
|
; 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 #C_BYTE_PROG
|
|
jsr flashoppreamble_acc ; preserves A,X
|
|
pla
|
|
; set right bank
|
|
sta $D500,x
|
|
ldy #{ sta.w }
|
|
jsr flashprocessbyte ; WRITE BYTE INVOKED !
|
|
|
|
wait4flashcheckresult ; sei mode
|
|
mva #0 flashcnt
|
|
ldy #1 ; first time wait short first turn to speed up byte write.
|
|
bne @+
|
|
|
|
flashwaitfordone
|
|
; 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
|
|
ldy#250
|
|
@ dey
|
|
nop
|
|
bne @-
|
|
|
|
@ ldy #{ lda.w }
|
|
jsr flashprocessbyte
|
|
sta flashval
|
|
ldy #{ eor.w }
|
|
jsr flashprocessbyte
|
|
inc flashcnt
|
|
bne @+
|
|
sta $d580
|
|
lda #$ff ; status
|
|
rts
|
|
@
|
|
and #$40
|
|
bne flashwaitfordone
|
|
sta $d580
|
|
flashval equ *+1
|
|
lda #0
|
|
flashcmp equ *+1
|
|
cmp #0
|
|
; when byte compare non zero = error
|
|
rts
|
|
|
|
flashcnt
|
|
dta 0
|
|
; ----------------------
|
|
; PROCEDURE
|
|
|
|
flashprocessbyte
|
|
|
|
; y - byteop for cpu to do with byte
|
|
; flashaddr - stored address
|
|
sty flashbyteop
|
|
flashaddr equ *+1
|
|
flashbyteop
|
|
sta $aaaa
|
|
rts
|
|
|
|
flashincaddr
|
|
inw flashaddr
|
|
rts
|
|
|
|
flashsetaddr
|
|
stx flashaddr
|
|
sty flashaddr+1
|
|
rts
|
|
|
|
flashcartoff
|
|
pha
|
|
sta $d580
|
|
lda $d013
|
|
sta $3fa
|
|
cli
|
|
pla
|
|
rts
|
|
|