This commit is contained in:
Ken Van Hoeylandt 2026-01-17 20:16:24 +01:00
parent e1a72ba9f0
commit 1f843750cd
9 changed files with 72 additions and 47 deletions

View File

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

View File

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

View File

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

View File

@ -5,8 +5,8 @@
#include <drivers-esp/esp32_i2c.h>
/ {
model = "LilyGO T-Lora Pager";
compatible = "lilygo,tlora-pager";
model = "LilyGO T-Lora Pager";
gpio0 {
compatible = "espressif,esp32-gpio";

View File

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

View File

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

View File

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

View File

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

View File

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