From f37f8d90bac131b00bbb0e18514b162f475fabdf Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Thu, 3 Aug 2023 19:07:41 -0700 Subject: [PATCH] cleanup build, prep for jungle (#1549) * cleanup build, prep for jungle * cleanup * update pedal obj path --- SConscript | 179 +++++++++++++++++++++++++++++++++++ board/SConscript | 193 ++------------------------------------ board/can_definitions.h | 1 - board/pedal/SConscript | 31 ++++++ board/pedal/recover.sh | 4 +- tests/libpanda/SConscript | 1 + tests/pedal/test_pedal.py | 4 +- 7 files changed, 224 insertions(+), 189 deletions(-) create mode 100644 board/pedal/SConscript diff --git a/SConscript b/SConscript index ed3aff75..84f82b91 100644 --- a/SConscript +++ b/SConscript @@ -1,6 +1,185 @@ +import os +import subprocess + + +PREFIX = "arm-none-eabi-" +BUILDER = "DEV" + +common_flags = [] + +if os.getenv("RELEASE"): + BUILD_TYPE = "RELEASE" + cert_fn = os.getenv("CERT") + assert cert_fn is not None, 'No certificate file specified. Please set CERT env variable' + assert os.path.exists(cert_fn), 'Certificate file not found. Please specify absolute path' +else: + BUILD_TYPE = "DEBUG" + cert_fn = File("#certs/debug").srcnode().abspath + common_flags += ["-DALLOW_DEBUG"] + + if os.getenv("DEBUG"): + common_flags += ["-DDEBUG"] + +def objcopy(source, target, env, for_signature): + return '$OBJCOPY -O binary %s %s' % (source[0], target[0]) + +def get_version(builder, build_type): + try: + git = subprocess.check_output(["git", "rev-parse", "--short=8", "HEAD"], encoding='utf8').strip() + except subprocess.CalledProcessError: + git = "unknown" + return f"{builder}-{git}-{build_type}" + +def get_key_header(name): + from Crypto.PublicKey import RSA + + public_fn = File(f'#certs/{name}.pub').srcnode().abspath + with open(public_fn) as f: + rsa = RSA.importKey(f.read()) + assert(rsa.size_in_bits() == 1024) + + rr = pow(2**1024, 2, rsa.n) + n0inv = 2**32 - pow(rsa.n, -1, 2**32) + + r = [ + f"RSAPublicKey {name}_rsa_key = {{", + f" .len = 0x20,", + f" .n0inv = {n0inv}U,", + f" .n = {to_c_uint32(rsa.n)},", + f" .rr = {to_c_uint32(rr)},", + f" .exponent = {rsa.e},", + f"}};", + ] + return r + +def to_c_uint32(x): + nums = [] + for _ in range(0x20): + nums.append(x % (2**32)) + x //= (2**32) + return "{" + 'U,'.join(map(str, nums)) + "U}" + + +def build_project(project_name, project, extra_flags): + linkerscript_fn = File(project["LINKER_SCRIPT"]).srcnode().abspath + + flags = project["PROJECT_FLAGS"] + extra_flags + common_flags + [ + "-Wall", + "-Wextra", + "-Wstrict-prototypes", + "-Werror", + "-mlittle-endian", + "-mthumb", + "-nostdlib", + "-fno-builtin", + "-std=gnu11", + "-fmax-errors=3", + f"-T{linkerscript_fn}", + ] + + includes = [ + ".", + "..", + Dir("#").abspath, + Dir("#board/").abspath, + Dir("#board/stm32fx/inc").abspath, + Dir("#board/stm32h7/inc").abspath, + ] + + env = Environment( + ENV=os.environ, + CC=PREFIX + 'gcc', + AS=PREFIX + 'gcc', + OBJCOPY=PREFIX + 'objcopy', + OBJDUMP=PREFIX + 'objdump', + CFLAGS=flags, + ASFLAGS=flags, + LINKFLAGS=flags, + CPPPATH=includes, + ASCOM="$AS $ASFLAGS -o $TARGET -c $SOURCES", + BUILDERS={ + 'Objcopy': Builder(generator=objcopy, suffix='.bin', src_suffix='.elf') + } + ) + + startup = env.Object(f"obj/startup_{project_name}", project["STARTUP_FILE"]) + + # Bootstub + crypto_obj = [ + env.Object(f"rsa-{project_name}", "#crypto/rsa.c"), + env.Object(f"sha-{project_name}", "#crypto/sha.c") + ] + bootstub_obj = env.Object(f"bootstub-{project_name}", project.get("BOOTSTUB", "#board/bootstub.c")) + bootstub_elf = env.Program(f"obj/bootstub.{project_name}.elf", + [startup] + crypto_obj + [bootstub_obj]) + env.Objcopy(f"obj/bootstub.{project_name}.bin", bootstub_elf) + + # Build main + main_obj = env.Object(f"main-{project_name}", project["MAIN"]) + main_elf = env.Program(f"obj/{project_name}.elf", [startup, main_obj], + LINKFLAGS=[f"-Wl,--section-start,.isr_vector={project['APP_START_ADDRESS']}"] + flags) + main_bin = env.Objcopy(f"obj/{project_name}.bin", main_elf) + + # Sign main + sign_py = File("#crypto/sign.py").srcnode().abspath + env.Command(f"obj/{project_name}.bin.signed", main_bin, f"SETLEN=1 {sign_py} $SOURCE $TARGET {cert_fn}") + + +base_project_f4 = { + "MAIN": "main.c", + "STARTUP_FILE": "#board/stm32fx/startup_stm32f413xx.s", + "LINKER_SCRIPT": "#board/stm32fx/stm32f4_flash.ld", + "APP_START_ADDRESS": "0x8004000", + "PROJECT_FLAGS": [ + "-mcpu=cortex-m4", + "-mhard-float", + "-DSTM32F4", + "-DSTM32F413xx", + "-mfpu=fpv4-sp-d16", + "-fsingle-precision-constant", + "-Os", + "-g", + ], +} + +base_project_h7 = { + "MAIN": "main.c", + "STARTUP_FILE": "#board/stm32h7/startup_stm32h7x5xx.s", + "LINKER_SCRIPT": "#board/stm32h7/stm32h7x5_flash.ld", + "APP_START_ADDRESS": "0x8020000", + "PROJECT_FLAGS": [ + "-mcpu=cortex-m7", + "-mhard-float", + "-DSTM32H7", + "-DSTM32H725xx", + "-mfpu=fpv5-d16", + "-fsingle-precision-constant", + "-Os", + "-g", + ], +} + +Export('base_project_f4', 'base_project_h7', 'build_project') + + +# Common autogenerated includes +with open("board/obj/gitversion.h", "w") as f: + f.write(f'const uint8_t gitversion[] = "{get_version(BUILDER, BUILD_TYPE)}";\n') + +with open("board/obj/version", "w") as f: + f.write(f'{get_version(BUILDER, BUILD_TYPE)}') + +certs = [get_key_header(n) for n in ["debug", "release"]] +with open("board/obj/cert.h", "w") as f: + for cert in certs: + f.write("\n".join(cert) + "\n") + # panda fw SConscript('board/SConscript') +# pedal fw +SConscript('board/pedal/SConscript') + # test files if GetOption('test'): SConscript('tests/libpanda/SConscript') diff --git a/board/SConscript b/board/SConscript index dc095e71..3b115a62 100644 --- a/board/SConscript +++ b/board/SConscript @@ -1,194 +1,19 @@ import os import copy -import subprocess -PREFIX = "arm-none-eabi-" -BUILDER = "DEV" +Import('build_project', 'base_project_f4', 'base_project_h7') -common_flags = [] -build_projects = {} - -build_projects["pedal"] = { - "MAIN": "pedal/main.c", - "STARTUP_FILE": "stm32fx/startup_stm32f205xx.s", - "LINKER_SCRIPT": "stm32fx/stm32f2_flash.ld", - "APP_START_ADDRESS": "0x8004000", - "PROJECT_FLAGS": [ - "-mcpu=cortex-m3", - "-msoft-float", - "-DSTM32F2", - "-DSTM32F205xx", - "-O2", - "-DPEDAL", - ], +build_projects = { + "panda": base_project_f4, + "panda_h7": base_project_h7, } -build_projects["pedal_usb"] = copy.deepcopy(build_projects["pedal"]) -build_projects["pedal_usb"]["PROJECT_FLAGS"].append("-DPEDAL_USB") - -build_projects["panda"] = { - "MAIN": "main.c", - "STARTUP_FILE": "stm32fx/startup_stm32f413xx.s", - "LINKER_SCRIPT": "stm32fx/stm32f4_flash.ld", - "APP_START_ADDRESS": "0x8004000", - "PROJECT_FLAGS": [ - "-mcpu=cortex-m4", - "-mhard-float", - "-DSTM32F4", - "-DSTM32F413xx", - "-mfpu=fpv4-sp-d16", - "-fsingle-precision-constant", - "-Os", - "-g", - "-DPANDA", - ], -} - -build_projects["panda_h7"] = { - "MAIN": "main.c", - "STARTUP_FILE": "stm32h7/startup_stm32h7x5xx.s", - "LINKER_SCRIPT": "stm32h7/stm32h7x5_flash.ld", - "APP_START_ADDRESS": "0x8020000", - "PROJECT_FLAGS": [ - "-mcpu=cortex-m7", - "-mhard-float", - "-DSTM32H7", - "-DSTM32H725xx", - "-mfpu=fpv5-d16", - "-fsingle-precision-constant", - "-Os", - "-g", - "-DPANDA", - ], -} - -if os.getenv("RELEASE"): - BUILD_TYPE = "RELEASE" - cert_fn = os.getenv("CERT") - assert cert_fn is not None, 'No certificate file specified. Please set CERT env variable' - assert os.path.exists(cert_fn), 'Certificate file not found. Please specify absolute path' -else: - BUILD_TYPE = "DEBUG" - cert_fn = File("../certs/debug").srcnode().abspath - common_flags += ["-DALLOW_DEBUG"] - -if os.getenv("DEBUG"): - common_flags += ["-DDEBUG"] - -includes = [ - "stm32fx/inc", - "stm32h7/inc", - "..", - ".", -] - -def get_version(builder, build_type): - try: - git = subprocess.check_output(["git", "rev-parse", "--short=8", "HEAD"], encoding='utf8').strip() - except subprocess.CalledProcessError: - git = "unknown" - return f"{builder}-{git}-{build_type}" - - -def to_c_uint32(x): - nums = [] - for _ in range(0x20): - nums.append(x % (2**32)) - x //= (2**32) - return "{" + 'U,'.join(map(str, nums)) + "U}" - - -def get_key_header(name): - from Crypto.PublicKey import RSA - - public_fn = File(f'../certs/{name}.pub').srcnode().abspath - with open(public_fn) as f: - rsa = RSA.importKey(f.read()) - assert(rsa.size_in_bits() == 1024) - - rr = pow(2**1024, 2, rsa.n) - n0inv = 2**32 - pow(rsa.n, -1, 2**32) - - r = [ - f"RSAPublicKey {name}_rsa_key = {{", - f" .len = 0x20,", - f" .n0inv = {n0inv}U,", - f" .n = {to_c_uint32(rsa.n)},", - f" .rr = {to_c_uint32(rr)},", - f" .exponent = {rsa.e},", - f"}};", - ] - return r - -def objcopy(source, target, env, for_signature): - return '$OBJCOPY -O binary %s %s' % (source[0], target[0]) - -# Common autogenerated includes -with open("obj/gitversion.h", "w") as f: - f.write(f'const uint8_t gitversion[] = "{get_version(BUILDER, BUILD_TYPE)}";\n') - -with open("obj/version", "w") as f: - f.write(f'{get_version(BUILDER, BUILD_TYPE)}') - -certs = [get_key_header(n) for n in ["debug", "release"]] -with open("obj/cert.h", "w") as f: - for cert in certs: - f.write("\n".join(cert) + "\n") - - -for project_name in build_projects: - project = build_projects[project_name] - linkerscript_fn = File(project["LINKER_SCRIPT"]).srcnode().abspath - +for project_name, project in build_projects.items(): flags = [ - "-Wall", - "-Wextra", - "-Wstrict-prototypes", - "-Werror", - "-mlittle-endian", - "-mthumb", - "-nostdlib", - "-fno-builtin", - f"-T{linkerscript_fn}", - "-std=gnu11", - ] + project["PROJECT_FLAGS"] + common_flags - + "-DPANDA", + "-DPANDA_BUS_CNT=4", + ] if ("ENABLE_SPI" in os.environ or "h7" in project_name) and not project_name.startswith('pedal'): flags.append('-DENABLE_SPI') - project_env = Environment( - ENV=os.environ, - CC=PREFIX + 'gcc', - AS=PREFIX + 'gcc', - OBJCOPY=PREFIX + 'objcopy', - OBJDUMP=PREFIX + 'objdump', - ASCOM="$AS $ASFLAGS -o $TARGET -c $SOURCES", - CFLAGS=flags, - ASFLAGS=flags, - LINKFLAGS=flags, - CPPPATH=includes, - BUILDERS={ - 'Objcopy': Builder(generator=objcopy, suffix='.bin', src_suffix='.elf') - } - ) - - startup = project_env.Object(f"obj/startup_{project_name}", project["STARTUP_FILE"]) - - # Bootstub - crypto_obj = [ - project_env.Object(f"rsa-{project_name}", "../crypto/rsa.c"), - project_env.Object(f"sha-{project_name}", "../crypto/sha.c") - ] - bootstub_obj = project_env.Object(f"bootstub-{project_name}", "bootstub.c") - bootstub_elf = project_env.Program(f"obj/bootstub.{project_name}.elf", [startup] + crypto_obj + [bootstub_obj]) - bootstub_bin = project_env.Objcopy(f"obj/bootstub.{project_name}.bin", bootstub_elf) - - # Build main - main_obj = project_env.Object(f"main-{project_name}", project["MAIN"]) - main_elf = project_env.Program(f"obj/{project_name}.elf", [startup, main_obj], - LINKFLAGS=[f"-Wl,--section-start,.isr_vector={project['APP_START_ADDRESS']}"] + flags) - main_bin = project_env.Objcopy(f"obj/{project_name}.bin", main_elf) - - # Sign main - sign_py = File("../crypto/sign.py").srcnode().abspath - panda_bin_signed = project_env.Command(f"obj/{project_name}.bin.signed", main_bin, f"SETLEN=1 {sign_py} $SOURCE $TARGET {cert_fn}") + build_project(project_name, project, flags) diff --git a/board/can_definitions.h b/board/can_definitions.h index daae4d04..b12d0e43 100644 --- a/board/can_definitions.h +++ b/board/can_definitions.h @@ -1,7 +1,6 @@ #pragma once const uint8_t PANDA_CAN_CNT = 3U; -const uint8_t PANDA_BUS_CNT = 4U; // bump this when changing the CAN packet #define CAN_PACKET_VERSION 4 diff --git a/board/pedal/SConscript b/board/pedal/SConscript new file mode 100644 index 00000000..5452fa66 --- /dev/null +++ b/board/pedal/SConscript @@ -0,0 +1,31 @@ +import copy + +Import('build_project') + +build_projects = {} + +build_projects["pedal"] = { + "MAIN": "#board/pedal/main.c", + "BOOTSTUB": "#board/bootstub.c", + "STARTUP_FILE": "#board/stm32fx/startup_stm32f205xx.s", + "LINKER_SCRIPT": "#board/stm32fx/stm32f2_flash.ld", + "APP_START_ADDRESS": "0x8004000", + "PROJECT_FLAGS": [ + "-mcpu=cortex-m3", + "-msoft-float", + "-DSTM32F2", + "-DSTM32F205xx", + "-O2", + "-DPEDAL", + ], +} + +# build with the USB driver enabled +build_projects["pedal_usb"] = copy.deepcopy(build_projects["pedal"]) +build_projects["pedal_usb"]["PROJECT_FLAGS"].append("-DPEDAL_USB") + +for project_name, project in build_projects.items(): + flags = [ + "-DPANDA_BUS_CNT=4", + ] + build_project(project_name, project, flags) diff --git a/board/pedal/recover.sh b/board/pedal/recover.sh index 98c5e198..f81f6727 100755 --- a/board/pedal/recover.sh +++ b/board/pedal/recover.sh @@ -7,5 +7,5 @@ cd .. PEDAL=1 scons -u -j$(nproc) cd pedal -$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D ../obj/pedal.bin.signed -$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D ../obj/bootstub.pedal.bin +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D obj/pedal.bin.signed +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.pedal.bin diff --git a/tests/libpanda/SConscript b/tests/libpanda/SConscript index f9f052e4..cf24949e 100644 --- a/tests/libpanda/SConscript +++ b/tests/libpanda/SConscript @@ -14,6 +14,7 @@ env = Environment( '-fno-builtin', '-std=gnu11', '-Wfatal-errors', + '-DPANDA_BUS_CNT=4', ], CPPPATH=[".", "../../board/"], ) diff --git a/tests/pedal/test_pedal.py b/tests/pedal/test_pedal.py index 05a05122..416a20fa 100755 --- a/tests/pedal/test_pedal.py +++ b/tests/pedal/test_pedal.py @@ -46,7 +46,7 @@ class TestPedal(unittest.TestCase): def test_usb_fw(self): subprocess.check_output(f"cd {BASEDIR} && PEDAL=1 PEDAL_USB=1 scons", shell=True) - self._flash_over_can(PEDAL_BUS, f"{BASEDIR}board/obj/pedal_usb.bin.signed") + self._flash_over_can(PEDAL_BUS, f"{BASEDIR}/board/pedal/obj/pedal_usb.bin.signed") time.sleep(2) with Panda(PEDAL_SERIAL) as p: self.assertTrue(p.get_type() == Panda.HW_TYPE_PEDAL) @@ -54,7 +54,7 @@ class TestPedal(unittest.TestCase): def test_nonusb_fw(self): subprocess.check_output(f"cd {BASEDIR} && PEDAL=1 scons", shell=True) - self._flash_over_can(PEDAL_BUS, f"{BASEDIR}board/obj/pedal.bin.signed") + self._flash_over_can(PEDAL_BUS, f"{BASEDIR}board/pedal/obj/pedal.bin.signed") time.sleep(2) self.assertTrue(self._listen_can_frames() > 40)