Mercurial > lcfOS
comparison python/stlink.py @ 119:f51791638cae
Simplified flashing
author | Windel Bouwman |
---|---|
date | Sat, 12 Jan 2013 10:23:33 +0100 |
parents | f2b37d78082d |
children | 347d7d8b96c0 |
comparison
equal
deleted
inserted
replaced
118:db8aafe00d27 | 119:f51791638cae |
---|---|
114 sectors.append((sectornum, sectorsize)) | 114 sectors.append((sectornum, sectorsize)) |
115 off += sectorsize | 115 off += sectorsize |
116 return sectors | 116 return sectors |
117 | 117 |
118 class STLink: | 118 class STLink: |
119 def __init__(self): | 119 """ ST link interface code """ |
120 self.context = UsbContext() | 120 def __init__(self, stlink2=None): |
121 if not stlink2: | |
122 context = UsbContext() | |
123 stlink2s = list(filter(checkDevice, context.DeviceList)) | |
124 if not stlink2s: | |
125 raise STLinkException('Could not find an ST link') | |
126 if len(stlink2s) > 1: | |
127 print('More then one stlink2 found, picking first one') | |
128 stlink2 = stlink2s[0] | |
129 self.stlink2 = stlink2 | |
121 def open(self): | 130 def open(self): |
122 context = UsbContext() | 131 self.devHandle = self.stlink2.open() |
123 stlink2s = list(filter(checkDevice, context.DeviceList)) | |
124 if not stlink2s: | |
125 raise STLinkException('Could not find an ST link') | |
126 if len(stlink2s) > 1: | |
127 print('More then one stlink2 found, picking first one') | |
128 stlink2 = stlink2s[0] | |
129 self.devHandle = stlink2.open() | |
130 if self.devHandle.Configuration != 1: | 132 if self.devHandle.Configuration != 1: |
131 self.devHandle.Configuration = 1 | 133 self.devHandle.Configuration = 1 |
132 self.devHandle.claimInterface(0) | 134 self.devHandle.claimInterface(0) |
133 | 135 |
134 # First initialization: | 136 # First initialization: |
243 | 245 |
244 # erase required space | 246 # erase required space |
245 sectors = calcSectors(address, len(content)) | 247 sectors = calcSectors(address, len(content)) |
246 print('erasing {0} sectors'.format(len(sectors))) | 248 print('erasing {0} sectors'.format(len(sectors))) |
247 for sector, secsize in sectors: | 249 for sector, secsize in sectors: |
248 print('erasing sector {0} of size {1}'.format(sector, secsize)) | 250 print('erasing sector {0} of {1} bytes'.format(sector, secsize)) |
249 self.eraseFlashSector(sector) | 251 self.eraseFlashSector(sector) |
250 | 252 |
251 # program pages: | 253 # program pages: |
252 self.initFlashLoader() | |
253 self.unlockFlashIf() | 254 self.unlockFlashIf() |
254 self.writeFlashCrPsiz(2) | 255 self.writeFlashCrPsiz(2) # writes are 32 bits aligned |
255 self.setFlashCrPg() | 256 self.setFlashCrPg() |
256 | 257 |
258 print('writing {0} bytes'.format(len(content)), end='') | |
257 offset = 0 | 259 offset = 0 |
260 t1 = time.time() | |
258 while offset < len(content): | 261 while offset < len(content): |
259 size = len(content) - offset | 262 size = len(content) - offset |
260 if size > 0x8000: | 263 if size > 0x8000: |
261 size = 0x8000 | 264 size = 0x8000 |
262 | 265 |
263 self.runFlashLoader(address + offset, content[offset:offset + size]) | 266 chunk = content[offset:offset + size] |
267 while len(chunk) % 4 != 0: | |
268 print('padding chunk') | |
269 chunk = chunk + bytes([0]) | |
270 | |
271 # Use simple mem32 writes: | |
272 self.write_mem32(address + offset, chunk) | |
273 | |
264 offset += size | 274 offset += size |
275 print('.', end='', flush=True) | |
276 t2 = time.time() | |
277 print('Done!') | |
278 print('Speed: {0} bytes/second'.format(len(content)/(t2-t1))) | |
265 | 279 |
266 self.lockFlash() | 280 self.lockFlash() |
267 | 281 |
268 # verfify program: | 282 # verfify program: |
269 self.verifyFlash(address, content) | 283 self.verifyFlash(address, content) |
285 def verifyFlash(self, address, content): | 299 def verifyFlash(self, address, content): |
286 device_content = self.readFlash(address, len(content)) | 300 device_content = self.readFlash(address, len(content)) |
287 ok = content == device_content | 301 ok = content == device_content |
288 print('Verify:', ok) | 302 print('Verify:', ok) |
289 def readFlash(self, address, size): | 303 def readFlash(self, address, size): |
290 print('reading', address, size) | 304 print('Reading {1} bytes from 0x{0:X}'.format(address, size), end='') |
291 offset = 0 | 305 offset = 0 |
292 tmp_size = 0x1800 | 306 tmp_size = 0x1800 |
293 t1 = time.time() | 307 t1 = time.time() |
294 image = bytes() | 308 image = bytes() |
295 while offset < size: | 309 while offset < size: |
310 | 324 |
311 # increase for next piece: | 325 # increase for next piece: |
312 offset += tmp_size | 326 offset += tmp_size |
313 t2 = time.time() | 327 t2 = time.time() |
314 assert size == len(image) | 328 assert size == len(image) |
315 print('done! {0} bytes/second'.format(size/(t2-t1))) | 329 print('Done!') |
330 print('Speed: {0} bytes/second'.format(size/(t2-t1))) | |
316 return image | 331 return image |
317 def initFlashLoader(self): | |
318 # TODO: support other loader code. | |
319 self.write_mem32(STM32_SRAM_BASE, loader_code_stm32f4) | |
320 def runFlashLoader(self, targetaddress, buf): | |
321 bufAddress = STM32_SRAM_BASE + len(loader_code_stm32f4) | |
322 print('running flash loader for {0} bytes'.format(len(buf))) | |
323 self.write_buffer_to_sram(buf) | |
324 count = int(len(buf) / 4) | |
325 if len(buf) % 4 != 0: count += 1 | |
326 self.write_reg(0, bufAddress) | |
327 self.write_reg(1, targetaddress) | |
328 self.write_reg(2, count) | |
329 self.write_reg(15, STM32_SRAM_BASE) # pc | |
330 | |
331 self.run() # Let loose cpu! | |
332 | |
333 while self.Status == CORE_RUNNING: | |
334 pass | |
335 | |
336 r2 = self.read_reg(2) | |
337 if r2 != 0: | |
338 raise STLinkException("write error! {0}".format(r2)) | |
339 def write_buffer_to_sram(self, buf): | |
340 bufAddress = STM32_SRAM_BASE + len(loader_code_stm32f4) | |
341 chunk = len(buf) >> 2 | |
342 rem = len(buf) & 0x3 | |
343 if chunk > 0: | |
344 self.write_mem32(bufAddress, buf[:chunk]) | |
345 if rem > 0: | |
346 self.write_mem8(bufAddress + chunk, buf[chunk:chunk+rem]) | |
347 | |
348 def readFlashSr(self): | 332 def readFlashSr(self): |
349 return self.read_debug32(FLASH_F4_SR) | 333 return self.read_debug32(FLASH_F4_SR) |
350 def readFlashCr(self): | 334 def readFlashCr(self): |
351 return self.read_debug32(FLASH_F4_CR) | 335 return self.read_debug32(FLASH_F4_CR) |
336 def writeFlashCr(self, x): | |
337 self.write_debug32(FLASH_F4_CR, x) | |
352 def writeFlashCrSnb(self, sector): | 338 def writeFlashCrSnb(self, sector): |
353 x = self.readFlashCr() | 339 x = self.readFlashCr() |
354 x &= ~FLASH_F4_CR_SNB_MASK | 340 x &= ~FLASH_F4_CR_SNB_MASK |
355 x |= sector << FLASH_F4_CR_SNB | 341 x |= sector << FLASH_F4_CR_SNB |
356 x |= 1 << FLASH_F4_CR_SER | 342 x |= 1 << FLASH_F4_CR_SER |
357 self.write_debug32(FLASH_F4_CR, x) | 343 self.writeFlashCr(x) |
358 def setFlashCrMer(self): | 344 def setFlashCrMer(self): |
359 x = self.readFlashCr() | 345 x = self.readFlashCr() |
360 x |= 1 << FLASH_CR_MER | 346 x |= 1 << FLASH_CR_MER |
361 self.write_debug32(FLASH_F4_CR, x) | 347 self.writeFlashCr(x) |
362 def setFlashCrPg(self): | 348 def setFlashCrPg(self): |
363 x = self.readFlashCr() | 349 x = self.readFlashCr() |
364 x |= 1 << FLASH_CR_PG | 350 x |= 1 << FLASH_CR_PG |
365 self.write_debug32(FLASH_F4_CR, x) | 351 self.writeFlashCr(x) |
366 def writeFlashCrPsiz(self, n): | 352 def writeFlashCrPsiz(self, n): |
367 x = self.readFlashCr() | 353 x = self.readFlashCr() |
368 x &= (0x3 << 8) | 354 x &= (0x3 << 8) |
369 x |= n << 8 | 355 x |= n << 8 |
370 print('psiz', n) | 356 self.writeFlashCr(x) |
371 self.write_debug32(FLASH_F4_CR, x) | |
372 def clearFlashCrMer(self): | 357 def clearFlashCrMer(self): |
373 x = self.readFlashCr() | 358 x = self.readFlashCr() |
374 x &= ~(1 << FLASH_CR_MER) | 359 x &= ~(1 << FLASH_CR_MER) |
375 self.write_debug32(FLASH_F4_CR, x) | 360 self.writeFlashCr(x) |
376 def setFlashCrStart(self): | 361 def setFlashCrStart(self): |
377 x = self.readFlashCr() | 362 x = self.readFlashCr() |
378 x |= 1 << FLASH_F4_CR_START | 363 x |= 1 << FLASH_F4_CR_START |
379 self.write_debug32(FLASH_F4_CR, x) | 364 self.writeFlashCr(x) |
380 def isFlashBusy(self): | 365 def isFlashBusy(self): |
381 mask = 1 << FLASH_F4_SR_BSY | 366 mask = 1 << FLASH_F4_SR_BSY |
382 sr = self.readFlashSr() | 367 sr = self.readFlashSr() |
368 # Check for error bits: | |
369 errorbits = {} | |
370 errorbits[7] = 'Programming sequence error' | |
371 errorbits[6] = 'Programming parallelism error' | |
372 errorbits[5] = 'Programming alignment error' | |
373 errorbits[4] = 'Write protection error' | |
374 errorbits[1] = 'Operation error' | |
375 #errorbits[0] = 'End of operation' | |
376 for bit, msg in errorbits.items(): | |
377 if sr & (1 << bit) == (1 << bit): | |
378 raise STLinkException(msg) | |
379 | |
383 return sr & mask == mask | 380 return sr & mask == mask |
384 def waitFlashBusy(self): | 381 def waitFlashBusy(self): |
385 """ block until flash operation completes. """ | 382 """ block until flash operation completes. """ |
386 while self.isFlashBusy(): | 383 while self.isFlashBusy(): |
387 pass | 384 pass |
389 cr = self.readFlashCr() | 386 cr = self.readFlashCr() |
390 mask = 1 << FLASH_F4_CR_LOCK | 387 mask = 1 << FLASH_F4_CR_LOCK |
391 return cr & mask == mask | 388 return cr & mask == mask |
392 def unlockFlashIf(self): | 389 def unlockFlashIf(self): |
393 if self.isFlashLocked(): | 390 if self.isFlashLocked(): |
394 print('unlocking') | |
395 self.write_debug32(FLASH_F4_KEYR, FLASH_KEY1) | 391 self.write_debug32(FLASH_F4_KEYR, FLASH_KEY1) |
396 self.write_debug32(FLASH_F4_KEYR, FLASH_KEY2) | 392 self.write_debug32(FLASH_F4_KEYR, FLASH_KEY2) |
397 if self.isFlashLocked(): | 393 if self.isFlashLocked(): |
398 raise STLinkException('Failed to unlock') | 394 raise STLinkException('Failed to unlock') |
399 def lockFlash(self): | 395 def lockFlash(self): |
400 print('locking') | |
401 x = self.readFlashCr() | (1 << FLASH_F4_CR_LOCK) | 396 x = self.readFlashCr() | (1 << FLASH_F4_CR_LOCK) |
402 self.write_debug32(FLASH_F4_CR, x) | 397 self.write_debug32(FLASH_F4_CR, x) |
403 | 398 |
404 # Helper 1 functions: | 399 # Helper 1 functions: |
405 def write_debug32(self, address, value): | 400 def write_debug32(self, address, value): |
406 cmd = bytearray(16) | 401 cmd = bytearray(16) |
407 cmd[0:2] = DEBUG_COMMAND, JTAG_WRITEDEBUG_32BIT | 402 cmd[0:2] = DEBUG_COMMAND, JTAG_WRITEDEBUG_32BIT |
408 cmd[2:6] = struct.pack('<I', address) | 403 cmd[2:10] = struct.pack('<II', address, value) |
409 cmd[6:10] = struct.pack('<I', value) | |
410 self.send_recv(cmd, 2) | 404 self.send_recv(cmd, 2) |
411 def read_debug32(self, address): | 405 def read_debug32(self, address): |
412 cmd = bytearray(16) | 406 cmd = bytearray(16) |
413 cmd[0:2] = DEBUG_COMMAND, JTAG_READDEBUG_32BIT | 407 cmd[0:2] = DEBUG_COMMAND, JTAG_READDEBUG_32BIT |
414 cmd[2:6] = struct.pack('<I', address) # pack into u32 little endian | 408 cmd[2:6] = struct.pack('<I', address) # pack into u32 little endian |
426 return struct.unpack('<I', reply)[0] | 420 return struct.unpack('<I', reply)[0] |
427 def write_mem32(self, address, content): | 421 def write_mem32(self, address, content): |
428 assert len(content) % 4 == 0 | 422 assert len(content) % 4 == 0 |
429 cmd = bytearray(16) | 423 cmd = bytearray(16) |
430 cmd[0:2] = DEBUG_COMMAND, DEBUG_WRITEMEM_32BIT | 424 cmd[0:2] = DEBUG_COMMAND, DEBUG_WRITEMEM_32BIT |
431 cmd[2:6] = struct.pack('<I', address) | 425 cmd[2:8] = struct.pack('<IH', address, len(content)) |
432 cmd[6:8] = struct.pack('<H', len(content)) | |
433 self.send_recv(cmd) | 426 self.send_recv(cmd) |
434 self.send_recv(content) | 427 self.send_recv(content) |
435 def read_mem32(self, address, length): | 428 def read_mem32(self, address, length): |
436 assert length % 4 == 0 | 429 assert length % 4 == 0 |
437 cmd = bytearray(16) | 430 cmd = bytearray(16) |
438 cmd[0:2] = DEBUG_COMMAND, DEBUG_READMEM_32BIT | 431 cmd[0:2] = DEBUG_COMMAND, DEBUG_READMEM_32BIT |
439 cmd[2:6] = struct.pack('<I', address) | 432 cmd[2:8] = struct.pack('<IH', address, length) |
440 cmd[6:8] = struct.pack('<H', length) # uint16 | |
441 reply = self.send_recv(cmd, length) # expect memory back! | 433 reply = self.send_recv(cmd, length) # expect memory back! |
442 return reply | 434 return reply |
443 | 435 |
444 # Helper 2 functions: | 436 # Helper 2 functions: |
445 def send_recv(self, tx, rxsize=0): | 437 def send_recv(self, tx, rxsize=0): |
485 | 477 |
486 sl.exitDebugMode() | 478 sl.exitDebugMode() |
487 print('mode at end:', sl.CurrentModeString) | 479 print('mode at end:', sl.CurrentModeString) |
488 | 480 |
489 sl.close() | 481 sl.close() |
490 | 482 print('Test succes!') |
483 |