; Orange programmer module v2.2 FASTSPI ; (c) 2008-2015 CnCLab & Evimix ; CHIP=W25X10,128K(128),W25X32.hpl ; CHIP=W25X20,256K(128),W25X32.hpl ; CHIP=W25X40,512K(256),W25X32.hpl ; CHIP=W25X80,1024K(256),W25X32.hpl ; CHIP=W25X16,2048K(256),W25X32.hpl ; CHIP=W25X32,4096K(256),W25X32.hpl ; CHIP=W25X64,8192K(256),W25X32.hpl ; CHIP=W25P10,128K(128),W25X32.hpl ; CHIP=W25P20,256K(128),W25X32.hpl ; CHIP=W25P40,512K(256),W25X32.hpl ; CHIP=W25P80,1024K(256),W25X32.hpl ; CHIP=W25P16,2048K(256),W25X32.hpl ; CHIP=W25P32,4096K(256),W25X32.hpl ; CHIP=W25P64,8192K(256),W25X32.hpl ;VCC=3250 ; SPI ;Tested W25X40,W25X16,W25X32,Pm25LD512,ST M25P16 ;Status Register: 7 6 5 4 3 2 1 0 ; WPEN X X BP2 BP1 BP0 WEL BUSY ; r/o r/o SOCKET=4 ;"SPI" OPTIONS=f PINO=SCK,0 PINO=SI,1 PINO=CS,2 PINO=WP,3 PINO=HOLD,4 PINI=SO,1 BUSO=SPIOUT,0xD4 BUSO=SPIOUT24,0xD6 BUSI=SPIIN,0xD4 CDELAY=0.1 ; one set delay R9=STATUS,C8,WPEN,x,x,BP2,BP1,BP0,WEL,BUSY ;R9=STATUS,B8 R1="Enter addr:",H6 R12=Erase,l,"Off,Block,Full" [_SENDBYTE] ;LOOP=(7,0){SI=R0[I],SCK=P} ;speed-up SPIOUT=R0 [_SENDADR0] ;LOOP=(23,0){SI=ADR[I],SCK=1,SCK=0} SPIOUT24=R0 [_SENDADR] ;LOOP=(23,0){SI=ADR[I],SCK=1,SCK=0} SPIOUT24=ADR [_WAITWR] ;Wait for end write memory... SCK=0 LOOP=(0,2000){ CS=0 _SENDBYTE(00000101b) ;RDSR SI=1 R9=0 ;LOOP=(7,0){SCK=1,R9[I]=SO,SCK=0} R9=SPIIN CS=1 R9[0]?0{BREAK} ;WIP bit P=10 } [INIT] HOLD=1 WP=0 CS=1 SCK=0 _WAITWR ; READ STATUS REGISTER and wait R9[0]?1{ ; if bit0 not READY, error present. PRINT=A("Chip not respond, continue?") RA?0{EXIT} } [_WREN] SCK=0 CS=0 R0=00000110b ; Write enable _SENDBYTE CS=1 [_CKSTREG1] SCK=0 R2=0 LOOP=(100000){ CS=0 PRINT=S("Erase %lu",R2) R2=+1 _SENDBYTE(00000101b) ;RDSR SI=1 R9=0 LOOP=(7,0){SCK=1,R9[I]=SO,SCK=0} CS=1 R9[0]?0{BREAK} ;WIP bit P=1000 } [_CKSTREG] SCK=0 R3=0 PRINT=P(0,22000) LOOP=(22000){ ;110 sec CS=0 _SENDBYTE(00000101b) ;RDSR SI=1 R9=0 LOOP=(7,0){SCK=1,R9[I]=SO,SCK=0} CS=1 R9[0]?0{BREAK} ;BUSY bit P=5000 R3=+1 PRINT=P(R3) } [READ] CS=0 _SENDBYTE(00000011b) ;Read ;LOOP=(23,0){SI=ADR[I],SCK=P} _SENDADR ;SI=1 ;LOOP=(7,0){SCK=1,DATA[I]=SO,SCK=0} DATA=SPIIN CS=1 [READBLOCK] CS=0 _SENDBYTE(00000011b) ;Read ;LOOP=(23,0){SI=ADR[I],SCK=P} _SENDADR SI=1 LOOP=($BLOCKSIZE){ ;LOOP=(7,0){SCK=1,DATA[I]=SO,SCK=0} ;old DATA=SPIIN ADR=+1 } CS=1 [WRITEINIT] HOLD=1 WP=1 CS=1 P=5000 _WREN CS=0 _SENDBYTE(00000001b) ;WRSR _SENDBYTE(0) ;Status Register CS=1 P=30000 ;! _WAITWR ;max 500ms [WRITE] R0=DATA,R0?0xFF{RETURN} SCK=0 _WREN CS=0 _SENDBYTE(00000010b) ; Write ;LOOP=(23,0){SI=ADR[I],SCK=P} _SENDADR ;LOOP=(7,0){SI=DATA[I],SCK=P} SPIOUT=DATA SI=1,CS=1 ;P=5000 _WAITWR [WRITEBLOCK] ;R1=0xFF 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 ;LOOP=(23,0){SI=ADR[I],SCK=P} _SENDADR LOOP=($BLOCKSIZE){ ;LOOP=(7,0){SI=DATA[I],SCK=P} SPIOUT=DATA ADR=+1 } CS=1 _WAITWR [READID] WP=1 SCK=0 CS=1 ; New ID (JEDEC) CS=0 R8=0 _SENDBYTE(0x9F) ;JEDEC Read ID - New SI=1 LOOP=(23,0){SCK=1,R8[I]=SO,SCK=0} CS=1 R8?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 R7=0 LOOP=(15,0){SCK=1,R7[I]=SO,SCK=0} CS=1 R0=R7 R7?0xEF10{PRINT=S("ID = %04lXH. Winbond W25P10",R7),RETURN} R7?0xEF11{PRINT=S("ID = %04lXH. Winbond W25P20",R7),RETURN} R7?0xEF12{PRINT=S("ID = %04lXH. Winbond W25P40",R7),RETURN} R7?!0xFFFF{PRINT=S("ID = %04lXH",R7),RETURN} } R0=R8 R8?0xEF2014{PRINT=S("ID = %04lXH. Winbond W25P80",R8),RETURN} R8?0xEF2015{PRINT=S("ID = %04lXH. Winbond W25P16",R8),RETURN} R8?0xEF2016{PRINT=S("ID = %04lXH. Winbond W25P32",R8),RETURN} R8?0xEF3011{PRINT=S("ID = %04lXH. Winbond W25X10",R8),RETURN} R8?0xEF3012{PRINT=S("ID = %04lXH. Winbond W25X20",R8),RETURN} R8?0xEF3013{PRINT=S("ID = %04lXH. Winbond W25X40",R8),RETURN} R8?0xEF3014{PRINT=S("ID = %04lXH. Winbond W25X80",R8),RETURN} R8?0xEF3015{PRINT=S("ID = %04lXH. Winbond W25X16",R8),RETURN} R8?0xEF3016{PRINT=S("ID = %04lXH. Winbond W25X32",R8),RETURN} R8?0xEF3017{PRINT=S("ID = %04lXH. Winbond W25X64",R8),RETURN} R8?0xEF4014{PRINT=S("ID = %04lXH. Winbond W25Q80",R8),RETURN} R8?0xEF4015{PRINT=S("ID = %04lXH. Winbond W25Q16",R8),RETURN} R8?0xEF4016{PRINT=S("ID = %04lXH. Winbond W25Q32",R8),RETURN} PRINT=S("ID value = %04lXH",R8) ["Read Status"] ;HOLD=1 WP=1 SCK=0 CS=1 CS=0 R9=0 R0=00000101b,_SENDBYTE ;RDSR SI=1 LOOP=(7,0){SCK=1,R9[I]=SO,SCK=0} CS=1 P=10000 GET=("Status",R9) ["Write Status"] GET=("Write Status",R9) RA?0{EXIT} WP=1 CS=1 SCK=0 ;PRINT=("value %02lX",R9) _WREN CS=0 R0=00000001b ;WRSR _SENDBYTE R0=R9 ;Status Register _SENDBYTE CS=1 P=20000 ; Not all chips support Sector Erase [_SectorErase] R1=0 ;GET=("Please enter sector address :",R1) GET=("Erase sector (4Kb)",R1) RA?0{EXIT} ;PRINT=A("Are You sure ERASE 0x%06lX address sector ?",R1),RA?0{EXIT} HOLD=1 WP=1 SCK=0 CS=1 _WREN CS=0 _SENDBYTE(00000001b) ;WRSR _SENDBYTE(0) ;Status Register CS=1 P=200000 _WAITWR _WREN CS=0 R0=00100000b ;Sector Erase _SENDBYTE LOOP=(23,0){SI=R1[I],SCK=P} CS=1 _CKSTREG [_BlockErase] R2=0 ;GET=("Please enter block address :",R1) GET=("Erase block (64Kb) :",R1) RA?0{EXIT} ;PRINT=A("Are You sure ERASE 0x%06lX address block ?",R1),RA?0{EXIT} HOLD=1 WP=1 SCK=0 CS=1 _WREN CS=0 _SENDBYTE(00000001b) ;WRSR _SENDBYTE(0) ;Status Register CS=1 P=200000 _WAITWR _WREN CS=0 R0=11011000b ;Block Erase _SENDBYTE LOOP=(23,0){SI=R1[I],SCK=P} CS=1 _CKSTREG [_FullErase] ;PRINT=A("Are You sure full ERASE flash ?"),RA?0{EXIT} HOLD=1 WP=1 SCK=0 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 _SENDBYTE(11000111b) ;BE Bulk Erase CS=1 ; Full erase time for 25P80 - 20 sec! _CKSTREG ["Erase"] GET=("ERASE type",R12) RA?0{EXIT} R12?1{_BlockErase,RETURN} R12?2{_FullErase,RETURN}