comparison python/stm32.py @ 128:51cc127648e4

Splitup in interface and device
author Windel Bouwman
date Sun, 13 Jan 2013 17:31:35 +0100
parents
children 9e350a7dde98
comparison
equal deleted inserted replaced
127:ec1f2cc04d95 128:51cc127648e4
1 import time
2 from devices import Device, registerDevice, STLinkException, Interface
3
4 # F4 specifics:
5 STM32_FLASH_BASE = 0x08000000
6 STM32_SRAM_BASE = 0x20000000
7
8 FLASH_KEY1 = 0x45670123
9 FLASH_KEY2 = 0xcdef89ab
10
11 # flash registers:
12 FLASH_F4_REGS_ADDR = 0x40023c00
13 FLASH_F4_KEYR = FLASH_F4_REGS_ADDR + 0x04
14 FLASH_F4_SR = FLASH_F4_REGS_ADDR + 0x0c
15 FLASH_F4_CR = FLASH_F4_REGS_ADDR + 0x10
16
17 FLASH_F4_CR_START = 16
18 FLASH_F4_CR_LOCK = 31
19 FLASH_CR_PG = 0
20 FLASH_F4_CR_SER = 1
21 FLASH_CR_MER = 2
22 FLASH_F4_CR_SNB = 3
23 FLASH_F4_CR_SNB_MASK = 0x38
24 FLASH_F4_SR_BSY = 16
25
26 def calculate_F4_sector(address):
27 """
28 from 0x8000000 to 0x80FFFFF
29 4 sectors of 0x4000 (16 kB)
30 1 sector of 0x10000 (64 kB)
31 7 of 0x20000 (128 kB)
32 """
33 sectorsizes = [0x4000] * 4 + [0x10000] + [0x20000] * 7
34 sectorstarts = []
35 a = STM32_FLASH_BASE
36 for sectorsize in sectorsizes:
37 sectorstarts.append(a)
38 a += sectorsize
39 # linear search:
40 sec = 0
41 while sec < len(sectorsizes) and address >= sectorstarts[sec]:
42 sec += 1
43 sec -= 1 # one back.
44 return sec, sectorsizes[sec]
45
46 def calcSectors(address, size):
47 off = 0
48 sectors = []
49 while off < size:
50 sectornum, sectorsize = calculate_F4_sector(address + off)
51 sectors.append((sectornum, sectorsize))
52 off += sectorsize
53 return sectors
54
55 @registerDevice(0x10016413)
56 class Stm32F4(Device):
57 def __init__(self, iface):
58 super().__init__()
59 assert isinstance(iface, Interface)
60 self.iface = iface
61 # flashing commands:
62 def writeFlash(self, address, content):
63 # TODO:
64 flashsize = 0x100000 # fixed 1 MB for now..
65 print('WARNING: using 1 MB as flash size')
66 pagesize = 0x4000 # fixed for now!
67 print('warning: page size hardcoded')
68
69 # Check address range:
70 if address < STM32_FLASH_BASE:
71 raise STLinkException('Flashing below flash start')
72 if address + len(content) > STM32_FLASH_BASE + flashsize:
73 raise STLinkException('Flashing above flash size')
74 if address & 1 == 1:
75 raise STLinkException('Unaligned flash')
76 if len(content) & 1 == 1:
77 print('unaligned length, padding with zero')
78 content += bytes([0])
79 if address & (pagesize - 1) != 0:
80 raise STLinkException('Address not aligned with pagesize')
81
82 # erase required space
83 sectors = calcSectors(address, len(content))
84 print('erasing {0} sectors'.format(len(sectors)))
85 for sector, secsize in sectors:
86 print('erasing sector {0} of {1} bytes'.format(sector, secsize))
87 self.eraseFlashSector(sector)
88
89 # program pages:
90 self.unlockFlashIf()
91 self.writeFlashCrPsiz(2) # writes are 32 bits aligned
92 self.setFlashCrPg()
93
94 print('writing {0} bytes'.format(len(content)), end='')
95 offset = 0
96 t1 = time.time()
97 while offset < len(content):
98 size = len(content) - offset
99 if size > 0x8000:
100 size = 0x8000
101
102 chunk = content[offset:offset + size]
103 while len(chunk) % 4 != 0:
104 print('padding chunk')
105 chunk = chunk + bytes([0])
106
107 # Use simple mem32 writes:
108 self.iface.write_mem32(address + offset, chunk)
109
110 offset += size
111 print('.', end='', flush=True)
112 t2 = time.time()
113 print('Done!')
114 print('Speed: {0} bytes/second'.format(len(content)/(t2-t1)))
115
116 self.lockFlash()
117
118 # verfify program:
119 self.verifyFlash(address, content)
120 def eraseFlashSector(self, sector):
121 self.waitFlashBusy()
122 self.unlockFlashIf()
123 self.writeFlashCrSnb(sector)
124 self.setFlashCrStart()
125 self.waitFlashBusy()
126 self.lockFlash()
127 def eraseFlash(self):
128 self.waitFlashBusy()
129 self.unlockFlashIf()
130 self.setFlashCrMer()
131 self.setFlashCrStart()
132 self.waitFlashBusy()
133 self.clearFlashCrMer()
134 self.lockFlash()
135 def verifyFlash(self, address, content):
136 device_content = self.readFlash(address, len(content))
137 ok = content == device_content
138 print('Verify:', ok)
139 def readFlash(self, address, size):
140 print('Reading {1} bytes from 0x{0:X}'.format(address, size), end='')
141 offset = 0
142 tmp_size = 0x1800
143 t1 = time.time()
144 image = bytes()
145 while offset < size:
146 # Correct for last page:
147 if offset + tmp_size > size:
148 tmp_size = size - offset
149
150 # align size to 4 bytes:
151 aligned_size = tmp_size
152 while aligned_size % 4 != 0:
153 aligned_size += 1
154
155 mem = self.iface.read_mem32(address + offset, aligned_size)
156 image += mem[:tmp_size]
157
158 # indicate progress:
159 print('.', end='', flush=True)
160
161 # increase for next piece:
162 offset += tmp_size
163 t2 = time.time()
164 assert size == len(image)
165 print('Done!')
166 print('Speed: {0} bytes/second'.format(size/(t2-t1)))
167 return image
168
169 def waitFlashBusy(self):
170 """ block until flash operation completes. """
171 while self.isFlashBusy():
172 pass
173 def isFlashLocked(self):
174 cr = self.readFlashCr()
175 mask = 1 << FLASH_F4_CR_LOCK
176 return cr & mask == mask
177 def unlockFlashIf(self):
178 if self.isFlashLocked():
179 self.iface.write_debug32(FLASH_F4_KEYR, FLASH_KEY1)
180 self.iface.write_debug32(FLASH_F4_KEYR, FLASH_KEY2)
181 if self.isFlashLocked():
182 raise STLinkException('Failed to unlock')
183 def lockFlash(self):
184 x = self.readFlashCr() | (1 << FLASH_F4_CR_LOCK)
185 self.writeFlashCr(x)
186
187 def readFlashSr(self):
188 return self.iface.read_debug32(FLASH_F4_SR)
189 def readFlashCr(self):
190 return self.iface.read_debug32(FLASH_F4_CR)
191 def writeFlashCr(self, x):
192 self.iface.write_debug32(FLASH_F4_CR, x)
193 def writeFlashCrSnb(self, sector):
194 x = self.readFlashCr()
195 x &= ~FLASH_F4_CR_SNB_MASK
196 x |= sector << FLASH_F4_CR_SNB
197 x |= 1 << FLASH_F4_CR_SER
198 self.writeFlashCr(x)
199 def setFlashCrMer(self):
200 x = self.readFlashCr()
201 x |= 1 << FLASH_CR_MER
202 self.writeFlashCr(x)
203 def setFlashCrPg(self):
204 x = self.readFlashCr()
205 x |= 1 << FLASH_CR_PG
206 self.writeFlashCr(x)
207 def writeFlashCrPsiz(self, n):
208 x = self.readFlashCr()
209 x &= (0x3 << 8)
210 x |= n << 8
211 self.writeFlashCr(x)
212 def clearFlashCrMer(self):
213 x = self.readFlashCr()
214 x &= ~(1 << FLASH_CR_MER)
215 self.writeFlashCr(x)
216 def setFlashCrStart(self):
217 x = self.readFlashCr()
218 x |= 1 << FLASH_F4_CR_START
219 self.writeFlashCr(x)
220 def isFlashBusy(self):
221 mask = 1 << FLASH_F4_SR_BSY
222 sr = self.readFlashSr()
223 # Check for error bits:
224 errorbits = {}
225 errorbits[7] = 'Programming sequence error'
226 errorbits[6] = 'Programming parallelism error'
227 errorbits[5] = 'Programming alignment error'
228 errorbits[4] = 'Write protection error'
229 errorbits[1] = 'Operation error'
230 #errorbits[0] = 'End of operation'
231 for bit, msg in errorbits.items():
232 if sr & (1 << bit) == (1 << bit):
233 raise STLinkException(msg)
234 return sr & mask == mask
235