2828import serial
2929import time
3030
31+
3132# Verbose level
3233QUIET = 20
3334
34- # these come from AN2606
35- chip_ids = {
35+ CHIP_IDS = {
36+ # see ST AN2606
3637 0x412 : "STM32 Low-density" ,
3738 0x410 : "STM32 Medium-density" ,
3839 0x414 : "STM32 High-density" ,
@@ -56,6 +57,27 @@ class CmdException(Exception):
5657
5758class CommandInterface :
5859
60+ class Command :
61+ # See ST AN3155
62+ GET = 0x00
63+ GET_VERSION = 0x01
64+ GET_ID = 0x02
65+ READ_MEMORY = 0x11
66+ GO = 0x21
67+ WRITE_MEMORY = 0x31
68+ ERASE = 0x43
69+ EXTENDED_ERASE = 0x44
70+ WRITE_PROTECT = 0x63
71+ WRITE_UNPROTECT = 0x73
72+ READOUT_PROTECT = 0x82
73+ READOUT_UNPROTECT = 0x92
74+
75+ class Reply :
76+ # See ST AN3155
77+ ACK = 0x79
78+ NACK = 0x1F
79+ EXTENDED_ERASE = 0x44
80+
5981 extended_erase = 0
6082
6183 def __init__ (self ):
@@ -73,24 +95,6 @@ def open(self, a_port='/dev/tty.usbserial-ftCYPMYJ', a_baud_rate=115200):
7395 timeout = 5 # set a timeout value, None for waiting forever
7496 )
7597
76- def _wait_for_ask (self , info = "" ):
77- # wait for ask
78- try :
79- ask = self .serial .read ()[0 ]
80- except TypeError :
81- raise CmdException ("Can't read port or timeout" )
82- else :
83- if ask == 0x79 :
84- # ACK
85- return 1
86- else :
87- if ask == 0x1F :
88- # NACK
89- raise CmdException ("NACK " + info )
90- else :
91- # Unknown response
92- raise CmdException ("Unknown response. " + info + ": " + hex (ask ))
93-
9498 def reset (self ):
9599 self .serial .setDTR (0 )
96100 time .sleep (0.1 )
@@ -104,132 +108,116 @@ def init_chip(self):
104108
105109 # Syncro
106110 self .serial .write (b'\x7F ' )
107- return self ._wait_for_ask ("Syncro" )
111+ return self ._wait_for_ack ("Syncro" )
108112
109113 def release_chip (self ):
110114 self .serial .setRTS (1 )
111115 self .reset ()
112116
113- def generic (self , command ):
117+ def command (self , command ):
114118 command_byte = bytes ([command ])
115119 control_byte = bytes ([command ^ 0xFF ])
116120
117121 self .serial .write (command_byte )
118122 self .serial .write (control_byte )
119123
120- return self ._wait_for_ask (hex (command ))
124+ return self ._wait_for_ack (hex (command ))
121125
122126 def get (self ):
123- if not self .generic ( 0x00 ):
127+ if not self .command ( self . Command . GET ):
124128 raise CmdException ("Get (0x00) failed" )
125129 debug (10 , "*** Get interface" )
126130 length = self .serial .read ()[0 ]
127131 version = self .serial .read ()[0 ]
128132 debug (10 , " Bootloader version: " + hex (version ))
129- data = [ hex ( c ) for c in self .serial .read (length )]
130- if '0x44' in data :
133+ data = self .serial .read (length )
134+ if self . Reply . EXTENDED_ERASE in data :
131135 self .extended_erase = 1
132136 debug (10 , " Available commands: " + ", " .join (data ))
133- self ._wait_for_ask ("0x00 end" )
137+ self ._wait_for_ack ("0x00 end" )
134138 return version
135139
136140 def get_version (self ):
137- if not self .generic ( 0x01 ):
141+ if not self .command ( self . Command . GET_VERSION ):
138142 raise CmdException ("GetVersion (0x01) failed" )
139143
140144 debug (10 , "*** GetVersion interface" )
141145 version = self .serial .read ()[0 ]
142146 self .serial .read (2 )
143- self ._wait_for_ask ("0x01 end" )
147+ self ._wait_for_ack ("0x01 end" )
144148 debug (10 , " Bootloader version: " + hex (version ))
145149 return version
146150
147151 def get_id (self ):
148- if not self .generic ( 0x02 ):
152+ if not self .command ( self . Command . GET_ID ):
149153 raise CmdException ("GetID (0x02) failed" )
150154
151155 debug (10 , "*** GetID interface" )
152156 length = self .serial .read ()[0 ]
153157 id_data = self .serial .read (length + 1 )
154- self ._wait_for_ask ("0x02 end" )
158+ self ._wait_for_ack ("0x02 end" )
155159 _device_id = reduce (lambda x , y : x * 0x100 + y , id_data )
156160 return _device_id
157161
158- @staticmethod
159- def _encode_address (address ):
160- byte3 = (address >> 0 ) & 0xFF
161- byte2 = (address >> 8 ) & 0xFF
162- byte1 = (address >> 16 ) & 0xFF
163- byte0 = (address >> 24 ) & 0xFF
164- crc = byte0 ^ byte1 ^ byte2 ^ byte3
165- return bytes ([byte0 , byte1 , byte2 , byte3 , crc ])
166-
167162 def read_memory (self , address , length ):
168163 assert (length <= 256 )
169- if not self .generic ( 0x11 ):
164+ if not self .command ( self . Command . READ_MEMORY ):
170165 raise CmdException ("ReadMemory (0x11) failed" )
171166
172167 debug (10 , "*** ReadMemory interface" )
173168 self .serial .write (self ._encode_address (address ))
174- self ._wait_for_ask ("0x11 address failed" )
169+ self ._wait_for_ack ("0x11 address failed" )
175170 n = (length - 1 ) & 0xFF
176- crc = n ^ 0xFF
177- self .serial .write (bytes ([n , crc ]))
178- self ._wait_for_ask ("0x11 length failed" )
171+ checksum = n ^ 0xFF
172+ self .serial .write (bytes ([n , checksum ]))
173+ self ._wait_for_ack ("0x11 length failed" )
179174 return self .serial .read (length )
180175
181176 def go (self , address ):
182- if not self .generic ( 0x21 ):
177+ if not self .command ( self . Command . GO ):
183178 raise CmdException ("Go (0x21) failed" )
184179
185180 debug (10 , "*** Go interface" )
186181 self .serial .write (self ._encode_address (address ))
187- self ._wait_for_ask ("0x21 go failed" )
182+ self ._wait_for_ack ("0x21 go failed" )
188183
189184 def write_memory (self , address , data ):
190185 assert (len (data ) <= 256 )
191- if not self .generic ( 0x31 ):
186+ if not self .command ( self . Command . WRITE_MEMORY ):
192187 raise CmdException ("Write memory (0x31) failed" )
193188
194189 debug (10 , "*** Write memory interface" )
195190 self .serial .write (self ._encode_address (address ))
196- self ._wait_for_ask ("0x31 address failed" )
191+ self ._wait_for_ack ("0x31 address failed" )
197192 length = (len (data )- 1 ) & 0xFF
198193 debug (10 , " %s bytes to write" % [length + 1 ])
199194 self .serial .write (bytes ([length ]))
200- crc = 0xFF
195+ checksum = 0xFF
201196 for c in data :
202- crc = crc ^ c
197+ checksum = checksum ^ c
203198 self .serial .write (bytes ([c ]))
204- self .serial .write (bytes ([crc ]))
205- self ._wait_for_ask ("0x31 programming failed" )
199+ self .serial .write (bytes ([checksum ]))
200+ self ._wait_for_ack ("0x31 programming failed" )
206201 debug (10 , " Write memory done" )
207202
208203 def erase_memory (self , sectors = None ):
209204 if self .extended_erase :
210205 return interface .extended_erase_memory ()
211206
212- if not self .generic ( 0x43 ):
207+ if not self .command ( self . Command . ERASE ):
213208 raise CmdException ("Erase memory (0x43) failed" )
214209
215210 debug (10 , "*** Erase memory interface" )
216- if sectors is None :
217- # Global erase and checksum byte
218- self .serial .write (b'\xff ' )
219- self .serial .write (b'\x00 ' )
211+
212+ if sectors :
213+ self ._page_erase (sectors )
220214 else :
221- # Sectors erase
222- self .serial .write (bytes ([(len (sectors ) - 1 ) & 0xFF ]))
223- crc = 0xFF
224- for c in sectors :
225- crc = crc ^ c
226- self .serial .write (bytes ([c ]))
227- self .serial .write (bytes ([crc ]))
228- self ._wait_for_ask ("0x43 erasing failed" )
215+ self ._global_erase ()
216+ self ._wait_for_ack ("0x43 erase failed" )
229217 debug (10 , " Erase memory done" )
230218
231219 def extended_erase_memory (self ):
232- if not self .generic ( 0x44 ):
220+ if not self .command ( self . Command . EXTENDED_ERASE ):
233221 raise CmdException ("Extended Erase memory (0x44) failed" )
234222
235223 debug (10 , "*** Extended Erase memory interface" )
@@ -240,54 +228,51 @@ def extended_erase_memory(self):
240228 tmp = self .serial .timeout
241229 self .serial .timeout = 30
242230 print ("Extended erase (0x44), this can take ten seconds or more" )
243- self ._wait_for_ask ("0x44 erasing failed" )
231+ self ._wait_for_ack ("0x44 erasing failed" )
244232 self .serial .timeout = tmp
245233 debug (10 , " Extended Erase memory done" )
246234
247235 def write_protect (self , sectors ):
248- if not self .generic ( 0x63 ):
236+ if not self .command ( self . Command . WRITE_PROTECT ):
249237 raise CmdException ("Write Protect memory (0x63) failed" )
250238
251239 debug (10 , "*** Write protect interface" )
252240 self .serial .write (bytes ([((len (sectors ) - 1 ) & 0xFF )]))
253- crc = 0xFF
241+ checksum = 0xFF
254242 for c in sectors :
255- crc = crc ^ c
243+ checksum = checksum ^ c
256244 self .serial .write (bytes ([c ]))
257- self .serial .write (bytes ([crc ]))
258- self ._wait_for_ask ("0x63 write protect failed" )
245+ self .serial .write (bytes ([checksum ]))
246+ self ._wait_for_ack ("0x63 write protect failed" )
259247 debug (10 , " Write protect done" )
260248
261249 def write_unprotect (self ):
262- if not self .generic ( 0x73 ):
250+ if not self .command ( self . Command . WRITE_UNPROTECT ):
263251 raise CmdException ("Write Unprotect (0x73) failed" )
264252
265253 debug (10 , "*** Write Unprotect interface" )
266- self ._wait_for_ask ("0x73 write unprotect failed" )
267- self ._wait_for_ask ("0x73 write unprotect 2 failed" )
254+ self ._wait_for_ack ("0x73 write unprotect failed" )
255+ self ._wait_for_ack ("0x73 write unprotect 2 failed" )
268256 debug (10 , " Write Unprotect done" )
269257
270258 def readout_protect (self ):
271- if not self .generic ( 0x82 ):
259+ if not self .command ( self . Command . READOUT_PROTECT ):
272260 raise CmdException ("Readout protect (0x82) failed" )
273261
274262 debug (10 , "*** Readout protect interface" )
275- self ._wait_for_ask ("0x82 readout protect failed" )
276- self ._wait_for_ask ("0x82 readout protect 2 failed" )
263+ self ._wait_for_ack ("0x82 readout protect failed" )
264+ self ._wait_for_ack ("0x82 readout protect 2 failed" )
277265 debug (10 , " Read protect done" )
278266
279267 def readout_unprotect (self ):
280- if not self .generic ( 0x92 ):
268+ if not self .command ( self . Command . READOUT_UNPROTECT ):
281269 raise CmdException ("Readout unprotect (0x92) failed" )
282270
283271 debug (10 , "*** Readout Unprotect interface" )
284- self ._wait_for_ask ("0x92 readout unprotect failed" )
285- self ._wait_for_ask ("0x92 readout unprotect 2 failed" )
272+ self ._wait_for_ack ("0x92 readout unprotect failed" )
273+ self ._wait_for_ack ("0x92 readout unprotect 2 failed" )
286274 debug (10 , " Read Unprotect done" )
287275
288-
289- # Complex commands section
290-
291276 def read_memory_data (self , address , length ):
292277 data = bytearray ()
293278 while length > 256 :
@@ -313,6 +298,44 @@ def write_memory_data(self, address, data):
313298 debug (5 , "Write %(len)d bytes at 0x%(address)X" % {'address' : address , 'len' : 256 })
314299 self .write_memory (address , data [offs :offs + length ] + (b'\xff ' * (256 - length )))
315300
301+ def _global_erase (self ):
302+ # global erase: n=255, see ST AN3155
303+ self .serial .write (b'\xff ' )
304+ self .serial .write (b'\x00 ' )
305+
306+ def _page_erase (self , pages ):
307+ # page erase, see ST AN3155
308+ nr_of_pages = (len (pages ) - 1 ) & 0xFF
309+ self .serial .write (bytes ([nr_of_pages ]))
310+ checksum = 0xFF
311+ for page_number in pages :
312+ self .serial .write (bytes ([page_number ]))
313+ checksum = checksum ^ page_number
314+ self .serial .write (bytes ([checksum ]))
315+
316+ def _wait_for_ack (self , info = "" ):
317+ try :
318+ ack = self .serial .read ()[0 ]
319+ except TypeError :
320+ raise CmdException ("Can't read port or timeout" )
321+
322+ if ack == self .Reply .NACK :
323+ raise CmdException ("NACK " + info )
324+
325+ if ack != self .Reply .ACK :
326+ raise CmdException ("Unknown response. " + info + ": " + hex (ack ))
327+
328+ return 1
329+
330+ @staticmethod
331+ def _encode_address (address ):
332+ byte3 = (address >> 0 ) & 0xFF
333+ byte2 = (address >> 8 ) & 0xFF
334+ byte1 = (address >> 16 ) & 0xFF
335+ byte0 = (address >> 24 ) & 0xFF
336+ checksum = byte0 ^ byte1 ^ byte2 ^ byte3
337+ return bytes ([byte0 , byte1 , byte2 , byte3 , checksum ])
338+
316339
317340def usage ():
318341 print ("""Usage: %s [-hqVewvr] [-l length] [-p port] [-b baud] [-a address] [-g address] [file.bin]
@@ -410,7 +433,7 @@ def usage():
410433 boot_version = interface .get ()
411434 debug (0 , "Bootloader version %X" % boot_version )
412435 device_id = interface .get_id ()
413- debug (0 , "Chip id: 0x%x (%s)" % (device_id , chip_ids .get (device_id , "Unknown" )))
436+ debug (0 , "Chip id: 0x%x (%s)" % (device_id , CHIP_IDS .get (device_id , "Unknown" )))
414437# interface.get_version()
415438# interface.get_id()
416439# interface.readout_unprotect()
0 commit comments