; Orange programmer module v2.2 FASTSPI ; (c) 2013-2014 CnCLab ; SPI FLASH ; 4 BYTE Address! 3 status registers! ; GROUP=Winbond ;CHIP=W25Q256,32768K(256),W25Q256.HPL ;AREA=FLASH,32768K(256) ;AREA=SECURITY,768 ;AREA=SFDP,256 ;VCC=3250 ;bits 7 6 5 4 3 2 1 0 ;Status Register1: SRP0 TB BP3 BP2 BP1 BP0 WEL BUSY ; r/o r/o ;Status Register2: SUS CMP LB3 LB2 LB1 R QE SRP1 ; r/o r/o r/o ;Status Register3: HOLD DRV1 DRV0 (R) (R) WPS ADP ADS ; Tested W25Q256 Orange5 SOCKET=4 ;"SPI" OPTIONS=f,,w 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 CDELAY=0.1 ; one set delay R9=STATUS1,C8,SRP0,TB,BP3,BP2,BP1,BP0,WEL,BUSY R10=STATUS2,C8,SUS,CMP,LB3,LB2,LB1,x,QE,SRP1 R11=STATUS3,C8,HOLD,DRV1,DRV0,x,x,WPS,ADP,ADS R12=UID,E8 ;R9=STATUS,B8 @UID=8 [_SENDBYTE] ;LOOP=(7,0){SI=R0[I],SCK=P} ;speed-up SPIOUT=R0 [_RX] SI=1 R1=0 LOOP=(7,0){R1[I]=SO,SCK=P} ;PRINT=L("%02X\n",R1) ;4 bytes [_SENDADR] LOOP=(31,0){SI=R0[I],SCK=P} ;Security Register address ;Security Register 1: A23-16 = 00h; A15-8 = 10h; A7-0 = byte address ;Security Register 2: A23-16 = 00h; A15-8 = 20h; A7-0 = byte address ;Security Register 3: A23-16 = 00h; A15-8 = 30h; A7-0 = byte address [_SENDADR_S] SI=0,SCK=P16 R0=ADR,R0=/256,R0=+1,R0=<<4 ;PRINT=L("RH=%04X\n",R0) LOOP=(7,0){SI=R0[I],SCK=P} LOOP=(7,0){SI=ADR[I],SCK=P} ;A7-0 [_RDID] CS=0 R0=0 _SENDBYTE(0x9F) ;JEDEC Read ID SI=1 LOOP=(23,0){SCK=1,R0[I]=SO,SCK=0} CS=1 [INIT] HOLD=1 WP=0 CS=1 SCK=0 _RDID R0?0xFFFFFF{ PRINT=A("Chip not respond, continue?") RA?0{EXIT} } R0?0x0{ PRINT=A("Chip not respond (SO=0), continue?") RA?0{EXIT} } ;Enter 4-Byte Mode (B7h) CS=0 _SENDBYTE(0xB7) CS=1 [READ] $AREA?1{ ;SECURITY CS=0 _SENDBYTE(0x48) ;Read _SENDADR_S SI=1 SCK=P8 ;Dummy LOOP=(7,0){SCK=1,DATA[I]=SO,SCK=0} CS=1 RETURN } $AREA?2{ ;SFDP CS=0 _SENDBYTE(0x5A) ;Read SFDP Register LOOP=(23,0){SI=ADR[I],SCK=P} SI=1 SCK=P8 ;Dummy LOOP=(7,0){SCK=1,DATA[I]=SO,SCK=0} CS=1 RETURN } CS=0 _SENDBYTE(0x03) ;Read main flash LOOP=(31,0){SI=ADR[I],SCK=P} SI=1 ;LOOP=(7,0){SCK=1,DATA[I]=SO,SCK=0} DATA=SPIIN CS=1 ;Only for FLASH [READBLOCK] CS=0 SPIOUT=0x03 ;_SENDBYTE(0x03) ;Read ;LOOP=(31,0){SI=ADR[I],SCK=P} SPIOUT32=ADR SI=1 LOOP=($BLOCKSIZE){ ;LOOP=(7,0){SCK=1,DATA[I]=SO,SCK=0} DATA=SPIIN ADR=+1 } CS=1 [_RDSTAT] CS=0 _SENDBYTE(00000101b) ;RDSR SI=1 R9=0 ;LOOP=(7,0){SCK=1,R9[I]=SO,SCK=0} R9=SPIIN CS=1 [_WAITWR] ;Wait for end write memory... SCK=0 LOOP=(0,500){ _RDSTAT R9[0]?0{BREAK} ;WIP bit P=10 } [_WREN] SCK=0 CS=0 _SENDBYTE(00000110b) ; Write enable CS=1 [WRITEINIT] HOLD=1 WP=1 CS=1 P=5000 _WREN CS=0 _SENDBYTE(00000001b) ;WRSR _SENDBYTE(00000000b) ;Status Register CS=1 P=50000 ;! _WAITWR [_WRSEC] _WREN CS=0 _SENDBYTE(0x42) ; Program Security Registers (42h) _SENDADR_S R0=DATA,_SENDBYTE CS=1 _WAITWR [WRITE] ;R0=DATA,R0?0xFF{RETURN} $AREA?1{_WRSEC,RETURN} SCK=0 _WREN CS=0 R0=00000010b ; Write _SENDBYTE LOOP=(31,0){SI=ADR[I],SCK=P} LOOP=(7,0){SI=DATA[I],SCK=P} SI=1,CS=1 ;P=5000 _WAITWR ; page program time - max 3ms [WRITEBLOCK] ;R2=ADR ;check empty (0xFF) block ;LOOP=($BLOCKSIZE){ ;R1=DATA ;R1?!0xFF{BREAK} ;ADR=+1 ;} ;R1?0xFF{RETURN} ;ADR=R2 SCK=0 _WREN CS=0 _SENDBYTE(00000010b) ; Write CMD ;LOOP=(31,0){SI=ADR[I],SCK=P} SPIOUT32=ADR LOOP=($BLOCKSIZE){ ;LOOP=(7,0){SI=DATA[I],SCK=P} SPIOUT=DATA ADR=+1 } CS=1 _WAITWR [READID] WP=1 SCK=0 CS=1 _RDID PRINT=S("ID value = %04lXH",R0) [ReadStatus] ;HOLD=1 WP=1 SCK=0 CS=1 CS=0 R9=0 _SENDBYTE(0x05) ;RDSR SI=1 LOOP=(7,0){SCK=1,R9[I]=SO,SCK=0} CS=1 P=10 R10=0 CS=0 _SENDBYTE(0x35) ;RDSR2 SI=1 LOOP=(7,0){SCK=1,R10[I]=SO,SCK=0} CS=1 R11=0 CS=0 _SENDBYTE(0x15) ;RDSR3 SI=1 LOOP=(7,0){SCK=1,R11[I]=SO,SCK=0} CS=1 P=10000 GET=("Status",R9,R10,R11) [WriteStatus] GET=("Write Status",R9,R10,R11) RA?0{EXIT} WP=1 CS=1 SCK=0 ;PRINT=("value %02lX",R9) _WREN CS=0 _SENDBYTE(0x01) ;WRSR _SENDBYTE(R9) ;Status Register CS=1 P=200000 ;Write Status Register Time 67... 150 ms _WREN CS=0 _SENDBYTE(0x31) ;WRSR2 _SENDBYTE(R10) CS=1 P=200000 ;Write Status Register Time 67... 150 ms _WREN CS=0 _SENDBYTE(0x11) ;WRSR3 _SENDBYTE(R11) CS=1 P=200000 ;Write Status Register Time 67... 150 ms ;Read Unique ID Number - factory-set read-only 64-bit number ;Run on PC [#ReadUniqueID] WP=0 CS=0 _SENDBYTE(0x4B) ;Read Unique ID Number (4Bh) SI=0,SCK=P32 ;Dummy Byte 1-4 SI=1 LOOP(0,7){ _RX @UID[I]=R1 } CS=1 R12=0 ;Array 0 GET=("UniqueID",R12) ;erase one Security Register #1 [_ERASESEC1] R2=R0 ;push PRINT=S("Erase sec...") CS=1 _WREN CS=0 _SENDBYTE(0x44) ;WRSR _SENDADR(R2) CS=1 P=200000 ;Write Status Register Time 67... 150 ms! _WAITWR [Erase] HOLD=1 WP=1 SCK=0 $AREA?1{ PRINT=S("Erase sec...") CS=1 _WREN CS=0 _SENDBYTE(00000001b) ;WRSR _SENDBYTE(0) ;Status Register CS=1 P=200000 ;Write Status Register Time 67... 150 ms! _WAITWR _WREN CS=0 _ERASESEC1(0x1000) _ERASESEC1(0x2000) _ERASESEC1(0x3000) RETURN} $AREA?2{ PRINT=E("This area is read-only!") EXIT} PRINT=S("Erase flash...") CS=1 _WREN CS=0 _SENDBYTE(00000001b) ;WRSR _SENDBYTE(0) ;Status Register CS=1 P=200000 ;Write Status Register Time 67... 150 ms! _WREN CS=0 _SENDBYTE(11000111b) ;BE Bulk Erase 0xC7 CS=1 ; Full erase time: ; Winbond 25..80 sec SCK=0 R3=0 PRINT=P(0,22000) LOOP=(22000){ ;110 sec _RDSTAT R9[0]?0{BREAK} ;BUSY bit P=5000 R3=+1 PRINT=P(R3) } PRINT=S("Erase status %02X",R9) P=400000 R9?!0{ P=600000 PRINT=L("Erase error. Status %02X\n",R9) }