diff --git a/lib/flashwritelib_new.asx b/lib/flashwritelib_new.asx new file mode 100644 index 0000000..bb6805a --- /dev/null +++ b/lib/flashwritelib_new.asx @@ -0,0 +1,327 @@ +; 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 + diff --git a/lib/lib_28sf0x0.asm b/lib/lib_28sf0x0.asm index 698d376..89852c1 100644 --- a/lib/lib_28sf0x0.asm +++ b/lib/lib_28sf0x0.asm @@ -1,16 +1,18 @@ TRIGGER_FORMAT_28SF equ $30 C_FORMAT_28SF equ $30 C_BYTE_PROG_28SF equ $10 -flashoppreamble +M_SSIZE_28SF equ $0100 ; sector size + +flashoppreamble_28SF pha lda #C_BYTE_PROG_28SF scc lda #C_FORMAT_28SF ; only if c set -flashoppreamble_acc ; 28SF0x0 +flashoppreamble_acc_28SF ; 28SF0x0 sta $d500,x ; can be any address sta $a000; command: FORMAT/ID_MODE/BYTE_PROG, any address rts -flash_unlockchip +flash_unlockchip_28SF sta $D500,x ; read from 1823H, 1820H, 1822H, 0418H, 041BH, 0419H, 041AH lda $B823 diff --git a/lib/lib_29f0x0.asm b/lib/lib_29f0x0.asm index d6d12e5..a8d2875 100644 --- a/lib/lib_29f0x0.asm +++ b/lib/lib_29f0x0.asm @@ -1,6 +1,8 @@ TRIGGER_FORMAT_29F equ $10 C_FORMAT_29F equ $80 C_BYTE_PROG_29F equ $a0 +M_SSIZE_29F equ $10000 ; sector size; MAXFlash, protocol compatible with 39sf0x0 +command_ZP = $f0 flashoppreamble_29F pha lda #C_BYTE_PROG_29F diff --git a/lib/lib_29sf0x0.asm b/lib/lib_29sf0x0.asm index 23d326b..fd3bb9c 100644 --- a/lib/lib_29sf0x0.asm +++ b/lib/lib_29sf0x0.asm @@ -1,6 +1,8 @@ TRIGGER_FORMAT_29SF equ $10 C_FORMAT_29SF equ $80 C_BYTE_PROG_29SF equ $a0 +M_SSIZE_29SF equ $0080 ; sector size +command_ZP = $f0 flashoppreamble_29SF pha lda #C_BYTE_PROG_29SF diff --git a/lib/lib_39sf0x0.asm b/lib/lib_39sf0x0.asm index e05388c..1ebc0b1 100644 --- a/lib/lib_39sf0x0.asm +++ b/lib/lib_39sf0x0.asm @@ -1,6 +1,9 @@ TRIGGER_FORMAT_39SF equ $10 C_FORMAT_39SF equ $80 C_BYTE_PROG_39SF equ $a0 +M_SSIZE_39SF equ $1000 ; sector size +command_ZP = $f0 + flashoppreamble_39SF pha lda #C_BYTE_PROG_39SF