-
Notifications
You must be signed in to change notification settings - Fork 5
/
flash_fastino.py
122 lines (108 loc) · 4.21 KB
/
flash_fastino.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
120
121
122
import logging
import sys
import time
from contextlib import contextmanager
from sinara import Sinara
from kasli import Kasli
import chips
logger = logging.getLogger(__name__)
class Fastino:
def __init__(self, bus):
self.bus = bus
self.eeprom = chips.EEPROM(bus)
self.temp1 = chips.LM75(bus, 0x48)
self.spi = chips.SPI(bus, 0x2a)
self.flash = chips.SPIFlash(self.spi, 0b0001)
def init(self):
self.spi.gpio_enable(0b1110) # use as GPIO
# ssel bidir (ignored), spi_en: push-pull, cdone: input, creset: bidir
self.spi.gpio_config(0b00, 0b01, 0b10, 0b01)
self.spi.gpio_write(0b1000) # GPIO output values
i = self.spi.gpio_read()
assert not i & 0b0010 # SPI disable
assert i & 0b0001 # SS deassert
assert i & 0b1000 # CRESET deassert
# MSB-first, CPOL/CPHA=00, 1.8 MHz
self.spi.configure(order=0, mode=0, f=0)
def report(self):
ee = self.eeprom.dump()
try:
logger.info("Sinara eeprom valid %s", Sinara.unpack(ee))
except:
logger.error("eeprom data invalid %r", ee)
self.temp1.report()
logging.info("gpio: %#02x", self.spi.gpio_read())
def report_flash(self):
logging.info("ident: %r", self.flash.read_identification())
logging.info("status: %#02x", self.flash.read_status())
def creload(self, timeout=.5):
self.spi.gpio_write(0b0000) # CRESET
i = self.spi.gpio_read()
assert not self.spi.gpio_read() & 0b1100, i # CRESET assert, not CDONE
self.spi.gpio_write(0b1000) # no CRESET
assert self.spi.gpio_read() & 0b1000 # CRESET deassert
t = time.monotonic()
while not self.spi.gpio_read() & 0b0100: # not CDONE
if time.monotonic() - t > timeout:
raise ValueError("cdone timeout")
logger.info("creload took %g s", time.monotonic() - t)
@contextmanager
def flash_upd(self):
# freeze it while loading
self.spi.gpio_write(0b0000) # assert CRESET
self.spi.gpio_write(0b1000) # deassert CRESET
self.spi.gpio_write(0b0000) # assert CRESET
self.spi.gpio_write(0b0010) # assert FLASH_UPD_EN
try:
self.flash.wakeup()
yield
self.flash.write_disable()
self.flash.power_down()
finally:
self.spi.gpio_write(0b1000)
self.spi.idle()
def dump(self, fil, length=0x22000, offset=0):
with open(fil, "wb") as fil:
for i in range(offset, offset + length, 196):
logger.info("read %s/%s", i, length)
fil.write(self.flash.read_data_bytes(i, 196))
def eeprom_update(self, **kwargs):
eui48 = self.eeprom.eui48()
logger.info("eui48 %s", self.eeprom.fmt_eui48())
ee_data = Sinara(
name="Fastino",
board=Sinara.boards.index("Fastino"),
major=1, minor=0, variant=0, port=0,
vendor=Sinara.vendors.index("QUARTIQ"),
vendor_data=Sinara._defaults.vendor_data)
kwargs["eui48"] = eui48
data = ee_data._replace(**kwargs)
self.eeprom.write(0, data.pack()[:128])
open("data/{}.bin".format(self.eeprom.fmt_eui48(eui48)),
"wb").write(data.pack())
try:
logger.info("data readback valid %s",
Sinara.unpack(self.eeprom.dump()))
except:
logger.error("data readback invalid", exc_info=True)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
serial = sys.argv[1]
logger.info("serial: %s", serial)
url = "ftdi://ftdi:4232h:{}/2".format(serial)
with Kasli().configure(url) as bus, bus.enabled(sys.argv[2]):
b = Fastino(bus)
b.report()
b.init()
action = sys.argv[3]
if action == "eeprom":
b.eeprom_update()
if True:
with b.flash_upd():
b.report_flash()
if action == "read":
b.dump(sys.argv[4])
elif action == "write":
with open(sys.argv[4], "rb") as fil:
b.flash.flash(0, fil.read(), verify=False)
b.creload()