Skip to content

Instantly share code, notes, and snippets.

@amaork
Created July 27, 2017 02:55
Show Gist options
  • Save amaork/4b62224ba32555f85b37b4f4cb58d824 to your computer and use it in GitHub Desktop.
Save amaork/4b62224ba32555f85b37b4f4cb58d824 to your computer and use it in GitHub Desktop.
Raspberry pi read/write winbond W25Q80 SPI Flash
import sys
from spidev import SpiDev
class SPIFlash(object):
READ_ID = 0x9f
READ_RS = 0x05
CHIP_ERASE = 0x60
PAGE_READ = 0x3
PAGE_WRITE = 0x2
WRITE_ENABLE = 0x6
WRITE_DISABLE = 0x4
# Flash attribute
W25Q80_MID = 0xEF
W25Q80_DID = 0x4014
FLASH_PAGE_SIZE = 256
FLASH_TOTAL_SIZE = 1024 * 1024
def __init__(self, bus, dev, speed):
"""Init a spi flash
:param bus: spi bus number
:param dev: spi device number
:param speed: spi speed unit khz
"""
try:
self.__spi = SpiDev()
self.__spi.open(bus, dev)
self.__spi.max_speed_hz = speed * 1000
print("Device:/dev/spidev{}.{}, speed:{}".format(bus, dev, speed))
except IOError:
raise("Do not found spi device:/dev/spidev{}.{}".format(bus, dev))
def __del__(self):
self.__spi.close()
def probe(self):
try:
data = self.__spi.xfer([self.READ_ID, 0, 0, 0])
return data[1], data[2] << 8 | data[3]
except IndexError:
return 0, 0
def erase(self):
# First enable write
self.__spi.xfer([self.WRITE_ENABLE])
# Second erase chip
self.__spi.xfer([self.CHIP_ERASE])
# Final wait chip erase done
while self.get_rs() & 0x1:
pass
def get_rs(self):
return self.__spi.xfer([self.READ_RS, 0])[1]
def read_page(self, page):
address = page * self.FLASH_PAGE_SIZE
# Msb first
cmd = [self.PAGE_READ, (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff]
return bytearray(self.__spi.xfer(cmd + [0] * self.FLASH_PAGE_SIZE)[4:])
def read_chip(self):
data = bytearray()
for page in range(self.FLASH_TOTAL_SIZE / self.FLASH_PAGE_SIZE):
data += self.read_page(page)
return data
def write_page(self, page, data):
address = page * self.FLASH_PAGE_SIZE
cmd = [self.PAGE_WRITE, (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff]
# First enable write
self.__spi.xfer([self.WRITE_ENABLE])
# Second write page data
self.__spi.xfer(cmd + data)
# Wait done
while self.get_rs() & 0x1:
pass
def write_chip(self, data, verify=False):
"""Write chip
:param data: data will write to chip
:param verify: verify data
:return:success return true else false
"""
# Check data len
if len(data) != self.FLASH_TOTAL_SIZE:
print("Data size error!")
return False
# First erase chip
self.erase()
# Convert data to list
data = list(data)
# Write data to page
for page in range(self.FLASH_TOTAL_SIZE / self.FLASH_PAGE_SIZE):
start = page * self.FLASH_PAGE_SIZE
write_buffer = map(ord, data[start: start + self.FLASH_PAGE_SIZE])
self.write_page(page, write_buffer)
if verify and bytearray(write_buffer) != self.read_page(page):
print("Verify error, page:{}".format(page))
return False
return True
if __name__ == "__main__":
flash = SPIFlash(0, 0, 8000)
# Get device manufacturer id and device id
mid, device_id = flash.probe()
print("Manufacturer ID:0x{0:X}, Device ID:0x{1:X}".format(mid, device_id))
if mid != SPIFlash.W25Q80_MID or device_id != SPIFlash.W25Q80_DID:
print("SPI Flash is not Winbond W25Q80")
sys.exit()
# Write RL6193_Project.bin to flash
with open("RL6193_Project.bin", "rb") as fp:
flash.write_chip(fp.read())
# Read data to flash.bin
with open("flash.bin", "wb") as fp:
fp.write(flash.read_chip())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment