Tab5 power expander driver and devicetree parsing improvements (#507)
* **New Features** * PI4IOE5V6408 I2C I/O expander driver with public GPIO APIs * CLI tool to list devicetree dependencies * **Device Tree Updates** * M5Stack Tab5 configured with two I2C IO expanders; PI4IOE5V6408 binding added * **Build / Tooling** * Devicetree code generation integrated into build; generated artifacts and dynamic dependency resolution exposed * **Refactor** * Kernel/run APIs updated to accept a null‑terminated devicetree modules array; many module symbols renamed * **Documentation** * Added README and Apache‑2.0 license for new driver module
This commit is contained in:
committed by
GitHub
parent
f0f764baff
commit
d2048e01b6
@@ -0,0 +1,35 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
from source.printing import print_error
|
||||
from source.config import parse_config
|
||||
|
||||
def print_help():
|
||||
print("Usage: python dependencies.py [path]\n")
|
||||
print("\t[in_file] the path where the root devicetree.yaml file is")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "--help" in sys.argv:
|
||||
print_help()
|
||||
sys.exit()
|
||||
args = [a for a in sys.argv[1:] if not a.startswith("--")]
|
||||
if len(args) < 1:
|
||||
print_error("Missing argument")
|
||||
print_help()
|
||||
sys.exit(1)
|
||||
|
||||
yaml_directory = args[0]
|
||||
|
||||
if not os.path.exists(yaml_directory):
|
||||
print_error(f"Path not found: {yaml_directory}")
|
||||
sys.exit(1)
|
||||
|
||||
config = parse_config(yaml_directory, os.getcwd())
|
||||
|
||||
# Device module is added first because it's started first:
|
||||
# It creates the root device, so it must exist before its children.
|
||||
device_dependency = os.path.basename(os.path.normpath(yaml_directory))
|
||||
print(device_dependency)
|
||||
for dependency in config.dependencies:
|
||||
dependency_name = os.path.basename(os.path.normpath(dependency))
|
||||
print(dependency_name)
|
||||
@@ -212,7 +212,7 @@ def gather_devices(device: Device, output: list[Device]):
|
||||
for child_device in device.devices:
|
||||
gather_devices(child_device, output)
|
||||
|
||||
def generate_devicetree_c(filename: str, items: list[object], bindings: list[Binding], verbose: bool):
|
||||
def generate_devicetree_c(filename: str, items: list[object], bindings: list[Binding], config, verbose: bool):
|
||||
# Create a cache for looking up device names and aliases easily
|
||||
# We still want to traverse it as a tree during code generation because of parent-setting
|
||||
devices = list()
|
||||
@@ -225,6 +225,7 @@ def generate_devicetree_c(filename: str, items: list[object], bindings: list[Bin
|
||||
// Default headers
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/dts.h>
|
||||
#include <tactility/module.h>
|
||||
// DTS headers
|
||||
'''))
|
||||
|
||||
@@ -246,6 +247,25 @@ def generate_devicetree_c(filename: str, items: list[object], bindings: list[Bin
|
||||
write_device_list_entry(file, item, bindings, verbose)
|
||||
file.write("\tDTS_DEVICE_TERMINATOR\n")
|
||||
file.write("};\n")
|
||||
# Gather module symbols
|
||||
module_symbol_names = []
|
||||
for dependency in config.dependencies:
|
||||
dependency_name = os.path.basename(os.path.normpath(dependency))
|
||||
module_symbol_name = f"{dependency_name.replace('-', '_')}"
|
||||
if not module_symbol_name.endswith("_module"):
|
||||
module_symbol_name += "_module"
|
||||
module_symbol_names.append(module_symbol_name)
|
||||
file.write("\n")
|
||||
# Forward declaration of symbol variables
|
||||
for symbol in module_symbol_names:
|
||||
file.write(f"extern struct Module {symbol};\n")
|
||||
file.write("\n")
|
||||
# Create array of symbol variables
|
||||
file.write("struct Module* dts_modules[] = {\n")
|
||||
for symbol in module_symbol_names:
|
||||
file.write(f"\t&{symbol},\n")
|
||||
file.write("\tNULL\n")
|
||||
file.write("};\n")
|
||||
|
||||
def generate_devicetree_h(filename: str):
|
||||
with open(filename, "w") as file:
|
||||
@@ -258,17 +278,21 @@ def generate_devicetree_h(filename: str):
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Array of device tree modules terminated with DTS_MODULE_TERMINATOR
|
||||
extern struct DtsDevice dts_devices[];
|
||||
|
||||
// Array of module symbols terminated with NULL
|
||||
extern struct Module* dts_modules[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
'''))
|
||||
|
||||
def generate(output_path: str, items: list[object], bindings: list[Binding], verbose: bool):
|
||||
def generate(output_path: str, items: list[object], bindings: list[Binding], config, verbose: bool):
|
||||
if not os.path.exists(output_path):
|
||||
os.makedirs(output_path)
|
||||
devicetree_c_filename = os.path.join(output_path, "devicetree.c")
|
||||
generate_devicetree_c(devicetree_c_filename, items, bindings, verbose)
|
||||
generate_devicetree_c(devicetree_c_filename, items, bindings, config, verbose)
|
||||
devicetree_h_filename = os.path.join(output_path, "devicetree.h")
|
||||
generate_devicetree_h(devicetree_h_filename)
|
||||
|
||||
@@ -46,7 +46,7 @@ def main(config_path: str, output_path: str, verbose: bool) -> int:
|
||||
if verbose:
|
||||
for binding in bindings:
|
||||
pprint(binding)
|
||||
generate(output_path, transformed, bindings, verbose)
|
||||
generate(output_path, transformed, bindings, config, verbose)
|
||||
return 0
|
||||
except DevicetreeException as caught:
|
||||
print("\033[31mError: ", caught, "\033[0m")
|
||||
|
||||
Reference in New Issue
Block a user