mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-05 21:10:04 +00:00
Add a new DTS/binding parser to scripts/dts/ for generating generated_dts_board.conf and generated_dts_board_unfixed.h. The old code is kept to generate some deprecated defines, using the --deprecated-only flag. It will be removed later. The new parser is implemented in three files in scripts/dts/: dtlib.py: A low-level .dts parsing library. This is similar to devicetree.py in the old code, but is a general robust DTS parser that doesn't rely on preprocessing. edtlib.py (e for extended): A library built on top of dtlib.py that brings together data from DTS files and bindings and creates Device instances with all the data for a device. gen_defines.py: A script that uses edtlib.py to generate generated_dts_board.conf and generated_dts_board_unfixed.h. Corresponds to extract_dts_includes.py and the files in extract/ in the old code. testdtlib.py: Test suite for dtlib.py. Can be run directly as a script. testedtlib.py (uses test.dts and test-bindings/): Test suite for edtlib.py. Can be run directly as a script. The test suites will be run automatically in CI. The new code turns some things that were warnings (or not checked) in the old code into errors, like missing properties that are specified with 'category: required' in the binding for the node. The code includes lots of documentation and tries to give helpful error messages instead of Python errors. Co-authored-by: Kumar Gala <kumar.gala@linaro.org> Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
124 lines
7.1 KiB
Python
Executable File
124 lines
7.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Copyright (c) 2019 Nordic Semiconductor ASA
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
import edtlib
|
|
|
|
# Test suite for edtlib.py. Mostly uses string comparisons via the various
|
|
# __repr__() methods. Can be run directly as an executable.
|
|
#
|
|
# This script expects to be run from the directory its in. This simplifies
|
|
# things, as paths in the output can be assumed below.
|
|
#
|
|
# test.dts is the test file, and test-bindings/ has bindings.
|
|
|
|
|
|
def run():
|
|
"""
|
|
Runs all edtlib tests. Immediately exits with status 1 and a message on
|
|
stderr on test suite failures.
|
|
"""
|
|
|
|
def fail(msg):
|
|
raise Exception("test failed: " + msg)
|
|
|
|
def verify_streq(actual, expected):
|
|
actual = str(actual)
|
|
if actual != expected:
|
|
# Put values on separate lines to make it easy to spot differences
|
|
fail("not equal (expected value last):\n'{}'\n'{}'"
|
|
.format(actual, expected))
|
|
|
|
edt = edtlib.EDT("test.dts", "test-bindings")
|
|
|
|
#
|
|
# Test interrupts
|
|
#
|
|
|
|
verify_streq(edt.get_dev("/interrupt-parent-test/node").interrupts,
|
|
"[<Interrupt, name: foo, target: <Device /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 1, 'two': 2, 'three': 3}>, <Interrupt, name: bar, target: <Device /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 4, 'two': 5, 'three': 6}>]")
|
|
|
|
verify_streq(edt.get_dev("/interrupts-extended-test/node").interrupts,
|
|
"[<Interrupt, target: <Device /interrupts-extended-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 1}>, <Interrupt, target: <Device /interrupts-extended-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 2, 'two': 3}>, <Interrupt, target: <Device /interrupts-extended-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 4, 'two': 5, 'three': 6}>]")
|
|
|
|
verify_streq(edt.get_dev("/interrupt-map-test/node@0").interrupts,
|
|
"[<Interrupt, target: <Device /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 0}>, <Interrupt, target: <Device /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 0, 'two': 1}>, <Interrupt, target: <Device /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 0, 'two': 0, 'three': 2}>]")
|
|
|
|
verify_streq(edt.get_dev("/interrupt-map-test/node@1").interrupts,
|
|
"[<Interrupt, target: <Device /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 3}>, <Interrupt, target: <Device /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 0, 'two': 4}>, <Interrupt, target: <Device /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 0, 'two': 0, 'three': 5}>]")
|
|
|
|
verify_streq(edt.get_dev("/interrupt-map-bitops-test/node@70000000E").interrupts,
|
|
"[<Interrupt, target: <Device /interrupt-map-bitops-test/controller in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 3, 'two': 2}>]")
|
|
|
|
#
|
|
# Test GPIOs
|
|
#
|
|
|
|
verify_streq(edt.get_dev("/gpio-test/node").gpios,
|
|
"{'': [<GPIO, name: , target: <Device /gpio-test/controller-0 in 'test.dts', binding test-bindings/gpio-1-cell.yaml>, specifier: {'one': 1}>, <GPIO, name: , target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 2, 'two': 3}>], 'foo': [<GPIO, name: foo, target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 4, 'two': 5}>], 'bar': [<GPIO, name: bar, target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 6, 'two': 7}>]}")
|
|
|
|
#
|
|
# Test clocks
|
|
#
|
|
|
|
verify_streq(edt.get_dev("/clock-test/node").clocks,
|
|
"[<Clock, name: fixed, frequency: 123, target: <Device /clock-test/fixed-clock in 'test.dts', binding test-bindings/fixed-clock.yaml>, specifier: {}>, <Clock, name: one-cell, target: <Device /clock-test/clock-1 in 'test.dts', binding test-bindings/clock-1-cell.yaml>, specifier: {'one': 1}>, <Clock, name: two-cell, target: <Device /clock-test/clock-2 in 'test.dts', binding test-bindings/clock-2-cell.yaml>, specifier: {'one': 1, 'two': 2}>]")
|
|
|
|
#
|
|
# Test PWMs
|
|
#
|
|
|
|
verify_streq(edt.get_dev("/pwm-test/node").pwms,
|
|
"[<PWM, name: zero-cell, target: <Device /pwm-test/pwm-0 in 'test.dts', binding test-bindings/pwm-0-cell.yaml>, specifier: {}>, <PWM, name: one-cell, target: <Device /pwm-test/pwm-1 in 'test.dts', binding test-bindings/pwm-1-cell.yaml>, specifier: {'one': 1}>]")
|
|
|
|
#
|
|
# Test 'reg'
|
|
#
|
|
|
|
verify_streq(edt.get_dev("/reg-zero-address-cells/node").regs,
|
|
"[<Register, addr: 0x0, size: 0x1>, <Register, addr: 0x0, size: 0x2>]")
|
|
|
|
verify_streq(edt.get_dev("/reg-zero-size-cells/node").regs,
|
|
"[<Register, addr: 0x1, size: 0x0>, <Register, addr: 0x2, size: 0x0>]")
|
|
|
|
verify_streq(edt.get_dev("/reg-ranges/parent/node").regs,
|
|
"[<Register, addr: 0x5, size: 0x1>, <Register, addr: 0xe0000000f, size: 0x1>, <Register, addr: 0xc0000000e, size: 0x1>, <Register, addr: 0xc0000000d, size: 0x1>, <Register, addr: 0xa0000000b, size: 0x1>, <Register, addr: 0x0, size: 0x1>]")
|
|
|
|
verify_streq(edt.get_dev("/reg-nested-ranges/grandparent/parent/node").regs,
|
|
"[<Register, addr: 0x30000000200000001, size: 0x1>]")
|
|
|
|
#
|
|
# Test !include in bindings
|
|
#
|
|
|
|
verify_streq(edt.get_dev("/binding-include").description,
|
|
"Parent binding")
|
|
|
|
verify_streq(edt.get_dev("/binding-include").props,
|
|
"{'compatible': <Property, name: compatible, value: ['binding-include-test']>, 'foo': <Property, name: foo, value: 0>, 'bar': <Property, name: bar, value: 1>, 'baz': <Property, name: baz, value: 2>}")
|
|
|
|
#
|
|
# Test 'sub-node:' in binding
|
|
#
|
|
|
|
verify_streq(edt.get_dev("/parent-with-sub-node/node").description,
|
|
"Sub-node test")
|
|
|
|
verify_streq(edt.get_dev("/parent-with-sub-node/node").props,
|
|
"{'foo': <Property, name: foo, value: 1>, 'bar': <Property, name: bar, value: 2>}")
|
|
|
|
#
|
|
# Test Device.property (derived from DT and 'properties:' in the binding)
|
|
#
|
|
|
|
verify_streq(edt.get_dev("/props").props,
|
|
r"{'compatible': <Property, name: compatible, value: ['props']>, 'int': <Property, name: int, value: 1>, 'array': <Property, name: array, value: [1, 2, 3]>, 'uint8-array': <Property, name: uint8-array, value: b'\x124'>, 'string': <Property, name: string, value: 'foo'>, 'string-array': <Property, name: string-array, value: ['foo', 'bar', 'baz']>}")
|
|
|
|
|
|
print("all tests passed")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run()
|