; Orange programmer module v2.1 FASTSPI ; (c) 2009-2014 CnCLab ;GROUP=Spansion ;CHIP=S25FL256S,32768K(256),S25FL256S.HPL ;AREA=MAIN,32768K(256) ;AREA=OTP,1024 ;VCC=3250 ; tested S25FL256SA ; OTP mode enter ENSO - 0xB1 ; OTP не стирается! ;Status Register: 7 6 5 4 3 2 1 0 ; SRWD X X BP2 BP1 BP0 WEL WIP ; r/o r/o INFO="Serial FLASH. Use ERASE before WRITE" SOCKET=4 ;"SPI" OPTIONS=f, CDELAY=0.1 ; one set delay 1...0.1us PINO=SCK,0 PINO=SI,1 PINO=CS,2 PINO=WP,3 PINO=HOLD,4 PINI=SO,1 BUSO=SPIOUT,0xD4 ;BUSO=SPIOUT24,0xD6 BUSO=SPIOUT32,0xD7 BUSI=SPIIN,0xD4 R9=ADDRESS,H R10=STATUS,C8,SRWD,P_ERR,E_ERR,BP2,BP1,BP0,WEL,WIP R11=STATUS2,C2,ES,PS R12=CONFIG,C8,LC1,LC0,TBPROT,RFU,BPNV,TBPARM,QUAD,FREEZE R13=ASPR,C3,PWDMLB,PSTMLB,RFU R14=AUTOBOOT,H8 ;R11=SECURITY,C8,WPSEL,E_FAIL,P_FAIL,x,ESB,PSB,LDSO,OTP ;R13=LOCK,C8,7,6,5,4,3,2,1,0 [_SENDBYTE] ;LOOP=(7,0){SI=R0[I],SCK=P} ;speed-up SPIOUT=R0 [_RX] SI=1 R1=SPIIN [_SENDADR] ;LOOP=(23,0){SI=ADR[I],SCK=P} SPIOUT32=ADR [_WREN] SCK=0 CS=0 _SENDBYTE(00000110b) ; Write enable CS=1 [_WRDI] SCK=0 CS=0 _SENDBYTE(00000100b) ; Write disable CS=1 ;Read any reg. R0 - cmd. return R1 [_RDREG] SCK=0 CS=0 _SENDBYTE ;Read cmd _RX CS=1 ;return R1 [_RDSR] _RDREG(0x05) ;RDSR = 05 ;return R1 [_RDSR2] _RDREG(0x07) ;RDSR = 05 [_WAITWR] ;Wait for end write memory... SCK=0 LOOP=(0,40000){ _RDSR R1[0]?0{BREAK} ;WIP bit P=5 } [_WRSR] R1=R0 SCK=0 CS=0 _SENDBYTE(00000001b) ;WRSR _SENDBYTE(R1) ;Status Register CS=1 P=10000 _WAITWR ;max 500ms [INIT] HOLD=1 WP=0 CS=1 SCK=0 P=10 CS=0 _SENDBYTE(0x9F) ;JEDEC Read ID - New SI=1 R7=0 LOOP=(23,0){SCK=1,R7[I]=SO,SCK=0} CS=1 PRINT=L("ID=%06X\n",R7) R7?0xFFFFFF{R7=0} R7?0{ PRINT=A("Chip not respond!\nContinue?") RA?0{EXIT} } ;Enter 4-Byte Mode (B7h) ;CS=0 ;_SENDBYTE(0xB7) ;CS=1 [READ] $AREA?1{ CS=0 _SENDBYTE(0x4B) ;Read OTP LOOP=(23,0){SI=ADR[I],SCK=P} _SENDBYTE(0) ;dummy SI=1 DATA=SPIIN CS=1 RETURN } CS=0 _SENDBYTE(0x13) ;Read _SENDADR SI=1 ;LOOP=(7,0){SCK=1,DATA[I]=SO,SCK=0} DATA=SPIIN CS=1 [READBLOCK] CS=0 ;_SENDBYTE(00000011b) ;Read _SENDBYTE(0x13) ;Read _SENDADR ;_SENDBYTE(0) ; dummy SI=1 LOOP=($BLOCKSIZE){ ;LOOP=(7,0){SCK=1,DATA[I]=SO,SCK=0} ;speed-up: DATA=SPIIN ADR=+1 } CS=1 [_READBLOCKT] ;$BLOCKSIZE=512 ;dbg CS=0 _SENDBYTE(00000011b) ;Read _SENDADR SI=1 LOOP=($BLOCKSIZE){ LOOP=(7,0){SCK=1,DATA[I]=SO,SCK=0} ADR=+1 } CS=1 [WRITEINIT] HOLD=1 WP=1 CS=1 P=2000 _WREN $AREA?0{ ;WRSR will not be executed in 4kbit mode _WRSR(0) ;Status Register clear P=5000 } [WRITE] _WREN CS=0 _SENDBYTE(0x12) ; Write _SENDADR _SENDBYTE(DATA); SI=1,CS=1 P=3000 _WAITWR [WRITEBLOCK] _WREN CS=0 _SENDBYTE(0x12) ; Write + increment _SENDADR LOOP=($BLOCKSIZE){ SPIOUT=DATA ;_SENDBYTE(DATA) ADR=+1 } CS=1,SI=1 P=100 _WAITWR [WRITEEND] _WRDI [READID] WP=1 SCK=0 CS=1 ;CS=0 ;_SENDBYTE(0x04) ;Write Disable / Exit OTP mode ;SI=1 ; New ID (JEDEC) CS=0 _SENDBYTE(0x9F) ;JEDEC Read ID - New SI=1 R7=0 LOOP=(23,0){SCK=1,R7[I]=SO,SCK=0} CS=1 PRINT=L("ID1=%06X\n",R7) ;R7?0xFFFFFF{ ;not supported id cmd? ;Try Old ID (90H) CS=0 _SENDBYTE(0x90) ;RES R0=0 ; DUMMY LOOP=(23,0){SI=R0[I],SCK=P} SI=1 R8=0 LOOP=(15,0){SCK=1,R8[I]=SO,SCK=0} CS=1 ;R0=R8 PRINT=L("ID2=%06X\n",R8) ;} R0=R7 R7?0xFFFFFF{R0=R8} ["Read Registers"] ;HOLD=1 ;WP=1 ;_WRDI ;_WREN WP=0 SCK=0 CS=1 _RDSR R10=R1 _RDSR2 R11=R1 _RDREG(0x35) ;Read Configuration Register (RDCR 35h) R12=R1 _RDREG(0x2B) ;ASP Read (ASPRD 2Bh) R12=R1 CS=0 _SENDBYTE(0x2D) ;AutoBoot Register Read (ABRD 14h) R14=0 LOOP(4){ _RX R1=<<24 R14=>>8 R14=|R1 } CS=1 ;CS=0 ;_SENDBYTE(0x15) ;RDCR (read configuration register) ;_RX ;CS=1 ;R12=R1 VCC=0 GET=("Status",R10,R11,R12,R13,R14) [WriteStatus] GET=("Write Status",R10) RA?0{EXIT} WP=1 ;enable ;PRINT=("value %02lX",R10) _WREN _WRSR(R10) P=50000 _RDSR PRINT=S("Status=%02X",R1) P=500000 [Erase] HOLD=1 WP=1 SCK=0 CS=1 _WREN _WRSR(0) _WREN CS=0 _SENDBYTE(0x60) ;BE Bulk Erase CS=1 R7=$SIZE, R7=/200 ;; Full erase time - 150 000 ms (150sec)! PRINT=P(0,R7) SCK=0 R2=0 LOOP=(R7){ CS=0 R2=+1 PRINT=P(R2) _RDSR PRINT=S("STATUS=%02X",R1) R1[0]?0{BREAK} ;RDY bit P=1000 } _WRDI P=200000 ["Erase Sector"] GET=("Sector Address",R9) RA?0{EXIT} HOLD=1 WP=1 SCK=0 CS=1 _WREN _WRSR(0) _WREN CS=0 _SENDBYTE(0x20) ;BE sec Erase ;_SENDBYTE(0x52) ;BE BLK Erase LOOP=(23,0){SI=R9[I],SCK=1,SCK=0} CS=1 P=10000 ; Full erase time - 4 sec! _WAITWR SCK=0 R2=0 LOOP=(20000){ CS=0 PRINT=S("Erase %lu",R2) R2=+1 _RDSR R1[0]?0{BREAK} ;RDY bit P=1000 } _WRDI P=200000 [END] $AREA?1{ ;4KEEP R2=R0 ;PUSH CS=0 _SENDBYTE(0xC1) ;EXSO - Exit 4Kb sector CS=1 R0=R2 ;POP }