gen_defines: play tricks to benefit DT_INST users

Even though it is about to be done for sound technical reasons, a
subsequent patch adding access to all device nodes at the last minute
in the 2.3 release is going to be playing a bit of a fast one on
the Zephyr community, especially users of DT_INST APIs.

In particular, instance numbers are currently allocated only to
enabled nodes, but that will not be true soon: *every* node of a
compatible will be allocated an instance number, even disabled ones.

This is especially unfortunate for drivers and applications that
expect singletons of their compatibles, and use DT_INST(0, ...) to
mean "the one enabled instance of my compatible".

To avoid gratuitous breakage, let's prepare for that by sorting each
edt.compat2nodes sub-list so that enabled instances always come before
disabled ones.

This doesn't break any API guarantees, because there basically *are*
no ordering guarantees, in part precisely to give us the flexibility
to do things like this. And it does help patterns that use instances 0
through N-1, including the important singleton case.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
Martí Bolívar 2020-05-07 12:07:02 -07:00 committed by Kumar Gala
commit e96ca54fd8

View file

@ -45,6 +45,25 @@ def main():
with open(args.dts_out, "w", encoding="utf-8") as f:
print(edt.dts_source, file=f)
# The raw index into edt.compat2nodes[compat] is used for node
# instance numbering within a compatible.
#
# As a way to satisfy people's intuitions about instance numbers,
# though, we sort this list so enabled instances come first.
#
# This might look like a hack, but it keeps drivers and
# applications which don't use instance numbers carefully working
# as expected, since e.g. instance number 0 is always the
# singleton instance if there's just one enabled node of a
# particular compatible.
#
# This doesn't violate any devicetree.h API guarantees about
# instance ordering, since we make no promises that instance
# numbers are stable across builds.
for compat, nodes in edt.compat2nodes.items():
edt.compat2nodes[compat] = sorted(
nodes, key=lambda node: 0 if node.status == "okay" else 1)
with open(args.header_out, "w", encoding="utf-8") as header_file:
write_top_comment(edt)