Permalink
Browse files

Merge branch 'master' of https://github.com/hugovincent/pirate-swd

Conflicts:
	.gitignore
	SWDCommon.py
  • Loading branch information...
2 parents b75e01a + f202d95 commit 41f85af002cf3507eb68fa151876a792f3b0f3f7 Martin Heistermann committed Jan 6, 2012
Showing with 157 additions and 8 deletions.
  1. +2 −1 .gitignore
  2. +62 −0 EFM32.py
  3. +14 −4 PirateSWD.py
  4. +3 −0 README
  5. +16 −3 SWDCommon.py
  6. +60 −0 flashEFM32.py
View
@@ -1,3 +1,4 @@
core
-*.pyc
*.pyo
+.*.swp
+*.pyc
View
@@ -0,0 +1,62 @@
+from SWDCommon import *
+import sys
+
+class EFM32:
+ def __init__ (self, debugPort):
+ self.ahb = MEM_AP(debugPort, 0)
+
+ #--------------------------------------------------------------------------
+ # Cortex M3 stuff
+
+ def halt (self):
+ # halt the processor core
+ self.ahb.writeWord(0xE000EDF0, 0xA05F0003)
+
+ def unhalt (self):
+ # unhalt the processor core
+ self.ahb.writeWord(0xE000EDF0, 0xA05F0000)
+
+ def sysReset (self):
+ # restart the processor and peripherals
+ self.ahb.writeWord(0xE000ED0C, 0x05FA0004)
+
+ #--------------------------------------------------------------------------
+ # EFM32-specific stuff
+
+ def flashUnlock (self):
+ # unlock main flash
+ self.ahb.writeWord(0x400C0000 + 0x008, 0x00000001) # MSC_WRITECTL.WREN <- 1
+
+ def flashErase (self, flash_size):
+ # erase page by page
+ sys.stdout.write(" 0.0 %") ; sys.stdout.flush()
+ for i in range(flash_size * 2): # page size is 512 bytes
+ self.ahb.writeWord(0x400C0000 + 0x010, 0x200 * i) # MSC_ADDRB <- page address
+ self.ahb.writeWord(0x400C0000 + 0x00C, 0x00000001) # MSC_WRITECMD.LADDRIM <- 1
+ self.ahb.writeWord(0x400C0000 + 0x00C, 0x00000002) # MSC_WRITECMD.ERASEPAGE <- 1
+ while (self.ahb.readWord(0x400C0000 + 0x01C) & 0x1) == 1:
+ pass # poll the BUSY bit in MSC_STATUS until it clears
+ if i % 8 == 0:
+ sys.stdout.write("\b" * 7)
+ sys.stdout.write("%5.1f %%" % (100.0 * i / (flash_size * 2)))
+ sys.stdout.flush()
+ sys.stdout.write("\b" * 7 + "100.0 %\n")
+
+ def flashProgram (self, vals):
+ # Write each word one by one .... SLOOOW!
+ # (don't bother with checking the busy/status bits as this is so slow it's
+ # always ready before we are anyway)
+ sys.stdout.write(" 0.0 %") ; sys.stdout.flush()
+ addr = 0
+ for i in vals:
+ self.ahb.writeWord(0x400C0000 + 0x010, addr) # MSC_ADDRB <- starting address
+ self.ahb.writeWord(0x400C0000 + 0x00C, 0x1) # MSC_WRITECMD.LADDRIM <- 1
+ self.ahb.writeWord(0x400C0000 + 0x018, i) # MSC_WDATA <- data
+ self.ahb.writeWord(0x400C0000 + 0x00C, 0x8) # MSC_WRITECMD.WRITETRIG <- 1
+ addr += 0x4
+ if addr % 0x40 == 0:
+ sys.stdout.write("\b" * 7)
+ sys.stdout.write("%5.1f %%" % (25.0 * addr / len(vals)))
+ sys.stdout.flush()
+ sys.stdout.write("\b" * 7 + "100.0 %\n")
+
View
@@ -3,14 +3,14 @@
from SWDErrors import *
class PirateSWD:
- def __init__ (self, f = "/dev/bus_pirate"):
+ def __init__ (self, f = "/dev/bus_pirate", vreg = False):
self.port = serial.Serial(port = f, baudrate = 115200, timeout = 0.01)
- self.resetBP()
+ self.resetBP(vreg = vreg)
self.sendBytes([0xFF] * 8)
self.sendBytes([0x79, 0xE7])
self.resyncSWD()
- def resetBP (self):
+ def resetBP (self, vreg = False):
self.expected = 9999
self.clear()
self.port.write(bytearray([0x0F]))
@@ -20,7 +20,17 @@ def resetBP (self):
self.port.write(bytearray([0x05]))
if self.port.read(4) != "RAW1":
raise SWDInitError("error initializing bus pirate")
- self.port.write(bytearray([0x63,0x88]))
+ if vreg:
+ self.port.write(bytearray([0x48])) # enable voltage regulator output
+ self.port.write(bytearray([0x63,0x88])) # set speed to 400 kHz, enable output pins
+ self.clear(9999)
+
+ def tristatePins(self):
+ self.clear(9999)
+ self.port.write(bytearray([0x00])) # exit RAW mode, unfortunately this kills power and generally resets a bunch of stuff
+ if self.port.read(5) != "BBIO1":
+ raise SWDInitError("unexpected response from bus pirate")
+ self.port.write(bytearray([0xc0, 0x5f])) # re-enable power, disable all output pins
self.clear(9999)
# this is the fastest port-clearing scheme I could devise
View
3 README
@@ -13,3 +13,6 @@ flash memory programmed with a sequence of words.
There are some example firmware files for the STM32VLDISCOVERY board, as
I mainly developed this code so I could program mine from Linux without
bothering with the embedded bootloader.
+
+UPDATES:
+* Added 6/7/2011 by hugovincent: Energy Micro EFM32 support.
View
@@ -1,12 +1,18 @@
import time
class DebugPort:
- IDCODES = (0x1BA01477, 0xBB11477)
+ ID_CODES = [
+ 0x1BA01477, # willdonnelly
+ 0x2BA01477, # hugovincent
+ 0x0BB11477, # NUC1xx
+ ]
def __init__ (self, swd):
self.swd = swd
# read the IDCODE
- if self.idcode() not in (0x1BA01477, 0xBB11477):
- print "warning: unexpected idcode %s" % hex(self.idcode())
+ # Hugo: according to ARM DDI 0316D we should have 0x2B.. not 0x1B.., but
+ # 0x1B.. is what upstream used, so leave it in here...
+ if self.idcode() not in DebugPort.ID_CODES:
+ print "warning: unexpected idcode"
# power shit up
self.swd.writeSWD(False, 1, 0x54000000)
if (self.status() >> 24) != 0xF4:
@@ -103,6 +109,13 @@ def writeBlock (self, adr, data):
for val in data:
self.dp.writeAP(self.apsel, 0x0C, val)
+ def writeBlockNonInc (self, adr, data):
+ self.csw(0, 2) # 32-bit non-incrementing addressing
+ self.dp.writeAP(self.apsel, 0x04, adr)
+ for val in data:
+ self.dp.writeAP(self.apsel, 0x0C, val)
+ self.csw(1, 2) # 32-bit auto-incrementing addressing
+
def writeHalfs (self, adr, data):
self.csw(2, 1) # 16-bit packed-incrementing addressing
self.dp.writeAP(self.apsel, 0x04, adr)
View
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+
+import time
+import sys
+import array
+
+from PirateSWD import *
+from SWDCommon import *
+from EFM32 import *
+
+def loadFile(path):
+ arr = array.array('I')
+ try:
+ arr.fromfile(open(sys.argv[1], 'rb'), 1024*1024)
+ except EOFError:
+ pass
+ return arr.tolist()
+
+def main():
+ busPirate = PirateSWD("/dev/tty.usbserial-buspirat", vreg = True)
+ debugPort = DebugPort(busPirate)
+ efm32 = EFM32(debugPort)
+
+ part_info = efm32.ahb.readWord(0x0FE081FC) # PART_NUMBER, PART_FAMILY, PROD_REV
+ mem_info = efm32.ahb.readWord(0x0FE081F8) # MEM_INFO_FLASH, MEM_INFO_RAM
+ rev = (efm32.ahb.readWord(0xE00FFFE8) & 0xF0) | ((efm32.ahb.readWord(0xE00FFFEC) & 0xF0) >> 4) # PID2 and PID3 - see section 7.3.4 in reference manual
+ rev = chr(rev + ord('A'))
+ flash_size = mem_info & 0xFFFF
+ if (part_info >> 16 & 0xFF) == 71:
+ print "Connected."
+ print "Part number: EFM32G%dF%d (rev %c, production ID %dd)" % (part_info & 0xFF,
+ flash_size, rev, part_info >> 24 & 0xFF)
+ else:
+ print "Warning: unknown part"
+ sys.exit()
+ print "Loading '%s'..." % sys.argv[1],
+ vals = loadFile(sys.argv[1])
+ size = len(vals) * 4
+ print "%d bytes." % size
+ if size / 1024.0 > flash_size:
+ print "Firmware will not fit into flash!"
+ sys.exit(1)
+
+ efm32.halt()
+ efm32.flashUnlock()
+ print "Erasing Flash...",
+ efm32.flashErase(flash_size)
+ start_time = time.time()
+ print "Programming Flash...",
+ efm32.flashProgram(vals)
+ time_passed = time.time() - start_time
+ print "Programmed %d bytes in %.2f seconds (%.2f kB/sec)." % (size,
+ time_passed, (size / 1024.0) / time_passed)
+
+ print "Resetting"
+ efm32.sysReset()
+ busPirate.tristatePins()
+
+if __name__ == "__main__":
+ main()

0 comments on commit 41f85af

Please sign in to comment.