From 540e49938963fdbf7f956d4e99ff3ef08537c6a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Tue, 14 Jun 2022 15:39:28 +0200 Subject: [PATCH] [beken-72xx] Implement SDK binary building --- boards/_base/beken-7231t-tuya.json | 3 +- builder/frameworks/beken-72xx-sdk.py | 551 ++++++++++++++++++ builder/frameworks/realtek-ambz-sdk.py | 24 +- builder/main.py | 5 +- builder/utils/config.py | 50 ++ builder/utils/env.py | 7 +- builder/utils/libs.py | 86 ++- platform/beken-7231t/fixups/inc/certs.h | 5 + platform/beken-7231t/fixups/inc/netdb.h | 5 + platform/beken-7231t/fixups/inc/sockets.h | 5 + platform/beken-7231t/fixups/sys_config.h | 116 ++++ platform/common/fixups/errno.h | 18 + platform/common/fixups/lwip/errno.h | 5 + .../realtek-ambz/fixups/inc/platform_opts.h | 9 +- tools/link2bin.py | 199 +++---- tools/soc/link2bin_ambz.py | 69 +++ tools/soc/link2bin_bk72xx.py | 57 ++ tools/util/fileio.py | 6 + 18 files changed, 1050 insertions(+), 170 deletions(-) create mode 100644 builder/frameworks/beken-72xx-sdk.py create mode 100644 builder/utils/config.py create mode 100644 platform/beken-7231t/fixups/inc/certs.h create mode 100644 platform/beken-7231t/fixups/inc/netdb.h create mode 100644 platform/beken-7231t/fixups/inc/sockets.h create mode 100644 platform/beken-7231t/fixups/sys_config.h create mode 100644 platform/common/fixups/errno.h create mode 100644 platform/common/fixups/lwip/errno.h create mode 100644 tools/soc/link2bin_ambz.py create mode 100644 tools/soc/link2bin_bk72xx.py diff --git a/boards/_base/beken-7231t-tuya.json b/boards/_base/beken-7231t-tuya.json index e8d5358..b4eb6f8 100644 --- a/boards/_base/beken-7231t-tuya.json +++ b/boards/_base/beken-7231t-tuya.json @@ -1,7 +1,8 @@ { "build": { "bkcrypt_coeffs": "510fb093a3cbeadc5993a17ec7adeb03", - "bkboot_version": "1.0.5-bk7231s" + "bkboot_version": "1.0.5-bk7231s", + "bkrbl_size_app": "0x107800" }, "flash": { "bootloader": "0x000000+0x11000", diff --git a/builder/frameworks/beken-72xx-sdk.py b/builder/frameworks/beken-72xx-sdk.py new file mode 100644 index 0000000..b5f98b8 --- /dev/null +++ b/builder/frameworks/beken-72xx-sdk.py @@ -0,0 +1,551 @@ +# Copyright (c) Kuba Szczodrzyński 2022-06-13. + +from os.path import join + +from SCons.Script import Builder, DefaultEnvironment + +env = DefaultEnvironment() +board = env.BoardConfig() + +ROOT_DIR = join("$SDK_DIR", "beken378") +APP_DIR = join(ROOT_DIR, "app") +DRIVER_DIR = join(ROOT_DIR, "driver") +FUNC_DIR = join(ROOT_DIR, "func") + +# Load sys_config.h into env +env.LoadConfig(join("$FAMILY_DIR", "fixups", "sys_config.h")) + +# Define vars used during build +SOC_BK7231 = 1 +SOC_BK7231U = 2 +SOC_BK7221U = 3 +SOC_BK7251 = 3 +SOC_BK7271 = 4 +SOC_BK7231N = 5 +SOC_BK7236 = 6 +SOC_NAMES = { + SOC_BK7231: "bk7231", + SOC_BK7231U: "bk7231u", + SOC_BK7221U: "bk7221u", + SOC_BK7271: "bk7271", + SOC_BK7231N: "bk7231n", + SOC_BK7236: "bk7236", +} +SOC = env.Cfg("CFG_SOC_NAME") +WPA_VERSION = "wpa_supplicant_2_9" if env.Cfg("CFG_USE_WPA_29") else "hostapd-2.5" + +# Flags +env.Append( + CCFLAGS=[ + "-mcpu=arm968e-s", + "-march=armv5te", + "-mthumb", + "-mthumb-interwork", + "-g", + "-O2", + "-fdata-sections", + "-ffunction-sections", + "-fno-strict-aliasing", + "-fsigned-char", + "-Wno-comment", + ], + CFLAGS=[ + "-std=c99", + "-nostdlib", + "-Wall", + "-Wno-format", + "-Wno-unknown-pragmas", + ], + CPPDEFINES=[ + # LibreTuya configuration + # (reserved) + # SDK options + ("CFG_OS_FREERTOS", "1"), + ("MBEDTLS_CONFIG_FILE", ""), + ("WIFI_BLE_COEXIST", "1"), + ("WOLFSSL_BEKEN", env.Cfg("CFG_WPA3")), + ], + ASFLAGS=[ + "-mcpu=arm968e-s", + "-march=armv5te", + "-marm", + "-mthumb-interwork", + "-g", + "-x", + "assembler-with-cpp", + ], + LINKFLAGS=[ + "-mcpu=arm968e-s", + "-marm", + "-mthumb-interwork", + "-g", + "-nostdlib", + "-Wl,--gc-sections", + "-Wl,-wrap,_free_r", + "-Wl,-wrap,_malloc_r", + "-Wl,-wrap,calloc", + "-Wl,-wrap,free", + "-Wl,-wrap,malloc", + "-Wl,-wrap,realloc", + "-Wl,-wrap,zalloc", + "-Wl,-wrap,_realloc_r", + "-Wl,-wrap,printf", + "-Wl,-wrap,puts", + "-Wl,-wrap,snprintf", + "-Wl,-wrap,sprintf", + "-Wl,-wrap,vsnprintf", + ], +) + +# Sources - from framework-beken-bdk/beken378/beken_src.mk +env.AddLibrary( + name="bdk_core", + base_dir=ROOT_DIR, + srcs=[ + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + ], + includes=[ + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+<../release>", + ], +) + +# Sources - app module +env.AddLibrary( + name="bdk_app", + base_dir=APP_DIR, + srcs=[ + "+", + "+", + "+", + "+", + "+", + ], + includes=[ + "+", + "+", + "+", + "+", + "+", + ], +) + +# Sources - drivers +env.AddLibrary( + name="bdk_driver", + base_dir=DRIVER_DIR, + srcs=[ + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "-", + "-", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + ], + includes=[ + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+<../ip/**>", + ], +) + +# Sources - functional components +env.AddLibrary( + name="bdk_func", + base_dir=FUNC_DIR, + srcs=[ + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "-", + "+", + "+", + ], + includes=[ + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + f"+<{WPA_VERSION}/bk_patch>", + f"+<{WPA_VERSION}/hostapd>", + f"+<{WPA_VERSION}/src>", + f"+<{WPA_VERSION}/src/ap>", + f"+<{WPA_VERSION}/src/common>", + f"+<{WPA_VERSION}/src/drivers>", + f"+<{WPA_VERSION}/src/utils>", + f"+<{WPA_VERSION}/wpa_supplicant>", + ], +) + +# Sources - FreeRTOS +env.AddLibrary( + name="bdk_freertos_thumb", + base_dir=ROOT_DIR, + srcs=[ + "+", + ], + includes=[ + "+", + ], +) +env.AddLibrary( + name="bdk_freertos_arm", + base_dir="$SDK_DIR", + srcs=[ + "+", + ], + includes=[ + "+", + "+", + ], + options=dict( + CCFLAGS=[ + # build FreeRTOS port in ARM mode + "+<-marm>", + "-<-mthumb>", + ], + ), +) + +# Sources - lwIP 2.0.2 +env.AddLibrary( + name="bdk_lwip", + base_dir=join(FUNC_DIR, "lwip_intf"), + srcs=[ + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + ], + includes=[ + "+", + "+", + "+", + ], + options=dict(CCFLAGS=["-Wno-missing-braces"]), +) + +# Sources - mbedTLS 2.6.0 +env.AddLibrary( + name="bdk_mbedtls", + base_dir=join(FUNC_DIR, "mbedtls"), + srcs=[ + "+", + "+", + "+", + ], + includes=[ + "+", + "+", + "+", + ], + options=dict( + CCFLAGS=["-Wno-unused-variable"], + CFLAGS=["-<-Wall>"], + ), +) + +# Sources - demos TODO remove this +env.AddLibrary( + name="bdk_demos", + base_dir="$SDK_DIR", + srcs=[ + "+", + "-", + "-", + "-", + ], + includes=[ + "+", + "+", + ], +) + +# Sources - chip-specific drivers +if SOC in [SOC_BK7231U, SOC_BK7251]: + env.AddLibrary( + name="bdk_driver_spi", + base_dir=join(DRIVER_DIR, "spi"), + srcs=[ + "+", + "+", + "+", + ], + ) +if SOC in [SOC_BK7231N]: + env.AddLibrary( + name="bdk_driver_spi", + base_dir=join(DRIVER_DIR, "spi"), + srcs=[ + "+", + "+", + "+", + ], + ) +if SOC in [SOC_BK7251]: + env.AddLibrary( + name="bdk_bk7251", + base_dir=ROOT_DIR, + srcs=[ + "+", + "+", + "+", + "+", + ], + includes=[ + "+", + "+", + ], + ) + +# Sources - enabled through config +if env.Cfg("CFG_SDIO"): + env.AddLibrary( + name="bdk_driver_sdio", + base_dir=ROOT_DIR, + srcs=[ + "+", + "+", + ], + ) +if env.Cfg("CFG_BK_AWARE"): + env.AddLibrary( + name="bdk_driver_sdio", + base_dir="$SDK_DIR", + srcs=[ + "+", + "+", + ], + includes=[ + "+", + ], + ) +if env.Cfg("CFG_USE_SDCARD_HOST"): + env.AddLibrary( + name="bdk_func_fatfs", + base_dir=join(FUNC_DIR, "fatfs"), + srcs=[ + "+<*.c>", + "-", + ], + includes=[ + "+<.>", + ], + ) +if env.Cfg("CFG_WPA3"): + env.AddLibrary( + name="bdk_wolfssl", + base_dir=join(FUNC_DIR, "wolfssl"), + srcs=[ + "+", + "+", + "+", + "+", + "+", + "+", + ], + includes=[ + "+<.>", + ], + ) +if env.Cfg("CFG_SUPPORT_BLE") and env.Cfg("CFG_BLE_VERSION") == env.Cfg( + "BLE_VERSION_4_2" +): + env.AddLibrary( + name="bdk_ble_4_2", + base_dir=join(DRIVER_DIR, "ble"), + srcs=[ + "+<**/*.c>", + ], + includes=[ + "+<.>", + "+<**/include>", + "+", + "+", + "+", + "+", + "+", + "+", + ], + ) +if env.Cfg("CFG_SUPPORT_BLE") and env.Cfg("CFG_BLE_VERSION") == env.Cfg( + "BLE_VERSION_5_x" +): + env.AddLibrary( + name="bdk_ble_5_x", + base_dir=join(DRIVER_DIR, "ble_5_x_rw"), + srcs=[ + "+<**/*.c>", + "-", + "-", + ], + includes=[ + "+<**/api>", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "+", + "-", + ], + ) +if env.Cfg("ATSVR_CFG"): + env.AddLibrary( + name="bdk_atsvr", + base_dir=join(FUNC_DIR, "at_server"), + srcs=[ + "+<**/*.c>", + ], + includes=[ + "+<.>", + "+<*>", + ], + ) +if env.Cfg("CFG_USB"): + env.AddLibrary( + name="bdk_driver_usb", + base_dir=ROOT_DIR, + srcs=[ + "+", + "+", + ], + includes=[ + "+", + ], + ) + +# Libs & linker config +env.Append( + LIBPATH=[ + join("$SDK_DIR", "beken378", "lib"), + join("$SDK_DIR", "beken378", "func", "airkiss"), + ], + LIBS=[ + "airkiss", + "sensor", + "usb", + # "wpa", # this is compiled from func/hostapd_intf/hostapd_intf.c + f"ble_{SOC_NAMES[SOC]}", + f"cal_{SOC_NAMES[SOC]}", + f"rf_test_{SOC_NAMES[SOC]}", + f"rf_use_{SOC_NAMES[SOC]}", + f"rwnx_{SOC_NAMES[SOC]}", + f"supplicant_{SOC_NAMES[SOC]}", + f"uart_debug_{SOC_NAMES[SOC]}", + "gcc", + "g", + "c", + "m", + "nosys", + ], +) + +# Misc options +env.Replace( + SIZEPROGREGEXP=r"^(?:\.vectors|\.text|\.rodata|\.data|\.ARM\.exidx)\s+([0-9]+).*", + SIZEDATAREGEXP=r"^(?:\.vectors|\.data|\.bss)\s+([0-9]+).*", + SIZECHECKCMD="$SIZETOOL -A -d $SOURCES", + SIZEPRINTCMD="$SIZETOOL -B -d $SOURCES", +) + +# Build all libraries +env.BuildLibraries() + +# Main firmware outputs and actions +env.Replace( + # linker command (encryption + packaging) + LINK="${LINK2BIN} ${VARIANT} '' ''", +) diff --git a/builder/frameworks/realtek-ambz-sdk.py b/builder/frameworks/realtek-ambz-sdk.py index 687b9a0..216dc35 100644 --- a/builder/frameworks/realtek-ambz-sdk.py +++ b/builder/frameworks/realtek-ambz-sdk.py @@ -9,8 +9,7 @@ board = env.BoardConfig() # Flags env.Append( - CFLAGS=[ - "-std=gnu99", + CCFLAGS=[ "-mcpu=cortex-m4", "-mthumb", "-mfloat-abi=hard", @@ -18,7 +17,6 @@ env.Append( "-g2", "-w", "-O2", - "-Wno-pointer-sign", "-fdata-sections", "-ffunction-sections", "-fmessage-length=0", @@ -27,26 +25,16 @@ env.Append( "-fomit-frame-pointer", "-fsigned-char", ], + CFLAGS=[ + "-std=gnu99", + "-Wno-pointer-sign", + ], CXXFLAGS=[ # borrowed from RtlDuino/development/rtl87xx/platform.txt "-std=c++11", - "-mcpu=cortex-m4", - "-mthumb", - "-mfloat-abi=hard", - "-mfpu=fpv4-sp-d16", - "-g2", - "-w", - "-O2", "-MMD", - "-fdata-sections", - "-ffunction-sections", - "-fmessage-length=0", - "-fno-common", "-fno-exceptions", "-fno-rtti", - "-fno-short-enums", - "-fomit-frame-pointer", - "-fsigned-char", ], CPPDEFINES=[ # LibreTuya configuration @@ -316,7 +304,7 @@ env.BuildLibraries() # Main firmware outputs and actions env.Replace( # linker command (dual .bin outputs) - LINK="${LINK2BIN} AMBZ xip1 xip2", + LINK="${LINK2BIN} ${VARIANT} xip1 xip2", # default output .bin name IMG_FW="image_${FLASH_OTA1_OFFSET}.ota1.bin", # UF2OTA input list diff --git a/builder/main.py b/builder/main.py index 3620526..4dcb3cb 100644 --- a/builder/main.py +++ b/builder/main.py @@ -12,6 +12,7 @@ board = env.BoardConfig() sys.path.insert(0, platform.get_dir()) # Utilities +env.SConscript("utils/config.py", exports="env") env.SConscript("utils/env.py", exports="env") env.SConscript("utils/flash.py", exports="env") env.SConscript("utils/libs.py", exports="env") @@ -72,6 +73,8 @@ elif "IMG_FW" in env: target_fw = env.subst("$IMG_FW") env.AddPlatformTarget("upload", target_fw, env["UPLOAD_ACTIONS"], "Upload") else: - sys.stderr.write("Warning! Firmware outputs not specified.\n") + sys.stderr.write( + "Warning! Firmware outputs not specified. Uploading is not possible.\n" + ) Default(targets) diff --git a/builder/utils/config.py b/builder/utils/config.py new file mode 100644 index 0000000..b301a8f --- /dev/null +++ b/builder/utils/config.py @@ -0,0 +1,50 @@ +# Copyright (c) Kuba Szczodrzyński 2022-06-13. + +from os.path import isfile + +from SCons.Script import DefaultEnvironment + +env = DefaultEnvironment() + + +def env_load_config(env, path): + path = env.subst(path) + if not isfile(path): + raise FileNotFoundError("Config file not found") + STRIP_CHARS = "\t " + config = {} + f = open(path, "r", encoding="utf-8") + for line in f: + line: str + if not line.startswith("#define"): + continue + line = line[7:].strip(STRIP_CHARS) + (key, value) = line.split(None, 2) + value = value.strip(STRIP_CHARS) + if value.isnumeric(): + value = int(value, 0) + elif value.startswith('"') and value.endswith('"'): + value = value[1:-1] + else: + # store defines as bytes + value = value.encode() + config[key] = value + env.Append( + CONFIG=config, + ) + f.close() + + +def env_get_config(env, key): + config: dict = env["CONFIG"] + if not config: + return None + value = config.get(key, None) + while isinstance(value, bytes): + value = config.get(value.decode(), None) + return value + + +env.AddMethod(env_load_config, "LoadConfig") +env.AddMethod(env_get_config, "Cfg") +env.AddMethod(env_get_config, "GetConfig") diff --git a/builder/utils/env.py b/builder/utils/env.py index f22780a..85b99c1 100644 --- a/builder/utils/env.py +++ b/builder/utils/env.py @@ -1,6 +1,6 @@ # Copyright (c) Kuba Szczodrzyński 2022-05-04. -from os.path import isdir, join +from os.path import join from SCons.Script import DefaultEnvironment @@ -43,13 +43,10 @@ def env_add_defaults(env, platform, board): env.Replace(**vars) # Store family parameters as environment variables env.Replace(**dict(family)) - # Check directories for validity - for k, v in vars.items(): - if k.endswith("_DIR"): - assert isdir(env.subst(v)), f"{env.subst(v)} is not a directory" # Default build options env.Prepend( CPPPATH=[ + "$LT_DIR/platform/common/fixups", "$BOARD_DIR", "$FAMILY_DIR/fixups", "$PARENT_DIR/fixups", diff --git a/builder/utils/libs.py b/builder/utils/libs.py index 11c0481..bd88c84 100644 --- a/builder/utils/libs.py +++ b/builder/utils/libs.py @@ -3,56 +3,66 @@ import fnmatch from glob import glob from os.path import isdir, join -from typing import List +from typing import Dict, Generator, List, Tuple from SCons.Script import DefaultEnvironment env = DefaultEnvironment() +def add_base_dir(env, base_dir: str, expressions: List[str], subst: bool = False): + out = [] + for expr in expressions: + if expr[1] != "<" or expr[-1] != ">": + raise ValueError(f"Not a valid glob: {expr}") + if expr[2] == "$": + # do not append base path + path = expr[2:-1] + else: + path = join(base_dir, expr[2:-1]) + if subst: + path = env.subst(path) + out.append(expr[0] + "<" + path + ">") + return out + + +def iter_expressions(expressions: List[str]) -> Generator[Tuple[str, str], None, None]: + for expr in expressions: + if expr[1] != "<" or expr[-1] != ">": + yield ("+", expr) + continue + yield (expr[0], expr[2:-1]) + + def env_add_library( env, name: str, base_dir: str, srcs: List[str], includes: List[str] = [], + options: Dict[str, List[str]] = {}, ): name = env.subst(name) - # add base dir to all source globs - sources = [] - for src in srcs: - if src[1] != "<" or src[-1] != ">": - raise ValueError(f"Not a source glob: {src}") - - if src[2] == "$": # do not append base path - expr = src[2:-1] - else: - expr = join(base_dir, src[2:-1]) - - sources.append(src[0] + "<" + expr + ">") + # add base dir to all globs + srcs = add_base_dir(env, base_dir, srcs) + includes = add_base_dir(env, base_dir, includes, subst=True) # allow removing sources from parent builders key = f"LIB_{name.upper()}_SKIP" if key in env: for expr in env[key]: - sources.append("-<" + expr + ">") + srcs.append("-<" + expr + ">") # queue library for further env clone and build - env.Prepend(LIBQUEUE=[[join("$BUILD_DIR", name), base_dir, sources]]) + env.Prepend( + LIBQUEUE=[ + (join("$BUILD_DIR", name), base_dir, srcs, options), + ] + ) - base_dir = env.subst(base_dir) # expand base_dir for includes - for dir in includes: - if dir[1] != "<" or dir[-1] != ">": - env.Append(CPPPATH=[dir]) - continue - - if dir[2] == "$": # do not append base path - expr = dir[2:-1] - else: - expr = join(base_dir, dir[2:-1]) - expr = env.subst(expr) - - if dir[0] == "-": + # search all include paths + for dir, expr in iter_expressions(includes): + if dir == "-": for item in fnmatch.filter(env["CPPPATH"], expr): if item in env["CPPPATH"]: env["CPPPATH"].remove(item) @@ -60,7 +70,7 @@ def env_add_library( for item in glob(expr, recursive=True): if not isdir(item): continue - if dir[0] == "!": + if dir == "!": env.Prepend(CPPPATH=[item]) else: env.Append(CPPPATH=[item]) @@ -72,9 +82,23 @@ def env_build_libraries(env, safe: bool = True): return queue = env["LIBQUEUE"] env["LIBQUEUE"] = [] - envsafe = env.Clone() if safe else env for lib in queue: - target = envsafe.BuildLibrary(*lib) + envsafe = env.Clone() if safe else env + # get env options to add/remove + options: Dict[str, List[str]] = lib[3] + # change only safe env options + for key, values in options.items(): + for dir, value in iter_expressions(values): + if dir == "+": + envsafe.Append(**{key: [value]}) + elif dir == "!": + envsafe.Prepend(**{key: [value]}) + elif dir == "-": + if value not in envsafe[key]: + raise ValueError(f"Invalid option; {value} is not in {key}") + envsafe[key].remove(value) + # build library with (name, base_dir, sources) options + target = envsafe.BuildLibrary(*lib[0:3]) env.Prepend(LIBS=[target]) diff --git a/platform/beken-7231t/fixups/inc/certs.h b/platform/beken-7231t/fixups/inc/certs.h new file mode 100644 index 0000000..13d0266 --- /dev/null +++ b/platform/beken-7231t/fixups/inc/certs.h @@ -0,0 +1,5 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-06-13. */ + +#pragma once + +#include diff --git a/platform/beken-7231t/fixups/inc/netdb.h b/platform/beken-7231t/fixups/inc/netdb.h new file mode 100644 index 0000000..75a707b --- /dev/null +++ b/platform/beken-7231t/fixups/inc/netdb.h @@ -0,0 +1,5 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-06-13. */ + +#pragma once + +#include diff --git a/platform/beken-7231t/fixups/inc/sockets.h b/platform/beken-7231t/fixups/inc/sockets.h new file mode 100644 index 0000000..3f34b76 --- /dev/null +++ b/platform/beken-7231t/fixups/inc/sockets.h @@ -0,0 +1,5 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-05-23. */ + +#pragma once + +#include diff --git a/platform/beken-7231t/fixups/sys_config.h b/platform/beken-7231t/fixups/sys_config.h new file mode 100644 index 0000000..0291e51 --- /dev/null +++ b/platform/beken-7231t/fixups/sys_config.h @@ -0,0 +1,116 @@ +#pragma once + +#define BLE_DEFAULT_WIFI_REQUEST 2 +#define BLE_VERSION_4_2 1 +#define BLE_VERSION_5_x 2 +#define BLE_WIFI_CO_REQUEST 3 +#define CFG_AIRKISS_TEST 0 +#define CFG_AP_MONITOR_COEXIST 0 +#define CFG_AP_SUPPORT_HT_IE 0 +#define CFG_BACKGROUND_PRINT 0 +#define CFG_BK_AWARE 0 +#define CFG_BK_AWARE_OUI "\xC8\x47\x8C" +#define CFG_BLE_VERSION BLE_VERSION_4_2 +#define CFG_EASY_FLASH 1 +#define CFG_ENABLE_BUTTON 0 +#define CFG_ENABLE_DEMO_TEST 0 +#define CFG_ENABLE_WPA_LOG 0 +#define CFG_GENERAL_DMA 1 +#define CFG_IEEE80211N 1 +#define CFG_IEEE80211W 0 +#define CFG_INT_WDG_ENABLED 1 +#define CFG_INT_WDG_PERIOD_MS 10000 +#define CFG_IPERF_TEST 0 +#define CFG_JTAG_ENABLE 0 +#define CFG_LESS_MEMERY_IN_RWNX 0 +#define CFG_MAC_PHY_BAPASS 1 +#define CFG_MSDU_RESV_HEAD_LEN 96 +#define CFG_MSDU_RESV_TAIL_LEN 16 +#define CFG_REAL_SDIO 0 +#define CFG_RELEASE_FIRMWARE 0 +#define CFG_RF_OTA_TEST 0 +#define CFG_ROLE_LAUNCH 0 +#define CFG_RUNNING_PLATFORM SOC_PLATFORM +#define CFG_RWNX_QOS_MSDU 1 +#define CFG_RX_SENSITIVITY_TEST 1 +#define CFG_SARADC_CALIBRATE 0 +#define CFG_SDIO 0 +#define CFG_SDIO_TRANS 0 +#define CFG_SOC_NAME SOC_BK7231U +#define CFG_SUPPORT_BKREG 1 +#define CFG_SUPPORT_BLE 1 +#define CFG_SUPPORT_BLE_MESH 0 +#define CFG_SUPPORT_BOOTLOADER 1 +#define CFG_SUPPORT_BSSID_CONNECT 0 +#define CFG_SUPPORT_CALIBRATION 1 +#define CFG_SUPPORT_MANUAL_CALI 1 +#define CFG_SUPPORT_OTA_HTTP 1 +#define CFG_SUPPORT_OTA_TFTP 0 +#define CFG_SUPPORT_TPC_PA_MAP 1 +#define CFG_SYS_REDUCE_NORMAL_POWER 0 +#define CFG_TASK_WDG_ENABLED 1 +#define CFG_TASK_WDG_PERIOD_MS 60000 +#define CFG_TCP_SERVER_TEST 0 +#define CFG_TX_EVM_TEST 1 +#define CFG_UART_DEBUG 0 +#define CFG_UART_DEBUG_COMMAND_LINE 1 +#define CFG_UDISK_MP3 0 +#define CFG_USB 0 +#define CFG_USE_AP_IDLE 0 +#define CFG_USE_AP_PS 0 +#define CFG_USE_APP_DEMO_VIDEO_TRANSFER 0 +#define CFG_USE_AUD_ADC 0 +#define CFG_USE_AUD_DAC 0 +#define CFG_USE_AUDIO 0 +#define CFG_USE_BLE_PS 1 +#define CFG_USE_CAMERA_INTF 0 +#define CFG_USE_DEEP_PS 1 +#define CFG_USE_DHCP 1 +#define CFG_USE_FAKERTC_PS 0 +#define CFG_USE_FTPD_UPGRADE 0 +#define CFG_USE_HSLAVE_SPI 0 +#define CFG_USE_LWIP_NETSTACK 1 +#define CFG_USE_MCU_PS 1 +#define CFG_USE_PTA 0 +#define CFG_USE_SDCARD_HOST 0 +#define CFG_USE_SPIDMA 0 +#define CFG_USE_STA_PS 1 +#define CFG_USE_TEMPERATURE_DETECT 0 +#define CFG_USE_TICK_CAL 1 +#define CFG_USE_UART1 0 +#define CFG_USE_USB_CHARGE 0 +#define CFG_USE_USB_DEVICE 1 +#define CFG_USE_USB_DEVICE_CARD_READER 1 +#define CFG_USE_USB_HOST 0 +#define CFG_USE_WPA_29 1 +#define CFG_WFA_CERT 0 +#define CFG_WIFI_RAW_TX_CMD 0 +#define CFG_WIFI_SENSOR 0 +#define CFG_WLAN_FAST_CONNECT 0 +#define CFG_WPA_CTRL_IFACE 1 +#define CFG_WPA3 0 +#define CFG_XTAL_FREQUENCE CFG_XTAL_FREQUENCE_26M +#define CFG_XTAL_FREQUENCE_26M 26000000 +#define CFG_XTAL_FREQUENCE_40M 40000000 +#define CONFIG_APP_MP3PLAYER 0 +#define FPGA_PLATFORM 0 +#define OSMALLOC_STATISTICAL 0 +#define RF_USE_POLICY WIFI_DEFAULT_BLE_REQUEST +#define SOC_BK7221U 3 +#define SOC_BK7231 1 +#define SOC_BK7231N 5 +#define SOC_BK7231U 2 +#define SOC_PLATFORM 1 +#define THD_APPLICATION_PRIORITY 3 +#define THD_CORE_PRIORITY 2 +#define THD_EXTENDED_APP_PRIORITY 5 +#define THD_HOSTAPD_PRIORITY 5 +#define THD_INIT_PRIORITY 4 +#define THD_LWIP_PRIORITY 4 +#define THD_MEDIA_PRIORITY 4 +#define THD_RECONNECT_PRIORITY 4 +#define THD_UBG_PRIORITY 5 +#define THD_UMP3_PRIORITY 4 +#define THD_WPAS_PRIORITY 5 +#define THDD_KEY_SCAN_PRIORITY 7 +#define WIFI_DEFAULT_BLE_REQUEST 1 diff --git a/platform/common/fixups/errno.h b/platform/common/fixups/errno.h new file mode 100644 index 0000000..3e47b85 --- /dev/null +++ b/platform/common/fixups/errno.h @@ -0,0 +1,18 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-06-13. */ + +#pragma once + +// This is an attempt to bring at least some order to , as +// it's generally a source of problems everywhere. +// The idea is that all units will try to import this errno.h first, +// which means it won't use lwIP's error codes. +// The code below was moved from realtek-ambz/fixups during +// porting of BK72XX SDK, when the errno stroke again. + +// There are two different errno's: +// - first is just an int +// - second is a macro that calls __errno() +// Here the first option is ensured in the entire project. +#include // use system __errno() & error codes +#undef errno // undefine __errno() macro +extern int errno; // use a global errno variable diff --git a/platform/common/fixups/lwip/errno.h b/platform/common/fixups/lwip/errno.h new file mode 100644 index 0000000..75e45b6 --- /dev/null +++ b/platform/common/fixups/lwip/errno.h @@ -0,0 +1,5 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-06-13. */ + +#pragma once + +#include "../errno.h" diff --git a/platform/realtek-ambz/fixups/inc/platform_opts.h b/platform/realtek-ambz/fixups/inc/platform_opts.h index a2d6d16..4a338f0 100644 --- a/platform/realtek-ambz/fixups/inc/platform_opts.h +++ b/platform/realtek-ambz/fixups/inc/platform_opts.h @@ -2,6 +2,7 @@ // - 2022-05-08 change CONFIG_USE_POLARSSL to CONFIG_USE_MBEDTLS // - 2022-05-08 use static int errno // - 2022-05-18 include lwip/init.h +// - 2022-06-13 extract errno to common/fixups/errno.h /** @@ -15,14 +16,6 @@ #include "platform_autoconf.h" -// There are two different errno's: -// - first is just an int -// - second is a macro that calls __errno() -// Here the first option is ensured in the entire project. -#include // use system __errno() & error codes -#undef errno // undefine __errno() macro -extern int errno; // use a static errno - #include /*For MP mode setting*/ diff --git a/tools/link2bin.py b/tools/link2bin.py index 8af38ca..345a88c 100644 --- a/tools/link2bin.py +++ b/tools/link2bin.py @@ -13,28 +13,62 @@ from shutil import copyfile from subprocess import PIPE, Popen from typing import IO, Dict, List, Tuple -from tools.util.fileio import chext, chname, isnewer, readbin -from tools.util.intbin import inttole32 +from tools.util.fileio import chext, isnewer +from tools.util.models import Family +from tools.util.obj import get +from tools.util.platform import get_board_manifest, get_family class SocType(Enum): UNSET = () - AMBZ = (1, "arm-none-eabi-", True) + # (index, toolchain prefix, has dual-OTA, argument count) + AMBZ = (1, "arm-none-eabi-", True, 0) + BK72XX = (2, "arm-none-eabi-", False, 0) def cmd(self, cmd: str) -> IO[bytes]: try: - process = Popen(self.value[1] + cmd, stdout=PIPE) + process = Popen(self.prefix + cmd, stdout=PIPE) except FileNotFoundError: - print(f"Toolchain not found while running: '{self.value[1] + cmd}'") + print(f"Toolchain not found while running: '{self.prefix + cmd}'") exit(1) return process.stdout @property - def dual_ota(self): + def prefix(self) -> str: + return self.value[1] + + @property + def dual_ota(self) -> bool: return self.value[2] + @property + def soc_argc(self) -> int: + return self.value[3] + + def nm(self, input: str) -> Dict[str, int]: + out = {} + stdout = self.cmd(f"gcc-nm {input}") + for line in stdout.readlines(): + line = line.decode().strip().split(" ") + if len(line) != 3: + continue + out[line[2]] = int(line[0], 16) + return out + + def objcopy( + self, + input: str, + output: str, + sections: List[str] = [], + fmt: str = "binary", + ) -> str: + # print graph element + print(f"| | |-- {basename(output)}") + if isnewer(input, output): + sections = " ".join(f"-j {section}" for section in sections) + self.cmd(f"objcopy {sections} -O {fmt} {input} {output}").read() + return output -soc: "SocType" = SocType.UNSET # _ _ _ _ _ _ _ _ # | | | | | (_) (_) | (_) @@ -47,102 +81,34 @@ def checkfile(path: str): exit(1) -# ____ _ _ _ _ -# | _ \(_) | | (_) | -# | |_) |_ _ __ _ _| |_ _| |___ -# | _ <| | '_ \| | | | __| | / __| -# | |_) | | | | | |_| | |_| | \__ \ -# |____/|_|_| |_|\__,_|\__|_|_|___/ -def nm(input: str) -> Dict[str, int]: - out = {} - stdout = soc.cmd(f"gcc-nm {input}") - for line in stdout.readlines(): - line = line.decode().strip().split(" ") - if len(line) != 3: - continue - out[line[2]] = int(line[0], 16) - return out - - -def objcopy( - input: str, - output: str, - sections: List[str], - fmt: str = "binary", -) -> str: - # print graph element - print(f"| | |-- {basename(output)}") - if isnewer(input, output): - sections = " ".join(f"-j {section}" for section in sections) - soc.cmd(f"objcopy {sections} -O {fmt} {input} {output}").read() - return output - - # ______ _ ______ _ ____ _____ _ _ # | ____| | | ____| | | | _ \_ _| \ | | # | |__ | | | |__ | |_ ___ | |_) || | | \| | # | __| | | | __| | __/ _ \ | _ < | | | . ` | # | |____| |____| | | || (_) | | |_) || |_| |\ | # |______|______|_| \__\___/ |____/_____|_| \_| -def elf2bin_ambz(input: str, ota_idx: int = 1) -> Tuple[int, str]: - def write_header(f: IO[bytes], start: int, end: int): - f.write(b"81958711") - f.write(inttole32(end - start)) - f.write(inttole32(start)) - f.write(b"\xff" * 16) - - sections_ram = [ - ".ram_image2.entry", - ".ram_image2.data", - ".ram_image2.bss", - ".ram_image2.skb.bss", - ".ram_heap.data", - ] - sections_xip = [".xip_image2.text"] - sections_rdp = [".ram_rdp.text"] - nmap = nm(input) - ram_start = nmap["__ram_image2_text_start__"] - ram_end = nmap["__ram_image2_text_end__"] - xip_start = nmap["__flash_text_start__"] - 0x8000020 - # build output name - output = chname(input, f"image_0x{xip_start:06X}.ota{ota_idx}.bin") - out_ram = chname(input, f"ota{ota_idx}.ram_2.r.bin") - out_xip = chname(input, f"ota{ota_idx}.xip_image2.bin") - out_rdp = chname(input, f"ota{ota_idx}.rdp.bin") - # print graph element - print(f"| |-- {basename(output)}") - # objcopy required images - ram = objcopy(input, out_ram, sections_ram) - xip = objcopy(input, out_xip, sections_xip) - objcopy(input, out_rdp, sections_rdp) - # return if images are up to date - if not isnewer(ram, output) and not isnewer(xip, output): - return (xip_start, output) - - # read and trim RAM image - ram = readbin(ram).rstrip(b"\x00") - # read XIP image - xip = readbin(xip) - # align images to 4 bytes - ram += b"\x00" * (((((len(ram) - 1) // 4) + 1) * 4) - len(ram)) - xip += b"\x00" * (((((len(xip) - 1) // 4) + 1) * 4) - len(xip)) - # write output file - with open(output, "wb") as f: - # write XIP header - write_header(f, 0, len(xip)) - # write XIP image - f.write(xip) - # write RAM header - write_header(f, ram_start, ram_end) - # write RAM image - f.write(ram) - return (xip_start, output) - - -def elf2bin(input: str, ota_idx: int = 1) -> Tuple[int, str]: +def elf2bin( + soc: SocType, + family: Family, + board: dict, + input: str, + ota_idx: int = 1, + args: List[str] = [], +) -> Tuple[int, str]: checkfile(input) + func = None + if soc == SocType.AMBZ: - return elf2bin_ambz(input, ota_idx) + from tools.soc.link2bin_ambz import elf2bin_ambz + + func = elf2bin_ambz + elif soc == SocType.BK72XX: + from tools.soc.link2bin_bk72xx import elf2bin_bk72xx + + func = elf2bin_bk72xx + + if func: + return func(soc, family, board, input, ota_idx, *args) raise NotImplementedError(f"SoC ELF->BIN not implemented: {soc}") @@ -181,17 +147,21 @@ def ldargs_parse( def link2bin( - args: List[str], + soc: SocType, + family: Family, + board: dict, + ld_args: List[str], ld_ota1: str = None, ld_ota2: str = None, + soc_args: List[str] = [], ) -> List[str]: elfs = [] if soc.dual_ota: # process linker arguments for dual-OTA chips - elfs = ldargs_parse(args, ld_ota1, ld_ota2) + elfs = ldargs_parse(ld_args, ld_ota1, ld_ota2) else: # just get .elf output name for single-OTA chips - elfs = ldargs_parse(args, None, None) + elfs = ldargs_parse(ld_args, None, None) if not elfs: return None @@ -206,12 +176,12 @@ def link2bin( soc.cmd(f"gcc {ldargs}").read() checkfile(elf) # generate a set of binaries for the SoC - elf2bin(elf, ota_idx) + elf2bin(soc, family, board, elf, ota_idx, soc_args) ota_idx += 1 if soc.dual_ota: # copy OTA1 file as firmware.elf to make PIO understand it - elf, _ = ldargs_parse(args, None, None)[0] + elf, _ = ldargs_parse(ld_args, None, None)[0] copyfile(elfs[0][0], elf) @@ -221,17 +191,34 @@ if __name__ == "__main__": description="Link to BIN format", prefix_chars="@", ) - parser.add_argument("soc", type=str, help="SoC name/family short name") + parser.add_argument("board", type=str, help="Target board name") parser.add_argument("ota1", type=str, help=".LD file OTA1 pattern") parser.add_argument("ota2", type=str, help=".LD file OTA2 pattern") - parser.add_argument("args", type=str, nargs="*", help="Linker arguments") + parser.add_argument("args", type=str, nargs="*", help="SoC+linker arguments") args = parser.parse_args() + try: - soc = next(soc for soc in SocType if soc.name == args.soc) - except StopIteration: - print(f"Not a valid SoC: {args.soc}") + board = get_board_manifest(args.board) + except FileNotFoundError: + print(f"Board not found: {args.board}") exit(1) + + family = get_family(short_name=get(board, "build.family")) + soc_types = {soc.name.lower(): soc for soc in SocType} + soc = soc_types.get(family.code, soc_types.get(family.parent_code, None)) + if not soc: + print(f"SoC type not found. Tried {family.code}, {family.parent_code}") + exit(1) + if not args.args: print(f"Linker arguments must not be empty") exit(1) - link2bin(args.args, args.ota1, args.ota2) + link2bin( + soc, + family, + board, + args.args[soc.soc_argc :], + args.ota1, + args.ota2, + args.args[: soc.soc_argc], + ) diff --git a/tools/soc/link2bin_ambz.py b/tools/soc/link2bin_ambz.py new file mode 100644 index 0000000..6bf6835 --- /dev/null +++ b/tools/soc/link2bin_ambz.py @@ -0,0 +1,69 @@ +# Copyright (c) Kuba Szczodrzyński 2022-06-14. + +from os.path import basename +from typing import IO, Tuple + +from tools.util.fileio import chname, isnewer, readbin +from tools.util.intbin import inttole32 +from tools.util.models import Family + + +def elf2bin_ambz( + soc, + family: Family, + board: dict, + input: str, + ota_idx: int = 1, +) -> Tuple[int, str]: + def write_header(f: IO[bytes], start: int, end: int): + f.write(b"81958711") + f.write(inttole32(end - start)) + f.write(inttole32(start)) + f.write(b"\xff" * 16) + + sections_ram = [ + ".ram_image2.entry", + ".ram_image2.data", + ".ram_image2.bss", + ".ram_image2.skb.bss", + ".ram_heap.data", + ] + sections_xip = [".xip_image2.text"] + sections_rdp = [".ram_rdp.text"] + nmap = soc.nm(input) + ram_start = nmap["__ram_image2_text_start__"] + ram_end = nmap["__ram_image2_text_end__"] + xip_start = nmap["__flash_text_start__"] - 0x8000020 + # build output name + output = chname(input, f"image_0x{xip_start:06X}.ota{ota_idx}.bin") + out_ram = chname(input, f"ota{ota_idx}.ram_2.r.bin") + out_xip = chname(input, f"ota{ota_idx}.xip_image2.bin") + out_rdp = chname(input, f"ota{ota_idx}.rdp.bin") + # print graph element + print(f"| |-- {basename(output)}") + # objcopy required images + ram = soc.objcopy(input, out_ram, sections_ram) + xip = soc.objcopy(input, out_xip, sections_xip) + soc.objcopy(input, out_rdp, sections_rdp) + # return if images are up to date + if not isnewer(ram, output) and not isnewer(xip, output): + return (xip_start, output) + + # read and trim RAM image + ram = readbin(ram).rstrip(b"\x00") + # read XIP image + xip = readbin(xip) + # align images to 4 bytes + ram += b"\x00" * (((((len(ram) - 1) // 4) + 1) * 4) - len(ram)) + xip += b"\x00" * (((((len(xip) - 1) // 4) + 1) * 4) - len(xip)) + # write output file + with open(output, "wb") as f: + # write XIP header + write_header(f, 0, len(xip)) + # write XIP image + f.write(xip) + # write RAM header + write_header(f, ram_start, ram_end) + # write RAM image + f.write(ram) + return (xip_start, output) diff --git a/tools/soc/link2bin_bk72xx.py b/tools/soc/link2bin_bk72xx.py new file mode 100644 index 0000000..31b3522 --- /dev/null +++ b/tools/soc/link2bin_bk72xx.py @@ -0,0 +1,57 @@ +# Copyright (c) Kuba Szczodrzyński 2022-06-14. + +from datetime import datetime +from os import stat +from os.path import basename +from typing import Tuple + +from tools.util.bkutil import RBL, BekenBinary +from tools.util.fileio import chext, chname, isnewer, writebin, writejson +from tools.util.models import Family +from tools.util.obj import get + + +def calc_offset(addr: int) -> int: + return int(addr + (addr // 32) * 2) + + +def elf2bin_bk72xx( + soc, + family: Family, + board: dict, + input: str, + ota_idx: int = 1, +) -> Tuple[int, str]: + mcu = get(board, "build.mcu") + coeffs = get(board, "build.bkcrypt_coeffs") or ("0" * 32) + rbl_size = get(board, "build.bkrbl_size_app") + version = datetime.now().strftime("%y.%m.%d") + + nmap = soc.nm(input) + app_addr = nmap["_vector_start"] + app_offs = calc_offset(app_addr) + app_size = int(rbl_size, 16) + + # build output name + output = chname(input, f"{mcu}_app_0x{app_offs:06X}.bin") + fw_bin = chext(input, "bin") + # objcopy ELF -> raw BIN + soc.objcopy(input, fw_bin) + # print graph element + print(f"| |-- {basename(output)}") + # return if images are up to date + if not isnewer(fw_bin, output): + return (app_offs, output) + + bk = BekenBinary(coeffs) + rbl = RBL( + name="app", + version=f"{version}-{mcu}", + container_size=app_size, + ) + + fw_size = stat(fw_bin).st_size + raw = open(fw_bin, "rb") + out = open(output, "wb") + for data in bk.package(raw, app_addr, fw_size, rbl): + out.write(data) diff --git a/tools/util/fileio.py b/tools/util/fileio.py index 328179a..82dcbdc 100644 --- a/tools/util/fileio.py +++ b/tools/util/fileio.py @@ -51,3 +51,9 @@ def readjson(file: str) -> Union[dict, list]: """Read a JSON file into a dict or list.""" with open(file, "r", encoding="utf-8") as f: return json.load(f) + + +def writejson(file: str, data: Union[dict, list]): + """Write a dict or list to a JSON file.""" + with open(file, "w", encoding="utf-8") as f: + json.dump(data, f)