-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathflash_phaser.py
115 lines (102 loc) · 3.92 KB
/
flash_phaser.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
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 Phaser:
def __init__(self, bus):
self.bus = bus
self.eeprom = chips.EEPROM(bus)
self.temp1 = chips.LM75(bus, 0x48)
self.temp2 = chips.LM75(bus, 0x49)
self.spi = chips.SPI(bus, 0x2a)
self.flash = chips.SPIFlash(self.spi, 0b0001)
def init(self):
self.spi.gpio_write(0b1000) # reset
self.spi.gpio_enable(0b1110) # all but select
self.spi.gpio_config(0b00, 0b01, 0b10, 0b01)
assert not self.spi.gpio_read() & 0b0010 # SPI disable
assert self.spi.gpio_read() & 0b0001 # SS deassert
assert self.spi.gpio_read() & 0b1000 # reset deassert
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, exc_info=True)
self.temp1.report()
self.temp2.report()
logging.info("gpio: %#02x", self.spi.gpio_read())
#logging.info("ident: %r", self.flash.read_identification())
#logging.info("status: %#02x", self.flash.read_status())
def creload(self, timeout=1):
self.spi.gpio_write(0b1000)
assert self.spi.gpio_read() & 0b1000 # reset
assert not self.spi.gpio_read() & 0b0100 # not done
assert self.spi.gpio_read() & 0b0001 # not select
self.spi.gpio_write(0b0000)
assert not self.spi.gpio_read() & 0b1000 # not reset
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(0b1010)
try:
self.flash.wakeup()
yield
finally:
self.spi.gpio_write(0b0001)
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="Phaser",
board=Sinara.boards.index("Phaser"),
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 = Phaser(bus)
b.init()
b.report()
action = sys.argv[3]
if action == "eeprom":
b.eeprom_update()
if False:
with b.flash_upd():
# b.report()
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())
b.creload()