-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy patharmv7m_sys.py
259 lines (232 loc) · 10.3 KB
/
armv7m_sys.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#
# Runtime for the ARMv7 base system
#
# Copyright (c) 2020, Arm Limited. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#
import itertools as it
import math
from .. import argstuff
from .. import runtimes
from ..box import Section
from ..glue.error_glue import ErrorGlue
from ..glue.write_glue import WriteGlue
from ..glue.abort_glue import AbortGlue
from ..glue.heap_glue import HeapGlue
DEFAULT_HANDLER = """
__attribute__((naked, noreturn))
void %(name)s(void) {
while (1) {}
}
"""
@runtimes.runtime
class ARMv7MSysRuntime(
ErrorGlue,
WriteGlue,
AbortGlue,
HeapGlue,
runtimes.Runtime):
"""
A bento-box runtime that runs in privledge mode on the system.
Usually required at the root of the project.
"""
__argname__ = "armv7m_sys"
__arghelp__ = __doc__
@classmethod
def __argparse__(cls, parser, **kwargs):
parser.add_argument('--no_startup', type=bool,
help="Don't emit startup code and isr_vector used to "
"initialize the device.")
parser.add_nestedparser('--isr_vector', Section)
def __init__(self, no_startup=None, isr_vector=None):
super().__init__()
self._no_startup = no_startup or False
self._isr_vector = Section('isr_vector', **{**isr_vector.__dict__,
'size': isr_vector.size
if isr_vector.size is not None else
0x400})
# may be overridden
def _box_esr_hooks(self, box):
return [
box.addimport('__box_nmi_handler', 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True),
box.addimport('__box_hardfault_handler', 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True),
box.addimport('__box_memmanage_handler', 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True),
box.addimport('__box_busfault_handler', 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True),
box.addimport('__box_usagefault_handler', 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True),
None,
None,
None,
None,
box.addimport('__box_svc_handler', 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True),
box.addimport('__box_debugmon_handler', 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True),
None,
box.addimport('__box_pendsv_handler', 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True),
box.addimport('__box_systick_handler', 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True),
]
def box(self, box):
if not box.stack.size:
print("warning: Box `%s` has no stack!" % box.name)
super().box(box)
self._isr_vector.alloc(box, 'rp')
box.stack.alloc(box, 'rw')
box.heap.alloc(box, 'rw')
if not self._no_startup:
# allow overloading main, but default to using main if available
self._main_hook = box.addimport(
'__box_main', 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True,
doc="Entry point to the program. By default this will be "
"hooked up to call the normal C main.")
# link isr vector entries
self._esr_hooks = self._box_esr_hooks(box)
self._isr_hooks = []
for i in range(self._isr_vector.size//4 - 16):
self._isr_hooks.append(box.addimport(
'__box_irq%d_handler' % i, 'fn() -> void',
scope=box.name, source=self.__argname__, weak=True))
def build_mk(self, output, box):
# target rule
output.decls.insert(0, '%(name)-16s ?= %(target)s',
name='TARGET', target=output.get('target', '%(box)s.elf'))
out = output.rules.append(doc='target rule')
out.printf('$(TARGET): $(OBJ) $(BOXES) $(LDSCRIPT)')
with out.indent():
out.printf('$(CC) $(OBJ) $(BOXES) $(LDFLAGS) -o $@')
super().build_mk(output, box)
def build_ld(self, output, box):
# reset handler
output.decls.append('ENTRY(__box_reset_handler)')
# interrupt vector
if self._isr_vector:
out = output.sections.append(
section='.isr_vector',
memory=self._isr_vector.memory.name)
out.printf('. = ALIGN(%(align)d);')
out.printf('__isr_vector_start = .;')
out.printf('.isr_vector . : {')
with out.pushindent():
out.printf('KEEP(*(.isr_vector))')
out.printf('. = __isr_vector_start + %(isr_vector_size)#x;',
isr_vector_size=self._isr_vector.size)
out.printf('} > %(MEMORY)s')
out.printf('. = ALIGN(%(align)d);')
out.printf('__isr_vector_end = .;')
super().build_ld(output, box)
def build_c(self, output, box):
super().build_c(output, box)
# default write/abort hooks
if not self._no_startup:
output.decls.append('//// ISR Vector definitions ////')
# default to standard main definition
if not self._main_hook.link:
output.decls.append('extern void main(void);')
# create entry point
out = output.decls.append(doc='Reset Handler')
out.printf('__attribute__((naked, noreturn))')
out.printf('int32_t __box_reset_handler(void) {')
with out.indent():
if self.data_init_hook.link:
out.printf('// data inited by %(hook)s',
hook=self.data_init_hook.link.export.source)
out.printf()
else:
out.printf('// load data')
out.printf('extern uint32_t __data_init_start;')
out.printf('extern uint32_t __data_start;')
out.printf('extern uint32_t __data_end;')
out.printf('const uint32_t *s = &__data_init_start;')
out.printf('for (uint32_t *d = &__data_start; '
'd < &__data_end; d++) {')
with out.indent():
out.printf('*d = *s++;')
out.printf('}')
out.printf()
if self.bss_init_hook.link:
out.printf('// bss inited by %(hook)s',
hook=self.bss_init_hook.link.export.source)
out.printf()
else:
out.printf('// zero bss')
out.printf('extern uint32_t __bss_start;')
out.printf('extern uint32_t __bss_end;')
out.printf('for (uint32_t *d = &__bss_start; '
'd < &__bss_end; d++) {')
with out.indent():
out.printf('*d = 0;')
out.printf('}')
out.printf()
out.printf()
out.printf('// FPU bringup?')
out.printf('#if defined(__VFP_FP__) && !defined(__SOFTFP__)')
out.printf('#define CPACR ((volatile uint32_t*)0xe000ed88)')
out.printf('*CPACR |= 0x00f00000;')
out.printf('__asm__ volatile ("dsb");')
out.printf('__asm__ volatile ("isb");')
out.printf('#endif')
out.printf()
out.printf('// init libc')
out.printf('extern void __libc_init_array(void);')
out.printf('__libc_init_array();')
out.printf()
out.printf('// enter main')
out.printf('%(main)s();',
main=self._main_hook.link.export.alias
if self._main_hook.link else 'main')
out.printf()
out.printf('// halt if main exits')
out.printf('while (1) {')
with out.indent():
out.printf('__asm__ volatile ("wfi");')
out.printf('}')
out.printf('}')
# create default isrs, we have the standard ARM isrs
# declared to help with debugging
output.decls.append('//// Default handlers ////')
for esr in self._esr_hooks:
if esr and not esr.link:
output.decls.append(DEFAULT_HANDLER,
name=esr.alias)
output.decls.append(DEFAULT_HANDLER,
name='__box_default_handler')
# forward declare internal exports as needed
out = output.decls.append()
for handler in it.chain(self._esr_hooks, self._isr_hooks):
if (handler and handler.link and
handler.link.export.source != box.name):
out.printf('void %(name)s(void);', name=handler.alias)
output.decls.append('extern uint32_t __stack_end;')
# now create actual vector table
output.decls.append('//// ISR Vector ////')
out = output.decls.append(
size=2+len(self._esr_hooks)+len(self._isr_hooks))
out.printf('__attribute__((used, section(".isr_vector")))')
out.printf('const uint32_t __isr_vector[%(size)d] = {')
with out.indent():
out.printf('(uint32_t)&__stack_end,')
out.printf('(uint32_t)&__box_reset_handler,')
out.printf('// Exception handlers')
for esr in self._esr_hooks:
out.printf('(uint32_t)%(handler)s,', handler=
0
if not esr else
esr.alias
if not esr.link else
esr.link.export.alias)
out.printf('// External IRQ handlers')
for isr in self._isr_hooks:
out.printf('(uint32_t)%(handler)s,', handler=
0
if not isr else
'__box_default_handler'
if not isr.link else
isr.link.export.alias)
out.printf('};')