summaryrefslogtreecommitdiffstatshomepage
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/boardgen.py8
-rwxr-xr-xtools/ci.sh84
-rwxr-xr-xtools/mpy_ld.py91
3 files changed, 139 insertions, 44 deletions
diff --git a/tools/boardgen.py b/tools/boardgen.py
index 39bedf71cd..3723e7ce31 100644
--- a/tools/boardgen.py
+++ b/tools/boardgen.py
@@ -108,6 +108,10 @@ class Pin:
)
)
+ # Iterate over board pin names in consistent sorted order.
+ def board_pin_names(self):
+ return sorted(self._board_pin_names, key=lambda x: x[0])
+
# Override this to handle an af specified in af.csv.
def add_af(self, af_idx, af_name, af):
raise NotImplementedError
@@ -295,7 +299,7 @@ class PinGenerator:
file=out_source,
)
for pin in self.available_pins():
- for board_pin_name, board_hidden in pin._board_pin_names:
+ for board_pin_name, board_hidden in pin.board_pin_names():
if board_hidden:
# Don't include hidden pins in Pins.board.
continue
@@ -389,7 +393,7 @@ class PinGenerator:
# #define pin_BOARDNAME (pin_CPUNAME)
if board:
- for board_pin_name, _board_hidden in pin._board_pin_names:
+ for board_pin_name, _board_hidden in pin.board_pin_names():
# Note: Hidden board pins are still available to C via the macro.
# Note: The RHS isn't wrapped in (), which is necessary to make the
# STATIC_AF_ macro work on STM32.
diff --git a/tools/ci.sh b/tools/ci.sh
index d12b4bcd31..a5cd326c1c 100755
--- a/tools/ci.sh
+++ b/tools/ci.sh
@@ -93,23 +93,30 @@ function ci_code_size_build {
function code_size_build_step {
COMMIT=$1
OUTFILE=$2
- IGNORE_ERRORS=$3
echo "Building ${COMMIT}..."
git checkout --detach $COMMIT
git submodule update --init $SUBMODULES
git show -s
tools/metrics.py clean $PORTS_TO_CHECK
- tools/metrics.py build $PORTS_TO_CHECK | tee $OUTFILE || $IGNORE_ERRORS
+ tools/metrics.py build $PORTS_TO_CHECK | tee $OUTFILE
+ return $?
}
+ # Allow errors from tools/metrics.py to propagate out of the pipe above.
+ set -o pipefail
+
# build reference, save to size0
# ignore any errors with this build, in case master is failing
- code_size_build_step $REFERENCE ~/size0 true
+ code_size_build_step $REFERENCE ~/size0
# build PR/branch, save to size1
- code_size_build_step $COMPARISON ~/size1 false
+ code_size_build_step $COMPARISON ~/size1
+ STATUS=$?
+ set +o pipefail
unset -f code_size_build_step
+
+ return $STATUS
}
########################################################################################
@@ -317,13 +324,24 @@ function ci_qemu_setup_rv32 {
qemu-system-riscv32 --version
}
-function ci_qemu_build_arm {
+function ci_qemu_build_arm_prepare {
make ${MAKEOPTS} -C mpy-cross
make ${MAKEOPTS} -C ports/qemu submodules
+}
+
+function ci_qemu_build_arm_bigendian {
+ ci_qemu_build_arm_prepare
make ${MAKEOPTS} -C ports/qemu CFLAGS_EXTRA=-DMP_ENDIANNESS_BIG=1
- make ${MAKEOPTS} -C ports/qemu clean
- make ${MAKEOPTS} -C ports/qemu test_full
+}
+
+function ci_qemu_build_arm_sabrelite {
+ ci_qemu_build_arm_prepare
make ${MAKEOPTS} -C ports/qemu BOARD=SABRELITE test_full
+}
+
+function ci_qemu_build_arm_thumb {
+ ci_qemu_build_arm_prepare
+ make ${MAKEOPTS} -C ports/qemu test_full
# Test building and running native .mpy with armv7m architecture.
ci_native_mpy_modules_build armv7m
@@ -509,13 +527,26 @@ function ci_unix_run_tests_helper {
make -C ports/unix "$@" test
}
+function ci_unix_run_tests_full_extra {
+ micropython=$1
+ (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-multitests.py multi_net/*.py)
+ (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-perfbench.py 1000 1000)
+}
+
+function ci_unix_run_tests_full_no_native_helper {
+ variant=$1
+ shift
+ micropython=../ports/unix/build-$variant/micropython
+ make -C ports/unix VARIANT=$variant "$@" test_full_no_native
+ ci_unix_run_tests_full_extra $micropython
+}
+
function ci_unix_run_tests_full_helper {
variant=$1
shift
micropython=../ports/unix/build-$variant/micropython
make -C ports/unix VARIANT=$variant "$@" test_full
- (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-multitests.py multi_net/*.py)
- (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-perfbench.py 1000 1000)
+ ci_unix_run_tests_full_extra $micropython
}
function ci_native_mpy_modules_build {
@@ -524,38 +555,23 @@ function ci_native_mpy_modules_build {
else
arch=$1
fi
- for natmod in features1 features3 features4 heapq re
+ for natmod in deflate features1 features3 features4 framebuf heapq random re
do
- make -C examples/natmod/$natmod clean
+ make -C examples/natmod/$natmod ARCH=$arch clean
make -C examples/natmod/$natmod ARCH=$arch
done
- # deflate, framebuf, and random currently cannot build on xtensa due to
- # some symbols that have been removed from the compiler's runtime, in
- # favour of being provided from ROM.
- if [ $arch != "xtensa" ]; then
- for natmod in deflate framebuf random
- do
- make -C examples/natmod/$natmod clean
- make -C examples/natmod/$natmod ARCH=$arch
- done
- fi
-
- # features2 requires soft-float on armv7m, rv32imc, and xtensa. On armv6m
- # the compiler generates absolute relocations in the object file
- # referencing soft-float functions, which is not supported at the moment.
- make -C examples/natmod/features2 clean
- if [ $arch = "rv32imc" ] || [ $arch = "armv7m" ] || [ $arch = "xtensa" ]; then
+ # features2 requires soft-float on rv32imc and xtensa.
+ make -C examples/natmod/features2 ARCH=$arch clean
+ if [ $arch = "rv32imc" ] || [ $arch = "xtensa" ]; then
make -C examples/natmod/features2 ARCH=$arch MICROPY_FLOAT_IMPL=float
- elif [ $arch != "armv6m" ]; then
+ else
make -C examples/natmod/features2 ARCH=$arch
fi
- # btree requires thread local storage support on rv32imc, whilst on xtensa
- # it relies on symbols that are provided from ROM but not exposed to
- # natmods at the moment.
- if [ $arch != "rv32imc" ] && [ $arch != "xtensa" ]; then
- make -C examples/natmod/btree clean
+ # btree requires thread local storage support on rv32imc.
+ if [ $arch != "rv32imc" ]; then
+ make -C examples/natmod/btree ARCH=$arch clean
make -C examples/natmod/btree ARCH=$arch
fi
}
@@ -668,7 +684,7 @@ function ci_unix_nanbox_build {
}
function ci_unix_nanbox_run_tests {
- ci_unix_run_tests_full_helper nanbox PYTHON=python2.7
+ ci_unix_run_tests_full_no_native_helper nanbox PYTHON=python2.7
}
function ci_unix_float_build {
diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py
index a47653f900..a600ec12c3 100755
--- a/tools/mpy_ld.py
+++ b/tools/mpy_ld.py
@@ -402,6 +402,7 @@ class LinkEnv:
self.known_syms = {} # dict of symbols that are defined
self.unresolved_syms = [] # list of unresolved symbols
self.mpy_relocs = [] # list of relocations needed in the output .mpy file
+ self.externs = {} # dict of externally-defined symbols
def check_arch(self, arch_name):
if arch_name != self.arch.name:
@@ -491,10 +492,14 @@ def populate_got(env):
sym = got_entry.sym
if hasattr(sym, "resolved"):
sym = sym.resolved
- sec = sym.section
- addr = sym["st_value"]
- got_entry.sec_name = sec.name
- got_entry.link_addr += sec.addr + addr
+ if sym.name in env.externs:
+ got_entry.sec_name = ".external.fixed_addr"
+ got_entry.link_addr = env.externs[sym.name]
+ else:
+ sec = sym.section
+ addr = sym["st_value"]
+ got_entry.sec_name = sec.name
+ got_entry.link_addr += sec.addr + addr
# Get sorted GOT, sorted by external, text, rodata, bss so relocations can be combined
got_list = sorted(
@@ -520,6 +525,9 @@ def populate_got(env):
dest = int(got_entry.name.split("+")[1], 16) // env.arch.word_size
elif got_entry.sec_name == ".external.mp_fun_table":
dest = got_entry.sym.mp_fun_table_offset
+ elif got_entry.sec_name == ".external.fixed_addr":
+ # Fixed-address symbols should not be relocated.
+ continue
elif got_entry.sec_name.startswith(".text"):
dest = ".text"
elif got_entry.sec_name.startswith(".rodata"):
@@ -703,8 +711,9 @@ def do_relocation_text(env, text_addr, r):
(addr, value) = process_riscv32_relocation(env, text_addr, r)
elif env.arch.name == "EM_ARM" and r_info_type == R_ARM_ABS32:
- # happens for soft-float on armv6m
- raise ValueError("Absolute relocations not supported on ARM")
+ # Absolute relocation, handled as a data relocation.
+ do_relocation_data(env, text_addr, r)
+ return
else:
# Unknown/unsupported relocation
@@ -773,9 +782,9 @@ def do_relocation_data(env, text_addr, r):
):
# Relocation in data.rel.ro to internal/external symbol
if env.arch.word_size == 4:
- struct_type = "<I"
+ struct_type = "<i"
elif env.arch.word_size == 8:
- struct_type = "<Q"
+ struct_type = "<q"
if hasattr(s, "resolved"):
s = s.resolved
sec = s.section
@@ -1207,6 +1216,9 @@ def link_objects(env, native_qstr_vals_len):
sym.section = env.obj_table_section
elif sym.name in env.known_syms:
sym.resolved = env.known_syms[sym.name]
+ elif sym.name in env.externs:
+ # Fixed-address symbols do not need pre-processing.
+ continue
else:
if sym.name in fun_table:
sym.section = mp_fun_table_sec
@@ -1214,6 +1226,15 @@ def link_objects(env, native_qstr_vals_len):
else:
undef_errors.append("{}: undefined symbol: {}".format(sym.filename, sym.name))
+ for sym in env.externs:
+ if sym in env.known_syms:
+ log(
+ LOG_LEVEL_1,
+ "Symbol {} is a fixed-address symbol at {:08x} and is also provided from an object file".format(
+ sym, env.externs[sym]
+ ),
+ )
+
if undef_errors:
raise LinkError("\n".join(undef_errors))
@@ -1456,6 +1477,9 @@ def do_link(args):
log(LOG_LEVEL_2, "qstr vals: " + ", ".join(native_qstr_vals))
env = LinkEnv(args.arch)
try:
+ if args.externs:
+ env.externs = parse_linkerscript(args.externs)
+
# Load object files
for fn in args.files:
with open(fn, "rb") as f:
@@ -1484,6 +1508,50 @@ def do_link(args):
sys.exit(1)
+def parse_linkerscript(source):
+ # This extracts fixed-address symbol lists from linkerscripts, only parsing
+ # a small subset of all possible directives. Right now the only
+ # linkerscript file this is really tested against is the ESP8266's builtin
+ # ROM functions list ($SDK/ld/eagle.rom.addr.v6.ld).
+ #
+ # The parser should be able to handle symbol entries inside ESP-IDF's ROM
+ # symbol lists for the ESP32 range of MCUs as well (see *.ld files in
+ # $SDK/components/esp_rom/<name>/).
+
+ symbols = {}
+
+ LINE_REGEX = re.compile(
+ r'^(?P<weak>PROVIDE\()?' # optional weak marker start
+ r'(?P<symbol>[a-zA-Z_]\w*)' # symbol name
+ r'=0x(?P<address>[\da-fA-F]{1,8})*' # symbol address
+ r'(?(weak)\));$', # optional weak marker end and line terminator
+ re.ASCII,
+ )
+
+ inside_comment = False
+ for line in (line.strip() for line in source.readlines()):
+ if line.startswith('/*') and not inside_comment:
+ if not line.endswith('*/'):
+ inside_comment = True
+ continue
+ if inside_comment:
+ if line.endswith('*/'):
+ inside_comment = False
+ continue
+ if line.startswith('//'):
+ continue
+ match = LINE_REGEX.match(''.join(line.split()))
+ if not match:
+ continue
+ tokens = match.groupdict()
+ symbol = tokens['symbol']
+ address = int(tokens['address'], 16)
+ if symbol in symbols:
+ raise ValueError(f"Symbol {symbol} already defined")
+ symbols[symbol] = address
+ return symbols
+
+
def main():
import argparse
@@ -1500,6 +1568,13 @@ def main():
cmd_parser.add_argument(
"--output", "-o", default=None, help="output .mpy file (default to input with .o->.mpy)"
)
+ cmd_parser.add_argument(
+ "--externs",
+ "-e",
+ type=argparse.FileType("rt"),
+ default=None,
+ help="linkerscript providing fixed-address symbols to augment symbol resolution",
+ )
cmd_parser.add_argument("files", nargs="+", help="input files")
args = cmd_parser.parse_args()