Code:
	'*  Notes   : writen for M25P80 8Mbit or simular                                         *
'*          : support of duel / quad options not as yet                                  *
'*          :3.3v - NOT 5V input tollerant                                               *
'*          : Code supports Software Protection of data , hardware WP and Hold pins high *
'*****************************************************************************************
'*  Revision:                                                                            *
'*                                                                                       *
'*                                                                                       *
'*                                                                                       *
'*                                                                                       *
'*                                                                                       *
'*****************************************************************************************
'                                                                                        *
'----------------------------------------------------------------------------------------*
'                                                                                        *
' Operational Notes on Timing Max and Min times                                          *
' =============================================                                          *
'                                                                                        *
'   1. powerup delay to CE & WR = 10ms max -1ms min                                      *
'   2. 256 bytes max per read / write                                                    *
'   3. spi bus and flash CE configures in main program                                   *
'   4. avg is 15ma during write /erase, 8ma for read                                     *
'   5. min 100ns  on CE deselect                                                         *
'   6. SPI chip interface timing has min of 10ns requirements , so no timing issues      *
'       for picbasic which has a min of 2us using shiftout cmd                           *
'                                                                                        *
'----------------------------------------------------------------------------------------*
 '----------SPI FLASH (M25P80) commands---------------------------------------------------
 '             SDC_cmd, SDC_CmdCode
 ' command 1-7 use the Write enable command ---
 Flash_Wr_reg   con 1 ' $01       'def write the Status Register  
 Flash_WR       con 2 ' $02       'def Page Program mode command  1- 256 bytes 
 Flash_Sec_Ers  con 3 ' $D8       'def Sector Erase command 
 Flash_Bulk_Ers con 4 ' $C7       'def Bulk Erase command 
 Flash_PWR_Dwn  con 5 ' $B9       'def Deep Power Down command
 Flash_Rd_Sign  con 6 ' $9E       'def read device signature - 1 byte RES COMMAND (13h)
  
 Flash_RD       con 7 ' $03       'def read data at normal speed 
 Flash_Rd_HS    con 8 ' $0B       'def read data at High speed 
 Flash_Rd_ID    con 9 ' $9F       'def Read manufacture/ device/UID codes upto 20 bytes 
 Flash_PWR_Up   con 10' $AB       'def Release From Deep Power Down command  
 '---- not in command lookup table - used directly -----
 Flash_Wr_dis   CON $04        'def write disable command 
 Flash_Rd_reg   con $05        'def read the Status Register 
 Flash_Wr_en    con $06        'def write Enable command   
 
' ---------- 8mb 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  Var Long       ' address sent to FLASH - may use  page  and sector varables to form address ?
 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_Sector   var byte       ' Sector address
 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_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 
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
    ' bug seems to return $FF in status register on first write access otherwise ???  
    
        FLASH_CE = 0                                  ' Bring the FLASH chip select line low  
         SDC_data_out = Flash_Rd_reg                  ' 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 low  
  return                                                        
 
 Flash_Format:
 'Note wont work if any sectors are protected 
  ' can take upto 20sec on 8mbit chip 
   sdc_cmd = Flash_Bulk_ers  ' excutes as it sounds
   gosub Flash_Comand 
 return
 
 
 Flash_Sec_Erase: 
  ' assumes sector address only 
  ' erases 1 sector at a time  address 
  ' Erases wont work on sectors that are write protected 
  ' sector erase take 600ms per instruction 
   sdc_cmd = Flash_Sec_Ers          ' Erases  sector ( 256 pages x 256 bytes ) 
   SDC_address.byte2 = SDC_Sector   ' set sector Address 0 to 15 for 8mb chip
   SDC_address.byte1 = 0            ' set page start address 0 to 255  
   SDC_address.byte0 = 0            ' set byte start address 0 to 255
   gosub Flash_Comand               ' Do the command 
 return
 
 
 Flash_Write: 
  ' assumes data length , address and upto 256 bytes in  SDC_buffer[] to send 
  ' writes bytes from SDC_buffer[] into flash , Sector/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.byte2 = SDC_Sector   ' set sector Address 0 to 15 for 8mb chip
   SDC_address.byte1 = SDC_Page     ' set page start address 0 to 255  
   SDC_address.byte0 = SDC_byte     ' set byte start address 0 to 255
   gosub Flash_Comand 
  return
 
 Flash_Read: 
  ' assumes data length input 
  ' gets upto bytes data into SDC_buffer[] from flash 
  ' uses normal read speed 
   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.byte2 = SDC_Sector   ' set sector Address 0 to 15 for 8mb chip
   SDC_address.byte1 = SDC_Page     ' set page start address 0 to 255  
   SDC_address.byte0 = SDC_byte     ' set byte start address 0 to 255
   gosub Flash_Comand
  return
 
 Flash_WR_protect:
 ' assumes sector protect block value - input sector block to protect 
 ' Sets Hardware protect bit 7 = 1 at same time , so HW protect can be used 
 '  bits7 = 1 HW protect enable ,bit6,5 = n/a  bit4-2 = sector protect select , bit1,0 = n/a
  
    sdc_cmd = Flash_Wr_reg  ' write register 
    data_length = 0        ' set 0 = 1 byte  
    if SDC_Sector = 0  then  SDC_buffer[0] =  $80                   ' proctects no sectors   bit 7 = 1 ,bits4-2= 000
    if SDC_Sector = 15 then  SDC_buffer[0] =  $84                   ' protect sector  15     bit 7 = 1 ,bits4-2= 001
    if SDC_Sector = 14 then  SDC_buffer[0] =  $88                   ' protects sector 14-15  bit 7 = 1 ,bits4-2= 010
    if SDC_Sector = 12 then  SDC_buffer[0] =  $8C                   ' protects sector 12-15  bit 7 = 1 ,bits4-2= 011
    if SDC_Sector = 8  then  SDC_buffer[0] =  $90                   ' protects sector 8 -15  bit 7 = 1 ,bits4-2= 100
    if SDC_Sector >0 and SDC_Sector < 8  then  SDC_buffer[0] = $94  ' protects All sectors   bit 7 = 1 ,bits4-2= 101
    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_reg                 ' 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 manufacture ID- 1byte,memory type 1 byte, memcapacity 1 byte , CFD length 1 byte , CFD bytes 16 bytes   
  ' need only first 3 bytes  for size calaculation of other devices later maybe 
    sdc_cmd =  Flash_Rd_ID   ' read id register 
    data_length = 2        ' 2 = 3 bytes  
    gosub Flash_Comand
    Flash_Manf_id =  SDC_buffer[0]
    Flash_Manf_type = SDC_buffer[1] 
    Flash_Manf_cap  = SDC_buffer[2]
    HSEROUT ["Flash_Manf_id = ",hex Flash_Manf_id,"Flash_Manf_type = ",hex Flash_Manf_type,"Flash_Manf_cap = ",hex Flash_Manf_cap,13,10]  ' debug
  return   
 
  Flash_Power_Down:
 ' sEt Flash chip to low power mode from standby mode - no command other tha powerup will wake the device 
    sdc_cmd =   Flash_PWR_Dwn   ' send the powerdown command  
    gosub Flash_Comand
  return
  
  Flash_Power_Up:
 ' sEt Flash chip to standby mode - no command other tha powerup will wake the device 
    sdc_cmd =   Flash_PWR_Up   ' send the powerUp command  
    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,$02,$D8,$C7,$B9,$9E,$03,$0B,$9F,$AB],SDC_CmdCode ' asignes command code to flash chip  
  
      Flash_tmp = 0                        ' ensure 0 - counter for busychk loop
     if SDC_cmd <=6 then gosub BSY_chk     ' do for writes, byte erase, sector erase,bulk erase , write reg protect , deep power down , signature read  
                                           ' test if Chip is busy writing
            
     if SDC_cmd <=4 then                   ' do for writes, sector erase,bulk erase , write reg protect 
        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 high to complete the write command 
     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 =>2 and SDC_cmd <=3 or _    ' if commands 2= Page write 3= Sector Erase,
        SDC_cmd =>6 and SDC_cmd <=7 then    ' or 7= read data normalspeed or 8 read data at Highspeed then set given address 
          SDC_data_out = SDC_address.Byte2     ' set sector Address 0 to 15 for 8mb chip
 	      Gosub Flash_spiw		               ' Write Byte SDC_data_out.
 	      SDC_data_out = SDC_address.Byte1     ' set page address 0 to 255  
 	      Gosub Flash_spiw	                   ' Write Byte SDC_data_out.
 	      SDC_data_out = SDC_address.Byte0     ' set byte address 0 to 255
          Gosub Flash_spiw		               ' Write Byte SDC_data_out.
          if SDC_cmd = 7 then                  ' read High speed mode 
             SDC_data_out = SDC_address.Byte0  ' used as dummy byte  for read High speed mode 
             Gosub Flash_spiw		           ' Write Byte SDC_data_out.
          endif
      endif
    
      if SDC_cmd <=2 or _                        ' if commands 1= write Register , 2= Page write ,3= byte erase
         SDC_cmd >=6 and SDC_cmd <= 9 then       ' or 6= read signature byte, 7=read data normalspeed, 8= read data at Highspeed , 9=read ID    
                                                 ' allow for data in/out buffer use
          For SDC_index = 0 To Data_Length 
              if SDC_cmd <= 2 then                       ' if write or Write 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 =>6 and SDC_cmd <=9 then       ' if 6= read signature byte, 7=read data normalspeed, 8= read data at Highspeed , 9=read ID
                 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
    
     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_reg                 ' Send the read status register command byte
 	    Gosub Flash_spiw	                        ' Write Byte SDC_data_out. , subroutine writes a byte on the SPI bus 
                         
       while  Flash_tmp <150                         '  loop test read        
         gosub Flash_SPIR  	                           ' Read Byte SDC_data_in from SPI bus.  Returns SDC_data_in.
         HSEROUT ["BSY-CHK = ",hex SDC_data_in,13,10]  ' debug
         HSEROUT ["Flash_tmp = ",dec2 Flash_tmp,13,10] ' debug
         Flash_tmp = Flash_tmp + 1 
         SDC_data_in =  SDC_data_in & $01 
         if  SDC_data_in = 0 then Flash_tmp = 151   ' Test bit 1 if write not busy,force exit of loop
       wend                  
       Flash_tmp = 0                                   ' clear counter
       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:
 
				
Bookmarks