Quantcast
Channel: MEL PICBASIC Forum
Viewing all articles
Browse latest Browse all 4745

Spi flash chip example - 8mb flash

$
0
0
Hi guys ,

I had a need to add a flash chip to a project

I could not find any sample of code on the site or elsewhere for Flash routines and use , and i hate having to redo the wheel if i dont have to

so now you dont have to - as much

This code works and is designed for 8mb Flash - M25P80 chip , at 75mhz

the code runs on a 64mhz 18F cpu , and software SPI ( for the Moment )
spi pins, chip select are done else where but it easy to add to this section
this code is used as an include to another core program .

The code will change to suite the duel /quad spi chip range 25Q80 series some time
No use of the "HOLD" PIN is supported at this time

the W and Hold Pins are tied High , but allows for the W pin to be tied low to lock sectors

it use the same name variables from the SDFS3 , so take care to consider the issues when using both., but double use of the defined buffers on both programs works

this code will change as other chips are used

hope it helps someone else avoid the days it took me

regards

Sheldon

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:


Viewing all articles
Browse latest Browse all 4745

Trending Articles