From 1f843750cd24cd099ed0f6690ea1364e7bd4a98d Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Sat, 17 Jan 2026 20:16:24 +0100 Subject: [PATCH] WIP --- .../source/binding_parser.py | 4 +- .../devicetree-compiler/source/generator.py | 17 ++++--- .../devicetree-compiler/source/models.py | 2 +- .../lilygo-tlora-pager/lilygo,tlora_pager.dts | 2 +- Drivers/drivers-core/include/device.h | 44 ++++++++++++++----- Drivers/drivers-core/source/device.c | 29 +++++++----- Firmware/CMakeLists.txt | 14 +++--- Tactility/Include/Tactility/Tactility.h | 2 - Tactility/Source/Tactility.cpp | 5 --- 9 files changed, 72 insertions(+), 47 deletions(-) diff --git a/Buildscripts/devicetree-compiler/source/binding_parser.py b/Buildscripts/devicetree-compiler/source/binding_parser.py index 765ea922..287fe638 100644 --- a/Buildscripts/devicetree-compiler/source/binding_parser.py +++ b/Buildscripts/devicetree-compiler/source/binding_parser.py @@ -30,6 +30,8 @@ def parse_binding(file_path: str, binding_dirs: list[str]) -> Binding: bus = parent_binding.bus for prop in parent_binding.properties: properties_dict[prop.name] = prop + for include in parent_binding.includes: + includes.append(include) # Parse local properties properties_raw = data.get('properties', {}) @@ -39,7 +41,6 @@ def parse_binding(file_path: str, binding_dirs: list[str]) -> Binding: type=details.get('type', 'unknown'), required=details.get('required', False), description=details.get('description', '').strip(), - includes=includes ) properties_dict[name] = prop @@ -50,5 +51,6 @@ def parse_binding(file_path: str, binding_dirs: list[str]) -> Binding: compatible=compatible, description=description.strip(), properties=list(properties_dict.values()), + includes=includes, bus=bus ) diff --git a/Buildscripts/devicetree-compiler/source/generator.py b/Buildscripts/devicetree-compiler/source/generator.py index 07ff78b7..36ae665f 100644 --- a/Buildscripts/devicetree-compiler/source/generator.py +++ b/Buildscripts/devicetree-compiler/source/generator.py @@ -99,7 +99,7 @@ def write_config(file, device: Device, bindings: list[Binding], type_name: str): file.write(f"{config_params_joined}\n") file.write("};\n\n") -def write_device(file, device: Device, parent_device: Device, bindings: list[Binding], verbose: bool): +def write_device(file, device: Device, bindings: list[Binding], verbose: bool): if verbose: print(f"Processing device '{device.identifier}'") # Assemble some pre-requisites @@ -108,6 +108,7 @@ def write_device(file, device: Device, parent_device: Device, bindings: list[Bin if compatible_property is None: raise Exception(f"Cannot find 'compatible' property for {device.identifier}") identifier = get_device_identifier_safe(device) + device_binding = find_binding(compatible_property.value, bindings) # Write config struct write_config(file, device, bindings, type_name) # Type & instance names @@ -129,12 +130,18 @@ def write_device(file, device: Device, parent_device: Device, bindings: list[Bin file.write(f".deinit = {deinit_function_name}") file.write("},\n") file.write("\t.metadata = {\n") - file.write("\t\t.num_node_labels = 0,\n") - file.write("\t\t.node_labels = nullptr\n") + node_label_count = len(device_binding.includes) + 1 + file.write(f"\t\t.compatible_count = {node_label_count},\n") + file.write("\t\t.compatible = (const char*[]) {\n") + file.write(f"\t\t\t\"{device_binding.compatible}\",\n") + for include in device_binding.includes: + include_compatible = include.removesuffix(".yaml") + file.write(f"\t\t\t\"{include_compatible}\",\n") + file.write("\t\t}\n") file.write("\t}\n") file.write("};\n\n") for child_device in device.devices: - write_device(file, child_device, device, bindings, verbose) + write_device(file, child_device, bindings, verbose) def write_device_list_entry(file, device: Device): compatible_property = find_binding_property(device, "compatible") @@ -165,7 +172,7 @@ def generate_devicetree_c(filename: str, items: list[object], bindings: list[Bin for item in items: if type(item) is Device: devices.append(item) - write_device(file, item, None, bindings, verbose) + write_device(file, item, bindings, verbose) write_device_list(file, devices) file.write(dedent('''\ struct device** devices_builtin_get() { diff --git a/Buildscripts/devicetree-compiler/source/models.py b/Buildscripts/devicetree-compiler/source/models.py index 9b0d2895..e764bf0f 100644 --- a/Buildscripts/devicetree-compiler/source/models.py +++ b/Buildscripts/devicetree-compiler/source/models.py @@ -31,7 +31,6 @@ class BindingProperty: type: str required: bool description: str - includes: list[str] @dataclass class Binding: @@ -39,4 +38,5 @@ class Binding: compatible: str description: str properties: list[BindingProperty] + includes: list[str] bus: str = None diff --git a/Devices/lilygo-tlora-pager/lilygo,tlora_pager.dts b/Devices/lilygo-tlora-pager/lilygo,tlora_pager.dts index 213463dd..df29b224 100644 --- a/Devices/lilygo-tlora-pager/lilygo,tlora_pager.dts +++ b/Devices/lilygo-tlora-pager/lilygo,tlora_pager.dts @@ -5,8 +5,8 @@ #include / { - model = "LilyGO T-Lora Pager"; compatible = "lilygo,tlora-pager"; + model = "LilyGO T-Lora Pager"; gpio0 { compatible = "espressif,esp32-gpio"; diff --git a/Drivers/drivers-core/include/device.h b/Drivers/drivers-core/include/device.h index 69236490..2a80bda0 100644 --- a/Drivers/drivers-core/include/device.h +++ b/Drivers/drivers-core/include/device.h @@ -21,16 +21,11 @@ struct device_state { bool initialized : 1; }; -#define DEVICE_LABEL(key, value) #key":"#value -#define DEVICE_LABEL_FOR_TYPE(_type) DEVICE_LABEL(type, _type) - struct device_metadata { - /* @brief number of elements in the nodelabels array */ - size_t num_node_labels; - /* @brief array of node labels as strings, exactly as they - * appear in the final devicetree - */ - const char** node_labels; + /** @brief number of elements in the compatible array */ + size_t compatible_count; + /** @brief array of strings containing the compatible device names */ + const char** compatible; }; struct device { @@ -50,10 +45,26 @@ struct device { struct device_metadata metadata; }; +/** + * Initialize a device. + * @param[in] dev + * @return the return code of the device's init function + */ uint8_t device_init(struct device* dev); +/** + * Initialize an array of devices. + * @param[in] device_array a null-terminated array of devices + * @retval true if all devices initialized successfully + * @retval false if any device failed to initialize + */ bool device_init_all(struct device** device_array); +/** + * Deinitialize a device. + * @param[in] dev + * @return the return code of the device's deinit function + */ uint8_t device_deinit(struct device* dev); /** @@ -69,7 +80,7 @@ bool device_is_ready(const struct device* dev); * * @param[in] dev non-null device pointer */ -bool device_add(const struct device* dev); +void device_add(const struct device* dev); /** * Register all devices in the specified array. @@ -79,9 +90,20 @@ bool device_add(const struct device* dev); */ void device_add_all(struct device** device_array); +/** + * Deregister a device + * @param[in] dev non-null device pointer + * @return true when the device was found and deregistered + */ bool device_remove(const struct device* dev); -bool device_find_next(const char* label, const struct device** device); +/** + * Iterate the devicetree. Find the next with the specified label. + * @param[in] identifier the identifier of the device, such as "root" or "i2c-controller" + * @param[inout] dev a pointer to a device pointer in the tree, or nullptr to start searching for the first device + * @return true if a device was found + */ +bool device_find_next_by_compatible(const char* identifier, const struct device** dev); #ifdef __cplusplus } diff --git a/Drivers/drivers-core/source/device.c b/Drivers/drivers-core/source/device.c index 323d4e76..ff66ded7 100644 --- a/Drivers/drivers-core/source/device.c +++ b/Drivers/drivers-core/source/device.c @@ -7,7 +7,12 @@ #define CONFIG_DEVICE_INDEX_SIZE 64 // TODO: Automatically increase allocated size -static const struct device* device_index[128] = { 0 }; +static const struct device* device_index[CONFIG_DEVICE_INDEX_SIZE ] = { + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr +}; uint8_t device_init(struct device* const dev) { assert(dev != nullptr); @@ -63,15 +68,15 @@ bool device_is_ready(const struct device* const dev) { } -bool device_add(const struct device* dev) { +void device_add(const struct device* dev) { assert(dev != nullptr); for (int i = 0; i < CONFIG_DEVICE_INDEX_SIZE; i++) { if (device_index[i] == nullptr) { device_index[i] = dev; - return true; + return; } } - return false; + assert(false); // out of space } void device_add_all(struct device** const device_array) { @@ -85,6 +90,7 @@ void device_add_all(struct device** const device_array) { } bool device_remove(const struct device* dev) { + assert(dev != nullptr); for (int i = 0; i < CONFIG_DEVICE_INDEX_SIZE; i++) { if (device_index[i] == dev) { device_index[i] = nullptr; @@ -94,20 +100,20 @@ bool device_remove(const struct device* dev) { return false; } -bool device_find_next(const char* label, const struct device** device) { - bool found_first = (device == nullptr); +bool device_find_next_by_compatible(const char* identifier, const struct device** dev) { + bool found_first = (*dev == nullptr); for (int device_idx = 0; device_idx < CONFIG_DEVICE_INDEX_SIZE; device_idx++) { auto indexed_device = device_index[device_idx]; if (indexed_device != nullptr) { if (!found_first) { - if (indexed_device == *device) { + if (indexed_device == *dev) { found_first = true; } } else { - for (int label_idx = 0; label_idx< indexed_device->metadata.num_node_labels; ++label_idx) { - const char* indexed_device_label = indexed_device->metadata.node_labels[label_idx]; - if (strcmp(indexed_device_label, label) == 0) { - *device = indexed_device; + for (int label_idx = 0; label_idx< indexed_device->metadata.compatible_count; ++label_idx) { + const char* indexed_device_label = indexed_device->metadata.compatible[label_idx]; + if (strcmp(indexed_device_label, identifier) == 0) { + *dev = indexed_device; return true; } } @@ -116,4 +122,3 @@ bool device_find_next(const char* label, const struct device** device) { } return false; } - diff --git a/Firmware/CMakeLists.txt b/Firmware/CMakeLists.txt index 97f591b3..8c7fd2b8 100644 --- a/Firmware/CMakeLists.txt +++ b/Firmware/CMakeLists.txt @@ -47,20 +47,16 @@ else () add_definitions(-D_Nullable=) add_definitions(-D_Nonnull=) - - add_dependencies(FirmwareSim Generated) endif () -# Generate devicetree code and attach to component -add_custom_command( - OUTPUT ${CMAKE_SOURCE_DIR}/Firmware/Generated/devicetree.c ${CMAKE_SOURCE_DIR}/Firmware/Generated/devicetree.h - COMMAND mkdir ${CMAKE_SOURCE_DIR}/Firmware/Generated | pip install lark pyyaml && python Buildscripts/devicetree-compiler/compile.py ${DEVICETREE_LOCATION} Firmware/Generated +# Generate devicetree code and attach to Firmware component +add_custom_target(Generated + COMMAND mkdir -p ${CMAKE_SOURCE_DIR}/Firmware/Generated | echo Firmware/Generated exists + COMMAND pip install lark pyyaml + COMMAND python Buildscripts/devicetree-compiler/compile.py ${DEVICETREE_LOCATION} Firmware/Generated WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - VERBATIM ) -add_custom_target(Generated DEPENDS ${CMAKE_SOURCE_DIR}/Firmware/Generated/devicetree.c ${CMAKE_SOURCE_DIR}/Firmware/Generated/devicetree.h) set_property(DIRECTORY "${CMAKE_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_CLEAN_FILES "Firmware/Generated/devicetree.c" "/Firmware/Generated/devicetree.h") -# Attach generated code to project target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_SOURCE_DIR}/Firmware/Generated/devicetree.c") target_include_directories(${COMPONENT_LIB} PRIVATE ${CMAKE_SOURCE_DIR}/Firmware/Generated) add_dependencies(${COMPONENT_LIB} Generated) diff --git a/Tactility/Include/Tactility/Tactility.h b/Tactility/Include/Tactility/Tactility.h index 04a51fa8..8b73cb0f 100644 --- a/Tactility/Include/Tactility/Tactility.h +++ b/Tactility/Include/Tactility/Tactility.h @@ -8,8 +8,6 @@ namespace tt { -namespace app::launcher { extern const AppManifest manifest; } - /** @brief The configuration for the operating system * It contains the hardware configuration, apps and services */ diff --git a/Tactility/Source/Tactility.cpp b/Tactility/Source/Tactility.cpp index 9111c7bd..a90deaf7 100644 --- a/Tactility/Source/Tactility.cpp +++ b/Tactility/Source/Tactility.cpp @@ -318,11 +318,6 @@ void run(const Configuration& config, device** devices) { if (devices != nullptr) { device_add_all(devices); device_init_all(devices); - - const struct device* i2c_controller = nullptr; - const char* label = DEVICE_LABEL_FOR_TYPE(i2c_controller); - while (device_find_next(label, &i2c_controller)) { - } } #ifdef ESP_PLATFORM