[core] Build with properties from Family object

This commit is contained in:
Kuba Szczodrzyński
2022-06-12 12:42:32 +02:00
parent dba602a081
commit c3e2c105d4
15 changed files with 290 additions and 196 deletions

View File

@@ -52,8 +52,75 @@ env.AddLibrary(
],
)
# Sources - board variant
env.AddLibrary(
name="board_${VARIANT}",
base_dir="$BOARD_DIR",
srcs=[
"+<variant.cpp>",
],
)
for code, base_dir in env["ARDUINO_DIRS"].items():
code = env.subst(code)
base_dir = env.subst(base_dir)
if not code or not isdir(base_dir):
# Skip unused paths
continue
# Sources - Arduino Core
env.AddLibrary(
name=f"{code}_arduino_core",
base_dir=base_dir,
srcs=[
# Wiring core
"+<cores/arduino/*.c>",
"+<cores/arduino/*.cpp>",
],
includes=[
# prepend these as the Arduino core may be incorrectly picking some includes from SDKs
"!<cores/arduino>",
],
)
# Sources - Arduino libraries
env.AddLibrary(
name=f"{code}_arduino_libs",
base_dir=base_dir,
srcs=[
"+<libraries/*/*.cpp>",
],
includes=[
"+<libraries/*>",
],
)
# Sources - external library ports
env.AddLibrary(
name=f"{code}_arduino_port",
base_dir=base_dir,
srcs=[
"+<port/**/*.c*>",
],
includes=[
"+<port/*>",
],
)
# Sources - external library ports
env.AddLibraryFlashDB(version="03500fa")
# Libs & linker config
env.Append(
LIBS=[
"stdc++",
"supc++",
],
)
env.Replace(
# Change to Arduino linker script
LDSCRIPT_PATH=["${LDSCRIPT_ARDUINO}"],
)
# Build all libraries
env.BuildLibraries(safe=False)

View File

@@ -1,7 +1,5 @@
# Copyright (c) Kuba Szczodrzyński 2022-04-22.
from os.path import join
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
@@ -64,72 +62,5 @@ env.Append(
# Arduino core uses __libc_init_array
env["LINKFLAGS"].remove("-nostartfiles")
# Sources - Arduino Core
env.AddLibrary(
name="ambz_arduino_core",
base_dir="$ARDUINO_DIR",
srcs=[
# Wiring core
"+<cores/arduino/*.c>",
"+<cores/arduino/*.cpp>",
],
includes=[
# prepend these as the Arduino core is incorrectly picking some includes from SDK
"!<cores/arduino>",
# includes that are missing in the vanilla SDK makefiles
"+<$SDK_DIR/component/common/drivers/sdio/realtek/sdio_host/inc>",
"+<$SDK_DIR/component/common/file_system/fatfs>",
"+<$SDK_DIR/component/common/file_system/fatfs/r0.10c/include>",
"+<$SDK_DIR/component/common/network/mdns>",
"+<$SDK_DIR/component/common/network/libwsclient>",
],
)
# Sources - board variant
env.AddLibrary(
name="ambz_${VARIANT}",
base_dir="$BOARD_DIR",
srcs=[
"+<variant.cpp>",
],
)
# Sources - Arduino libraries
env.AddLibrary(
name="ambz_arduino_libs",
base_dir="$ARDUINO_DIR",
srcs=[
"+<libraries/*/*.cpp>",
],
includes=[
"+<libraries/*>",
],
)
# Sources - external library ports
env.AddLibrary(
name="ambz_arduino_port",
base_dir="$ARDUINO_DIR",
srcs=[
"+<port/**/*.c*>",
],
includes=[
"+<port/*>",
],
)
# Libs & linker config
env.Append(
LIBS=[
"stdc++",
"supc++",
],
)
env.Replace(
LDSCRIPT_PATH=[
join("$LD_DIR", "$LDSCRIPT_ARDUINO"),
],
)
# Build all libraries
env.BuildLibraries()

View File

@@ -7,8 +7,6 @@ from SCons.Script import Builder, DefaultEnvironment
env = DefaultEnvironment()
board = env.BoardConfig()
env.AddDefaults("realtek-ambz", "framework-realtek-amb1")
# Flags
env.Append(
CFLAGS=[
@@ -187,8 +185,14 @@ env.AddLibrary(
"+<component/common/mbed/hal_ext>",
"+<component/common/mbed/targets/cmsis>",
"+<component/common/mbed/targets/hal/rtl8711b>",
# keep PolarSSL for headers for ROM crypto functions
# keep PolarSSL headers for ROM crypto functions
"+<component/common/network/ssl/polarssl-1.3.8/include>",
# includes that are missing in the vanilla SDK makefiles
"+<component/common/drivers/sdio/realtek/sdio_host/inc>",
"+<component/common/file_system/fatfs>",
"+<component/common/file_system/fatfs/r0.10c/include>",
"+<component/common/network/mdns>",
"+<component/common/network/libwsclient>",
],
)
@@ -214,7 +218,7 @@ env.AddLibrary(
# Sources - family fixups
env.AddLibrary(
name="ambz_fixups",
base_dir="$FIXUPS_DIR",
base_dir="$FAMILY_DIR/fixups",
srcs=[
"+<app_start_patch.c>",
"+<cmsis_ipsr.c>",
@@ -249,11 +253,6 @@ env.Append(
"_mdns",
],
)
env.Replace(
LDSCRIPT_PATH=[
join("$LD_DIR", "$LDSCRIPT_SDK"),
],
)
# Misc options
env.Replace(

View File

@@ -5,11 +5,17 @@ import sys
from SCons.Script import Default, DefaultEnvironment
env = DefaultEnvironment()
platform = env.PioPlatform()
board = env.BoardConfig()
# Make tools available
sys.path.insert(0, platform.get_dir())
# Utilities
env.SConscript("utils.py", exports="env")
env.SConscript("uf2.py", exports="env")
env.SConscript("utils/env.py", exports="env")
env.SConscript("utils/flash.py", exports="env")
env.SConscript("utils/libs.py", exports="env")
env.SConscript("utils/uf2.py", exports="env")
# Vendor-specific library ports
env.SConscript("libs/lwip.py", exports="env")
env.SConscript("libs/flashdb.py", exports="env")
@@ -34,26 +40,12 @@ env.Replace(
SIZETOOL="arm-none-eabi-size",
)
# Default environment options
env.AddDefaults(platform, board)
# Flash layout defines
flash_layout: dict = board.get("flash")
if flash_layout:
defines = {}
flash_size = 0
fal_items = ""
for name, layout in flash_layout.items():
name = name.upper()
(offset, _, length) = layout.partition("+")
defines[f"FLASH_{name}_OFFSET"] = offset
defines[f"FLASH_{name}_LENGTH"] = length
fal_items += f"FAL_PART_TABLE_ITEM({name.lower()}, {name})"
flash_size = max(flash_size, int(offset, 16) + int(length, 16))
defines["FLASH_LENGTH"] = flash_size
defines["FAL_PART_TABLE"] = "{" + fal_items + "}"
env.Append(CPPDEFINES=defines.items())
env.Replace(**defines)
env.AddFlashLayout(board)
# Family builders details:
# - call env.AddDefaults("family name", "sdk name") to add dir paths
# - call env.AddLibrary("lib name", "base dir", [sources]) to add lib sources
# - call env.BuildLibraries() to build lib targets with safe envs
# - configure LINK, UF2OTA and UPLOAD_ACTIONS

76
builder/utils/env.py Normal file
View File

@@ -0,0 +1,76 @@
# Copyright (c) Kuba Szczodrzyński 2022-05-04.
from os.path import isdir, join
from SCons.Script import DefaultEnvironment
from tools.util.platform import get_family
env = DefaultEnvironment()
def env_add_defaults(env, platform, board):
# Get Family object for this board
family = get_family(short_name=board.get("build.family"))
# Default environment variables
vars = dict(
SDK_DIR=platform.get_package_dir(family.framework),
LT_DIR=platform.get_dir(),
# Root dirs
BOARD_DIR=join("${LT_DIR}", "boards", "${VARIANT}"),
ARDUINO_DIRS={
"$FAMILY_CODE": join("${LT_DIR}", "arduino", "${FAMILY_NAME}"),
"$FAMILY_PARENT_CODE": join("${LT_DIR}", "arduino", "${FAMILY_PARENT}"),
},
FAMILY_DIR=join("${LT_DIR}", "platform", "${FAMILY_NAME}"),
PARENT_DIR=join("${LT_DIR}", "platform", "${FAMILY_PARENT}"),
TOOLS_DIR=join("${LT_DIR}", "tools"),
# Family-specific paths
BIN_DIR=join("${FAMILY_DIR}", "bin"),
OPENOCD_DIR=join("${FAMILY_DIR}", "openocd"),
# Use SDK linker script by default
LDSCRIPT_PATH=["${LDSCRIPT_SDK}"],
# Board config variables
MCU=board.get("build.mcu").upper(),
VARIANT=board.get("build.variant"),
LDSCRIPT_SDK=board.get("build.ldscript_sdk"),
LDSCRIPT_ARDUINO=board.get("build.ldscript_arduino"),
# Link2Bin tool
LINK2BIN='"${PYTHONEXE}" "${LT_DIR}/tools/link2bin.py"',
UF2OTA_PY='"${PYTHONEXE}" "${LT_DIR}/tools/uf2ota/uf2ota.py"',
UF2UPLOAD_PY='"${PYTHONEXE}" "${LT_DIR}/tools/upload/uf2upload.py"',
)
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=[
"$BOARD_DIR",
"$FAMILY_DIR/fixups",
"$PARENT_DIR/fixups",
"$FAMILY_DIR/fixups/inc",
"$PARENT_DIR/fixups/inc",
],
LIBPATH=[
"$FAMILY_DIR/ld",
"$PARENT_DIR/ld",
"$FAMILY_DIR/fixups",
"$PARENT_DIR/fixups",
],
CPPDEFINES=[
("LIBRETUYA", "1"),
("LT_VERSION", platform.version),
("LT_BOARD", "${VARIANT}"),
("F_CPU", board.get("build.f_cpu")),
("MCU", "${MCU}"),
("FAMILY", "${FAMILY}"),
],
)
env.AddMethod(env_add_defaults, "AddDefaults")

27
builder/utils/flash.py Normal file
View File

@@ -0,0 +1,27 @@
# Copyright (c) Kuba Szczodrzyński 2022-06-12.
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
def env_add_flash_layout(env, board):
flash_layout: dict = board.get("flash")
if flash_layout:
defines = {}
flash_size = 0
fal_items = ""
for name, layout in flash_layout.items():
name = name.upper()
(offset, _, length) = layout.partition("+")
defines[f"FLASH_{name}_OFFSET"] = offset
defines[f"FLASH_{name}_LENGTH"] = length
fal_items += f"FAL_PART_TABLE_ITEM({name.lower()}, {name})"
flash_size = max(flash_size, int(offset, 16) + int(length, 16))
defines["FLASH_LENGTH"] = flash_size
defines["FAL_PART_TABLE"] = "{" + fal_items + "}"
env.Append(CPPDEFINES=list(defines.items()))
env.Replace(**defines)
env.AddMethod(env_add_flash_layout, "AddFlashLayout")

View File

@@ -8,58 +8,6 @@ from typing import List
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
platform = env.PioPlatform()
board = env.BoardConfig()
def env_add_defaults(env, family_name: str, sdk_name: str):
vars = dict(
SDK_DIR=platform.get_package_dir(sdk_name),
LT_DIR=platform.get_dir(),
# Root dirs
BOARD_DIR=join("${LT_DIR}", "boards", "${VARIANT}"),
ARDUINO_DIR=join("${LT_DIR}", "arduino", family_name),
FAMILY_DIR=join("${LT_DIR}", "platform", family_name),
TOOLS_DIR=join("${LT_DIR}", "tools"),
# Family-specific dirs
BIN_DIR=join("${FAMILY_DIR}", "bin"),
FIXUPS_DIR=join("${FAMILY_DIR}", "fixups"),
LD_DIR=join("${FAMILY_DIR}", "ld"),
OPENOCD_DIR=join("${FAMILY_DIR}", "openocd"),
# Board config variables
MCU=board.get("build.mcu").upper(),
FAMILY=board.get("build.family"),
VARIANT=board.get("build.variant"),
LDSCRIPT_SDK=board.get("build.ldscript_sdk"),
LDSCRIPT_ARDUINO=board.get("build.ldscript_arduino"),
# Link2Bin tool
LINK2BIN='"${PYTHONEXE}" "${LT_DIR}/tools/link2bin.py"',
UF2OTA_PY='"${PYTHONEXE}" "${LT_DIR}/tools/uf2ota/uf2ota.py"',
UF2UPLOAD_PY='"${PYTHONEXE}" "${LT_DIR}/tools/upload/uf2upload.py"',
)
env.Replace(**vars)
for k, v in vars.items():
if "DIR" in k:
assert isdir(env.subst(v)), f"{env.subst(v)} is not a directory"
env.Prepend(
CPPPATH=[
"$BOARD_DIR",
"$FIXUPS_DIR",
"$FIXUPS_DIR/inc",
],
LIBPATH=[
"$LD_DIR",
"$FIXUPS_DIR",
],
CPPDEFINES=[
("LIBRETUYA", "1"),
("LT_VERSION", platform.version),
("LT_BOARD", board.get("build.variant")),
("F_CPU", board.get("build.f_cpu")),
("MCU", board.get("build.mcu").upper()),
("FAMILY", board.get("build.family")),
],
)
def env_add_library(
@@ -130,6 +78,5 @@ def env_build_libraries(env, safe: bool = True):
env.Prepend(LIBS=[target])
env.AddMethod(env_add_defaults, "AddDefaults")
env.AddMethod(env_add_library, "AddLibrary")
env.AddMethod(env_build_libraries, "BuildLibraries")

View File

@@ -4,15 +4,15 @@ A list of families currently available in this project.
**Note:** the term *family* was chosen over *platform*, in order to reduce possible confusion between LibreTuya supported "platforms" and PlatformIO's "platform", as an entire package. *Family* is also more compatible with the UF2 term.
The following list corresponds to UF2 OTA format family names, and is also [available as JSON](../uf2families.json). The IDs are also present in [ChipType.h](../arduino/libretuya/core/ChipType.h).
The following list corresponds to UF2 OTA format family names, and is also [available as JSON](../families.json). The IDs are also present in [ChipType.h](../arduino/libretuya/core/ChipType.h).
Full name | Code | Short name & ID | Supported MCU(s) | Arduino Core | Source SDK
-----------------------------------------------------------------------|--------|-------------------------|------------------|--------------|--------------------------------------------------------------------------
Realtek Ameba1 | `-` | `RTL8710A` (0x9FFFD543) | - | ❌ | -
[Realtek AmebaZ](https://www.amebaiot.com/en/amebaz/) (`realtek-ambz`) | `ambz` | `RTL8710B` (0x22E0D6FC) | RTL87xxB | ✔️ | `framework-realtek-amb1` ([amb1_sdk](https://github.com/ambiot/amb1_sdk))
Realtek AmebaZ2 | `-` | `RTL8720C` (0xE08F7564) | - | ❌ | -
Realtek AmebaD | `-` | `RTL8720D` (0x3379CFE2) | - | ❌ | -
Beken 7231T | `-` | `BK7231T` (0x675A40B0) | - | ❌ | -
Beken 7231N | `-` | `BK7231N` (0x7B3EF230) | - | ❌ | -
Boufallo 602 | `-` | `BL602` (0xDE1270B7) | - | ❌ | -
Xradiotech 809 | `-` | `XR809` (0x51E903A8) | - | ❌ | -
Title | Name (parent) | Code | Short name & ID | Supported MCU(s) | Arduino Core | Source SDK
------------------------------------------------------|----------------|--------|-------------------------|------------------|--------------|--------------------------------------------------------------------------
Realtek Ameba1 | `-` | `-` | `RTL8710A` (0x9FFFD543) | - | ❌ | -
[Realtek AmebaZ](https://www.amebaiot.com/en/amebaz/) | `realtek-ambz` | `ambz` | `RTL8710B` (0x22E0D6FC) | RTL8710BN | ✔️ | `framework-realtek-amb1` ([amb1_sdk](https://github.com/ambiot/amb1_sdk))
Realtek AmebaZ2 | `-` | `-` | `RTL8720C` (0xE08F7564) | - | ❌ | -
Realtek AmebaD | `-` | `-` | `RTL8720D` (0x3379CFE2) | - | ❌ | -
Beken 7231T | `-` | `-` | `BK7231T` (0x675A40B0) | - | ❌ | -
Beken 7231N | `-` | `-` | `BK7231N` (0x7B3EF230) | - | ❌ | -
Boufallo 602 | `-` | `-` | `BL602` (0xDE1270B7) | - | ❌ | -
Xradiotech 809 | `-` | `-` | `XR809` (0x51E903A8) | - | ❌ | -

View File

@@ -1,7 +1,11 @@
# Copyright (c) Kuba Szczodrzyński 2022-05-31.
import json
from os.path import dirname, isdir, join
import sys
from os.path import dirname, join
sys.path.append(join(dirname(__file__), ".."))
from tools.util.platform import get_families
HEADER = """\
# Families
@@ -10,7 +14,7 @@ A list of families currently available in this project.
**Note:** the term *family* was chosen over *platform*, in order to reduce possible confusion between LibreTuya supported "platforms" and PlatformIO's "platform", as an entire package. *Family* is also more compatible with the UF2 term.
The following list corresponds to UF2 OTA format family names, and is also [available as JSON](../uf2families.json). The IDs are also present in [ChipType.h](../arduino/libretuya/core/ChipType.h).
The following list corresponds to UF2 OTA format family names, and is also [available as JSON](../families.json). The IDs are also present in [ChipType.h](../arduino/libretuya/core/ChipType.h).
"""
@@ -20,16 +24,14 @@ def format_row(row: list, lengths: list) -> str:
if __name__ == "__main__":
data = join(dirname(__file__), "..", "families.json")
out = join(dirname(__file__), "families.md")
with open(data, "r") as f:
data = json.load(f)
md = [HEADER]
lengths = [0, 0, 0, 0, 0, 0]
lengths = [0, 0, 0, 0, 0, 0, 0]
header = [
"Full name",
"Title",
"Name (parent)",
"Code",
"Short name & ID",
"Supported MCU(s)",
@@ -38,27 +40,42 @@ if __name__ == "__main__":
]
rows = []
for family in data:
id = family["id"]
short_name = family["short_name"]
description = family["description"]
name = family.get("name", "")
code = family.get("code", "-")
url = family.get("url", "-")
sdk = family.get("sdk", "-")
framework = family.get("framework", "-")
mcus = family.get("mcus", "-")
sdk_name = sdk.rpartition("/")[2]
arduino = (
isdir(join(dirname(__file__), "..", "arduino", name)) if name else False
)
for family in get_families():
row = [
f"[{description}]({url}) (`{name}`)" if name else description,
f"`{code}`",
f"`{short_name}` ({id})",
", ".join(mcus),
"✔️" if arduino else "",
f"`{framework}` ([{sdk_name}]({sdk}))" if name else "-",
# Title
"[{}]({})".format(
family.description,
family.url,
family.name,
)
if family.name
else family.description,
# Name (parent)
f"`{family.name or '-'}`"
if not family.parent
else f"`{family.name}` (`{family.parent}`)",
# Code
f"`{family.code or '-'}`"
if not family.parent
else f"`{family.code}` (`{family.parent_code}`)",
# Short name & ID
"`{}` (0x{:X})".format(
family.short_name,
family.id,
),
# f"`{family.short_name}` (0x{family.id:X})",
# Supported MCU(s)
", ".join(family.mcus) or "-",
# Arduino Core
"✔️" if family.has_arduino_core else "",
# Source SDK
"`{}` ([{}]({}))".format(
family.framework,
family.sdk_name,
family.sdk,
)
if family.name
else "-",
]
rows.append(row)

View File

@@ -2,16 +2,20 @@
```
arduino/
├─ <family name>/ Arduino Core for specific SoC
├─ <family name>/ Arduino Core for a specific SoC family
│ ├─ cores/ Wiring core files
│ ├─ libraries/ Supported built-in family libraries
│ ├─ port/ External library port units
├─ libretuya/
│ ├─ api/ Library interfaces
│ ├─ common/ Units common to all families
│ ├─ compat/ Fixes for compatibility with ESP32 framework
│ ├─ core/ LibreTuya API for Arduino cores
│ ├─ libraries/ Built-in family-independent libraries
| ├─ port/ External library port units
| ├─ posix/ POSIX-like C utility functions
boards/
├─ _base/ Base board manifests
├─ <board name>/ Board-specific code
│ ├─ variant.cpp Arduino variant initialization
│ ├─ variant.h Arduino variant pin configs
@@ -20,9 +24,10 @@ builder/
├─ frameworks/ Framework builders for PlatformIO
│ ├─ <family name>-sdk.py Vanilla SDK build system
│ ├─ <family name>-arduino.py Arduino Core build system
├─ libs/ Builders for external libraries
├─ utils/ SCons utils used during the build
├─ arduino-common.py Builder to provide ArduinoCore-API and LibreTuya APIs
├─ main.py Main PlatformIO builder
├─ utils.py SCons utils used during the build
docs/ Project documentation, guides, tips, etc.
platform/
├─ <family name>/ Family-specific configurations
@@ -31,7 +36,8 @@ platform/
│ ├─ ld/ Linker scripts
│ ├─ openocd/ OpenOCD configuration files
tools/
├─ <tool name>/ Tools used during the build
├─ <tool name>/ Tools used during the build
├─ util/ Utilities used by CLI tools and the builders
families.json List of supported device families
platform.json PlatformIO manifest
platform.py Custom PlatformIO script

View File

@@ -14,7 +14,7 @@
"sdk": "https://github.com/ambiot/amb1_sdk",
"framework": "framework-realtek-amb1",
"mcus": [
"RTL87xxB"
"RTL8710BN"
]
},
{

1
tools/__init__.py Normal file
View File

@@ -0,0 +1 @@
# Copyright (c) Kuba Szczodrzyński 2022-06-12.

View File

@@ -1,5 +1,6 @@
# Copyright (c) Kuba Szczodrzyński 2022-06-02.
from os.path import dirname, isdir, join
from typing import List
@@ -8,7 +9,9 @@ class Family:
short_name: str
description: str
name: str = None
parent: str = None
code: str = None
parent_code: str = None
url: str = None
sdk: str = None
framework: str = None
@@ -21,5 +24,31 @@ class Family:
else:
setattr(self, key, value)
@property
def sdk_name(self) -> str:
return self.sdk.rpartition("/")[2] if self.sdk else None
@property
def has_arduino_core(self) -> bool:
if not self.name:
return False
return isdir(join(dirname(__file__), "..", "..", "arduino", self.name))
def dict(self) -> dict:
return dict(
FAMILY=self.short_name,
FAMILY_ID=self.id,
FAMILY_NAME=self.name,
FAMILY_PARENT=self.parent,
FAMILY_CODE=self.code,
FAMILY_PARENT_CODE=self.parent_code,
)
def __eq__(self, __o: object) -> bool:
return isinstance(__o, Family) and self.id == __o.id
def __iter__(self):
return iter(self.dict().items())
def __repr__(self) -> str:
return f"<Family: {self.short_name}(0x{self.id:X}), name={self.name}, parent={self.parent}>"

View File

@@ -60,11 +60,13 @@ def get_family(
for family in get_families():
if id and family.id == id:
return family
if short_name and family.short_name == short_name:
if short_name and family.short_name == short_name.upper():
return family
if name and family.name == name:
if name and family.name == name.lower():
return family
if code and family.code == code:
if code and family.code == code.lower():
return family
if any:
raise ValueError(f"Family not found - {any}")
text = ", ".join(filter(None, [id, short_name, name, code]))
raise ValueError(f"Family not found - {text}")