8000 stm32/boards/NUCLEO_WB55: Add Python helper for rfcore. · micropython/micropython@5b9fbb4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5b9fbb4

Browse files
committed
stm32/boards/NUCLEO_WB55: Add Python helper for rfcore.
This allows prototyping rfcore.c improvements from Python. This was mostly written by @dpgeorge with small modifications to work after rfcore_init() by @jimmo.
1 parent e0e0c02 commit 5b9fbb4

File tree

1 file changed

+306
-0
lines changed

1 file changed

+306
-0
lines changed
Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
# This file is part of the MicroPython project, http://micropython.org/
2+
#
3+
# The MIT License (MIT)
4+
#
5+
# Copyright 8000 (c) 2020 Damien P. George
6+
# Copyright (c) 2020 Jim Mussared
7+
#
8+
# Permission is hereby granted, free of charge, to any person obtaining a copy
9+
# of this software and associated documentation files (the "Software"), to deal
10+
# in the Software without restriction, including without limitation the rights
11+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
# copies of the Software, and to permit persons to whom the Software is
13+
# furnished to do so, subject to the following conditions:
14+
#
15+
# The above copyright notice and this permission notice shall be included in
16+
# all copies or substantial portions of the Software.
17+
#
18+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
# THE SOFTWARE.
25+
26+
# This script provides some helpers to allow Python code to access the IPCC
27+
# mechanism in the WB55, and works with the memory layout configured in
28+
# ports/stm32/rfcore.c -- i.e. it expects that rfcore_init() has been run.
29+
30+
# At this stage this is useful for debugging, but can be extended to support
31+
# FUS/WS firmware updates.
32+
# e.g.
33+
# ../tools/pyboard.py --device /dev/ttyACM0 boards/NUCLEO_WB55/rfcore.py
34+
# to print out SRAM2A, register state and FUS/WS info.
35+
36+
from machine import mem8, mem16, mem32
37+
import time, struct, uctypes
38+
import stm
39+
40+
class Flash:
41+
FLASH_KEY1 = 0x45670123
42+
FLASH_KEY2 = 0xcdef89ab
43+
44+
def wait_not_busy(self):
45+
while mem32[stm.FLASH + stm.FLASH_SR] & 1 << 16:
46+
machine.idle()
47+
48+
def unlock(self):
49+
mem32[stm.FLASH + stm.FLASH_KEYR] = Flash.FLASH_KEY1
50+
mem32[stm.FLASH + stm.FLASH_KEYR] = Flash.FLASH_KEY2
51+
52+
def lock(self):
53+
mem32[stm.FLASH + stm.FLASH_CR] = 1 << 31 # LOCK
54+
55+
def erase_page(self, page):
56+
print('erase', page)
57+
assert 0 <= page <= 255 # 1MiB range (4k page)
58+
self.wait_not_busy()
59+
cr = (
60+
page << 3 # PNB
61+
| 1 << 1 # PER
62+
)
63+
mem32[stm.FLASH + stm.FLASH_CR] = cr
64+
mem32[stm.FLASH + stm.FLASH_CR] = cr | 1 << 16 # STRT
65+
self.wait_not_busy()
66+
mem32[stm.FLASH + stm.FLASH_CR] = 0
67+
68+
def write(self, addr, buf):
69+
assert len(buf) % 4 == 0
70+
self.wait_not_busy()
71+
cr = (
72+
1 << 0 # PG
73+
)
74+
mem32[stm.FLASH + stm.FLASH_CR] = cr
75+
buf_addr = uctypes.addressof(buf)
76+
off = 0
77+
while off < len(buf):
78+
mem32[addr + off] = mem32[buf_addr + off]
79+
off += 4
80+
if off % 8 == 0:
81+
self.wait_not_busy()
82+
if off % 8:
83+
mem32[addr + off] = 0
84+
self.wait_not_busy()
85+
mem32[stm.FLASH + stm.FLASH_CR] = 0
86+
87+
def copy_file_to_flash(filename, addr):
88+
flash = Flash()
89+
flash.unlock()
90+
try:
91+
with open(filename, 'rb') as f:
92+
buf = bytearray(4096)
93+
while 1:
94+
sz = f.readinto(buf)
95+
if sz == 0:
96+
break
97+
print('write', hex(addr), sz)
98+
flash.erase_page((addr - 0x08000000) // 4096)
99+
print('done e')
100+
flash.write(addr, buf)
101+
print('done')
102+
addr += 4096
103+
finally:
104+
flash.lock()
105+
106+
SRAM2A_BASE = const(0x2003_0000)
107+
108+
# for vendor OGF
109+
OGF_VENDOR = const(0x3f)
110+
OCF_FUS_GET_STATE = const(0x52)
111+
OCF_FUS_FW_UPGRADE = const(0x54)
112+
OCF_FUS_FW_DELETE = const(0x55)
113+
OCF_FUS_START_WS = const(0x5a)
114+
OCF_BLE_INIT = const(0x66)
115+
116+
@micropython.asm_thumb
117+
def asm_sev_wfe():
118+
data(2, 0xbf40) # sev
119+
data(2, 0xbf20) # wfe
120+
121+
TABLE_DEVICE_INFO = const(0)
122+
TABLE_BLE = const(1)
123+
TABLE_SYS = const(3)
124+
TABLE_MEM_MANAGER = const(4)
125+
126+
CHANNEL_BLE = const(1)
127+
CHANNEL_SYS = const(2)
128+
CHANNEL_TRACES = const(4)
129+
CHANNEL_ACL = const(6)
130+
131+
INDICATOR_HCI_COMMAND = const(0x01)
132+
INDICATOR_HCI_EVENT = const(0x04)
133+
INDICATOR_FUS_COMMAND = const(0x10)
134+
INDICATOR_FUS_RESPONSE = const(0x11)
135+
INDICATOR_FUS_EVENT = const(0x12)
136+
137+
MAGIC_FUS_ACTIVE = const(0xa94656b9)
138+
139+
def get_ipccdba():
140+
return mem32[stm.FLASH + stm.FLASH_IPCCBR] & 0x3fff
141+
142+
def get_ipcc_table(table):
143+
return mem32[SRAM2A_BASE + get_ipccdba() + table * 4]
144+
145+
def get_ipcc_table_word(table, offset):
146+
return mem32[get_ipcc_table(table) + offset * 4] & 0xffffffff
147+
148+
def get_ipcc_table_byte(table, offset):
149+
return mem8[get_ipcc_table(table) + offset] & 0xff
150+
151+
def sram2a_dump(num_words=64, width=8):
152+
print('SRAM2A @%08x' % SRAM2A_BASE)
153+
for i in range((num_words + width - 1) // width):
154+
print(' %04x ' % (i * 4 * width), end='')
155+
for j in range(width):
156+
print(' %08x' % (mem32[SRAM2A_BASE + (i * width + j) * 4] & 0xffffffff), end='')
157+
print()
158+
159+
SYS_CMD_BUF = 0 # next*,prev*,type8,...; 272 bytes
160+
SYS_SYS_QUEUE = 0 # next*,prev*
161+
162+
MM_BLE_SPARE_EVT_BUF = 0 # next*,prev*; 272 bytes
163+
MM_SYS_SPARE_EVT_BUF = 0 # next*,prev*; 272 bytes
164+
MM_BLE_POOL = 0 # ?
165+
MM_BLE_POOL_SIZE = 0 # ?
166+
MM_FREE_BUF_QUEUE = 0 # next*,prev*
167+
MM_EV_POOL = 0 # ?
168+
MM_EV_POOL_SIZE = 0 # ?
169+
170+
BLE_CMD_BUF = 0
171+
BLE_CS_BUF = 0
172+
BLE_EVT_QUEUE = 0
173+
BLE_HCI_ACL_DATA_BUF = 0
174+
175+
def ipcc_init():
176+
global SYS_CMD_BUF, SYS_SYS_QUEUE
177+
SYS_CMD_BUF = get_ipcc_table_word(TABLE_SYS, 0)
178+
SYS_SYS_QUEUE = get_ipcc_table_word(TABLE_SYS, 1)
179+
180+
global MM_BLE_SPARE_EVT_BUF, MM_SYS_SPARE_EVT_BUF, MM_BLE_POOL, MM_BLE_POOL_SIZE, MM_FREE_BUF_QUEUE, MM_EV_POOL, MM_EV_POOL_SIZE
181+
MM_BLE_SPARE_EVT_BUF = get_ipcc_table_word(TABLE_MEM_MANAGER, 0)
182+
MM_SYS_SPARE_EVT_BUF = get_ipcc_table_word(TABLE_MEM_MANAGER, 1)
183+
MM_BLE_POOL = get_ipcc_table_word(TABLE_MEM_MANAGER, 2)
184+
MM_BLE_POOL_SIZE = get_ipcc_table_word(TABLE_MEM_MANAGER, 3)
185+
MM_FREE_BUF_QUEUE = get_ipcc_table_word(TABLE_MEM_MANAGER, 4)
186+
MM_EV_POOL = get_ipcc_table_word(TABLE_MEM_MANAGER, 5)
187+
MM_EV_POOL_SIZE = get_ipcc_table_word(TABLE_MEM_MANAGER, 6)
188+
189+
global BLE_CMD_BUF, BLE_CS_BUF, BLE_EVT_QUEUE, BLE_HCI_ACL_DATA_BUF
190+
BLE_CMD_BUF = get_ipcc_table_word(TABLE_BLE, 0)
191+
BLE_CS_BUF = get_ipcc_table_word(TABLE_BLE, 1)
192+
BLE_EVT_QUEUE = get_ipcc_table_word(TABLE_BLE, 2)
193+
BLE_HCI_ACL_DATA_BUF = get_ipcc_table_word(TABLE_BLE, 3)
194+
195+
print('IPCC initialised')
196+
print('SYS: 0x%08x 0x%08x' % (SYS_CMD_BUF, SYS_SYS_QUEUE))
197+
print('BLE: 0x%08x 0x%08x 0x%08x' % (BLE_CMD_BUF, BLE_CS_BUF, BLE_EVT_QUEUE))
198+
199+
200+
def tl_list_init(addr):
201+
mem32[addr] = addr # next
202+
mem32[addr + 4] = addr # prev
203+
204+
def tl_list_append(head, n):
205+
sram2a_dump(1024)
206+
print('Appending 0x%08x to 0x%08x' % (head, n))
207+
# item->next = head
208+
mem32[n] = head
209+
# item->prev = head->prev
210+
mem32[n + 4] = mem32[head + 4]
211+
# head->prev->next = item
212+
mem32[mem32[head + 4]] = n
213+
# head->prev = item
214+
mem32[head + 4] = n
215+
216+
def tl_list_unlink(n):
217+
# next = item->next
218+
next = mem32[n]
219+
# prev = item->prev
220+
prev = mem32[n + 4]
221+
# prev->next = item->next
222+
mem32[prev] = next
223+
# item->next->prev = prev
224+
mem32[next + 4] = prev
225+
226+
return next
227+
228+
def tl_list_dump(head):
229+
print('list(%08x, %08x, %08x):' % (head, mem32[head] & 0xffffffff, mem32[head + 4] & 0xffffffff), end='')
230+
cur = mem32[head]
231+
while cur != head:
232+
print(' %08x' % (cur & 0xffffffff), end='')
233+
cur = mem32[cur]
234+
print()
235+
236+
def fus_active():
237+
return get_ipcc_table_word(TABLE_DEVICE_INFO, 0) == MAGIC_FUS_ACTIVE
238+
239+
def info():
240+
sfr = mem32[stm.FLASH + stm.FLASH_SFR]
241+
srrvr = mem32[stm.FLASH + stm.FLASH_SRRVR]
242+
243+
print('IPCCDBA : 0x%08x' % (get_ipccdba() & 0x3fff))
244+
print('DDS : %r' % bool(sfr & (1 << 12)))
245+
print('FSD : %r' % bool(sfr & (1 << 8)))
246+
print('SFSA : 0x%08x' % (sfr & 0xff))
247+
print('C2OPT : %r' % bool(srrvr & (1 << 31)))
248+
print('NBRSD : %r' % bool(srrvr & (1 << 30)))
249+
print('SNBRSA : 0x%08x' % ((srrvr >> 25) & 0x1f))
250+
print('BRSD : %r' % bool(srrvr & (1 << 23)))
251+
print('SBRSA : 0x%08x' % ((srrvr >> 18) & 0x1f))
252+
print('SBRV : 0x%08x' % (srrvr & 0x3ffff))
253+
254+
def dev_info():
255+
def dump_version(offset):
256+
x = get_ipcc_table_word(TABLE_DEVICE_INFO, offset)
257+
print('0x%08x (%u.%u.%u.%u.%u)' % (x, x >> 24, x >> 16 & 0xff, x >> 8 & 0xff, x >> 4 & 0xf, x & 0xf))
258+
def dump_memory_size(offset):
259+
x = get_ipcc_table_word(TABLE_DEVICE_INFO, offset)
260+
print('0x%08x (SRAM2b=%uk SRAM2a=%uk flash=%uk)' % (x, x >> 24, x >> 16 & 0xff, (x & 0xff) * 4))
261+
262+
print('Device information table @%08x:' % get_ipcc_table(TABLE_DEVICE_INFO))
263+
if fus_active():
264+
# layout when running FUS
265+
print('FUS is active')
266+
print('state : 0x%08x' % get_ipcc_table_word(TABLE_DEVICE_INFO, 0))
267+
print('last FUS active state : 0x%02x' % get_ipcc_table_byte(TABLE_DEVICE_INFO, 5))
268+
print('last wireless stack state: 0x%02x' % get_ipcc_table_byte(TABLE_DEVICE_INFO, 6))
269+
print('cur wireless stack type : 0x%02x' % get_ipcc_table_byte(TABLE_DEVICE_INFO, 7))
270+
print('safe boot version : ', end=''); dump_version(2)
271+
print('FUS version : ', end=''); dump_version(3)
272+
print('FUS memory size : ', end=''); dump_memory_size(4)
273+
print('wireless stack version : ', end=''); dump_version(5)
274+
print('wireless stack mem size : ', end=''); dump_memory_size(6)
275+
print('wireless FW-BLE info : 0x%08x' % get_ipcc_table_word(TABLE_DEVICE_INFO, 7))
276+
print('wireless FW-thread info : 0x%08x' % get_ipcc_table_word(TABLE_DEVICE_INFO, 8))
277+
print('UID64 : 0x%08x 0x%08x' % (get_ipcc_table_word(TABLE_DEVICE_INFO, 9), get_ipcc_table_word(TABLE_DEVICE_INFO, 10)))
278+
print('device ID : 0x%04x' % get_ipcc_table_word(TABLE_DEVICE_INFO, 11))
279+
else:
280+
# layout when running WS
281+
print('WS is active')
282+
print('safe boot version : ', end=''); dump_version(0)
283+
print('FUS version : ', end=''); dump_version(1)
284+
print('FUS memory size : ', end=''); dump_memory_size(2)
285+
print('FUS info : 0x%08x' % get_ipcc_table_word(TABLE_DEVICE_INFO, 3))
286+
print('wireless stack version : ', end=''); dump_version(4)
287+
print('wireless stack mem size : ', end=''); dump_memory_size(5)
288+
print('wireless stack info : 0x%08x' % get_ipcc_table_word(TABLE_DEVICE_INFO, 7))
289+
print('wireless reserved : 0x%08x' % get_ipcc_table_word(TABLE_DEVICE_INFO, 7))
290+
291+
def ipcc_state():
292+
print('IPCC:')
293+
print(' C1CR: 0x%08x' % (mem32[stm.IPCC + stm.IPCC_C1CR] & 0xffffffff), end='')
294+
print(' C2CR: 0x%08x' % (mem32[stm.IPCC + stm.IPCC_C2CR] & 0xffffffff))
295+
print(' C1MR: 0x%08x' % (mem32[stm.IPCC + stm.IPCC_C1MR] & 0xffffffff), end='')
296+
print(' C2MR: 0x%08x' % (mem32[stm.IPCC + stm.IPCC_C2MR] & 0xffffffff))
297+
# these always read 0
298+
#print(' C1SCR: 0x%08x' % (mem32[stm.IPCC + stm.IPCC_C1SCR] & 0xffffffff), end='')
299+
#print(' C2SCR: 0x%08x' % (mem32[stm.IPCC + stm.IPCC_C2SCR] & 0xffffffff))
300+
print(' C1TOC2SR: 0x%08x' % (mem32[stm.IPCC + stm.IPCC_C1TOC2SR] & 0xffffffff), end='')
301+
print(' C2TOC1SR: 0x%08x' % (mem32[stm.IPCC + stm.IPCC_C2TOC1SR] & 0xffffffff))
302+
303+
sram2a_dump(264)
304+
ipcc_init()
305+
info()
306+
dev_info()

0 commit comments

Comments
 (0)
0