Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions Buildscripts/DevicetreeCompiler/source/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de

node_name = get_device_node_name_safe(device)
result = []
phandle_arrays = []
array_decls = []
for binding_property in binding_properties:
device_property = find_device_property(device, binding_property.name)

Expand All @@ -172,7 +172,35 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
array_var = f"{node_name}_{prop_safe}"
if device_property is not None:
entries = resolve_phandle_array_entries(device_property, devices)
phandle_arrays.append((array_var, binding_property.element_type, entries))
array_decls.append((array_var, binding_property.element_type, entries))
result.append(f"({binding_property.element_type}*){array_var}")
result.append(str(len(entries)))
elif binding_property.default is not None:
result.append("NULL")
result.append("0")
elif binding_property.required:
raise DevicetreeException(f"device {device.node_name} doesn't have property '{binding_property.name}'")
else:
result.append("NULL")
result.append("0")
continue

if binding_property.type == "array":
# A flat literal array (DTS `[ ... ]` syntax, e.g. a byte blob), as opposed to
# phandle-array's list of resolved device references. Emits the same
# (pointer, length) parameter pair, backed by a plain data array instead of one
# holding phandle-derived initializers.
if binding_property.element_type is None:
raise DevicetreeException(f"array property '{binding_property.name}' requires 'element-type' in binding")
prop_safe = binding_property.name.replace("-", "_")
array_var = f"{node_name}_{prop_safe}"
if device_property is not None:
if device_property.type != "array":
raise DevicetreeException(
f"Device '{device.node_name}' property '{binding_property.name}' must use '[ ... ]' array syntax"
)
entries = [str(value) for value in device_property.value]
array_decls.append((array_var, binding_property.element_type, entries))
result.append(f"({binding_property.element_type}*){array_var}")
result.append(str(len(entries)))
elif binding_property.default is not None:
Expand Down Expand Up @@ -207,17 +235,17 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
validate_property_range(device, binding_property, device_property.value)
result.append(property_to_string(device_property, devices))

return result, phandle_arrays
return result, array_decls

def write_config(file, device: Device, bindings: list[Binding], devices: list[Device], type_name: str):
node_name = get_device_node_name_safe(device)
config_type = f"{type_name}_config_dt"
config_variable_name = f"{node_name}_config"

config_params, phandle_arrays = resolve_parameters_from_bindings(device, bindings, devices)
config_params, array_decls = resolve_parameters_from_bindings(device, bindings, devices)

# Write phandle-array variables before the config struct
for array_var, element_type, entries in phandle_arrays:
# Write phandle-array/array variables before the config struct
for array_var, element_type, entries in array_decls:
entries_str = ", ".join(entries)
file.write(f"static {element_type} {array_var}[] = {{ {entries_str} }};\n")

Expand Down
90 changes: 89 additions & 1 deletion Buildscripts/DevicetreeCompiler/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,92 @@ def test_minmax_symbolic_value_skips_validation():
print("PASSED")
return True

def write_array_config(tmp_dir, device_property_line):
config_dir = os.path.join(tmp_dir, "array_data")
bindings_dir = os.path.join(config_dir, "bindings")
os.makedirs(bindings_dir)

with open(os.path.join(config_dir, "devicetree.yaml"), "w") as f:
f.write("dts: test.dts\nbindings: bindings")

with open(os.path.join(config_dir, "test.dts"), "w") as f:
f.write(f"""/dts-v1/;

/ {{
compatible = "test,root";
model = "Test Model";

test-device@0 {{
compatible = "test,array-device";
{device_property_line}
}};
}};
""")

with open(os.path.join(bindings_dir, "test,root.yaml"), "w") as f:
f.write("description: Test root binding\ncompatible: \"test,root\"\nproperties:\n model:\n type: string\n")

with open(os.path.join(bindings_dir, "test,array-device.yaml"), "w") as f:
f.write("""description: Test array binding
compatible: "test,array-device"
properties:
init-sequence:
type: array
element-type: uint8_t
""")

return config_dir

def test_array_property_generates_static_array_and_length():
print("Running test_array_property_generates_static_array_and_length...")
with tempfile.TemporaryDirectory() as tmp_dir:
config_dir = write_array_config(tmp_dir, "init-sequence = [0xFF 0x01 0x00 0x00 0x10 5 0];")
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)

result = run_compiler(config_dir, output_dir)

if result.returncode != 0:
print(f"FAILED: Compilation should have succeeded: {result.stderr} {result.stdout}")
return False

with open(os.path.join(output_dir, "devicetree.c")) as f:
generated = f.read()

if "static uint8_t test_device_init_sequence[] = { 0xFF, 0x01, 0x00, 0x00, 0x10, 5, 0 };" not in generated:
print(f"FAILED: Expected static array declaration not found:\n{generated}")
return False

if "(uint8_t*)test_device_init_sequence" not in generated or "\t7\n" not in generated:
print(f"FAILED: Expected (pointer, length) config params not found:\n{generated}")
return False

print("PASSED")
return True

def test_array_property_defaults_to_null_when_absent():
print("Running test_array_property_defaults_to_null_when_absent...")
with tempfile.TemporaryDirectory() as tmp_dir:
config_dir = write_array_config(tmp_dir, "")
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)

result = run_compiler(config_dir, output_dir)

if result.returncode != 0:
print(f"FAILED: Compilation should have succeeded: {result.stderr} {result.stdout}")
return False

with open(os.path.join(output_dir, "devicetree.c")) as f:
generated = f.read()

if "NULL,\n\t0" not in generated:
print(f"FAILED: Expected NULL/0 defaults not found:\n{generated}")
return False

print("PASSED")
return True

def test_compile_missing_config():
print("Running test_compile_missing_config...")
with tempfile.TemporaryDirectory() as output_dir:
Expand All @@ -234,7 +320,9 @@ def test_compile_missing_config():
test_minmax_below_minimum_fails,
test_minmax_above_maximum_fails,
test_minmax_out_of_range_default_fails,
test_minmax_symbolic_value_skips_validation
test_minmax_symbolic_value_skips_validation,
test_array_property_generates_static_array_and_length,
test_array_property_defaults_to_null_when_absent
]

failed = 0
Expand Down
5 changes: 2 additions & 3 deletions Devices/cyd-4848s040c/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)

idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility EspLcdCompat esp_lcd_st7701 esp_lcd_panel_io_additions GT911 PwmBacklight driver vfs fatfs
REQUIRES TactilityKernel driver
)
21 changes: 0 additions & 21 deletions Devices/cyd-4848s040c/Source/Configuration.cpp

This file was deleted.

Loading
Loading