5
5
:author: Emmanuel Blot <eblot@rivosinc.com>
6
6
"""
7
7
8
- # Copyright (c) 2024 Rivos, Inc.
8
+ # Copyright (c) 2024-2025 Rivos, Inc.
9
9
# SPDX-License-Identifier: Apache2
10
10
11
11
from argparse import ArgumentParser , FileType
14
14
from os .path import dirname , join as joinpath , normpath
15
15
from time import sleep , time as now
16
16
from traceback import format_exc
17
+ from typing import Optional
17
18
import sys
18
19
19
20
QEMU_PYPATH = joinpath (dirname (dirname (dirname (normpath (__file__ )))),
@@ -35,9 +36,30 @@ def __init__(self):
35
36
self ._log = getLogger ('spidev.flash' )
36
37
self ._spidev = SpiDevice ()
37
38
38
- def connect (self , host : str , port : int ):
39
- """Connect to the remote SPI device and wait for sync."""
40
- self ._spidev .connect (host , port )
39
+ def connect (self , host : str , port : Optional [int ], retry_count : int = 1 ,
40
+ sync_time : Optional [float ] = None ):
41
+ """Connect to the remote SPI device and wait for sync.
42
+
43
+ :param host: a hostname or a connection string
44
+ :param port: a TCP port, should be None if a connection string is
45
+ defined
46
+ :param retry_count: how many attempts should be made at most to
47
+ coonnect to the remote peer (once per second)
48
+ :param sync_time: max allowed synchronization time once a connection
49
+ is established to receive a valid JEDEC ID.
50
+
51
+ Supported connection string format:
52
+ - tcp:<host>:<port>
53
+ - unix:<path>
54
+ """
55
+ while True :
56
+ try :
57
+ self ._spidev .connect (host , port )
58
+ break
59
+ except TimeoutError :
60
+ retry_count -= 1
61
+ if not retry_count :
62
+ raise
41
63
self ._wait_for_remote ()
42
64
43
65
def disconnect (self ):
@@ -95,12 +117,14 @@ def main():
95
117
help = 'Binary file to flash' )
96
118
argparser .add_argument ('-a' , '--address' , type = HexInt .parse ,
97
119
default = '0' ,
98
- help = 'Address in the SPI flash (default to 0)' )
120
+ help = 'Address in the SPI flash (default: 0)' )
121
+ argparser .add_argument ('-S' , '--socket' ,
122
+ help = 'connection string' )
123
+ argparser .add_argument ('-R' , '--retry-count' , type = int , default = 1 ,
124
+ help = 'connection retry count (default: 1)' )
99
125
argparser .add_argument ('-r' , '--host' ,
100
- default = '127.0.0.1' ,
101
126
help = 'remote host name (default: localhost)' )
102
127
argparser .add_argument ('-p' , '--port' , type = int ,
103
- default = SpiDeviceFlasher .DEFAULT_PORT ,
104
128
help = f'remote host TCP port (defaults to '
105
129
f'{ SpiDeviceFlasher .DEFAULT_PORT } )' )
106
130
argparser .add_argument ('-v' , '--verbose' , action = 'count' ,
@@ -113,7 +137,15 @@ def main():
113
137
configure_loggers (args .verbose , 'spidev' )
114
138
115
139
flasher = SpiDeviceFlasher ()
116
- flasher .connect (args .host , args .port )
140
+ if args .socket :
141
+ if any ((args .host , args .port )):
142
+ argparser .error ('Connection string is mutually exclusive '
143
+ 'with host and port' )
144
+ flasher .connect (args .socket , None , retry_count = args .retry_count )
145
+ else :
146
+ flasher .connect (args .host or 'localhost' ,
147
+ args .port or SpiDeviceFlasher .DEFAULT_PORT ,
148
+ retry_count = args .retry_count )
117
149
data = args .file .read ()
118
150
args .file .close ()
119
151
flasher .program (data , args .address )
0 commit comments