[beken-72xx] Implement SDK binary building

This commit is contained in:
Kuba Szczodrzyński
2022-06-14 15:39:28 +02:00
parent 191a2bdd2a
commit 540e499389
18 changed files with 1050 additions and 170 deletions

View File

@@ -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",

View File

@@ -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", "<tls_config.h>"),
("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=[
"+<app/app.c>",
"+<app/ate_app.c>",
"+<app/config/param_config.c>",
"+<demo/*.c>",
"+<driver/driver.c>",
"+<driver/entry/arch_main.c>",
"+<driver/entry/boot_handlers.S>",
"+<driver/entry/boot_vectors.S>",
"+<driver/intc/intc.c>",
"+<func/func.c>",
"+<func/wlan_ui/bk_peripheral_test.c>",
"+<func/wlan_ui/wlan_cli.c>",
"+<func/wlan_ui/wlan_ui.c>",
],
includes=[
"+<app>",
"+<app/config>",
"+<common>",
"+<demo>",
"+<driver/entry>",
"+<driver/intc>",
"+<release>",
"+<../release>",
],
)
# Sources - app module
env.AddLibrary(
name="bdk_app",
base_dir=APP_DIR,
srcs=[
"+<http/*.c>",
"+<net_work/*.c>",
"+<standalone-ap/*.c>",
"+<standalone-station/*.c>",
"+<video_work/*.c>",
],
includes=[
"+<http>",
"+<net_work>",
"+<standalone-ap>",
"+<standalone-station>",
"+<video_work>",
],
)
# Sources - drivers
env.AddLibrary(
name="bdk_driver",
base_dir=DRIVER_DIR,
srcs=[
"+<calendar/*.c>",
"+<common/*.c>",
"+<dma/*.c>",
"+<fft/*.c>",
"+<flash/*.c>",
"+<general_dma/*.c>",
"+<gpio/*.c>",
"+<i2c/*.c>",
"+<i2s/*.c>",
"+<icu/*.c>",
"+<irda/*.c>",
"+<jpeg/*.c>",
"+<macphy_bypass/*.c>",
"+<phy/*.c>",
"+<pwm/*.c>",
"-<pwm/pwm_bk7271.c>",
"-<pwm/pwm_new.c>",
"+<qspi/*.c>",
"+<rw_pub/*.c>",
"+<saradc/*.c>",
"+<security/*.c>",
"+<spidma/*.c>",
"+<sys_ctrl/*.c>",
"+<uart/*.c>",
"+<wdt/*.c>",
],
includes=[
"+<common>",
"+<common/reg>",
"+<dma>",
"+<flash>",
"+<general_dma>",
"+<gpio>",
"+<i2c>",
"+<icu>",
"+<include>",
"+<jpeg>",
"+<phy>",
"+<pwm>",
"+<rc_beken>",
"+<rw_pub>",
"+<spi>",
"+<spidma>",
"+<sys_ctrl>",
"+<uart>",
"+<usb>",
"+<../ip/**>",
],
)
# Sources - functional components
env.AddLibrary(
name="bdk_func",
base_dir=FUNC_DIR,
srcs=[
"+<airkiss/*.c>",
"+<base64/*.c>",
"+<ble_wifi_exchange/*.c>",
"+<camera_intf/*.c>",
"+<hostapd_intf/*.c>",
"+<joint_up/*.c>",
"+<misc/*.c>",
"+<net_param_intf/*.c>",
"+<power_save/*.c>",
"+<rwnx_intf/*.c>",
"+<saradc_intf/*.c>",
"+<security/*.c>",
"+<sim_uart/*.c>",
"+<spidma_intf/*.c>",
"+<temp_detect/*.c>",
"+<usb_plug/*.c>",
"+<user_driver/*.c>",
"-<user_driver/BkDriverQspi.c>",
"+<utf8/*.c>",
"+<video_transfer/*.c>",
],
includes=[
"+<base64>",
"+<ble_wifi_exchange>",
"+<camera_intf>",
"+<easy_flash>",
"+<easy_flash/inc>",
"+<easy_flash/port>",
"+<ethernet_intf>",
"+<include>",
"+<joint_up>",
"+<power_save>",
"+<rf_test>",
"+<rf_use>",
"+<rwnx_intf>",
"+<saradc_intf>",
"+<sensor>",
"+<spidma_intf>",
"+<temp_detect>",
"+<uart_debug>",
"+<usb>",
"+<user_driver>",
"+<utf8>",
"+<video_transfer>",
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=[
"+<os/**/*.c>",
],
includes=[
"+<os/*>",
],
)
env.AddLibrary(
name="bdk_freertos_arm",
base_dir="$SDK_DIR",
srcs=[
"+<FreeRTOSv9.0.0/FreeRTOS/Source/**/*.c>",
],
includes=[
"+<FreeRTOSv9.0.0/FreeRTOS/Source/include>",
"+<FreeRTOSv9.0.0/FreeRTOS/Source/portable/Keil/ARM968es>",
],
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=[
"+<lwip-2.0.2/port/*.c>",
"+<lwip-2.0.2/src/api/*.c>",
"+<lwip-2.0.2/src/apps/ping/*.c>",
"+<lwip-2.0.2/src/core/*.c>",
"+<lwip-2.0.2/src/core/ipv4/*.c>",
"+<lwip-2.0.2/src/core/ipv6/*.c>",
"+<lwip-2.0.2/src/netif/ethernet.c>",
"+<dhcpd/*.c>",
],
includes=[
"+<lwip-2.0.2/port>",
"+<lwip-2.0.2/src/include>",
"+<lwip-2.0.2/src/include/netif>",
],
options=dict(CCFLAGS=["-Wno-missing-braces"]),
)
# Sources - mbedTLS 2.6.0
env.AddLibrary(
name="bdk_mbedtls",
base_dir=join(FUNC_DIR, "mbedtls"),
srcs=[
"+<mbedtls/library/*.c>",
"+<mbedtls_ui/*.c>",
"+<mbedtls-port/src/*.c>",
],
includes=[
"+<mbedtls/include>",
"+<mbedtls_ui>",
"+<mbedtls-port/inc>",
],
options=dict(
CCFLAGS=["-Wno-unused-variable"],
CFLAGS=["-<-Wall>"],
),
)
# Sources - demos TODO remove this
env.AddLibrary(
name="bdk_demos",
base_dir="$SDK_DIR",
srcs=[
"+<demos/**/*.c>",
"-<demos/components/**/*.c>",
"-<demos/net/mqtt/*>",
"-<demos/wifi/bk_aware/*.c>",
],
includes=[
"+<demos>",
"+<demos/**>",
],
)
# Sources - chip-specific drivers
if SOC in [SOC_BK7231U, SOC_BK7251]:
env.AddLibrary(
name="bdk_driver_spi",
base_dir=join(DRIVER_DIR, "spi"),
srcs=[
"+<spi.c>",
"+<spi_master.c>",
"+<spi_slave.c>",
],
)
if SOC in [SOC_BK7231N]:
env.AddLibrary(
name="bdk_driver_spi",
base_dir=join(DRIVER_DIR, "spi"),
srcs=[
"+<spi_bk7231n.c>",
"+<spi_master_bk7231n.c>",
"+<spi_slave_bk7231n.c>",
],
)
if SOC in [SOC_BK7251]:
env.AddLibrary(
name="bdk_bk7251",
base_dir=ROOT_DIR,
srcs=[
"+<driver/audio/*.c>",
"+<driver/sdcard/*.c>",
"+<func/audio/*.c>",
"+<func/sd_music/*.c>",
],
includes=[
"+<driver/audio>",
"+<driver/sdcard>",
],
)
# Sources - enabled through config
if env.Cfg("CFG_SDIO"):
env.AddLibrary(
name="bdk_driver_sdio",
base_dir=ROOT_DIR,
srcs=[
"+<driver/sdio/*.c>",
"+<func/sdio_intf/*.c>",
],
)
if env.Cfg("CFG_BK_AWARE"):
env.AddLibrary(
name="bdk_driver_sdio",
base_dir="$SDK_DIR",
srcs=[
"+<beken378/func/bk_aware/*.c>",
"+<demos/wifi/bk_aware/*.c>",
],
includes=[
"+<beken378/func/bk_aware>",
],
)
if env.Cfg("CFG_USE_SDCARD_HOST"):
env.AddLibrary(
name="bdk_func_fatfs",
base_dir=join(FUNC_DIR, "fatfs"),
srcs=[
"+<*.c>",
"-<test_fatfs.c>",
],
includes=[
"+<.>",
],
)
if env.Cfg("CFG_WPA3"):
env.AddLibrary(
name="bdk_wolfssl",
base_dir=join(FUNC_DIR, "wolfssl"),
srcs=[
"+<wolfcrypt/src/ecc.c>",
"+<wolfcrypt/src/memory.c>",
"+<wolfcrypt/src/random.c>",
"+<wolfcrypt/src/sha256.c>",
"+<wolfcrypt/src/tfm.c>",
"+<wolfcrypt/src/wolfmath.c>",
],
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>",
"+<beken_ble_sdk/mesh/src/dbg>",
"+<config>",
"+<modules/**>",
"+<plactform/arch>",
"+<plactform/driver/*>",
"+<profiles/*/api>",
],
)
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>",
"-<ble_pub/app/src/app_ble_task.c>",
"-<platform/7231n/nvds/src/nvds.c>",
],
includes=[
"+<**/api>",
"+<arch/**>",
"+<ble_lib/ip/ble/**>",
"+<ble_lib/ip/hci/src>",
"+<ble_lib/ip/sch/import>",
"+<ble_lib/modules/*/src>",
"+<ble_pub/prf>",
"+<ble_pub/ui>",
"+<platform/7231n/**>",
"-<platform/7231n/nvds/**>",
],
)
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=[
"+<driver/usb/*.c>",
"+<func/usb/*.c>",
],
includes=[
"+<driver/usb/**>",
],
)
# 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} '' ''",
)

View File

@@ -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

View File

@@ -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)

50
builder/utils/config.py Normal file
View File

@@ -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")

View File

@@ -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",

View File

@@ -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])

View File

@@ -0,0 +1,5 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-13. */
#pragma once
#include <mbedtls/certs.h>

View File

@@ -0,0 +1,5 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-13. */
#pragma once
#include <lwip/netdb.h>

View File

@@ -0,0 +1,5 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-23. */
#pragma once
#include <lwip/sockets.h>

View File

@@ -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

View File

@@ -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 <errno.h>, 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 <sys/errno.h> // use system __errno() & error codes
#undef errno // undefine __errno() macro
extern int errno; // use a global errno variable

View File

@@ -0,0 +1,5 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-13. */
#pragma once
#include "../errno.h"

View File

@@ -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 <errno.h> // use system __errno() & error codes
#undef errno // undefine __errno() macro
extern int errno; // use a static errno
#include <lwip/init.h>
/*For MP mode setting*/

View File

@@ -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],
)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)