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