modm_data.atdf.avr

  1# Copyright 2013, Niklas Hauser
  2# Copyright 2016, Fabian Greif
  3# SPDX-License-Identifier: MPL-2.0
  4
  5import logging
  6from pathlib import Path
  7
  8from ..utils import ext_path, XmlReader
  9from .identifier import avr_did_from_string
 10
 11LOGGER = logging.getLogger(__name__)
 12_ATDF_PATH = ext_path("microchip/avr")
 13
 14# Data is from avrdude v6.3
 15avrdude_mcu_map = {
 16    "at90s1200": "1200",
 17    "at90s2313": "2313",
 18    "at90s2333": "2333",
 19    "at90s2343": "2343",
 20    "at90s4414": "4414",
 21    "at90s4433": "4433",
 22    "at90s4434": "4434",
 23    "at90s8515": "8515",
 24    "at90s8535": "8535",
 25    "at90can128": "c128",
 26    "at90can32": "c32",
 27    "at90can64": "c64",
 28    "at90pwm216": "pwm216",
 29    "at90pwm2": "pwm2",
 30    "at90pwm2b": "pwm2b",
 31    "at90pwm3": "pwm3",
 32    "at90pwm316": "pwm316",
 33    "at90pwm3b": "pwm3b",
 34    "at90usb1286": "usb1286",
 35    "at90usb1287": "usb1287",
 36    "at90usb162": "usb162",
 37    "at90usb646": "usb646",
 38    "at90usb647": "usb647",
 39    "at90usb82": "usb82",
 40    "atmega103": "m103",
 41    "atmega128": "m128",
 42    "atmega1280": "m1280",
 43    "atmega1281": "m1281",
 44    "atmega1284": "m1284",
 45    "atmega1284p": "m1284p",
 46    "atmega1284rfr2": "m1284rfr2",
 47    "atmega128rfa1": "m128rfa1",
 48    "atmega128rfr2": "m128rfr2",
 49    "atmega16": "m16",
 50    "atmega161": "m161",
 51    "atmega162": "m162",
 52    "atmega163": "m163",
 53    "atmega164p": "m164p",
 54    "atmega168": "m168",
 55    "atmega168p": "m168p",
 56    "atmega168pb": "m168pb",
 57    "atmega169": "m169",
 58    "atmega16u2": "m16u2",
 59    "atmega2560": "m2560",
 60    "atmega2561": "m2561",
 61    "atmega2564rfr2": "m2564rfr2",
 62    "atmega256rfr2": "m256rfr2",
 63    "atmega32": "m32",
 64    "atmega324p": "m324p",
 65    "atmega324pa": "m324pa",
 66    "atmega325": "m325",
 67    "atmega3250": "m3250",
 68    "atmega328": "m328",
 69    "atmega328p": "m328p",
 70    "atmega329": "m329",
 71    "atmega3290": "m3290",
 72    "atmega3290p": "m3290p",
 73    "atmega329p": "m329p",
 74    "atmega32m1": "m32m1",
 75    "atmega32u2": "m32u2",
 76    "atmega32u4": "m32u4",
 77    "atmega406": "m406",
 78    "atmega48": "m48",
 79    "atmega48p": "m48p",
 80    "atmega48pb": "m48pb",
 81    "atmega64": "m64",
 82    "atmega640": "m640",
 83    "atmega644": "m644",
 84    "atmega644p": "m644p",
 85    "atmega644rfr2": "m644rfr2",
 86    "atmega645": "m645",
 87    "atmega6450": "m6450",
 88    "atmega649": "m649",
 89    "atmega6490": "m6490",
 90    "atmega64rfr2": "m64rfr2",
 91    "atmega8": "m8",
 92    "atmega8515": "m8515",
 93    "atmega8535": "m8535",
 94    "atmega88": "m88",
 95    "atmega88p": "m88p",
 96    "atmega88pb": "m88pb",
 97    "atmega8u2": "m8u2",
 98    "attiny10": "t10",
 99    "attiny11": "t11",
100    "attiny12": "t12",
101    "attiny13": "t13",
102    "attiny15": "t15",
103    "attiny1634": "t1634",
104    "attiny20": "t20",
105    "attiny2313": "t2313",
106    "attiny24": "t24",
107    "attiny25": "t25",
108    "attiny26": "t26",
109    "attiny261": "t261",
110    "attiny28": "t28",
111    "attiny4": "t4",
112    "attiny40": "t40",
113    "attiny4313": "t4313",
114    "attiny43u": "t43u",
115    "attiny44": "t44",
116    "attiny45": "t45",
117    "attiny461": "t461",
118    "attiny5": "t5",
119    "attiny84": "t84",
120    "attiny85": "t85",
121    "attiny861": "t861",
122    "attiny88": "t88",
123    "attiny9": "t9",
124    "atxmega128a1": "x128a1",
125    "atxmega128a1revd": "x128a1d",
126    "atxmega128a1u": "x128a1u",
127    "atxmega128a3": "x128a3",
128    "atxmega128a3u": "x128a3u",
129    "atxmega128a4": "x128a4",
130    "atxmega128a4u": "x128a4u",
131    "atxmega128b1": "x128b1",
132    "atxmega128b3": "x128b3",
133    "atxmega128c3": "x128c3",
134    "atxmega128d3": "x128d3",
135    "atxmega128d4": "x128d4",
136    "atxmega16a4": "x16a4",
137    "atxmega16a4u": "x16a4u",
138    "atxmega16c4": "x16c4",
139    "atxmega16d4": "x16d4",
140    "atxmega16e5": "x16e5",
141    "atxmega192a1": "x192a1",
142    "atxmega192a3": "x192a3",
143    "atxmega192a3u": "x192a3u",
144    "atxmega192c3": "x192c3",
145    "atxmega192d3": "x192d3",
146    "atxmega256a1": "x256a1",
147    "atxmega256a3": "x256a3",
148    "atxmega256a3b": "x256a3b",
149    "atxmega256a3bu": "x256a3bu",
150    "atxmega256a3u": "x256a3u",
151    "atxmega256c3": "x256c3",
152    "atxmega256d3": "x256d3",
153    "atxmega32a4": "x32a4",
154    "atxmega32a4u": "x32a4u",
155    "atxmega32c4": "x32c4",
156    "atxmega32d4": "x32d4",
157    "atxmega32e5": "x32e5",
158    "atxmega384c3": "x384c3",
159    "atxmega384d3": "x384d3",
160    "atxmega64a1": "x64a1",
161    "atxmega64a1u": "x64a1u",
162    "atxmega64a3": "x64a3",
163    "atxmega64a3u": "x64a3u",
164    "atxmega64a4": "x64a4",
165    "atxmega64a4u": "x64a4u",
166    "atxmega64b1": "x64b1",
167    "atxmega64b3": "x64b3",
168    "atxmega64c3": "x64c3",
169    "atxmega64d3": "x64d3",
170    "atxmega64d4": "x64d4",
171    "atxmega8e5": "x8e5",
172}
173
174
175def avrdude_mcu(did) -> str | None:
176    """:return: The avrdude MCU name for a device identifier or None."""
177    d = did.copy()
178    # Search for key by truncating type
179    while True:
180        name = d.string.split("-")[0]
181        if name in avrdude_mcu_map:
182            return avrdude_mcu_map[name]
183        if len(d.type) == 0:
184            break
185        d.set("type", d.type[:-1])
186    LOGGER.warning("Avrdude mcu not found for '%s'!", did.string)
187    return None
188
189
190def device_files(prefix: str) -> list[Path]:
191    """
192    :param prefix: An AVR device prefix, for example, `atmega`, `attiny`, `at90`.
193    :return: A sorted list of ATDF files matching the prefix.
194    """
195    return sorted(_ATDF_PATH.glob(f"*/AT{prefix[2:]}*"))
196
197
198def devices_from_file(path: Path) -> list[str]:
199    """:return: A sorted list of device order codes described in the ATDF file."""
200    device_file = XmlReader(path)
201    return sorted(set(d for d in device_file.query("//variants/variant/@ordercode") if d != "standard"))
202
203
204def device_from_ordercode(path: Path, ordercode: str) -> dict | None:
205    """
206    Extracts the device data of one order code from an AVR ATDF file.
207
208    :param path: Path to the ATDF file.
209    :param ordercode: The device order code, for example, `ATmega328P-AU`.
210    :return: A dictionary of device properties or None if the device is not supported.
211    """
212    p = {}
213
214    device_file = XmlReader(path)
215    device = device_file.query("//device")[0]
216    variant = device_file.query(f'//variants/variant[@ordercode="{ordercode}"]')[0]
217    did = avr_did_from_string(ordercode.lower())
218    if did is None:
219        LOGGER.error("Parse Error: unknown platform. Device string: '%s'", ordercode)
220        return None
221    p["id"] = did
222    LOGGER.info("Parsing '%s'", did.string)
223
224    mcu = avrdude_mcu(did)
225    p["mcu"] = "unsupported" if mcu is None else mcu
226    p["core"] = device.get("architecture").lower()
227    # We don't care about Microchip's new AVR8X devices
228    if p["core"] == "avr8x":
229        return None
230
231    p["define"] = "__AVR_" + device.get("name") + "__"
232    p["max_fcpu"] = variant.get("speedmax")
233    p["package"] = variant.get("package")
234    p["pinout"] = variant.get("pinout")
235    pinouts = device_file.query(f'//pinouts/pinout[@name="{p["pinout"]}"]/pin')
236    if not pinouts:
237        pinouts = device_file.query("//pinouts/pinout[1]/pin")
238    p["pinout_pins"] = {pin.get("position"): pin.get("pad") for pin in pinouts}
239
240    # find the values for flash, ram and (optional) eeprom
241    for memory_segment in device_file.query("//memory-segment"):
242        name = memory_segment.get("name")
243        size = int(memory_segment.get("size"), 16)
244        if name in ["FLASH", "APP_SECTION", "PROGMEM"]:
245            p["flash"] = size
246        elif name in ["IRAM", "SRAM", "INTERNAL_SRAM"]:
247            p["ram"] = size
248        elif name == "EEPROM":
249            p["eeprom"] = size
250
251    modules = []
252    ports = []
253    for m in device_file.query("//peripherals/module/instance"):
254        tmp = {"module": m.getparent().get("name").lower(), "instance": m.get("name").lower()}
255        # module SPI has two instances USART0_SPI, USART1_SPI
256        if tmp["module"] == "spi" and tmp["instance"].startswith("usart"):
257            continue
258        # some RF modules mistakenly claim flash module
259        if tmp["module"] == "flash":
260            continue
261        if tmp["module"] == "port":
262            ports.append(tmp)
263        else:
264            modules.append(tmp)
265    p["modules"] = sorted(list(set([(m["module"], m["instance"]) for m in modules])))
266
267    signals = []
268    gpios = []
269    raw_signals = device_file.query("//peripherals/module/instance/signals/signal")
270    p["modules_only"] = not len(raw_signals)
271    if p["modules_only"]:
272        # Parse GPIOs manually from mask
273        for port in ports:
274            port = port["instance"][-1:]
275            register = f'//modules/module[@name="PORT"]/register-group[@name="PORT{port.upper()}"]/register[@name="PORT{port.upper()}"]'
276            port_mask = device_file.query(register + "/@mask")
277            if len(port_mask) == 0:
278                # The port mask is split up
279                port_mask = sum([int(mask, 16) for mask in device_file.query(register + "/bitfield/@mask")])
280            else:
281                port_mask = int(port_mask[0], 16)
282            for pos in range(8):
283                if (1 << pos) & port_mask:
284                    gpios.append((port, str(pos)))
285        gpios = sorted(gpios)
286    else:
287        signal_hashs = set()
288        for s in raw_signals:
289            tmp = {
290                "module": s.getparent().getparent().getparent().get("name").lower(),
291                "instance": s.getparent().getparent().get("name").lower(),
292            }
293            # Some ATDF files contain trailing whitespace, for example, group="SCL "
294            tmp.update({k: v.strip().lower() for k, v in s.items()})
295            if tmp["group"] in ["p", "pin"] or tmp["group"].startswith("port"):
296                gpios.append(tmp)
297            else:
298                # filter out duplicates
299                shash = tmp.get("instance", "") + tmp.get("group", "") + tmp.get("pad", "") + tmp.get("index", "")
300                if shash not in signal_hashs:
301                    signal_hashs.add(shash)
302                    signals.append(tmp)
303                else:
304                    LOGGER.debug("Duplicate signal '%s'", tmp)
305        gpios = sorted([(g["pad"][1], g["pad"][2]) for g in gpios])
306
307    p["signals"] = signals
308    # Filter gpios by pinout
309    p["gpios"] = [pin for pin in gpios if f"P{pin[0].upper()}{pin[1]}" in p["pinout_pins"].values()]
310    if not p["gpios"]:
311        LOGGER.error("No GPIOs found for '%s'!", did.string)
312        return None
313
314    p["interrupts"] = [
315        {"position": i.get("index"), "name": i.get("name")} for i in device_file.query("//interrupts/interrupt")
316    ]
317    return p
LOGGER = <Logger modm_data.atdf.avr (WARNING)>
avrdude_mcu_map = {'at90s1200': '1200', 'at90s2313': '2313', 'at90s2333': '2333', 'at90s2343': '2343', 'at90s4414': '4414', 'at90s4433': '4433', 'at90s4434': '4434', 'at90s8515': '8515', 'at90s8535': '8535', 'at90can128': 'c128', 'at90can32': 'c32', 'at90can64': 'c64', 'at90pwm216': 'pwm216', 'at90pwm2': 'pwm2', 'at90pwm2b': 'pwm2b', 'at90pwm3': 'pwm3', 'at90pwm316': 'pwm316', 'at90pwm3b': 'pwm3b', 'at90usb1286': 'usb1286', 'at90usb1287': 'usb1287', 'at90usb162': 'usb162', 'at90usb646': 'usb646', 'at90usb647': 'usb647', 'at90usb82': 'usb82', 'atmega103': 'm103', 'atmega128': 'm128', 'atmega1280': 'm1280', 'atmega1281': 'm1281', 'atmega1284': 'm1284', 'atmega1284p': 'm1284p', 'atmega1284rfr2': 'm1284rfr2', 'atmega128rfa1': 'm128rfa1', 'atmega128rfr2': 'm128rfr2', 'atmega16': 'm16', 'atmega161': 'm161', 'atmega162': 'm162', 'atmega163': 'm163', 'atmega164p': 'm164p', 'atmega168': 'm168', 'atmega168p': 'm168p', 'atmega168pb': 'm168pb', 'atmega169': 'm169', 'atmega16u2': 'm16u2', 'atmega2560': 'm2560', 'atmega2561': 'm2561', 'atmega2564rfr2': 'm2564rfr2', 'atmega256rfr2': 'm256rfr2', 'atmega32': 'm32', 'atmega324p': 'm324p', 'atmega324pa': 'm324pa', 'atmega325': 'm325', 'atmega3250': 'm3250', 'atmega328': 'm328', 'atmega328p': 'm328p', 'atmega329': 'm329', 'atmega3290': 'm3290', 'atmega3290p': 'm3290p', 'atmega329p': 'm329p', 'atmega32m1': 'm32m1', 'atmega32u2': 'm32u2', 'atmega32u4': 'm32u4', 'atmega406': 'm406', 'atmega48': 'm48', 'atmega48p': 'm48p', 'atmega48pb': 'm48pb', 'atmega64': 'm64', 'atmega640': 'm640', 'atmega644': 'm644', 'atmega644p': 'm644p', 'atmega644rfr2': 'm644rfr2', 'atmega645': 'm645', 'atmega6450': 'm6450', 'atmega649': 'm649', 'atmega6490': 'm6490', 'atmega64rfr2': 'm64rfr2', 'atmega8': 'm8', 'atmega8515': 'm8515', 'atmega8535': 'm8535', 'atmega88': 'm88', 'atmega88p': 'm88p', 'atmega88pb': 'm88pb', 'atmega8u2': 'm8u2', 'attiny10': 't10', 'attiny11': 't11', 'attiny12': 't12', 'attiny13': 't13', 'attiny15': 't15', 'attiny1634': 't1634', 'attiny20': 't20', 'attiny2313': 't2313', 'attiny24': 't24', 'attiny25': 't25', 'attiny26': 't26', 'attiny261': 't261', 'attiny28': 't28', 'attiny4': 't4', 'attiny40': 't40', 'attiny4313': 't4313', 'attiny43u': 't43u', 'attiny44': 't44', 'attiny45': 't45', 'attiny461': 't461', 'attiny5': 't5', 'attiny84': 't84', 'attiny85': 't85', 'attiny861': 't861', 'attiny88': 't88', 'attiny9': 't9', 'atxmega128a1': 'x128a1', 'atxmega128a1revd': 'x128a1d', 'atxmega128a1u': 'x128a1u', 'atxmega128a3': 'x128a3', 'atxmega128a3u': 'x128a3u', 'atxmega128a4': 'x128a4', 'atxmega128a4u': 'x128a4u', 'atxmega128b1': 'x128b1', 'atxmega128b3': 'x128b3', 'atxmega128c3': 'x128c3', 'atxmega128d3': 'x128d3', 'atxmega128d4': 'x128d4', 'atxmega16a4': 'x16a4', 'atxmega16a4u': 'x16a4u', 'atxmega16c4': 'x16c4', 'atxmega16d4': 'x16d4', 'atxmega16e5': 'x16e5', 'atxmega192a1': 'x192a1', 'atxmega192a3': 'x192a3', 'atxmega192a3u': 'x192a3u', 'atxmega192c3': 'x192c3', 'atxmega192d3': 'x192d3', 'atxmega256a1': 'x256a1', 'atxmega256a3': 'x256a3', 'atxmega256a3b': 'x256a3b', 'atxmega256a3bu': 'x256a3bu', 'atxmega256a3u': 'x256a3u', 'atxmega256c3': 'x256c3', 'atxmega256d3': 'x256d3', 'atxmega32a4': 'x32a4', 'atxmega32a4u': 'x32a4u', 'atxmega32c4': 'x32c4', 'atxmega32d4': 'x32d4', 'atxmega32e5': 'x32e5', 'atxmega384c3': 'x384c3', 'atxmega384d3': 'x384d3', 'atxmega64a1': 'x64a1', 'atxmega64a1u': 'x64a1u', 'atxmega64a3': 'x64a3', 'atxmega64a3u': 'x64a3u', 'atxmega64a4': 'x64a4', 'atxmega64a4u': 'x64a4u', 'atxmega64b1': 'x64b1', 'atxmega64b3': 'x64b3', 'atxmega64c3': 'x64c3', 'atxmega64d3': 'x64d3', 'atxmega64d4': 'x64d4', 'atxmega8e5': 'x8e5'}
def avrdude_mcu(did) -> str | None:
176def avrdude_mcu(did) -> str | None:
177    """:return: The avrdude MCU name for a device identifier or None."""
178    d = did.copy()
179    # Search for key by truncating type
180    while True:
181        name = d.string.split("-")[0]
182        if name in avrdude_mcu_map:
183            return avrdude_mcu_map[name]
184        if len(d.type) == 0:
185            break
186        d.set("type", d.type[:-1])
187    LOGGER.warning("Avrdude mcu not found for '%s'!", did.string)
188    return None
Returns

The avrdude MCU name for a device identifier or None.

def device_files(prefix: str) -> list[pathlib.Path]:
191def device_files(prefix: str) -> list[Path]:
192    """
193    :param prefix: An AVR device prefix, for example, `atmega`, `attiny`, `at90`.
194    :return: A sorted list of ATDF files matching the prefix.
195    """
196    return sorted(_ATDF_PATH.glob(f"*/AT{prefix[2:]}*"))
Parameters
  • prefix: An AVR device prefix, for example, atmega, attiny, at90.
Returns

A sorted list of ATDF files matching the prefix.

def devices_from_file(path: pathlib.Path) -> list[str]:
199def devices_from_file(path: Path) -> list[str]:
200    """:return: A sorted list of device order codes described in the ATDF file."""
201    device_file = XmlReader(path)
202    return sorted(set(d for d in device_file.query("//variants/variant/@ordercode") if d != "standard"))
Returns

A sorted list of device order codes described in the ATDF file.

def device_from_ordercode(path: pathlib.Path, ordercode: str) -> dict | None:
205def device_from_ordercode(path: Path, ordercode: str) -> dict | None:
206    """
207    Extracts the device data of one order code from an AVR ATDF file.
208
209    :param path: Path to the ATDF file.
210    :param ordercode: The device order code, for example, `ATmega328P-AU`.
211    :return: A dictionary of device properties or None if the device is not supported.
212    """
213    p = {}
214
215    device_file = XmlReader(path)
216    device = device_file.query("//device")[0]
217    variant = device_file.query(f'//variants/variant[@ordercode="{ordercode}"]')[0]
218    did = avr_did_from_string(ordercode.lower())
219    if did is None:
220        LOGGER.error("Parse Error: unknown platform. Device string: '%s'", ordercode)
221        return None
222    p["id"] = did
223    LOGGER.info("Parsing '%s'", did.string)
224
225    mcu = avrdude_mcu(did)
226    p["mcu"] = "unsupported" if mcu is None else mcu
227    p["core"] = device.get("architecture").lower()
228    # We don't care about Microchip's new AVR8X devices
229    if p["core"] == "avr8x":
230        return None
231
232    p["define"] = "__AVR_" + device.get("name") + "__"
233    p["max_fcpu"] = variant.get("speedmax")
234    p["package"] = variant.get("package")
235    p["pinout"] = variant.get("pinout")
236    pinouts = device_file.query(f'//pinouts/pinout[@name="{p["pinout"]}"]/pin')
237    if not pinouts:
238        pinouts = device_file.query("//pinouts/pinout[1]/pin")
239    p["pinout_pins"] = {pin.get("position"): pin.get("pad") for pin in pinouts}
240
241    # find the values for flash, ram and (optional) eeprom
242    for memory_segment in device_file.query("//memory-segment"):
243        name = memory_segment.get("name")
244        size = int(memory_segment.get("size"), 16)
245        if name in ["FLASH", "APP_SECTION", "PROGMEM"]:
246            p["flash"] = size
247        elif name in ["IRAM", "SRAM", "INTERNAL_SRAM"]:
248            p["ram"] = size
249        elif name == "EEPROM":
250            p["eeprom"] = size
251
252    modules = []
253    ports = []
254    for m in device_file.query("//peripherals/module/instance"):
255        tmp = {"module": m.getparent().get("name").lower(), "instance": m.get("name").lower()}
256        # module SPI has two instances USART0_SPI, USART1_SPI
257        if tmp["module"] == "spi" and tmp["instance"].startswith("usart"):
258            continue
259        # some RF modules mistakenly claim flash module
260        if tmp["module"] == "flash":
261            continue
262        if tmp["module"] == "port":
263            ports.append(tmp)
264        else:
265            modules.append(tmp)
266    p["modules"] = sorted(list(set([(m["module"], m["instance"]) for m in modules])))
267
268    signals = []
269    gpios = []
270    raw_signals = device_file.query("//peripherals/module/instance/signals/signal")
271    p["modules_only"] = not len(raw_signals)
272    if p["modules_only"]:
273        # Parse GPIOs manually from mask
274        for port in ports:
275            port = port["instance"][-1:]
276            register = f'//modules/module[@name="PORT"]/register-group[@name="PORT{port.upper()}"]/register[@name="PORT{port.upper()}"]'
277            port_mask = device_file.query(register + "/@mask")
278            if len(port_mask) == 0:
279                # The port mask is split up
280                port_mask = sum([int(mask, 16) for mask in device_file.query(register + "/bitfield/@mask")])
281            else:
282                port_mask = int(port_mask[0], 16)
283            for pos in range(8):
284                if (1 << pos) & port_mask:
285                    gpios.append((port, str(pos)))
286        gpios = sorted(gpios)
287    else:
288        signal_hashs = set()
289        for s in raw_signals:
290            tmp = {
291                "module": s.getparent().getparent().getparent().get("name").lower(),
292                "instance": s.getparent().getparent().get("name").lower(),
293            }
294            # Some ATDF files contain trailing whitespace, for example, group="SCL "
295            tmp.update({k: v.strip().lower() for k, v in s.items()})
296            if tmp["group"] in ["p", "pin"] or tmp["group"].startswith("port"):
297                gpios.append(tmp)
298            else:
299                # filter out duplicates
300                shash = tmp.get("instance", "") + tmp.get("group", "") + tmp.get("pad", "") + tmp.get("index", "")
301                if shash not in signal_hashs:
302                    signal_hashs.add(shash)
303                    signals.append(tmp)
304                else:
305                    LOGGER.debug("Duplicate signal '%s'", tmp)
306        gpios = sorted([(g["pad"][1], g["pad"][2]) for g in gpios])
307
308    p["signals"] = signals
309    # Filter gpios by pinout
310    p["gpios"] = [pin for pin in gpios if f"P{pin[0].upper()}{pin[1]}" in p["pinout_pins"].values()]
311    if not p["gpios"]:
312        LOGGER.error("No GPIOs found for '%s'!", did.string)
313        return None
314
315    p["interrupts"] = [
316        {"position": i.get("index"), "name": i.get("name")} for i in device_file.query("//interrupts/interrupt")
317    ]
318    return p

Extracts the device data of one order code from an AVR ATDF file.

Parameters
  • path: Path to the ATDF file.
  • ordercode: The device order code, for example, ATmega328P-AU.
Returns

A dictionary of device properties or None if the device is not supported.