-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathspiflash.py
119 lines (100 loc) · 2.88 KB
/
spiflash.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#
# spiflash.py
#
# Adapted from https://github.com/manitou48/pyboard
#
# SPI flash http://www.adafruit.com/product/1564
# SPI 1 42mhz max SPI 2 21 mhz max
# SPI1 X5-X8 CS CLK MISO MOSI 3.3v grnd
__all__ = ('SPIFLash',)
from micropython import const
CMD_JEDEC_ID = const(0x9F)
CMD_READ_STATUS = const(0x05) # Read status register
CMD_READ = const(0x03) # Read @ low speed
CMD_READ_HI_SPEED = const(0x0B) # Read @ high speed
CMD_WRITE_ENABLE = const(0x06) # Write enable
CMD_PROGRAM_PAGE = const(0x02) # Write page
CMD_ERASE_4K = const(0x20)
CMD_ERASE_32K = const(0x52)
CMD_ERASE_64K = const(0xD8)
CMD_ERASE_CHIP = const(0xC7)
CMD_READ_UID = const(0x4B)
PAGE_SIZE = const(256)
COMMANDS = {
'4k': CMD_ERASE_4K,
'32k': CMD_ERASE_32K,
'64k': CMD_ERASE_64K
}
class SPIFlash:
def __init__(self, spi, cs):
self._spi = spi
self._cs = cs
self._cs.high()
self._buf = bytearray([0])
def _write(self, val):
if isinstance(val, int):
self._buf[0] = val
self._spi.write(self._buf)
else:
self._spi.write(val)
def read_block(self, addr, buf):
self._cs.low()
self._write(CMD_READ)
self._write(addr >> 16)
self._write(addr >> 8)
self._write(addr)
self._spi.readinto(buf)
self._cs.high()
def getid(self):
self._cs.low()
self._write(CMD_JEDEC_ID) # id
res = self._spi.read(3)
self._cs.high()
return res
def wait(self):
while True:
self._cs.low()
self._write(CMD_READ_STATUS)
r = self._spi.read(1)[0]
self._cs.high()
if r == 0:
return
def write_block(self, addr, buf):
# Write in 256-byte chunks
# XXX: Should check that write doesn't go past end of flash ...
length = len(buf)
pos = 0
while pos < length:
size = min(length - pos, PAGE_SIZE)
self._cs.low()
self._write(CMD_WRITE_ENABLE)
self._cs.high()
self._cs.low()
self._write(CMD_PROGRAM_PAGE)
self._write(addr >> 16)
self._write(addr >> 8)
self._write(addr)
self._write(buf[pos:pos + size])
self._cs.high()
self.wait()
addr += size
pos += size
def erase(self, addr, cmd):
self._cs.low()
self._write(CMD_WRITE_ENABLE)
self._cs.high()
self._cs.low()
self._write(COMMANDS[cmd])
self._write(addr >> 16)
self._write(addr >> 8)
self._write(addr)
self._cs.high()
self.wait()
def erase_chip(self):
self._cs.low()
self._write(CMD_WRITE_ENABLE)
self._cs.high()
self._cs.low()
self._write(CMD_ERASE_CHIP)
self._cs.high()
self.wait()