Skip to content

Commit de5c3ca

Browse files
committed
INCOMPLETE: use "friendly" names for GPIO ports
Starting with Zephyr 3.2.0, the `label` property of DT nodes was made obsolete, which means that is no longer possible to write: ``` pin = Pin(("GPIO_1", 21), Pin.IN) ``` Instead, a much less friendly format must be used: ``` pin = Pin(("gpio@842500", 21), Pin.IN) ``` This commit adds a new script (`gen_dt_node_names.py`) which is heavily based on [this script](https://github.com/zephyrproject-rtos/zephyr/blob/main/scripts/dts/gen_dts_cmake.py) and attempts to generate and map friendly names for DT nodes. For example, a node defined like this: ``` gpio0: gpio@842500 { ... } ``` will generate a mapping like this: ``` struct dt_node_name_map { const char *const gen_name; const char *const actual_name; }; static const struct dt_node_name_map dt_node_map[] = { {"GPIO_0", "gpio@842500"} ... } ``` The code then checks this mapping if the node name supplied by the user does not exist and uses the actual DT name instead.
1 parent 0c4f14e commit de5c3ca

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

ports/zephyr/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
2828
project(micropython)
2929

3030
set(MICROPY_PORT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
31+
set(MICROPY_BUILD_DIR ${MICROPY_PORT_DIR}/build)
3132
set(MICROPY_DIR ${MICROPY_PORT_DIR}/../..)
3233
set(MICROPY_TARGET micropython)
3334

@@ -74,7 +75,12 @@ set(MICROPY_SOURCE_LIB
7475
)
7576
list(TRANSFORM MICROPY_SOURCE_LIB PREPEND ${MICROPY_DIR}/lib/)
7677

78+
add_custom_command(OUTPUT ${MICROPY_BUILD_DIR}/gen_dt_node_names.h
79+
DEPENDS ${MICROPY_BUILD_DIR}/zephyr/edt.pickle ${MICROPY_PORT_DIR}/gen_dt_node_names.py
80+
COMMAND ${Python3_EXECUTABLE} ${MICROPY_PORT_DIR}/gen_dt_node_names.py -i ${MICROPY_BUILD_DIR}/zephyr/edt.pickle -o ${MICROPY_BUILD_DIR}/gen_dt_node_names.h)
81+
7782
set(MICROPY_SOURCE_QSTR
83+
${MICROPY_BUILD_DIR}/gen_dt_node_names.h
7884
${MICROPY_SOURCE_PY}
7985
${MICROPY_SOURCE_EXTMOD}
8086
${MICROPY_SOURCE_SHARED}

ports/zephyr/gen_dt_node_names.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import os
5+
import sys
6+
import pickle
7+
import re
8+
9+
# This is needed by the "pickle.load" call below
10+
zephyr_base = os.environ["ZEPHYR_BASE"]
11+
sys.path.insert(0, os.path.join(zephyr_base, "scripts", "dts", "python-devicetree", "src"))
12+
13+
# The prefixes to look for in the device tree
14+
prefixes = ("gpio", "spi", "i2c", "uart")
15+
16+
# Prefix for the generated header
17+
header_prefix = """#ifndef MICROPY_INCLUDED_ZEPHYR_GEN_DT_NODE_NAMES_H
18+
#define MICROPY_INCLUDED_ZEPHYR_GEN_DT_NODE_NAMES_H
19+
20+
struct dt_node_name_map {
21+
const char *const gen_name;
22+
const char *const actual_name;
23+
};
24+
25+
static const struct dt_node_name_map dt_node_map[] = {
26+
"""
27+
# Suffix for the generated header
28+
header_sufix = """};
29+
30+
#endif
31+
"""
32+
33+
def main():
34+
parser = argparse.ArgumentParser(description="Generate friendly names for Zephyr DT nodess")
35+
parser.add_argument("-i", "--input", required=True, help="path to edt.pickle")
36+
parser.add_argument("-o", "--output", required=True, help="path to the output file")
37+
args = parser.parse_args()
38+
39+
# Load the representation of the device tree generated by Zephyr
40+
with open(args.input, 'rb') as f:
41+
edt = pickle.load(f)
42+
43+
# Create regular expressions for all prefix that we need to check
44+
all_re = re.compile(fr'^({"|".join(prefixes)})(\d+)$')
45+
46+
# Look in the device tree for all nodes with labels
47+
name_map = {}
48+
for n in edt.nodes:
49+
if n.status == "okay": # consider only nodes that are enabled
50+
# Check prefixes for all labels
51+
for l in n.labels:
52+
found = all_re.match(l)
53+
if found != None:
54+
# Transform name (from "gpio0" to "GPIO_0" and so on)
55+
new_name = found.group(1).upper() + "_" + found.group(2)
56+
name_map[new_name] = n.name
57+
break
58+
59+
# Write data to output file
60+
with open(args.output, "wt") as f:
61+
f.write(header_prefix)
62+
for n in name_map:
63+
f.write(f' {{"{n}", "{name_map[n]}"}},\n')
64+
f.write(" {NULL, NULL}\n")
65+
f.write(header_sufix)
66+
67+
if __name__ == "__main__":
68+
main()

ports/zephyr/machine_pin.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "py/mphal.h"
3838
#include "shared/runtime/mpirq.h"
3939
#include "modmachine.h"
40+
#include "gen_dt_node_names.h"
4041

4142
#if MICROPY_PY_MACHINE
4243

@@ -133,6 +134,14 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
133134
const char *drv_name = mp_obj_str_get_str(items[0]);
134135
int wanted_pin = mp_obj_get_int(items[1]);
135136
const struct device *wanted_port = device_get_binding(drv_name);
137+
if (!wanted_port) {
138+
for (const struct dt_node_name_map *m = &dt_node_map[0]; m->gen_name != NULL; m ++) {
139+
if (!strcmp(m->gen_name, drv_name)) {
140+
wanted_port = device_get_binding(m->actual_name);
141+
break;
142+
}
143+
}
144+
}
136145
if (!wanted_port) {
137146
mp_raise_ValueError(MP_ERROR_TEXT("invalid port"));
138147
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy