Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series



THE BOOK of DT's INTERRUPTS is an organization of interrupt service routines and other works written by Darrel Taylor, RIP.

Interrupt routines are arranged per Darrel's original list. Darrel Taylor's Instant Interrupts are an extension of the work of Tim Box whom in October of 2002 wrote INT_CTRL.pbp

Many of the forum members felt this is a long overdue project.

THE BOOK of DT's INTERRUPTS
will be a valuable resource and a tribute to Darrel Taylor the "Fanatical Contributor".

THE BOOK of DT's INTERRUPTS is located at http://dt.picbasic.co.uk/

+ Reply to Thread
Results 1 to 10 of 10
  1. #1
    Join Date
    Feb 2012
    Location
    PERTH AUSTRALIA
    Posts
    838

    Default Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series

    Hi Guys
    had need to review the SPI flash routines to incorporate the 4kb/32kb/64kb erase support and other features offered by the WINBOND series of flash chips

    this is a re- vamp of the code i did last year and i posted for the 8mb chip to support another flash chip manufacture

    hope you find it of use and dont have to re do the code wheel - again
    this should be as an include to your main code

    regards

    Sheldon

    Code:
    '*          : All Rights Reserved                                                        *
    '*  Date    : 4/05/2015                                                                 *
    '*  Version : 2.0                                                                        *
    '*  Notes   : Rewriten for Winbond SPI W25Q series Serial NOR Flash chips ..             *
    '*          :  W25Q32 - 32Mbit(4MB)                                                      *
    '*          : --- Orginal code (V1.1) based on support for M25P80 8Mbit chip or simular  *
    '*          :  no support of duel / quad SPI & QPI options                               *
    '*          :  No support for Fast Write ( W25Q80 )                                      *
    '*          :  NO support of Suspend write/read operations                               *
    '*          : chips are 3.3v - NOT 5V input tollerant                                    *
    '*          : Code supports .....                                                        *
    '*          : 1  Software Protection of data , hardware WP and Hold pins high            *
    '*          : 2. 4KB sectors , 32/64KB blocks, for protection / erasing, copy commnads   * 
    '*          : 3. Manufacture ID /Chip size detection / selection for number of blocks    *  
    '*          : 4. Copy commands reseved use of scratch pad area of Block 0                *
    '*       : code does not need Longs to be enabled to save on code space                  *
    '*****************************************************************************************
    '                                                                                        *
    ' Operational Notes on Timing Max and Min times                                          *
    ' =============================================                                          *
    '                                                                                        *
    '   1. powerup delay to CE & WR = 5ms min                                                *
    '   2. 256 bytes max per read / write                                                    *
    '   3. spi bus (mode 3) (clock idle High) and flash CE configures in main program        *
    '   4. avg is 20ma during write /25ma for erase, 15ma for read                           *
    '   5. min 50ns  on CE deselect                                                          *
    '   6. SPI chip interface timing has min of 5ns requirements , so no timing issues       *
    '       for picbasic which has a min of 2us using shiftout cmd                           *
    '   7. software reset via spi = min 30us - BUSY & SUS bits are checked before issue      *
    '   8. sector erase (4KB)= min 45mS  max 400ms,                                          *
    '   9. block Erace(32KB) = min 120ms max 1.6sec                                          *
    '  10. Block Erase (64KB)= min 150ms max 2.0sec                                          *
    '  11. Chip Erase(32Mbit)=min 10sec max 50sec                                            *
    '  12. hold/reset pin - factory dephalt is hold                                          *
    '  13. WP pin is not active - SRP1=0 , SRP0 =0 - FACTORY DEPHALT                         *
    '  14. 25QxxIQ has QE bit in register 2 = 1 from factory and cannot be cleared           *  
    '----------------------------------------------------------------------------------------*
    
    
     '---------- Winbond SPI FLASH (W25Q series) commands set --------------------------------
     ' NOTE: No support for DUAL/QUAD/ QPI instruction sets 
     ' 
     '             SDC_cmd, SDC_CmdCode
     ' command 1-13 use the Write enable command ---
     Flash_Wr_reg1        con 1  ' $01       'def write the Status Register 1(S7-S0)   - 1 byte data - write enable req prior
     Flash_Wr_reg2        con 2  ' $31       'def write the Status Register 2(S15-S8)  - 1 byte data - write enable req prior
     Flash_Wr_reg3        con 3  ' $11       'def write the Status Register 3(S23-S16) - 1 byte data - write enable req prior
     Flash_WR             con 4  ' $02       'def Page Program mode command        ( 24bit address req)+ (1 byte data)- write enable req prior
     Flash_Wr_Secreg      con 5  ' $42       'def Program Security Register write  ( 24bit address req)+ (1 byte data)- write enable req prior  - holds access upto 256byte data per register  
     Flash_Sec_Ers        con 6  ' $20       'def Sector Erase command (4KB)       ( 24bit address req)               - write enable req prior
     Flash_Blk32_Ers      con 7  ' $52       'def Block 32KB Erase Command (32KB)  ( 24bit address req)               - write enable req prior
     Flash_Blk64_Ers      con 8  ' $D8       'def Block 64KB Erase Command (64KB)  ( 24bit address req)               - write enable req prior
     Flash_Indv_Blk_LCK   CON 9  ' $36       'def Indervidual Block/Sector Lock    ( 24bit address req): WEP must be 1 to setup and use  - write enable req prior
     Flash_Indv_Blk_UNLCK CON 10 ' $39       'def Indervidual Block/Sector UNLock  ( 24bit address req): WEP must be 1 to setup and use  - write enable req prior
     Flash_Secreg_Ers     con 11 ' $44       'def Erase Program Security Register  ( 24bit address req) - write enable req prior
     Flash_Bulk_Ers       con 12 ' $C7       'def Bulk Erase command                 - write enable req prior
     Flash_Globe_LCK      con 13 ' $7E       'def Globel Block /Sector Lock      : WEP must be 1 to setup and use   - write enable req prior
     Flash_Globe_UNLCK    con 14 ' $98       'def Globle Block/Sector Unlock     : WEP must be 1 to setup and use   - write enable req prior
     
    
     ' commands 14-12 use the Read command --- 
     Flash_RD             con 15 ' $03       'def read data at normal speed        ( 24bit address req)+ (1 byte data)
     Flash_Rd_HS          con 16 ' $0B       'def read data at High speed (Fast Read) ( 24bit address req)+ (1dummy+1 byte data)
     Flash_Rd_Secreg      con 17 ' $48       'def Program Security Register read  ( 24bit address req)+ (1 dummy +1 data)( simular to fast read command )
     Flash_Rd_Sig         con 18 ' $4B       'def read Flash device Unique ID signature - cmd + 4 dummy bytes , returns 64bit ID MSB first
     Flash_Rd_Blk_LCK     con 19 ' $3D       'def Read Block/Sector Lock status  , returns 0= unlocked 1= Locked ( 24bit address req)+ (1 byte data)
     Flash_Rd_ID          con 20 ' $9F       'def Read manufacture 1byte/device/UID code 2 bytes ( JEDEC ID) - returns 3 bytes 
     Flash_Rd_reg2        con 21 ' $35       'def read the Status Register 2(S15-S8)  - returns 1 data byte 
     Flash_Rd_reg3        con 22 ' $15       'def read the Status Register 3(S23-S16) - returns 1 data byte 
    
     '---- not in command lookup table - used directly -----
     Flash_Wr_dis      CON $04        'def write disable command 
     Flash_Rd_reg1     con $05        'def read the Status Register 1(S7-S0)  - done by Bsy_chk routine
     Flash_Wr_en       con $06        'def write Enable command   
     Flash_Vol_Wr_EN   con $50        'def  Volatile SR Write Enable - used to change write_reg1 bits but wont set WEL flag - quick way of changeing register for protection bits ( no write enable 
     Flash_EN_Rst      con $66        'def Enable Software Reset  - reset takes min 30us 
     Flash_Rst         Con $99        'def Do a Reset  - Must be combined with Flash_EN_Rst
     Flash_PWR_Dwn     con $B9        'def Deep Power Down command   
     Flash_PWR_Up      con $AB        'def Release From Deep Power Down command  
     
    ' ----------  FLASH varables -------------------------
    
     Data_Length    var byte       ' table of data length
     SDC_buffer	    Var Byte[256]  ' indexed data - max 256 bytes - 8mb FLASH has a 256 Limit from page Writes - Note 512 used in SD routines 
     SDC_data_in    Var Byte       ' Data in byte from flash 
     SDC_data_out   Var Byte       ' Data out byte from Flash - 
     SDC_address_High   Var word   ' address higher word sent to FLASH 
     SDC_address_Low    Var word   ' address lower  word sent to FLASH 
     SDC_index	    Var Word       ' Loop index counter 
     SDC_CmdCode    Var Byte       ' used here as Sector protect value for the Write Status register 
     SDC_cmd	    Var Byte       ' command code for selected operation 
     SDC_Block      var Byte       ' 64K block Address   - uses SDC_address_High.low , each block 0-63(32Kbit) 0-127(64Kbit), addressing used both 
     SDC_Sector     var byte       ' 4K Sector address   - uses SDC_address_Low.highbyte , each sector = 16 pages , so sector 0 = page 0-15  - values = 0 -15
     SDC_Page       var byte       ' Page Address
     SDC_Byte       Var byte       ' Bytes Address
     Flash_RD_Fast  var bit        ' Flag for High speed read 1 = Highspeed read speed 0= normal read speed 
     Flash_Install  var bit        ' flag set when flash install program used  
     Flash_32KB_Block_Sel  var bit ' Sets StartPage address for 32KB Block erase - 0 = lower block - sets start page address - page 0 - 127, 1 = High block - page 128 - 256
     Flash_Protect  var bit        ' Set Protect =1 / Unprotect =0 of a block , used as a read of block status as well
     
     Flash_Blk_Orgin    var byte  ' Orgin sector value     - copy sector command 
     Flash_Blk_Dest     var byte  ' destination  sector value  - copy Sector Command   
     Flash_Sec_Orgin    var byte  ' Orgin sector value     - copy sector command 
     Flash_Sec_Dest     var byte  ' destination  sector value  - copy Sector Command  
     Flash_Page_Orgin   var byte  ' Orgin Page value
     Flash_Page_Dest    var Byte  ' Dest Page Value 
     Flash_Page_Length  var byte  ' number of pages 
     Flash_Clear         var bit  ' flag to clear orginal sector 1= clear  
     
     Flash_Manf_id   var byte    ' manufacture id code 
     Flash_Manf_type var byte    ' device type code 
     Flash_Manf_cap  var byte    ' device capacity code 
     Flash_tmp       var byte    ' used as a temp varable 
     Flash_tmp2      VAR BYTE    ' used as a temp varable  
     Flash_Reg_val   var byte    ' Flash register value 
    
     Flash_Addr_Copy_Low  var word  ' low word temp storage of input address and data length 
     Flash_Addr_Copy_High var word  ' high word temp storage of input address and data length
    
    
    '----------- Varable settings at startup ---------------------------------------------
    
       Flash_RD_Fast = 0        ' Set to normal read at start
       Flash_Install = 0        ' set to 0 when flash  install not being used  
       Flash_Clear = 0          ' set not to clear 
       Flash_32KB_Block_Sel = 0 ' set to use low address 
      
    '---------------- Routines  ------------------ 
    goto JumpOverSPIFLASH     ' Jump to end of this include file  for Correct compile  
     
      Flash_Init:
        ' do a read register command to clear the Flash register after power up
      
             FLASH_CE = 0                                  ' Bring the FLASH chip select line low  
              SDC_data_out = Flash_Rd_reg1                 ' Send the read status register command byte
     	      Gosub Flash_spiw	                           ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
             FLASH_CE = 1                                  ' Bring the FLASH chip select line high  
             gosub buffer_clear                            ' clear varables area 
          
      return                                                        
    ' -----------------------------
      Buffer_Clear:
     
          For SDC_index = 0 To 255
              SDC_buffer[SDC_index] = 0
          next SDC_index
      return
    
    '--------------------------------------- 
      Flash_Reset:
      ' routine to software reset the flash 
      ' enable reset and reset must be consecutive 
       
        FLASH_CE = 0                                  ' Bring the FLASH chip select line low  
          SDC_data_out = Flash_EN_Rst                 ' Send Enable Reset command 
          gosub Flash_spiw	                          ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
          SDC_data_out = Flash_Rst                    ' Send Reset command 
       	  Gosub Flash_spiw	                          ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus  
        FLASH_CE = 1                                  ' Bring the FLASH chip select line high  
         
      return
    
    '-----------------------------------------
    
     Flash_Format:
     'Note wont work if any sectors are protected 
      ' can take upto 50sec on 32mbit chip 
       sdc_cmd = Flash_Bulk_ers  ' excutes as it sounds
       gosub Flash_Comand 
     return
     
    '-------------------------------------------------
     
     Flash_Sec_Erase: 
      ' assumes Block address  0-63 
      ' assumes Sector value 0 -15 
      ' erases 1 Sector at a time  address (4KB)= 15 pages 
      ' Erases wont work on sectors that are write protected 
      ' sector erase take 400ms per instruction 
       SDC_pAGE = 0                          ' ensure 0 
       SDC_pAGE = sdc_SECTOR << 4            ' shift given sector 0-15 to upper page value   
      
       sdc_cmd = Flash_Sec_Ers               ' Erases  sector ( 256 pages x 256 bytes ) 
       SDC_address_high.byte0 = SDC_Block    ' set sector Address 0 to 15 for chip
       SDC_address_low.byte1  = SDC_Page     ' set page start address 0 to 255  
       SDC_address_low.byte0  = 0            ' set byte start address 0 to 255
       gosub Flash_Comand                    ' Do the command 
     return
    
    '----------------------------------------------------
    
     Flash_Blk32_Erase: 
      ' assumes Block address   
      ' assumes flag 32KB_Block_Sel 0 = bottom 32Kb start address page, 1= 128page address
      ' erases 1/2 a 64KB Block at a time  address (32KB)= 128 pages 
      ' Erases wont work on sectors that are write protected 
      ' sector erase take min 120ms max 1.6Sec per instruction 
       IF Flash_32KB_Block_Sel = 0 THEN           ' select offset page for 32 byte sector 
           SDC_PAGE = 0
       ELSE
           SDC_PAGE = 128
       ENDIF    
       sdc_cmd = Flash_blk32_Ers             ' Erases 32kB block ( 128 pages of 256 bytes ) 
       SDC_address_high.byte0 = SDC_Block    ' set block Address for chip
       SDC_address_low.byte1  = SDC_PAGE     ' set page start address 0 to 255  
       SDC_address_low.byte0  = 0            ' set byte start address 0 to 255
       gosub Flash_Comand                    ' Do the command 
     return
    '-------------------------------------------------------------
     
     Flash_Blk64_Erase: 
      ' assumes Block address  
      ' erases a 64KB Block at a time  address (64KB)= 256 pages 
      ' Erases wont work on sectors that are write protected 
      ' sector erase take min 160ms max 2.0Sec per instruction 
      
       sdc_cmd = Flash_blk64_Ers             ' Erases 64kB block ( 256 pages of 256 bytes ) 
       SDC_address_high.byte0 = SDC_Block    ' set Block Address for chip
       SDC_address_low.byte1  = 0            ' set page start address 0 to 255  
       SDC_address_low.byte0  = 0            ' set byte start address 0 to 255
       gosub Flash_Comand                    ' Do the command 
     return
    
    '------------------------------------------------------------------
     
     Flash_Block_Copy:
      ' copys data from 1 block to another 
      ' erases destination block - optional clean of orginal block 
      ' assumes Flash_Sect_Orgin,Flash_Sect_Dest ,Flash_clear
      ' Erases wont work on blocks that are write protected 
      ' block erase take 400ms per instruction 
          SDC_Block  = Flash_Blk_Dest            ' clear destination block 
          gosub Flash_blk64_Erase                ' use SDC_blk64_erase info to erase destination sector 
           for SDC_PAGE = 0 to 255               ' copy pages to selected block ( 256bytes at a time) 
               SDC_Block  = Flash_blk_Orgin      ' block to copy 
               SDC_byte    = 0
               Data_Length = 255
               gosub Flash_Read                  ' read the data to buffer 
               SDC_Block  = Flash_Blk_Dest       ' block to copy to
               SDC_byte    = 0                   ' use block details for destination
               Data_Length = 255
               gosub Flash_Write                 ' write the data
           next SDC_PAGE
         if Flash_clear = 1 then 
            SDC_Block = Flash_Blk_Orgin         ' clean up orgin Block 
            gosub Flash_Blk64_Erase               
         endif
     return
         
     Flash_Page_Copy:
      ' copys data from pages 0 -255 from orgin or destination block 
      ' assumes destination block pages are Erased 
      ' assumes pages orgin and pages destination do not cross block boundrys 
      ' assumes Flash_Page_Orgin,Flash_Page_dest ,Flash_Page_length, Flash_blk_orgin ,Flash_blk_dest  
      ' writes wont work on blocks that are write protected 
          
         for  Flash_tmp2 =  Flash_Page_Orgin to Flash_Page_length    '  copy sector 0 pages to selected sector 0 ( 256bytes at a time) 
               SDC_Block  = Flash_blk_Orgin                     ' sector to copy 
               SDC_PAGE =  Flash_tmp2
               SDC_byte    = 0
               Data_Length = 255
               gosub Flash_Read                                  ' read the data to buffer 
             
               SDC_Block  = Flash_blk_Dest                       ' sector to copy to
               SDC_PAGE = Flash_Page_Dest                        ' page to copy to 
               SDC_byte    = 0                
               Data_Length = 255
               gosub Flash_Write                                 ' write the data
               Flash_Page_Dest = Flash_Page_Dest + 1              ' increment destination page 
         next Flash_tmp2
     
     
     return 
    '---------------------------------------- 
     
           
     Flash_Write: 
      ' assumes data length , address and upto 256 bytes in  SDC_buffer[] to send 
      ' writes bytes from SDC_buffer[] into flash , block/page/byte loction must be "FF" at start
      ' write wont work on sectors that are write protected 
     
       sdc_cmd = Flash_WR               ' excutes as it sounds - max of 256 bytes
       SDC_address_high.byte0 = SDC_Block   ' set block Address for  chip
       SDC_address_low.byte1  = SDC_Page     ' set page start address 0 to 255  
       SDC_address_low.byte0  = SDC_byte     ' set byte start address 0 to 255
       gosub Flash_Comand 
      
      return
     
    '--------------------------------------
    
     Flash_Read: 
      ' assumes Block, page, bytes , data length input 
      ' gets upto bytes data into SDC_buffer[] from flash 
      ' uses normal read speed if no Flash_RD_Fast flag set
       if Flash_RD_Fast = 1 then
         sdc_cmd = Flash_Rd_HS          ' excutes fast read  - max of 256 bytes 
       else
         sdc_cmd = Flash_RD             ' excutes normal read - max of 256 bytes cos of buffers size/ page size 
       endif
       SDC_address_high.byte0 = SDC_Block   ' set block Address  for chip
       SDC_address_low.byte1  = SDC_Page     ' set page start address 0 to 255  
       SDC_address_low.byte0  = SDC_byte     ' set byte start address 0 to 255
       gosub Flash_Comand
      return
    
     
     Flash_WR_protect:
     ' routine to protect/ unprotect a set block of 60-63 in 32kbit chip ( block 60-63 used by K9 system stored settings )
     ' Assumes Flash_Protect - 0 = unprotect 1 = Protect a sector 
     ' SETUP FOR 32kB CHIP 
     '  Bit7 = SRP0 - Set to 0 - software protect (SRP1= 0 DEPHALT(stat_reg2(bit0), not WP pin 
     ' bits6(SEC) = 0 = 64KB Block 1= 4Kb SECTOR , Bit5(TB) 0= Top, 1 = Bottom , Bit4-2 = BP2-BP0. bits 1-0 (wel, busy )
       
       
         if Flash_Protect = 0 then 
            SDC_buffer[0] = $00 ' clear all blocks
         else
            SDC_buffer[0] = $0C ' set blocks 60-63 protected for K9 project 
         endif 
      
          sdc_cmd = Flash_Wr_reg1  ' write register 
          data_length = 1          ' set 1 byte  
          gosub Flash_Comand 
       return
    
    '-----------------------------------------------------------
       Flash_WR_Disable:
       ' reset the write enable latch 
          FLASH_CE = 0                                ' Bring the FLASH chip select line low  
            SDC_data_out = Flash_Rd_reg1                 ' Send the read status register command byte
     	    Gosub Flash_spiw	                        ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
           FLASH_CE = 1                               ' Bring the FLASH chip select line high  
       return
    '----------------------------------------------------
      Flash_Read_ID:
      ' returns JEDEC ID-  returns Manufacture ID byte($EF), mem type - (ID15-ID8)1byte ,capacity(ID7-ID0)1byte)   
          
        sdc_cmd =  Flash_Rd_ID              ' Flash Read ID 
        data_length = 3                     ' 3 bytes  
        gosub Flash_Comand
        Flash_Manf_id =  SDC_buffer[0]
        Flash_Manf_type = SDC_buffer[1] 
        Flash_Manf_cap  = SDC_buffer[2]
        IF FLASH_Install = 1 then
           HSEROUT ["Flash Manf ID = ",hex Flash_Manf_id,"  Flash Device ID = ",hex Flash_Manf_type,"  Device Capacity ID = ",hex Flash_Manf_cap,13,10]  
         endif
      return   
    '---------------------------------------------------------------------
      Flash_Read_Sig:
      ' returns the flash chips Unique ID number ( 64Bit)
        sdc_cmd = Flash_Rd_Sig               ' Flash Read Unique ID signature 
        data_length = 4                      ' 4 bytes                ' Flash Read Unique ID signature 
        gosub Flash_Comand
      return
      '----------------------------------------------
     Flash_Read_BLK_Lock:
     'routine to read block or sector locks ( WPS=1 to work )
       sdc_cmd =  Flash_Rd_Blk_LCK                          ' Flash Read block lock  
       data_length = 1                                     ' 1 bytes   
       gosub Flash_Comand
       Flash_Protect = SDC_buffer[0] & $01                  ' get bit0 value - 1 = locked .0 = unlocked  
      return
     '--------------------------------------------- 
     
      Flash_Power_Down:
     ' sEt Flash chip to low power mode from standby mode - no command other tha powerup will wake the device 
        FLASH_CE = 0                                ' Bring the FLASH chip select line low  
          SDC_data_out = Flash_PWR_Dwn              ' command to pwr down
     	  Gosub Flash_spiw	                        ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
        FLASH_CE = 1                                ' Bring the FLASH chip select line high  
      return
    '----------------------------  
      Flash_Power_Up:
     ' sEt Flash chip to standby mode - no command other tha powerup will wake the device 
    ' sEt Flash chip to low power mode from standby mode - no command other tha powerup will wake the device 
        FLASH_CE = 0                                ' Bring the FLASH chip select line low  
          SDC_data_out =  Flash_PWR_Up              ' command to pwr up
     	  Gosub Flash_spiw	                        ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
        FLASH_CE = 1                                ' Bring the FLASH chip select line high  
      return
     '-----------------------------
    
    
    ' -----------------------------
     Flash_Read_reg2:
     ' reads write register 2 -  
     ' Register 2 controls ..... 
     ' bit7(S15)- Suspend Status 
     ' bit6(S14)CMP -Compliment Protect - dephalt CMP =0 
     ' bit5-3(S13-11)- Security Register(One time programable) dephalt = 000
     ' bit1(S9) - QE - Quad SPI Mode Enable ( default =0 when chips NOT FVIQ type)
     ' bit0(S8) - SRP1-  Protect bit1 _ dephalt =0 
     '  
       sdc_cmd =  Flash_Rd_reg2                          ' Flash Read register 2   
       data_length = 1                                   ' 1 bytes returned     
       gosub Flash_Comand
     return
     
     '---------------------------------------
     
     Flash_Read_reg3:
     ' Register 3 controls ..... 
     ' bit7(S23) - Hold(0- dephalt)/Reset(1) pin fuction  
     ' bit6,5(S22,S21)(0,0=100%),(0,1=75%),(1,0=50%),(1,1=25%- dephalt) read driver strength- used to overcome cpacitive loading ,trace impendace issues with signal at high speed reads 
     ' bits4,3 - reserved (writen as 0)
     ' Bit2(S18) WPS - selects Protection methode - Indervidual block/sectors(WPS=1) or by grouping range(WPS=0) ( WPS dephalt is 0 ) 
     ' Bits1,0-reserved(writen as 0)  
       sdc_cmd =  Flash_Rd_reg3                          ' Flash Read register 3   
       data_length = 1                                   ' 1 bytes returned     
       gosub Flash_Comand
      return
      
      '-----------------------------------
       
      Flash_Comand:
      ' assumes SDC_address long
      ' assumbe data_Length = Lookup table to fill 
      ' max 256 bytes per write 
      ' erase of the sector by byte  / bulk is needed prior to write , as a write only changes a 1 to 0 , and the erase chanse the 0 to 1 
       if  SDC_cmd = 0 then return           ' invalid command if value =0 
    
    
     
     Lookup SDC_cmd,[$00,$01,$31,$11,$02,$42,$20,$52,$D8,$36,$39,$44,$C7,$7E,$98,$03,$0B,$48,$4B,$3D,$9F,$35,$15],SDC_CmdCode ' asignes command code to flash chip  
      
          Flash_tmp = 0                        ' ensure 0 - counter for busychk loop
          gosub BSY_chk                        ' do for all commands 
             
         if SDC_cmd <=14 then                  ' do for writes, sector erase,bulk erase , write reg protect - commands 1-14 use writen enable first
            FLASH_CE = 0                       ' Bring the FLASH chip select line low.
     	    SDC_data_out = Flash_Wr_en         ' Send  command byte that requires a write 
            Gosub Flash_spiw	               ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus
       	    FLASH_CE = 1                       ' Bring the FLASH chip select line high to complete the write command 
     	    pauseus 1                          ' pause between prev command  - may not need 
         endif
    	
         FLASH_CE = 0                          ' Bring the FLASH chip select line low 
         SDC_data_out =  SDC_CmdCode           ' Send the  command byte,
       	 Gosub Flash_spiw	                   ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus
        
         if SDC_cmd =>4 and SDC_cmd <=11 or _           ' if write commands 4-11 then use 24bit address assigned 
            SDC_cmd =>15 and SDC_cmd <=19 then          ' or read commands 15-19 then use 24bit address assigned , command 18 uses 24bit address as 3 dummy bytes 
              SDC_data_out = SDC_address_high.Byte0     ' set block Address for chip
     	      Gosub Flash_spiw		                    ' Write Byte SDC_data_out.
     	      SDC_data_out = SDC_address_low.Byte1      ' set page address 0 to 255  
     	      Gosub Flash_spiw	                        ' Write Byte SDC_data_out.
     	      SDC_data_out = SDC_address_low.Byte0      ' set byte address 0 to 255
              Gosub Flash_spiw		                    ' Write Byte SDC_data_out.
              if SDC_cmd => 16 and SDC_cmd <= 18 then   ' if read High speed mode ,Program security read , Read Unique ID(add 4th dummy byte) 
                 SDC_data_out = $00                     ' add a dummy byte to command  
                 Gosub Flash_spiw		                ' Write Byte SDC_data_out.
              endif
          endif
        
          if SDC_cmd <=5 or _                                ' if write commands require data bytes sent 
             SDC_cmd >=15 and SDC_cmd <= 22 then             ' or read commands require data bytes returned     
                     
              For SDC_index = 0 To Data_Length-1             ' DATA LENGTH -1  so byte 0 is counted when setting data length  
                  if SDC_cmd <= 5 then                       ' if write ,Write register,write Security register then 
                     SDC_data_out = SDC_buffer[SDC_index]    ' send contents of indexed SDC_buffer 
                     gosub  Flash_SPIw  	                 ' write byte SDC_data_in from SPI bus.  Returns SDC_data_in.
                  endif
                
                  if SDC_cmd =>15 and SDC_cmd <=22 then      ' if read scommand returns data 
                     gosub  Flash_SPIR  	                 ' Read Byte SDC_data_in from SPI bus.  Returns SDC_data_in.
     	             SDC_buffer[SDC_index] = SDC_data_in
                  endif
              Next SDC_index
          endif
          pauseus 1 
         FLASH_CE = 1                          ' Bring the FLASH chip select line high.
    
      return
    '----------------------------------------------------
     Bsy_chk:
            FLASH_CE = 0                                ' Bring the FLASH chip select line low  
            SDC_data_out = Flash_Rd_reg1                ' Send the read status register1 command byte
     	    Gosub Flash_spiw	                        ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
            Flash_tmp = 0                               ' clear counter                  
           while  Flash_tmp <150                        '  loop test read for busy ( counter may need to be increased depending on size of chip and time for block erase command to complete       
             gosub Flash_SPIR  	                        ' Read Byte SDC_data_in from SPI bus.  Returns SDC_data_in.
             IF FLASH_Install = 1 then 
               Flash_Reg_val  = SDC_data_in               ' get value of read status reg value for use in flash install program checks for protection 
               HSEROUT ["STATUS REG = ",hex Flash_Reg_val,13,10]  ' show on terminal when doing flash install 
               HSEROUT ["Flash_tmp = ",dec2 Flash_tmp,13,10]     
             endif 
             Flash_tmp = Flash_tmp + 1 
             SDC_data_in =  SDC_data_in & $01          ' mask bit 0 ( busy flag)
            if SDC_data_in = 0 then Flash_tmp = 151    ' Test bit 0 if write not busy,force exit of loop
           wend                  
           FLASH_CE = 1                                    ' Bring the FLASH chip select line high
     return  
    '------------------------------- 
      Flash_SPIR:
        SO = 1			                    ' Shift out high bits while shifing in data.
     	Shiftin SO, SCK, 6,[SDC_data_in]	' MSb first, clock idle high.
      
      Return
    '-------------------------------
    
      Flash_SPIW: 
          shiftout SI,SCK,5,[SDC_data_out]	    ' MSb first, clock idle high.
                           
      return
    '------------------------
    
    
    
    
    
    JumpOverSPIFLASH:

  2. #2
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default Re: Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series

    Thank you for sharing with the forum!
    Dave
    Always wear safety glasses while programming.

  3. #3
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166


    Did you find this post helpful? Yes | No

    Default Re: Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series

    You can't use that Dave, Didn't you read the first line in the header!!!!!!
    Dave Purola,
    N8NTA
    EN82fn

  4. #4
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default Re: Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series

    Well crap, I did not notice the first line...
    Dave
    Always wear safety glasses while programming.

  5. #5
    Join Date
    Feb 2012
    Location
    PERTH AUSTRALIA
    Posts
    838


    Did you find this post helpful? Yes | No

    Default Re: Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series

    you can use it , i wrote it from scratch and you are welcome to it

  6. #6
    Join Date
    Feb 2012
    Location
    PERTH AUSTRALIA
    Posts
    838


    Did you find this post helpful? Yes | No

    Default Re: Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series

    i am sure there will be further updates as i would like to use the suspend operations and other protection modes better

    what i like about flash is always the pricing for the size

    cheers

    sheldon

  7. #7
    Join Date
    Feb 2012
    Location
    PERTH AUSTRALIA
    Posts
    838


    Did you find this post helpful? Yes | No

    Default Re: Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series

    since i put the data_length -1 in the "flash command " are so that value set in the data_length is the true byte value that will be returned - eg if data_lenght = 10 then 10 bytes are returned

    but the problem is that when you need 256byte (byte 0-255) then data_length needs to be a word value , not a byte

    cheers

    Sheldon

  8. #8
    Join Date
    Feb 2012
    Location
    PERTH AUSTRALIA
    Posts
    838


    Did you find this post helpful? Yes | No

    Default Re: Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series

    did some updates

    this inlcude has a lot of bloat so comment it out if you not need the routines to reduce compile space
    i have shown some examples of how to use the routines as i got a few MP's on it recently


    remove comments as needed

    Code:
    '*  Date    : 24/04/2022                                                                 *
    '*  Version : 2.0a                                                                        *
    '*  Notes   : Rewriten for Winbond SPI W25Q series Serial NOR Flash chips ..             *
    '*          :  W25Q32 - 32Mbit(4MB)                                                      *
    '*          : --- Orginal code (V1.1) based on support for M25P80 8Mbit chip or simular  *
    '*          :  no support of duel / quad SPI & QPI options                               *
    '*          :  No support for Fast Write ( W25Q80 )                                      *
    '*          :  NO support of Suspend write/read operations                               *
    '*          : chips are 3.3v - NOT 5V input tollerant                                    *
    '*          : Code supports .....                                                        *
    '*          : 1  Software Protection of data , hardware WP and Hold pins high            *
    '*          : 2. 4KB sectors , 32/64KB blocks, for protection / erasing, copy commnads   * 
    '*          : 3. Manufacture ID /Chip size detection / selection for number of blocks    *  
    '*          : 4. Copy commands reseved use of scratch pad area of Block 0                *
    '*       : code does not need Longs to be enabled to save on code space                  *
    ' ========================================================================================
    ' Ver 2.0a - change example - fix Bsy_chk loop error for when multi 64k errace used      *
    '          - change to use flash_ce offset                                               *
    '          - change include name as SPI_flash.bas                                        *
    '          - make  Data_Length var a word cos of how the length input uses value of 256  *
    '            for selection                                                               *
    '*****************************************************************************************
    '                                                                                        *
    ' Operational Notes on Timing Max and Min times                                          *
    ' =============================================                                          *
    '                                                                                        *
    '   1. powerup delay to CE & WR = 5ms min                                                *
    '   2. 256 bytes max per read / write                                                    *
    '   3. spi bus (mode 3) (clock idle High) and flash CE configures in main program        *
    '   4. avg is 20ma during write /25ma for erase, 15ma for read                           *
    '   5. min 50ns  on CE deselect                                                          *
    '   6. SPI chip interface timing has min of 5ns requirements , so no timing issues       *
    '       for picbasic which has a min of 2us using shiftout cmd                           *
    '   7. software reset via spi = min 30us - BUSY & SUS bits are checked before issue      *
    '   8. sector erase (4KB)= min 45mS  max 400ms,                                          *
    '   9. block Erace(32KB) = min 120ms max 1.6sec                                          *
    '  10. Block Erase (64KB)= min 150ms max 2.0sec                                          *
    '  11. Chip Erase(32Mbit)=min 10sec max 50sec                                            *
    '  12. hold/reset pin - factory dephalt is hold                                          *
    '  13. WP pin is not active - SRP1=0 , SRP0 =0 - FACTORY DEPHALT                         *
    ' 
    '----------------------------------------------------------------------------------------*
    'SECTOR	PAGES REF          |   *** LATA.0 OFFSET VALUE CALCULATIONS FOR FLASH_CE ***     *
    '  0	0-15               |       LATA.0[0]  - LATA.0[7]  = LATA Port pins 0-7          *
    '  1	16-31              |       LATA.0[8]  - LATA.0[15] = LATB Port pins 0-7          *
    '  2	32-47              |       LATA.0[16] - LATA.0[23] = LATC Port pins 0-7          *
    '  3	48-63              |       LATA.0[24] - LATA.0[31] = LATD Port pins 0-7          *
    '  4	64-79              |       LATA.0[32] - LATA.0[39] = LATE Port pins 0-7          *
    '  5	80-95              |       LATA.0[40] - LATA.0[47] = LATF Port pins 0-7          *
    '  6	96-111             |       LATA.0[48] - LATA.0[55] = LATG Port pins 0-7          *
    '  7	112-127            |       LATA.0[56] - LATA.0[63] = LATH Port pins 0-7          *
    '  8	128-143            |       LATA.0[64] - LATA.0[71] = LATI Port pins 0-7          *
    '  9	144-159            |                                                             *
    '  10	160-175            |                                                             *
    '  11	176-191            |                                                             *
    '  12	192 -207           |                                                             *
    '  13	208-223            |                                                             *
    '  14	224-239            |                                                             *
    '  15	240-255            |                                                             *
    '----------------------------------------------------------------------------------------*
    
    '============== EXAMPLE OF HOW TO USE THIS INCLUDE ======================================* 
    '
    ' a: SETUP I/O PINS FOR FLASH USE IN MAIN PROGRAM
    '    SCK           VAR LATC.3       ' Clock pin (output to RF modual)
    '    SO            Var PORTC.4      ' Master In   - flash chip Data out pin     
    '    SI            Var LATC.5       ' Master Out  - flash chip Data in pin      
    '    FLASH1_CE     con 22'= LATC.6  ' Chip select FLASH chip ( low) 
    '   Note: i use an offset constant to select flash_ce, but normal var is fine 
    '   offset methode used cos of multi flash chips on same spi pins and no need to change include to address them 
    
    '   '*** NOTE: FLASH1_CE use LATA.0[LATA offset]
    '    LATA.0[FLASH1_CE] = 1          ' Active Low so set High to start  
    '    SI = 1                         ' Set SI to idle high to start
    '    SCK = 1                        ' Set SCK to idle high to start
    '   Flash_EN = FLASH1_CE            ' Set Flash1_CE at start as the Flash1 to use in var of flash include   
    ' 
    ' b:   place include statement in main code 
    '     INCLUDE "modedefs.bas"              ' Required for shiftout,shiftin commands as defined symbols
    '     include "SPI_Flash.bas"            ' include support of 8mbit Flash chip W25Q series 
    ' 
    ' C: examples of use 
    '    most commands require the assumed variables listed in each command
    '   1. example 1 - Flash_Test:  routine to erase / write / read test data for scratchpad sector 0 - test of flash chip 
    '   2. example 2 - erase lower 32k of block1 
    '                  SDC_Block =1   
    '                  Flash_32KB_Block_Sel = 0  ' select lower 32k of block 
    '                  gosub Flash_Blk32_Erase    
    '   3. example 3 - read block2 pages 0-2, 256 bytes of each page to serial monitor port 
    '                - refer ' EXAMPLE 3  at end of page 
    
     ' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     ' NOTE: there is a lot of bloat in this included where if you not need / use the routines they should be commented out 
     '       this also should remove unused varables they use in routines you not need 
     ' ====================================================================================================================
    
     '---------- Winbond SPI FLASH (W25Q series) commands set --------------------------------
     ' NOTE: No support for DUAL/QUAD/ QPI instruction sets 
     ' 
     '             SDC_cmd, SDC_CmdCode
     ' command 1-14 use the Write enable command ---
     Flash_Wr_reg1        con 1  ' $01       'def write the Status Register 1(S7-S0)   - 1 byte data - write enable req prior
     Flash_Wr_reg2        con 2  ' $31       'def write the Status Register 2(S15-S8)  - 1 byte data - write enable req prior
     Flash_Wr_reg3        con 3  ' $11       'def write the Status Register 3(S23-S16) - 1 byte data - write enable req prior
     Flash_WR             con 4  ' $02       'def Page Program mode command        ( 24bit address req)+ (1 byte data)- write enable req prior
     Flash_Wr_Secreg      con 5  ' $42       'def Program Security Register write  ( 24bit address req)+ (1 byte data)- write enable req prior  - holds access upto 256byte data per register  
     Flash_Sec_Ers        con 6  ' $20       'def Sector Erase command (4KB)       ( 24bit address req)               - write enable req prior
     Flash_Blk32_Ers      con 7  ' $52       'def Block 32KB Erase Command (32KB)  ( 24bit address req)               - write enable req prior
     Flash_Blk64_Ers      con 8  ' $D8       'def Block 64KB Erase Command (64KB)  ( 24bit address req)               - write enable req prior
     Flash_Indv_Blk_LCK   CON 9  ' $36       'def Indervidual Block/Sector Lock    ( 24bit address req): WEP must be 1 to setup and use  - write enable req prior
     Flash_Indv_Blk_UNLCK CON 10 ' $39       'def Indervidual Block/Sector UNLock  ( 24bit address req): WEP must be 1 to setup and use  - write enable req prior
     Flash_Secreg_Ers     con 11 ' $44       'def Erase Program Security Register  ( 24bit address req) - write enable req prior
     Flash_Bulk_Ers       con 12 ' $C7       'def Bulk Erase command                 - write enable req prior
     Flash_Globe_LCK      con 13 ' $7E       'def Globel Block /Sector Lock      : WEP must be 1 to setup and use   - write enable req prior
     Flash_Globe_UNLCK    con 14 ' $98       'def Globle Block/Sector Unlock     : WEP must be 1 to setup and use   - write enable req prior
     
    
     ' commands 15-22 use the Read command --- 
     Flash_RD             con 15 ' $03       'def read data at normal speed        ( 24bit address req)+ (1 byte data)
     Flash_Rd_HS          con 16 ' $0B       'def read data at High speed (Fast Read) ( 24bit address req)+ (1dummy+1 byte data)
     Flash_Rd_Secreg      con 17 ' $48       'def Program Security Register read  ( 24bit address req)+ (1 dummy +1 data)( simular to fast read command )
     Flash_Rd_Sig         con 18 ' $4B       'def read Flash device Unique ID signature - cmd + 4 dummy bytes , returns 64bit ID MSB first
     Flash_Rd_Blk_LCK     con 19 ' $3D       'def Read Block/Sector Lock status  , returns 0= unlocked 1= Locked ( 24bit address req)+ (1 byte data)
     Flash_Rd_ID          con 20 ' $9F       'def Read manufacture 1byte/device/UID code 2 bytes ( JEDEC ID) - returns 3 bytes 
     Flash_Rd_reg2        con 21 ' $35       'def read the Status Register 2(S15-S8)  - returns 1 data byte 
     Flash_Rd_reg3        con 22 ' $15       'def read the Status Register 3(S23-S16) - returns 1 data byte 
    
     '---- not in command lookup table - used directly -----
     Flash_Wr_dis      CON $04        'def write disable command 
     Flash_Rd_reg1     con $05        'def read the Status Register 1(S7-S0)  - done by Bsy_chk routine
     Flash_Wr_en       con $06        'def write Enable command   
     Flash_Vol_Wr_EN   con $50        'def  Volatile SR Write Enable - used to change write_reg1 bits but wont set WEL flag - quick way of changeing register for protection bits ( no write enable 
     Flash_EN_Rst      con $66        'def Enable Software Reset  - reset takes min 30us 
     Flash_Rst         Con $99        'def Do a Reset  - Must be combined with Flash_EN_Rst
     Flash_PWR_Dwn     con $B9        'def Deep Power Down command   
     Flash_PWR_Up      con $AB        'def Release From Deep Power Down command  
     
    ' ----------  FLASH varables -------------------------
    
     Data_Length    var word       ' table of data length ( made word cos data length can be 256 so 0-255 byte = 256 total bytes
     SDC_buffer	    Var Byte[256]  ' indexed data - max 256 bytes - 8mb FLASH has a 256 Limit from page Writes - Note 512 used in SD routines 
     SDC_data_in    Var Byte       ' Data in byte from flash 
     SDC_data_out   Var Byte       ' Data out byte from Flash - 
     SDC_address_High   Var word   ' address higher word sent to FLASH 
     SDC_address_Low    Var word   ' address lower  word sent to FLASH 
     SDC_index	    Var Word       ' Loop index counter 
     SDC_CmdCode    Var Byte       ' used here as Sector protect value for the Write Status register 
     SDC_cmd	    Var Byte       ' command code for selected operation 
     SDC_Block      var Byte       ' 64K block Address   - uses SDC_address_High.low , each block 0-63(32Kbit) 0-127(64Kbit), addressing used both 
     SDC_Sector     var byte       ' 4K Sector address   - uses SDC_address_Low.highbyte , each sector = 16 pages , so sector 0 = page 0-15  - values = 0 -15
     SDC_Page       var byte       ' Page Address
     SDC_Byte       Var byte       ' Bytes Address
     Flash_RD_Fast  var bit        ' Flag for High speed read 1 = Highspeed read speed 0= normal read speed 
     Flash_Install  var bit        ' flag set when flash install program used  
     Flash_32KB_Block_Sel  var bit ' Sets StartPage address for 32KB Block erase - 0 = lower block - sets start page address - page 0 - 127, 1 = High block - page 128 - 256
     Flash_Protect  var bit        ' Set Protect =1 / Unprotect =0 of a block , used as a read of block status as well
     Flash_Chk_Fail var bit        ' Flag result status of flash_test routine - called at startup 
     
     Flash_Blk_Orgin    var byte   ' Orgin sector value     - copy sector command 
     Flash_Blk_Dest     var byte   ' destination  sector value  - copy Sector Command   
     Flash_Sec_Orgin    var byte   ' Orgin sector value     - copy sector command 
     Flash_Sec_Dest     var byte   ' destination  sector value  - copy Sector Command  
     Flash_Page_Orgin   var byte   ' Orgin Page value
     Flash_Page_Dest    var Byte   ' Dest Page Value 
     Flash_Page_Length  var byte   ' number of pages 
     Flash_Clear        var bit    ' flag to clear orginal sector 1= clear  
     Flash_SPI_Shared   var bit    ' Flag Set (1) when SPI is a shared bus between flash and RF module 
     
     Flash_EN        var byte      ' Flash_CE pin value offset from LATA - value set in main program - allows for multi Flash chip CE from same routine 
     Flash_Manf_id   var byte      ' manufacture id code 
     Flash_Manf_type var byte      ' device type code 
     Flash_Manf_cap  var byte      ' device capacity code 
     Flash_tmp       var byte      ' used as a temp varable  - used in busy loop counter 
     Flash_tmp2      VAR BYTE      ' used as a temp varable  
     Flash_Reg_val   var byte      ' Flash register value 
    
     Flash_Addr_Copy_Low  var word  ' low word temp storage of input address and data length 
     Flash_Addr_Copy_High var word  ' high word temp storage of input address and data length
    
    
    '----------- Varable settings at startup ---------------------------------------------
    
       Flash_RD_Fast = 0        ' Set to normal read at start
       Flash_Install = 0        ' set to 0 when flash  install not being used  
       Flash_Clear = 0          ' set not to clear 
       Flash_32KB_Block_Sel = 0 ' set to use low address 
      
    '---------------- Routines  ------------------ 
    goto JumpOverSPIFLASH     ' Jump to end of this include file  for Correct compile  
     '-----------------------------------------------  
      Flash_Init:
        ' do a read register command to clear the Flash register after power up
        ' called by gate_config routine at start 
             
             
             LATA.0[Flash_EN] = 0                          ' Bring the FLASH chip select line low  
              SDC_data_out = Flash_Rd_reg1                 ' Send the read status register command byte
     	      Gosub Flash_spiw	                           ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
             LATA.0[Flash_EN] = 1                          ' Bring the FLASH chip select line high  
              gosub buffer_clear                           ' clear varables area 
         '    gosub Flash_Reg_Setup                         ' setup req2 and reg3 for dephalts use of the flash 32Kb  ( not needed ) 
       
        
      return                                                        
    ' -----------------------------
      Buffer_Clear:
     
          For SDC_index = 0 To 255
              SDC_buffer[SDC_index] = 0
          next SDC_index
      return
    
    '--------------------------------------- 
      Flash_Reset:
      ' routine to software reset the flash 
      ' enable reset and reset must be consecutive 
       
        LATA.0[Flash_EN] = 0                          ' Bring the FLASH chip select line low  
          SDC_data_out = Flash_EN_Rst                 ' Send Enable Reset command 
          gosub Flash_spiw	                          ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
          SDC_data_out = Flash_Rst                    ' Send Reset command 
       	  Gosub Flash_spiw	                          ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus  
        LATA.0[Flash_EN] = 1                          ' Bring the FLASH chip select line high  
         
      return
    
    '-----------------------------------------
    
     Flash_Format:
     'Note wont work if any sectors are protected 
      ' can take upto 50sec on 32mbit chip 
       sdc_cmd = Flash_Bulk_ers  ' excutes as it sounds
       gosub Flash_Comand 
     return
     
    '-------------------------------------------------
     'SECTOR	PAGES REF
    '  0    	0-15
    '  1	    16-31
    '  2	    32-47
    '  3	    48-63
    '  4	    64-79
    '  5	    80-95
    '  6	    96-111
    '  7	    112-127
    '  8	    128-143
    '  9	    144-159
    '  10	    160-175
    '  11	    176-191
    '  12	    192 -207
    '  13	    208-223
    '  14	    224-239
    '  15	    240-255
    
     Flash_Sec_Erase: 
      ' assumes Block address  0-63 
      ' assumes Sector value 0 -15 
      ' erases 1 Sector at a time  address (4KB)= 16 pages - page 0 - 15 = sector 0  
      ' Erases wont work on sectors that are write protected 
      ' sector erase take 400ms per instruction 
       SDC_pAGE = 0                          ' ensure 0 
       SDC_pAGE = sdc_SECTOR << 4            ' shift given sector 0-15 to upper page value   
      
       sdc_cmd = Flash_Sec_Ers               ' Erases  sector (15 pages x 256 bytes ) 
       SDC_address_high.byte0 = SDC_Block    ' set sector Address 0 to 15 for chip
       SDC_address_low.byte1  = SDC_Page     ' set page start address 0 to 255  
       SDC_address_low.byte0  = 0            ' set byte start address 0 to 255
       gosub Flash_Comand                    ' Do the command 
     return
    
    '----------------------------------------------------
    
     Flash_Blk32_Erase: 
      ' assumes Block address   
      ' assumes flag 32KB_Block_Sel 0 = bottom 32Kb start address page, 1= 128page address
      ' erases 1/2 a 64KB Block at a time  address (32KB)= 128 pages 
      ' Erases wont work on sectors that are write protected 
      ' sector erase take min 120ms max 1.6Sec per instruction 
       IF Flash_32KB_Block_Sel = 0 THEN           ' select offset page for 32 byte sector 
           SDC_PAGE = 0
       ELSE
           SDC_PAGE = 128
       ENDIF    
       sdc_cmd = Flash_blk32_Ers             ' Erases 32kB block ( 128 pages of 256 bytes ) 
       SDC_address_high.byte0 = SDC_Block    ' set block Address for chip
       SDC_address_low.byte1  = SDC_PAGE     ' set page start address 0 to 255  
       SDC_address_low.byte0  = 0            ' set byte start address 0 to 255
       gosub Flash_Comand                    ' Do the command 
     return
    '-------------------------------------------------------------
     
     Flash_Blk64_Erase: 
      ' assumes Block address  
      ' erases a 64KB Block at a time  address (64KB)= 256 pages 
      ' Erases wont work on sectors that are write protected 
      ' sector erase take min 160ms max 2.0Sec per instruction 
      
       sdc_cmd = Flash_blk64_Ers             ' Erases 64kB block ( 256 pages of 256 bytes ) 
       SDC_address_high.byte0 = SDC_Block    ' set Block Address for chip
       SDC_address_low.byte1  = 0            ' set page start address 0 to 255  
       SDC_address_low.byte0  = 0            ' set byte start address 0 to 255
       gosub Flash_Comand                    ' Do the command 
     return
    
    '------------------------------------------------------------------
     ' command routine commented out as it was not used to save space - but works ok 
     ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
     'Flash_Byte_Modify:
     ' assumes Event_Get_Block_Page routine has given the event block and page  
     ' assumes event selected block, event page address , event start SDC_byte , data length ( upto 256bytes )
     ' asusmes bytes changed are in the same sector and no boundry cross
     ' assumes block/sector 0 is not protected , block 0 is scrachpad 
     ' assumes selected modifed block/sector is not protected
     ' assumes buffer[0]+ (length-1)  has bytes data that is to be modfifed 
      
     ' Flash_Addr_Copy_high.byte1 =  Data_Length ' number of bytes to change  - save length in temp location 
     ' Flash_Addr_Copy_high.byte0 =  SDC_Block   ' save event block address 
     ' Flash_Addr_Copy_low.byte1  =  SDC_Page    ' save page addrees
     ' Flash_Addr_Copy_low.byte0  =  SDC_Byte    ' save start byte 
     
     ' SDC_Sector = (SDC_Page & $F0) >> 4        ' get 4k sector from page number  
     ' SDC_Block = 0                             ' set block to 0 
     ' gosub Flash_Sec_Erase                     ' erase block 0 ,4k sector of page range 
     
     ' SDC_Block = 0                             ' use sector 0,instead of given sector , but use given page, byte length  
     ' SDC_Page =  Flash_Addr_Copy_low.byte1     ' restore orgin page addrees
       
     ' sDC_Byte =  Flash_Addr_Copy_low.byte0     ' restore orgin byte start address 
        
     ' gosub Flash_write                         ' Write the changed byte data from buffer to sector 0
      
     
     ' if Flash_Addr_Copy_low.byte0 = 0 then               ' find the byte to copy - copy all bytes above 0 for given sector  
           
           
     '       Flash_Page_Orgin =1                           ' start page of orgin
     '       Flash_Page_length = 255                       ' how many pages 
     '       Flash_Sec_Orgin =  Flash_Addr_Copy_high.byte0 ' sector  
     '       Flash_Sec_Dest = 0
     '       Flash_Page_Dest = 1        
     '       gosub Flash_Page_Copy
    '   endif 
    
    '  if Flash_Addr_Copy_low.byte1 = 255 then             ' find the pages to copy - copy all pages/ bytes  below given page/ byte of sector  
    '        Flash_Page_Orgin =0                           ' start page of orgin
    '        Flash_Page_length = 254                       ' how many pages 
    '        Flash_Sec_Orgin =  Flash_Addr_Copy_high.byte0 ' sector  
    '        Flash_Sec_Dest = 0
    '        Flash_Page_Dest = 0        
    '        gosub Flash_Page_Copy
    '   endif
    
    '  if Flash_Addr_Copy_low.byte1 >0 and Flash_Addr_Copy_Low.byte1 < 254 then       ' find the pages to copy - copy all pages/ bytes  below given page/ byte of sector  
    '        Flash_Page_Orgin =0                               ' start page of orgin
    '        Flash_Page_length = Flash_Addr_Copy_low.byte1 - 1 ' how many pages 
    '        Flash_Sec_Orgin =  Flash_Addr_Copy_high.byte0     ' sector  
    '        Flash_Sec_Dest = 0                                ' start at same page value as orgin
    '        Flash_Page_Dest = 0         
    '        gosub Flash_Page_Copy
        
    '        Flash_Page_Orgin = Flash_Addr_Copy_Low.byte1 + 1  ' start page of orgin
    '        Flash_Page_length = 255 - Flash_Page_Orgin        ' panges to copy  = 255 - start address +1  
    '        Flash_Sec_Orgin =  Flash_Addr_Copy_high.byte0     ' sector  
    '        Flash_Sec_Dest = 0
    '        Flash_Page_Dest = Flash_Addr_Copy_low.byte1 + 1          
    '        gosub Flash_Page_Copy
    '   endif
        
    '  if Flash_Addr_Copy_low.byte0 + Flash_Addr_Copy_high.byte1  < 255 then   ' if the start byte + data length of the data changed is < 255 bytes , 
               ' then copy  bytes  below the selected changed data 
    '         SDC_Block  = Flash_Addr_Copy_high.byte0         ' read selected sector 
    '         SDC_PAGE   =  Flash_Addr_Copy_low.byte1          ' of selected page 
    '         SDC_byte = 0                                     ' start address bytes 0 to  
    '         Data_Length = Flash_Addr_Copy_Low.byte0 - 1      ' selected byte - 1  ( length)
    '         gosub Flash_Read                                 ' read  
    '         SDC_Block  = 0                                  ' use sector 0 aselected sector 
    '         SDC_PAGE   =  Flash_Addr_Copy_low.byte1          ' of selected page 
    '         SDC_byte = 0                                     ' start address bytes 0 to  
    '         Data_Length = Flash_Addr_Copy_low.byte0 - 1      ' selected byte - 1  ( length)
    '         gosub Flash_Write                                ' write  
          
              ' then copy  bytes above the selected changed data 
    '         SDC_Block  = Flash_Addr_Copy_high.byte0                          ' read selected sector 
    '         SDC_PAGE    = Flash_Addr_Copy_low.byte1                          ' of selected page 
    '         SDC_byte    = Flash_Addr_Copy_low.byte0 + Flash_Addr_Copy_high.byte1  ' start address bytes above given address and length  
    '         Data_Length = 255 - SDC_byte                                 ' data above changed bytes ( length = 255 bytes  - given addrees + given length )
    '         gosub Flash_Read                                             ' read the data  
    '         SDC_Block  = 0                                              ' use sector 0 
    '         SDC_PAGE   =  Flash_Addr_Copy_low.byte1                          ' of selected page 
    '         SDC_byte    = Flash_Addr_Copy_low.byte0 + Flash_Addr_Copy_high.byte1  ' start address bytes above given address and length  
    '         Data_Length = 255 - SDC_byte                                 ' data above changed bytes ( length = 255 bytes  - given addrees + given length )
    '         gosub Flash_Write                                            ' write  the data 
         
    ' endif
     
        ' Block 0 should now have a complete copy of the data + changed data from the orginal selected sector 
    '       Flash_Sec_Orgin = 0                          ' copy sector 0 
    '       Flash_Sec_dest = Flash_Addr_Copy_high.byte0  ' erase destination  and copy data from flash orgin
    '       Flash_clear = 1                              ' set flag erase orgin sector 0 after copy
    '       gosub Flash_Block_Copy                      ' copy the sector 
     
       
     
    ' return
    '----------------------------------------------------
     ' command routine commented out as it was not used to save space - but works ok 
     ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    
    ' Flash_Block_Copy:
    '  ' copys data from 1 block to another 
    '  ' erases destination block - optional clean of orginal block 
    '  ' assumes Flash_Sect_Orgin,Flash_Sect_Dest ,Flash_clear
    '  ' Erases wont work on blocks that are write protected 
    '  ' block erase take 400ms per instruction 
    '      SDC_Block  = Flash_Blk_Dest            ' clear destination block 
    '      gosub Flash_blk64_Erase                ' use SDC_blk64_erase info to erase destination sector 
    '       for SDC_PAGE = 0 to 255               ' copy pages to selected block ( 256bytes at a time) 
    '           SDC_Block  = Flash_blk_Orgin      ' block to copy 
    '           SDC_byte    = 0
    '           Data_Length = 255
    '           gosub Flash_Read                  ' read the data to buffer 
    '           SDC_Block  = Flash_Blk_Dest       ' block to copy to
    '           SDC_byte    = 0                   ' use block details for destination
    '           Data_Length = 255
    '           gosub Flash_Write                 ' write the data
    '       next SDC_PAGE
    '     if Flash_clear = 1 then 
    '        SDC_Block = Flash_Blk_Orgin         ' clean up orgin Block 
    '        gosub Flash_Blk64_Erase               
    '     endif
    ' return
    '----------------------------------------------------------------------------------     
    ' command routine commented out as it was not used to save space - but works ok 
     ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    ' Flash_Page_Copy:
    '  ' copys data from pages 0 -255 from orgin or destination block 
    '  ' assumes destination block pages are Erased 
    '  ' assumes pages orgin and pages destination do not cross block boundrys 
    '  ' assumes Flash_Page_Orgin,Flash_Page_dest ,Flash_Page_length, Flash_blk_orgin ,Flash_blk_dest  
    '  ' writes wont work on blocks that are write protected 
          
    '     for  Flash_tmp2 =  Flash_Page_Orgin to Flash_Page_length    '  copy sector 0 pages to selected sector 0 ( 256bytes at a time) 
    '           SDC_Block  = Flash_blk_Orgin                     ' sector to copy 
    '           SDC_PAGE =  Flash_tmp2
    '           SDC_byte    = 0
    '           Data_Length = 255
    '           gosub Flash_Read                                  ' read the data to buffer 
    '         
    '           SDC_Block  = Flash_blk_Dest                       ' sector to copy to
    '           SDC_PAGE = Flash_Page_Dest                        ' page to copy to 
    '           SDC_byte    = 0                
    '           Data_Length = 255
    '           gosub Flash_Write                                 ' write the data
    '           Flash_Page_Dest = Flash_Page_Dest + 1              ' increment destination page 
    '     next Flash_tmp2
     
     
    ' return 
    '---------------------------------------- 
     
           
     Flash_Write: 
      ' assumes data length , address and upto 256 bytes in  SDC_buffer[] to send 
      ' writes bytes from SDC_buffer[] into flash , block/page/byte loction must be "FF" at start
      ' write wont work on sectors that are write protected 
     
       sdc_cmd = Flash_WR               ' excutes as it sounds - max of 256 bytes
       SDC_address_high.byte0 = SDC_Block   ' set block Address for  chip
       SDC_address_low.byte1  = SDC_Page     ' set page start address 0 to 255  
       SDC_address_low.byte0  = SDC_byte     ' set byte start address 0 to 255
       gosub Flash_Comand 
      
      return
     
    '--------------------------------------
    
     Flash_Read: 
      ' assumes Block, page, bytes , data length input 
      ' gets upto bytes data into SDC_buffer[] from flash 
      ' uses normal read speed if no Flash_RD_Fast flag set
       if Flash_RD_Fast = 1 then
         sdc_cmd = Flash_Rd_HS          ' excutes fast read  - max of 256 bytes 
       else
         sdc_cmd = Flash_RD             ' excutes normal read - max of 256 bytes cos of buffers size/ page size 
       endif
       SDC_address_high.byte0 = SDC_Block   ' set block Address  for chip
       SDC_address_low.byte1  = SDC_Page     ' set page start address 0 to 255  
       SDC_address_low.byte0  = SDC_byte     ' set byte start address 0 to 255
       gosub Flash_Comand
      return
    
     '------------------------------------------------------------
     Flash_WR_protect:
     ' routine to protect/ unprotect a set block of 60-63 in 32kbit chip ( block 60-63 used by K9 system stored settings )
     ' Assumes Flash_Protect - 0 = unprotect 1 = Protect a sector 
     ' SETUP FOR 32kB CHIP 
     '  Bit7 = SRP0 - Set to 0 - software protect (SRP1= 0 DEPHALT(stat_reg2(bit0), not WP pin 
     ' bits6(SEC) = 0 = 64KB Block 1= 4Kb SECTOR , Bit5(TB) 0= Top, 1 = Bottom , Bit4-2 = BP2-BP0. bits 1-0 (wel, busy )
       
       
         if Flash_Protect = 0 then 
            SDC_buffer[0] = $00 ' clear all blocks
         else
            SDC_buffer[0] = $0C ' set blocks 60-63 protected for K9 project 
         endif 
      
          sdc_cmd = Flash_Wr_reg1  ' write register 
          data_length = 1          ' set 1 byte  
          gosub Flash_Comand 
       return
    
    '-----------------------------------------------------------
       Flash_WR_Disable:
       ' reset the write enable latch 
           LATA.0[Flash_EN] = 0                               ' Bring the FLASH chip select line low  
            SDC_data_out = Flash_Rd_reg1                      ' Send the read status register command byte
     	    Gosub Flash_spiw	                              ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
           LATA.0[Flash_EN] = 1                               ' Bring the FLASH chip select line high  
       return
    '----------------------------------------------------
    ' command routine commented out as it was not used to save space - but works ok 
     ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    
    '  Flash_Read_ID:
      ' returns JEDEC ID-  returns Manufacture ID byte($EF), mem type - (ID15-ID8)1byte ,capacity(ID7-ID0)1byte)   
          
    '     sdc_cmd =  Flash_Rd_ID              ' Flash Read ID 
    '     data_length = 3                     ' 3 bytes  
    '     gosub Flash_Comand
    '     Flash_Manf_id =  SDC_buffer[0]
    '     Flash_Manf_type = SDC_buffer[1] 
    '     Flash_Manf_cap  = SDC_buffer[2]
    '     IF FLASH_Install = 1 then
    '        HSEROUT2 ["Flash Manf ID = ",hex Flash_Manf_id,"  Flash Device ID = ",hex Flash_Manf_type,"  Device Capacity ID = ",hex Flash_Manf_cap,13,10]  
    '      endif
    '   return   
    '---------------------------------------------------------------------
    
    
    ' command routine commented out as it was not used to save space - but works ok 
     ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    
    '  Flash_Read_Sig:
      ' returns the flash chips Unique ID number ( 64Bit)
    '    sdc_cmd = Flash_Rd_Sig               ' Flash Read Unique ID signature 
    '    data_length = 4                      ' 4 bytes                ' Flash Read Unique ID signature 
     '   gosub Flash_Comand
     ' return
      '----------------------------------------------
    
    
    ' command routine commented out as it was not used to save space - but works ok 
     ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    
    ' Flash_Read_BLK_Lock:
     'routine to read block or sector locks ( WPS=1 to work )
    '   sdc_cmd =  Flash_Rd_Blk_LCK                          ' Flash Read block lock  
    '   data_length = 1                                      ' 1 bytes   
    '   gosub Flash_Comand
     '  Flash_Protect = SDC_buffer[0] & $01                  ' get bit0 value - 1 = locked .0 = unlocked  
    '  return
     '--------------------------------------------- 
     
      Flash_Power_Down:
     ' sEt Flash chip to low power mode from standby mode - no command other tha powerup will wake the device 
        LATA.0[Flash_EN] = 0                                ' Bring the FLASH chip select line low  
          SDC_data_out = Flash_PWR_Dwn                      ' command to pwr down
     	  Gosub Flash_spiw	                                ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
        LATA.0[Flash_EN] = 1                                ' Bring the FLASH chip select line high  
      return
    '----------------------------  
      Flash_Power_Up:
     ' sEt Flash chip to standby mode - no command other tha powerup will wake the device 
    ' sEt Flash chip to low power mode from standby mode - no command other tha powerup will wake the device 
        LATA.0[Flash_EN] = 0                                ' Bring the FLASH chip select line low  
          SDC_data_out =  Flash_PWR_Up                      ' command to pwr up
     	  Gosub Flash_spiw	                                ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
        LATA.0[Flash_EN] = 1                                ' Bring the FLASH chip select line high  
      return
     '-----------------------------
    
     ' command routine commented out as it was not used to save space - but works ok 
     ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    
    ' Flash_Reg_Setup:
    
     ' ========== Note - NOT REQUIRED IT SEEMS ============
     ' Routine to write setup of status registers 2,3
     ' Register 2 controls ..... 
     ' bit7(S15)- Suspend Status 
     ' bit6(S14)CMP -Compliment Protect - dephalt CMP =0 
     ' bit5-3(S13-11)- Security Register(One time programable) dephalt = 000
     ' bit1(S9) - QE - Quad SPI Mode Enable ( default =0 when chips NOT FVIQ type)
     ' bit0(S8) - SRP1-  Protect bit1 _ dephalt =0 
     '  
    '      SDC_buffer[0] = %00000000 ' QE(bit1) is forced to 0 so that if FVIQ chip Fitted uses standard SPI bus , and not force pin Hold/ WP az data i/o
    '      sdc_cmd = Flash_Wr_reg2   ' write Status register2
    '      data_length = 1           ' set 1 byte  
    '      gosub Flash_Comand 
     
     ' Register 3 controls ..... 
     ' bit7(S23) - Hold(0- dephalt)/Reset(1) pin fuction  
     ' bit6,5(S22,S21)(0,0=100%),(0,1=75%),(1,0=50%),(1,1=25%- dephalt) read driver strength- used to overcome cpacitive loading ,trace impendace issues with signal at high speed reads 
     ' bits4,3 - reserved (writen as 0)
     ' Bit2(S18) WPS - selects Protection methode - Indervidual block/sectors(WPS=1) or by grouping range(WPS=0) ( WPS dephalt is 0 ) 
     ' Bits1,0-reserved(writen as 0)  
       
    '      SDC_buffer[0] = %01100000   ' this is the factory dephalt for chip
    '      sdc_cmd = Flash_Wr_reg3     ' write Status register3 
    '      data_length = 1             ' set 1 byte  
    '      gosub Flash_Comand 
     
    ' return  
    
    ' -----------------------------
    ' Flash_Read_reg2:
    ' ' reads write register 2 -  
    ' ' Register 2 controls ..... 
    ' ' bit7(S15)- Suspend Status 
    ' ' bit6(S14)CMP -Compliment Protect - dephalt CMP =0 
    ' ' bit5-3(S13-11)- Security Register(One time programable) dephalt = 000
    ' ' bit1(S9) - QE - Quad SPI Mode Enable ( default =0 when chips NOT FVIQ type)
    ' ' bit0(S8) - SRP1-  Protect bit1 _ dephalt =0 
    ' '  
    '   sdc_cmd =  Flash_Rd_reg2                          ' Flash Read register 2   
    '   data_length = 1                                   ' 1 bytes returned     
    '   gosub Flash_Comand
    ' return
     
     '---------------------------------------
     
    ' Flash_Read_reg3:
    ' ' Register 3 controls ..... 
    ' ' bit7(S23) - Hold(0- dephalt)/Reset(1) pin fuction  
    ' ' bit6,5(S22,S21)(0,0=100%),(0,1=75%),(1,0=50%),(1,1=25%- dephalt) read driver strength- used to overcome cpacitive loading ,trace impendace issues with signal at high speed reads 
    ' ' bits4,3 - reserved (writen as 0)
    ' ' Bit2(S18) WPS - selects Protection methode - Indervidual block/sectors(WPS=1) or by grouping range(WPS=0) ( WPS dephalt is 0 ) 
    ' ' Bits1,0-reserved(writen as 0)  
    '   sdc_cmd =  Flash_Rd_reg3                          ' Flash Read register 3   
    '   data_length = 1                                   ' 1 bytes returned     
    '   gosub Flash_Comand
    '  return
      
      '-----------------------------------
       
      Flash_Comand:
      ' assumes SDC_address long
      ' assumbe data_Length = Lookup table to fill 
      ' max 256 bytes per write 
      ' erase of the sector by byte  / bulk is needed prior to write , as a write only changes a 1 to 0 , and the erase chanse the 0 to 1 
       if  SDC_cmd = 0 then return                     ' invalid command if value =0 
      
    '   if Flash_SPI_Shared = 0 then NO_disable_rbc     ' if flag = 0 then is not a shared SPI bus with Rf Module  - jump over disable command
    '   #if __PROCESSOR__ = "18F27K40" or __PROCESSOR__ = "18F47K40"  
    '@ INT_DISABLE IOC_INT                              ; Turn off IOC interupts (xxk40) for RX_mode   - done so shared SPI BUS ON RF-MODULE does not corrupt flash data
    '   #else 
    '@ INT_DISABLE RBC_INT                              ; Turn off IOC interupts (xxk80,k22) for RX_mode   - done so shared SPI BUS ON RF-MODULE does not corrupt flash data
    '   #endif 
    '  NO_disable_RBC:                                 ' label to jump over the INT_disable 
     
     Lookup SDC_cmd,[$00,$01,$31,$11,$02,$42,$20,$52,$D8,$36,$39,$44,$C7,$7E,$98,$03,$0B,$48,$4B,$3D,$9F,$35,$15],SDC_CmdCode ' asignes command code to flash chip  
      
          gosub BSY_chk                        ' do for all commands 
             
         if SDC_cmd <=14 then                  ' do for writes, sector erase,bulk erase , write reg protect - commands 1-14 use writen enable first
            LATA.0[Flash_EN] = 0               ' Bring the FLASH chip select line low.
     	    SDC_data_out = Flash_Wr_en         ' Send  command byte that requires a write 
            Gosub Flash_spiw	               ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus
       	    LATA.0[Flash_EN] = 1               ' Bring the FLASH chip select line high to complete the write command 
     	   
         endif
    	
         LATA.0[Flash_EN] = 0                  ' Bring the FLASH chip select line low 
         SDC_data_out =  SDC_CmdCode           ' Send the  command byte,
       	 Gosub Flash_spiw	                   ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus
        
         if SDC_cmd =>4 and SDC_cmd <=11 or _           ' if write commands 4-11 then use 24bit address assigned 
            SDC_cmd =>15 and SDC_cmd <=19 then          ' or read commands 15-19 then use 24bit address assigned , command 18 uses 24bit address as 3 dummy bytes 
              SDC_data_out = SDC_address_high.Byte0     ' set block Address for chip
     	      Gosub Flash_spiw		                    ' Write Byte SDC_data_out.
     	      SDC_data_out = SDC_address_low.Byte1      ' set page address 0 to 255  
     	      Gosub Flash_spiw	                        ' Write Byte SDC_data_out.
     	      SDC_data_out = SDC_address_low.Byte0      ' set byte address 0 to 255
              Gosub Flash_spiw		                    ' Write Byte SDC_data_out.
              if SDC_cmd => 16 and SDC_cmd <= 18 then   ' if read High speed mode ,Program security read , Read Unique ID(add 4th dummy byte) 
                 SDC_data_out = $00                     ' add a dummy byte to command  
                 Gosub Flash_spiw		                ' Write Byte SDC_data_out.
              endif
          endif
        
          if SDC_cmd <=5 or _                                ' if write commands require data bytes sent 
             SDC_cmd >=15 and SDC_cmd <= 22 then             ' or read commands require data bytes returned     
                     
              For SDC_index = 0 To Data_Length-1             ' DATA LENGTH -1  so byte 0 is counted when setting data length  
                  if SDC_cmd <= 5 then                       ' if write ,Write register,write Security register then 
                     SDC_data_out = SDC_buffer[SDC_index]    ' send contents of indexed SDC_buffer 
                     gosub  Flash_SPIw  	                 ' write byte SDC_data_in from SPI bus.  Returns SDC_data_in.
                  endif
                
                  if SDC_cmd =>15 and SDC_cmd <=22 then      ' if read scommand returns data 
                     gosub  Flash_SPIR  	                 ' Read Byte SDC_data_in from SPI bus.  Returns SDC_data_in.
     	             SDC_buffer[SDC_index] = SDC_data_in
                  endif
              Next SDC_index
          endif
        
         LATA.0[Flash_EN] = 1                          ' Bring the FLASH chip select line high.
    
    '    #if __PROCESSOR__ = "18F27K40" or __PROCESSOR__ = "18F47K40"  
    '     IOCCF.7 =0                                    ' 18f27k40 do a manual clear of the IOC port pin flag interupt - not done by DT_18_k40 atm 30/7/18
    '@ INT_ENABLE IOC_INT                              ; Turn on IOC interupts (xxk40) for RX_mode   - done so shared SPI BUS ON RF-MODULE does not corrupt flash data
    '   #else 
    '@ INT_ENABLE RBC_INT                              ; Turn on IOC interupts (xxk80,k22) for RX_mode   - done so shared SPI BUS ON RF-MODULE does not corrupt flash data
    '   #endif 
      return
    '----------------------------------------------------
     Bsy_chk:
            LATA.0[Flash_EN] = 0                        ' Bring the FLASH chip select line low  
            SDC_data_out = Flash_Rd_reg1                ' Send the read status register1 command byte
     	    Gosub Flash_spiw	                        ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
            gosub Flash_SPIR  	                        ' Read Byte SDC_data_in from SPI bus.  Returns SDC_data_in.
            Flash_tmp = 0                               ' ensure 0 - counter for busychk loop
            while SDC_data_in.0 = 1                     ' while busy flag =1        
                gosub Flash_SPIR  	                    ' Read Byte SDC_data_in from SPI bus.  Returns SDC_data_in.
                Flash_tmp = Flash_tmp + 1               ' tmp counter 
                if Flash_tmp>65000 then goto BSY_Exit   ' if fail safe counter >65000 then exit - normaly under 65000 unless bulk erase  
            wend                  
    BSY_Exit:
           LATA.0[Flash_EN] = 1                                   ' Bring the FLASH chip select line high
         '  IF FLASH_Install = 1 then                          ' used only for info 
         '      HSEROUT2 [" Flash_tmp = ",dec Flash_tmp,13,10] 
         '      IF Flash_tmp >65000 THEN HSEROUT2 [" Flash_tmp value HIGH - IF NOT CHIP ERASE",13,10] ' debug 
         '  ENDIF 
     return  
    '------------------------------- 
      Flash_SPIR:
        SO = 1			                    ' Shift out high bits while shifing in data.
     	Shiftin SO, SCK, 6,[SDC_data_in]	' MSb first, clock idle high.
      
      Return
    '-------------------------------
    
      Flash_SPIW: 
          shiftout SI,SCK,5,[SDC_data_out]	    ' MSb first, clock idle high.
                           
      return
    '------------------------
     ' routine to erase / write / read test data for scratchpad sector 0 - test of flash chip 
     '  
     Flash_Test:
        SDC_Block = 0          ' set block address 
        sdc_SECTOR = 0         ' set sector start address 
        gosub Flash_Sec_Erase  ' erase sector 0  ( block0, pages 0-15 ) 
     
        SDC_Page = 0           ' set page start address 0 to 255  
        SDC_byte = 0           ' set byte start address 0 to 255 
        Data_Length = 256      ' set address length of 256 bytes  (0- 255)
       
        For  SDC_index = 0 to Data_Length -1          ' fill the data buffer  with 0 - 255  values
               SDC_buffer[SDC_index] = SDC_index      
        next SDC_index
        
        pause 100                 ' seems buffer write error if no delay of 50ms or more from the prev erase command  
        gosub Flash_Write         ' write test data to sector 0  to datalength
        gosub Buffer_Clear        ' clear the buffer after write 
        Flash_RD_Fast = 1         ' set fast read 
        gosub flash_read          ' read flash to buffer to datalength
        Flash_Chk_Fail = 1        ' set flag prior to test  
       
        For  SDC_index = 0 to Data_Length-1                 ' check data  
             if  SDC_buffer[SDC_index] <> SDC_index then 
                 Flash_Chk_Fail = 0  ' if not correct value clear  flag , flag status shown on terminal at startup 
               '  HSEROUT2 ["Fail - IDX = ",DEC SDC_index,"  Buffer Data = ", dec SDC_buffer[SDC_index],13,10]  ' DEBUG 
             ENDIF
        next SDC_index
        gosub Buffer_Clear        ' clear the buffer at end of routine 
      return  
    '------------------------------------------------------------------
    
    ' EXAMPLE 3 
    ' READ BLOCK 2 PAGES 0-2 , BYTES 0-255 OF EACH PAGE OUT TO SERIAL PORT MONITOR
    
    ' SDC_Block = 2         ' SET BLOCK TO READ    0-15 range
    ' Flash_Page_Orgin =0   ' SET Page START LOCATION READ value  0-255 range 
    ' Flash_Page_Length = 2 ' SET number of pages TO READ VALUE  0-255 range
    ' Data_Length = 256     ' SET BYTES NUMBER TO READ -  0-256 range  note:  
    ' gosub Flash_Test_RD   ' PLACE THE DATA OUT SERIAL PORT 
    'return
    
    '----------------------------------------------------------------
     'Flash_Test_RD: 
     'assumes  SDC_Block, Flash_Page_Orgin,Flash_Page_Length,Data_Length
     'Places seleted read data location out to serial port1 
      
     ' FLASH_Install = 1 ' show status  info for ref 
     ' gosub Bsy_chk ' just get the status reg value for ref 
     
     ' for SDC_Page = Flash_Page_Orgin0 to Flash_Page_Length    ' set page range for read
     '   gosub Flash_Read                                        ' read page into buffers 
     '   HSEROUT [13,10,"Sector ",dec SDC_Block," PAGE ",dec SDC_Page, 13,10]
     '   For SDC_index = 0 To Data_Length-1
     '     	HSEROUT [",",hex SDC_buffer[SDC_index] ] 
     '   next SDC_index
     ' next SDC_Page 
     
    'return
    '------------------------------------------
    'Flash_Test_copy:
    
     
      ' copys data from 1 sector to another 
      ' erases destination sector - optional clean of orginal sector 
      ' assumes Flash_Orgin,Flash_clear flag,SDC_Block for destination 
      ' erases 1 sector at a time  address 
      ' Erases wont work on sectors that are write protected 
      ' sector erase take 600ms per instruction 
     
    '       Flash_Sec_Orgin =  0 ' sector  
    '       Flash_Page_Orgin = 0                   ' start page of orgin
    '       Flash_Page_length = 9 ' how many pages 
    '       Flash_Sec_Dest = Flash_Sec_Orgin          ' start at same page value as orgin
    '       Flash_Page_Dest = 20        
    '       gosub Flash_Page_Copy
     
    '---------- FLASH_MODIFY_BYTE TEST
        
     '   Data_Length = 10     ' changed data length
     '  For SDC_index = 0 to Data_Length  
     '      SDC_buffer[SDC_index] = SDC_index  ' fill the data buffer  with 0 - 255  values 
     '   next SDC_index 
        
     '   SDC_Block = 1  ' sector start 
     '   SDC_Page = 3    ' page start
     '   SDC_Byte = 16   ' byte star address   ($0f)
     '   gosub Flash_Byte_Modify
     
     ' Flash_Sec_Orgin = 0  ' copy sector 0 
     ' Flash_Sec_dest = 1   ' erase sector 1 destination  and copy data from flash orgin
     ' Flash_clear = 1  ' erase sector 0 after copy
      
     ' gosub Flash_Sec_Copy
     '  SDC_Block = 1 
     ' gosub  Flash_Test_RD
     ' pause 3000
    '  SDC_Block = 1 
    '  gosub  Flash_Test_RD
     
     ' return
    'Flash_protect_test:
    '  SDC_Block = 0
    '  gosub Flash_WR_protect 
    '  gosub Bsy_chk 
    '  gosub Flash_Read_ID
    'return
    
    
    
    
    
    
    
    
    
    
    
    
    
    JumpOverSPIFLASH:

  9. #9
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,276


    Did you find this post helpful? Yes | No

    Default Re: Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series

    Thanks for the code.

    Though I found it easier to use the cheap DF Player, using an SD-Card for the files. It is small, stereo and decodes mp3 and wav files. It also includes a power amp to drive speakers or line out to drive external speaker amplifier.

    Using it is dead simple. Either locally by push buttons or serially by a MCU.

    https://wiki.dfrobot.com/DFPlayer_Mi...R0299#target_3

    And here for the cheaper sell https://www.banggood.com/Geekcreit-D...ientCountry=GR

    Ioannis

  10. #10
    Join Date
    Feb 2012
    Location
    PERTH AUSTRALIA
    Posts
    838


    Did you find this post helpful? Yes | No

    Default Re: Spi flash example - 4kb/32kb/64kb erase support / winbond 25q series

    for my needs i have several winbond 4mb chips in circuit and they are programmed updated via the pic , with other chips accessing the same flash chips off the bus

    i thought about going sd cards , but for my requirement flash chips were a better option

Similar Threads

  1. Spi flash chip example - 8mb flash
    By longpole001 in forum Code Examples
    Replies: 6
    Last Post: - 1st August 2014, 11:00
  2. Flash erase byte routine
    By longpole001 in forum mel PIC BASIC Pro
    Replies: 20
    Last Post: - 24th June 2014, 04:36
  3. ISD1700 series Winbond chipcorder
    By rickeybell in forum mel PIC BASIC Pro
    Replies: 12
    Last Post: - 21st March 2010, 06:13
  4. PBP PIC32 series support?
    By foss in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 18th August 2008, 12:10
  5. Compact flash support,fat16 included...
    By Moldava in forum PBP Wish List
    Replies: 0
    Last Post: - 11th September 2004, 17:28

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts