10000 stmhal: Add lots of constants to stm module. · errordeveloper/micropython@f20e093 · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit f20e093

Browse files
committed
stmhal: Add lots of constants to stm module.
1 parent 561f83c commit f20e093

File tree

4 files changed

+721
-9
lines changed

4 files changed

+721
-9
lines changed

stmhal/make-stmconst.py

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
"""
2+
Read in the cmsis/devinc/stm32f405xx.h header, extract relevant constants,
3+
and create modstmconst.c.
4+
5+
This is not part of the automatic build process because stm32f405xx.h isn't
6+
expected to change. After generating the file, some manual intervention is
7+
needed to copy the new qstr definitions to qstrdefsport.h.
8+
"""
9+
10+
import argparse
11+
import re
12+
13+
# given a list of (name,regex) pairs, find the first one that matches the given line
14+
def re_match_first(regexs, line):
15+
for name, regex in regexs:
16+
match = re.match(regex, line)
17+
if match:
18+
return name, match
19+
return None, None
20+
21+
class LexerError(Exception):
22+
def __init__(self, line):
23+
self.line = line
24+
25+
class Lexer:
26+
re_io_reg = r'__IO uint(?P<bits>8|16|32)_t +(?P<reg>[A-Z0-9]+)'
27+
re_comment = r'(?P<comment>[A-Za-z0-9 \-/_()]+)'
28+
re_addr_offset = r'Address offset: (?P<offset>0x[0-9A-Z]{2,3})'
29+
regexs = (
30+
('#define hex', re.compile(r'#define +(?P<id>[A-Z0-9_]+) +\(\(uint32_t\)(?P<hex>0x[0-9A-F]+)\)($| +/\*)')),
31+
('#define X', re.compile(r'#define +(?P<id>[A-Z0-9_]+) +(?P<id2>[A-Z0-9_]+)($| +/\*)')),
32+
('#define X+hex', re.compile(r'#define +(?P<id>[A-Z0-9_]+) +\((?P<id2>[A-Z0-9_]+) \+ (?P<hex>0x[0-9A-F]+)\)($| +/\*)')),
33+
('#define typedef', re.compile(r'#define +(?P<id>[A-Z0-9_]+) +\(\([A-Za-z0-9_]+_TypeDef \*\) (?P<id2>[A-Z0-9_]+)\)($| +/\*)')),
34+
('typedef struct', re.compile(r'typedef struct$')),
35+
('{', re.compile(r'{$')),
36+
('}', re.compile(r'}$')),
37+
('} TypeDef', re.compile(r'} *(?P<id>[A-Z][A-Za-z0-9_]+)_(?P<global>(Global)?)TypeDef;$')),
38+
('IO reg', re.compile(re_io_reg + r'; +/\*!< ' + re_comment + r', +' + re_addr_offset + r' *\*/')),
39+
('IO reg array', re.compile(re_io_reg + r'\[(?P<array>[2-8])\]; +/\*!< ' + re_comment + r', +' + re_addr_offset + r'-(0x[0-9A-Z]{2,3}) *\*/')),
40+
)
41+
42+
def __init__(self, filename):
43+
self.file = open(filename, 'rt')
44+
self.line_number = 0
45+
46+
def next_match(self, strictly_next=False):
47+
while True:
48+
line = self.file.readline()
49+
self.line_number += 1
50+
if len(line) == 0:
51+
return ('EOF', None)
52+
match = re_match_first(Lexer.regexs, line.strip())
53+
if strictly_next or match[0] is not None:
54+
return match
55+
56+
def must_match(self, kind):
57+
match = self.next_match(strictly_next=True)
58+
if match[0] != kind:
59+
raise LexerError(self.line_number)
60+
return match
61+
62+
def parse_file(filename):
63+
lexer = Lexer(filename)
64+
65+
reg_defs = {}
66+
consts = {}
67+
periphs = []
68+
while True:
69+
m = lexer.next_match()
70+
if m[0] == 'EOF':
71+
break
72+
elif m[0] == '#define hex':
73+
d = m[1].groupdict()
74+
consts[d['id']] = int(d['hex'], base=16)
75+
elif m[0] == '#define X':
76+
d = m[1].groupdict()
77+
if d['id2'] in consts:
78+
consts[d['id']] = consts[d['id2']]
79+
elif m[0] == '#define X+hex':
80+
d = m[1].groupdict()
81+
if d['id2'] in consts:
82+
consts[d['id']] = consts[d['id2']] + int(d['hex'], base=16)
83+
elif m[0] == '#define typedef':
84+
d = m[1].groupdict()
85+
if d['id2'] in consts:
86+
periphs.append((d['id'], consts[d['id2']]))
87+
elif m[0] == 'typedef struct':
88+
lexer.must_match('{')
89+
m = lexer.next_match()
90+
regs = []
91+
while m[0] in ('IO reg', 'IO reg array'):
92+
d = m[1].groupdict()
93+
reg = d['reg']
94+
offset = int(d['offset'], base=16)
95+
bits = int(d['bits'])
96+
comment = d['commen 10000 t']
97+
if m[0] == 'IO reg':
98+
regs.append((reg, offset, bits, comment))
99+
else:
100+
for i in range(int(d['array'])):
101+
regs.append((reg + str(i), offset + i * bits // 8, bits, comment))
102+
m = lexer.next_match()
103+
if m[0] == '}':
104+
pass
105+
elif m[0] == '} TypeDef':
106+
reg_defs[m[1].groupdict()['id']] = regs
107+
else:
108+
raise LexerError(lexer.line_number)
109+
110+
return periphs, reg_defs
111+
112+
def print_periph(periph_name, periph_val, needed_qstrs):
113+
qstr = periph_name.upper()
114+
print('{ MP_OBJ_NEW_QSTR(MP_QSTR_%s), MP_OBJ_NEW_SMALL_INT(%#x) },' % (qstr, periph_val))
115+
needed_qstrs.add(qstr)
116+
117+
def print_regs(reg_name, reg_defs, needed_qstrs):
118+
reg_name = reg_name.upper()
119+
for r in reg_defs:
120+
qstr = reg_name + '_' + r[0]
121+
print('{ MP_OBJ_NEW_QSTR(MP_QSTR_%s), MP_OBJ_NEW_SMALL_INT(%#x) }, // %s-bits, %s' % (qstr, r[1], r[2], r[3]))
122+
needed_qstrs.add(qstr)
123+
124+
# This version of print regs groups registers together into submodules (eg GPIO submodule).
125+
# This makes the qstrs shorter, and makes the list of constants more manageable (since
126+
# they are not all in one big module) but it is then harder to compile the constants, and
127+
# is more cumbersome to access.
128+
# As such, we don't use this version.
129+
# And for the number of constants we have, this function seems to use about the same amount
130+
# of ROM as print_regs.
131+
def print_regs_as_submodules(reg_name, reg_defs, modules, needed_qstrs):
132+
mod_name_lower = reg_name.lower() + '_'
133+
mod_name_upper = mod_name_lower.upper()
134+
modules.append((mod_name_lower, mod_name_upper))
135+
136+
print("""
137+
STATIC const mp_map_elem_t stm_%s_globals_table[] = {
138+
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_%s) },
139+
""" % (mod_name_lower, mod_name_upper))
140+
needed_qstrs.add(mod_name_upper)
141+
142+
for r in reg_defs:
143+
print(' { MP_OBJ_NEW_QSTR(MP_QSTR_%s), MP_OBJ_NEW_SMALL_INT(%#x) }, // %s-bits, %s' % (r[0], r[1], r[2], r[3]))
144+
needed_qstrs.add(r[0])
145+
146+
print("""};
147+
148+
STATIC const mp_obj_dict_t stm_%s_globals = {
149+
.base = {&mp_type_dict},
150+
.map = {
151+
.all_keys_are_qstrs = 1,
152+
.table_is_fixed_array = 1,
153+
.used = sizeof(stm_%s_globals_table) / sizeof(mp_map_elem_t),
154+
.alloc = sizeof(stm_%s_globals_table) / sizeof(mp_map_elem_t),
155+
.table = (mp_map_elem_t*)stm_%s_globals_table,
156+
},
157+
};
158+
159+
const mp_obj_module_t stm_%s_obj = {
160+
.base = { &mp_type_module },
161+
.name = MP_QSTR_%s,
162+
.globals = (mp_obj_dict_t*)&stm_%s_globals,
163+
};
164+
""" % (mod_name_lower, mod_name_lower, mod_name_lower, mod_name_lower, mod_name_lower, mod_name_upper, mod_name_lower))
165+
166+
def main():
167+
cmd_parser = argparse.ArgumentParser(description='Extract ST constants from a C header file.')
168+
cmd_parser.add_argument('file', nargs=1, help='input file')
169+
args = cmd_parser.parse_args()
170+
171+
periphs, reg_defs = parse_file(args.file[0])
172+
173+
modules = []
174+
needed_qstrs = set()
175+
176+
print("// Automatically generated from %s by make-stmconst.py" % args.file[0])
177+
print("")
178+
179+
for periph_name, periph_val in periphs:
180+
print_periph(periph_name, periph_val, needed_qstrs)
181+
182+
for reg in (
183+
'ADC', 10000
184+
#'ADC_Common',
185+
#'CAN_TxMailBox',
186+
#'CAN_FIFOMailBox',
187+
#'CAN_FilterRegister',
188+
#'CAN',
189+
'CRC',
190+
'DAC',
191+
'DBGMCU',
192+
'DMA_Stream',
193+
'DMA',
194+
'EXTI',
195+
'FLASH',
196+
'GPIO',
197+
'SYSCFG',
198+
'I2C',
199+
'IWDG',
200+
'PWR',
201+
'RCC',
202+
'RTC',
203+
#'SDIO',
204+
'SPI',
205+
'TIM',
206+
'USART',
207+
'WWDG',
208+
'RNG',
209+
):
210+
print_regs(reg, reg_defs[reg], needed_qstrs)
211+
#print_regs_as_submodules(reg, reg_defs[reg], modules, needed_qstrs)
212+
213+
#print("#define MOD_STM_CONST_MODULES \\")
214+
#for mod_lower, mod_upper in modules:
215+
# print(" { MP_OBJ_NEW_QSTR(MP_QSTR_%s), (mp_obj_t)&stm_%s_obj }, \\" % (mod_upper, mod_lower))
216+
217+
print("")
218+
219+
for qstr in sorted(needed_qstrs):
220+
print('Q({})'.format(qstr))
221+
222+
if __name__ == "__main__":
223+
main()

stmhal/modstm.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,7 @@ STATIC const mp_map_elem_t stm_module_globals_table[] = {
9797
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem16), (mp_obj_t)&stm_mem16_obj },
9898
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem32), (mp_obj_t)&stm_mem32_obj },
9999

100-
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIOA), MP_OBJ_NEW_SMALL_INT(GPIOA_BASE) },
101-
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIOB), MP_OBJ_NEW_SMALL_INT(GPIOB_BASE) },
102-
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIOC), MP_OBJ_NEW_SMALL_INT(GPIOC_BASE) },
103-
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIOD), MP_OBJ_NEW_SMALL_INT(GPIOD_BASE) },
104-
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO_IDR), MP_OBJ_NEW_SMALL_INT(0x10) },
105-
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO_BSRRL), MP_OBJ_NEW_SMALL_INT(0x18) },
106-
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO_BSRRH), MP_OBJ_NEW_SMALL_INT(0x1a) },
100+
#include "modstmconst.gen.c"
107101
};
108102

109103
STATIC const mp_obj_dict_t stm_module_globals = {

0 commit comments

Comments
 (0)
0