diff --git a/.travis.yml b/.travis.yml index acb909b4..323eca95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ script: - (cd tools/generator; make generate-avr) - (cd tools/generator; make generate-stm32) - (cd tools/generator; make generate-sam) + - (cd tools/generator; make generate-nrf) - tools/device/scripts/stats --count - tools/device/scripts/stats --name >/dev/null - tools/device/scripts/stats --ram >/dev/null diff --git a/README.md b/README.md index 4f4ad5c3..0fea2987 100644 --- a/README.md +++ b/README.md @@ -13,18 +13,19 @@ These tools and this data set is maintained and curated by It is licensed under the MPLv2 license. The CI checks daily for new data: [![](https://travis-ci.org/modm-io/modm-devices.svg?branch=develop)](https://travis-ci.org/modm-io/modm-devices) -Currently data for 3240 devices is available. +Currently data for 3247 devices is available. Please open an issue or better yet a pull request for additional support. | Family | Devices | Family | Devices | Family | Devices | |:--------------|:--------|:--------------|:--------|:--------------|:--------| | AT90 | 12 | ATMEGA | 370 | ATTINY | 148 | -| SAMD | 209 | SAML | 47 | STM32F0 | 168 | -| STM32F1 | 194 | STM32F2 | 71 | STM32F3 | 143 | -| STM32F4 | 340 | STM32F7 | 174 | STM32G0 | 117 | -| STM32G4 | 263 | STM32H7 | 153 | STM32L0 | 307 | -| STM32L1 | 140 | STM32L4 | 353 | STM32WB | 31 | +| NRF52 | 7 | SAMD | 209 | SAML | 47 | +| STM32F0 | 168 | STM32F1 | 194 | STM32F2 | 71 | +| STM32F3 | 143 | STM32F4 | 340 | STM32F7 | 174 | +| STM32G0 | 117 | STM32G4 | 263 | STM32H7 | 153 | +| STM32L0 | 307 | STM32L1 | 140 | STM32L4 | 353 | +| STM32WB | 31 | diff --git a/devices/nrf/nrf52810.xml b/devices/nrf/nrf52810.xml new file mode 100644 index 00000000..956965c9 --- /dev/null +++ b/devices/nrf/nrf52810.xml @@ -0,0 +1,169 @@ + + + + + {platform}{family}{series}-{package}{function} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/devices/nrf/nrf52811.xml b/devices/nrf/nrf52811.xml new file mode 100644 index 00000000..e6cbeea4 --- /dev/null +++ b/devices/nrf/nrf52811.xml @@ -0,0 +1,182 @@ + + + + + {platform}{family}{series}-{package}{function} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/devices/nrf/nrf52820.xml b/devices/nrf/nrf52820.xml new file mode 100644 index 00000000..3ed75754 --- /dev/null +++ b/devices/nrf/nrf52820.xml @@ -0,0 +1,189 @@ + + + + + {platform}{family}{series}-{package}{function} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/devices/nrf/nrf52832.xml b/devices/nrf/nrf52832.xml new file mode 100644 index 00000000..23da70c8 --- /dev/null +++ b/devices/nrf/nrf52832.xml @@ -0,0 +1,228 @@ + + + + + {platform}{family}{series}-{package}{function} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/devices/nrf/nrf52833.xml b/devices/nrf/nrf52833.xml new file mode 100644 index 00000000..3fef5258 --- /dev/null +++ b/devices/nrf/nrf52833.xml @@ -0,0 +1,284 @@ + + + + + {platform}{family}{series}-{package}{function} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/devices/nrf/nrf52840.xml b/devices/nrf/nrf52840.xml new file mode 100644 index 00000000..dfd73e9a --- /dev/null +++ b/devices/nrf/nrf52840.xml @@ -0,0 +1,296 @@ + + + + + {platform}{family}{series}-{package}{function} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/generator/Makefile b/tools/generator/Makefile index 69b5de56..bde282a7 100644 --- a/tools/generator/Makefile +++ b/tools/generator/Makefile @@ -15,7 +15,7 @@ raw-device-data/%-devices: (cd raw-data-extractor && python3 extract-$(@:raw-device-data/%-devices=%).py) .PHONY: extract -extract: raw-device-data/avr-devices raw-device-data/stm32-devices raw-device-data/sam-devices +extract: raw-device-data/avr-devices raw-device-data/stm32-devices raw-device-data/sam-devices raw-device-data/nrf-devices .PHONY: clean_extract clean_extract: @@ -41,6 +41,17 @@ generate-sam%: raw-device-data/sam-devices ext/cmsis-5-partial generate-sam: generate-saml21 generate-samd21 generate-samd51 + +# NRF device files +.PHONY: generate-nrf% +generate-nrf%: raw-device-data/nrf-devices ext/cmsis-5-partial + @rm -f ../../devices/nrf/$(@:generate-%=%)* + ./nrf_generator.py $(@:generate-%=%) + +.PHONY: generate-nrf +generate-nrf: generate-nrf52810 generate-nrf52811 generate-nrf52820 generate-nrf52832 generate-nrf52833 generate-nrf52840 + + # STM32 device files .PHONY: generate-stm32% generate-stm32%: raw-device-data/sam-devices ext/cmsis-5-partial ext/cmsis-header-stm32 diff --git a/tools/generator/dfg/nrf/__init__.py b/tools/generator/dfg/nrf/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tools/generator/dfg/nrf/nrf_device_tree.py b/tools/generator/dfg/nrf/nrf_device_tree.py new file mode 100644 index 00000000..58790ffa --- /dev/null +++ b/tools/generator/dfg/nrf/nrf_device_tree.py @@ -0,0 +1,300 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2013-2016, Niklas Hauser +# Copyright (c) 2016, Fabian Greif +# Copyright (c) 2020, Hannes Ellinger +# All rights reserved. + +import math +import logging +import re +import os + +from ..device_tree import DeviceTree +from ..input.xml import XMLReader + +from .nrf_identifier import NRFIdentifier + +LOGGER = logging.getLogger('dfg.nrf.reader') + +class NRFDeviceTree: + """ NRFDeviceTree + This NRF specific part description file reader knows the structure and + translates the data into a platform independent format. + """ + + @staticmethod + def _properties_from_file(ld_filename): + xml_filename = re.sub('\_\w{4}.ld', '.svd', ld_filename) + device_file = XMLReader(xml_filename) + p = {} + + partname = ld_filename.split('/')[-1] + partname = partname.split('.')[0] + partname = partname.replace('_', '-') + + did = NRFIdentifier.from_string(partname.lower()) + p['id'] = did + + LOGGER.info("Parsing '%s'", did.string) + + # information about the core and architecture + core = device_file.query("//device/cpu/name")[0].text.lower().replace("cm", "cortex-m") + if device_file.query("//device/cpu/fpuPresent")[0].text == '1': + core += "f" + p["core"] = core + + + # find the values for flash and ram + memlines = [] + with open(ld_filename, 'r') as linkerfile: + status = 0 + for line in linkerfile: + if status == 0 and "MEMORY" in line: + status = 1 + elif status == 1 and "{" in line: + status = 2 + elif status == 2: + if "}" in line: + status = 3 + else: + memlines.append(line) + + memories = [] + + for memline in memlines: + matchString = r" (?P\w*) \((?P\w*)\) : ORIGIN = (?P0x\d*), LENGTH = (?P0x\d*)" + match = re.search(matchString, memline) + memories.append({ + "name": match.group("name").lower(), + "access": match.group("access").lower(), + "size": str(int(match.group("size").lower(), 16)), + "start": match.group("start").lower()}) + + p["memories"] = memories + + + # Signals + signals = {} + raw_signals = device_file.query("//peripherals/peripheral/registers/cluster") + for s in raw_signals: + if s.find('name').text == "PSEL": + + # find parent peripheral + parent_peripheral_instance = s.getparent().getparent().find('name').text.lower() + signals[parent_peripheral_instance] = [] + + # find all signals of peripheral + signal_elements = s.findall('register/name') + for signal_element in signal_elements: + signal_name = signal_element.text.lower() + signals[parent_peripheral_instance].append(signal_name) + + + # drivers and gpios + raw_modules = device_file.query("//peripherals/peripheral") + modules = [] + ports = {} + gpios = [] + for m in raw_modules: + modulename = m.find('name').text + moduledesc = m.find('description').text + + if "GPIO Port" in moduledesc: + # omit the leading P of the port names, also of the derived ports + portnumber = modulename[1:] + if m.get('derivedFrom') is not None: + portsize = ports[m.get('derivedFrom')[1:]] + else: + portsize = int(m.find('size').text, base=0) + + ports[portnumber] = portsize + for i in range(portsize): + gpios.append((portnumber, str(i))) + + else: + matchString = r"(?P.*\D)(?P\d*$)" + match = re.search(matchString, modulename) + modules.append({'module': match.group("module").lower(), 'instance': modulename.lower()}) + + # copy available signals to all derived peripherals + if m.get('derivedFrom') is not None: + if m.get('derivedFrom').lower() in signals: + LOGGER.debug(modulename.lower() + " is derived from " + m.get('derivedFrom').lower()) + signals[modulename.lower()] = signals[m.get('derivedFrom').lower()] + p['modules'] = sorted(list(set([(m['module'], m['instance']) for m in modules]))) + p['gpios'] = gpios + p['signals'] = [] + for instance in signals: + for signal in signals[instance]: + matchString = r"(?P.*\D)(?P\d*$)" + match = re.search(matchString, instance) + if not "[%s]" in signal: # TODO take care of multichannel signals like OUT[%s] of PWM peripheral + p['signals'].append({'driver': match.group("module").lower(), 'instance': instance, 'name': signal}) + + + interrupts = [] + raw_interrupt = device_file.query("//peripherals/peripheral/interrupt") + for i in raw_interrupt: + interruptname = i.find('name').text + interruptnum = i.find('value').text + interrupts.append({'position': interruptnum, 'name': interruptname}) + + # Unique interrupts + p['interrupts'] = [] + for interrupt in interrupts: + if interrupt not in p['interrupts']: + p['interrupts'].append(interrupt) + + LOGGER.debug("Found GPIOs: [%s]", ", ".join([p.upper() + "." + i for p,i in p['gpios']])) + LOGGER.debug("Available Modules are:\n" + NRFDeviceTree._modulesToString(p['modules'])) + LOGGER.debug("Found Signals:") + for sig in p['signals']: + LOGGER.debug(" %s", sig) + LOGGER.debug("Found Interrupts:") + for intr in p['interrupts']: + LOGGER.debug(" %s", intr) + + return p + + @staticmethod + def _modulesToString(modules): + string = "" + mods = sorted(modules) + char = mods[0][0][0:1] + for module, instance in mods: + if not instance.startswith(char): + string += "\n" + string += instance + " \t" + char = instance[0][0:1] + return string + + @staticmethod + def _device_tree_from_properties(p): + tree = DeviceTree('device') + tree.ids.append(p['id']) + + def topLevelOrder(e): + order = ['attribute-flash', 'attribute-ram', 'attribute-eeprom', 'attribute-core', 'attribute-mcu', 'header', 'attribute-define'] + if e.name in order: + if e.name in ['attribute-flash', 'attribute-eeprom', 'attribute-ram']: + return (order.index(e.name), int(e['value'])) + else: + return (order.index(e.name), e['value']) + return (len(order), -1) + # tree.addSortKey(topLevelOrder) + + # NRFDeviceTree.addDeviceAttributesToNode(p, tree, 'attribute-flash') + # NRFDeviceTree.addDeviceAttributesToNode(p, tree, 'attribute-ram') + # NRFDeviceTree.addDeviceAttributesToNode(p, tree, 'attribute-eeprom') + # NRFDeviceTree.addDeviceAttributesToNode(p, tree, 'attribute-mcu') + + def driverOrder(e): + if e.name == 'driver': + if e['name'] == 'core': + # place the core at the very beginning + return ('aaaaaaa', e['type']) + if e['name'] == 'gpio': + # place the gpio at the very end + return ('zzzzzzz', e['type']) + # sort remaining drivers by type and compatible strings + return (e['name'], e['type']) + return ("", "") + tree.addSortKey(driverOrder) + + # Core + core_child = tree.addChild('driver') + core_child.setAttributes('name', 'core', 'type', p['core']) + core_child.addSortKey(lambda e: (int(e['position']), e['name']) if e.name == 'vector' else (-1, "")) + core_child.addSortKey(lambda e: (e['name'], int(e['size'])) if e.name == 'memory' else ("", -1)) + + for section in p["memories"]: + memory_section = core_child.addChild("memory") + memory_section.setAttributes(["name", "access", "start", "size"], section) + # sort the node children by start address and size + core_child.addSortKey(lambda e: (int(e["start"], 16), int(e["size"])) if e.name == "memory" else (-1, -1)) + + # for memory in ['flash', 'ram', 'lpram', 'eeprom']: + # if memory not in p: continue; + # memory_section = core_child.addChild('memory') + # memory_section.setAttribute('name', memory) + # memory_section.setAttribute('size', p[memory]) + + for vector in p['interrupts']: + if int(vector['position']) < 0: continue; + vector_section = core_child.addChild('vector') + vector_section.setAttributes(['position', 'name'], vector) + + modules = {} + for m, i in p['modules']: + # filter out non-peripherals: fuses, micro-trace buffer + if m in ['fuses', 'mtb', 'systemcontrol', 'systick', 'hmatrixb', 'hmatrix']: continue; + if m not in modules: + modules[m] = [i] + else: + modules[m].append(i) + + + compatible = p['id']['platform'] + p['id']['family'] + # add all other modules + for name, instances in modules.items(): + driver = tree.addChild('driver') + dtype = name + + driver.setAttributes('name', dtype, 'type', compatible) + # Add all instances to this driver + if any(i != dtype for i in instances): + driver.addSortKey(lambda e: e['value']) + for i in instances: + inst = driver.addChild('instance') + inst.setValue(i[len(dtype):]) + + # GPIO driver + gpio_driver = tree.addChild('driver') + gpio_driver.setAttributes('name', 'gpio', 'type', compatible) + # gpio_driver.addSortKey(lambda e : (e['port'], int(e['pin']))) + + # add all signals + for s in p['signals']: + driver, instance, name = s['driver'], s['instance'], s['name'] + # add the af node + gpio_signal = {'driver': driver} + if instance != driver: + gpio_signal['instance'] = instance.replace(driver, '') + if name != driver and name != 'int': + if 'index' in s: name += s['index']; + gpio_signal['name'] = name + elif 'index' in s: + gpio_signal['name'] = s['index'] + if "name" not in gpio_signal: + LOGGER.error("%s has no name!", s) + continue + + af = gpio_driver.addChild('signal') + af.setAttributes(['driver', 'instance', 'name'], gpio_signal) + + # add all GPIOs + for port, pin in p['gpios']: + pin_driver = gpio_driver.addChild('gpio') + pin_driver.setAttributes('port', port, 'pin', pin) + pin_driver.addSortKey(lambda e: (e['driver'], + e['instance'] if e['instance'] is not None else '', + e['name'] if e['name'] is not None else '')) + + return tree + + @staticmethod + def addDeviceAttributesToNode(p, node, name): + pname = name.split('-')[-1] + if pname not in p: return; + props = p[pname] + if not isinstance(props, list): + props = [props] + for prop in props: + child = node.addChild(name) + child.setValue(prop) + + @staticmethod + def from_file(filename): + p = NRFDeviceTree._properties_from_file(filename) + if p is None: return None; + return NRFDeviceTree._device_tree_from_properties(p) diff --git a/tools/generator/dfg/nrf/nrf_groups.py b/tools/generator/dfg/nrf/nrf_groups.py new file mode 100644 index 00000000..dcca1bab --- /dev/null +++ b/tools/generator/dfg/nrf/nrf_groups.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2020 Hannes Ellinger +# All rights reserved. + +nrf_groups = \ +[ + # NRF5 devices + { + 'family': ['51'], + 'series': ['822'] + },{ + 'family': ['52'], + 'series': ['810', '811', '820', '832', '833', '840'] + }, +] diff --git a/tools/generator/dfg/nrf/nrf_identifier.py b/tools/generator/dfg/nrf/nrf_identifier.py new file mode 100644 index 00000000..64a4c303 --- /dev/null +++ b/tools/generator/dfg/nrf/nrf_identifier.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2013 , Kevin Läufer +# Copyright (c) 2013-2014, Niklas Hauser +# Copyright (c) 2016, Fabian Greif +# Copyright (c) 2020, Hannes Ellinger +# All rights reserved. + +import re +import logging + +from modm_devices.device_identifier import DeviceIdentifier + +LOGGER = logging.getLogger("dfg.nrf.identifier") + +class NRFIdentifier: + """ NRFIdentifier + A class to parse NRF device strings, e.g. NRF52840-QIAA. + Device names are organized as follows: + NRF 52 840 - QI AA + {platform}{family}{series}-{package}{function} + """ + + @staticmethod + def from_string(string): + string = string.lower() + + if string.startswith("nrf"): + matchString = r"nrf(?P[0-9]{2})(?P[0-9]{3})-(?P\w{2})(?P\w{2})" + match = re.search(matchString, string) + if match: + i = DeviceIdentifier("{platform}{family}{series}-{package}{function}") + i.set("platform", "nrf") + i.set("family", match.group("family").lower()) + i.set("series", match.group("series").lower()) + i.set("package", match.group("package").lower()) + i.set("function", match.group("function").lower()) + return i + + + LOGGER.error("Parse Error: unknown platform. Device string: '%s'", string) + exit(1) diff --git a/tools/generator/nrf_generator.py b/tools/generator/nrf_generator.py new file mode 100755 index 00000000..bf6e8c1c --- /dev/null +++ b/tools/generator/nrf_generator.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (c) 2013-2016, Niklas Hauser +# Copyright (c) 2016, Fabian Greif +# All rights reserved. +# TESTING: exec(open("./nrf_generator.py").read()) + +import os +import sys +import glob +import logging + +import dfg.logger + +from dfg.merger import DeviceMerger +from dfg.nrf.nrf_device_tree import NRFDeviceTree +from dfg.nrf.nrf_groups import nrf_groups +from dfg.output.device_file import DeviceFileWriter +from modm_devices.parser import DeviceParser +from deepdiff import DeepDiff + +LOGGER = logging.getLogger('dfg.nrf') + +if __name__ == "__main__": + loglevel = 'INFO' + devs = [] + device_depth = 1e6 + simulate = False + + for arg in sys.argv[1:]: + if arg.startswith('-n'): + simulate = True + continue + if arg.startswith('--log='): + loglevel = arg.replace('--log=', '') + continue + if arg.startswith('--depth='): + device_depth = int(arg.replace('--depth=', '')) - 1 + continue + devs.append(arg) + + if not len(devs): + devs.append('nrf52810') + devs.append('nrf52811') + devs.append('nrf52820') + devs.append('nrf52832') + devs.append('nrf52833') + devs.append('nrf52840') + + dfg.logger.configure_logger(loglevel) + + devices = {} + for dev in devs: + ld_path = os.path.join(os.path.dirname(__file__), 'raw-device-data', 'nrf-devices', 'nrf', (dev.lower() + '_*.ld')) + files = glob.glob(ld_path) + for filename in files: + device = NRFDeviceTree.from_file(filename) + if device is None: continue; + devices[device.ids.string] = device + if device_depth > 0: + device_depth -= 1 + else: + exit(1) + + mergedDevices = DeviceMerger.merge(nrf_groups, [d.copy() for d in devices.values()]) + + def filename(ids): + p = {} + for k in ids.keys(): + v = [] + for b in ids.getAttribute(k): + if b == "": b = 'n' + v.append(b) + if k in ['type', 'pin']: v.sort() + if len(v) > 0: + p[k] = "_".join(v) + fmt = "{platform}{family}{series}" + return fmt.format(**p) + + folder = os.path.join(os.path.dirname(__file__), '..', '..', 'devices', 'nrf') + parser = DeviceParser() + parsed_devices = {} + for dev in mergedDevices: + # dump the merged device file into the devices folder + path = DeviceFileWriter.write(dev, folder, filename) + # immediately parse this file + device_file = parser.parse(path) + for device in device_file.get_devices(): + # and extract all the devices from it + parsed_devices[device.partname] = device + + tmp_folder = os.path.join(os.path.dirname(__file__), 'single') + os.makedirs(tmp_folder, exist_ok=True) + for pname, pdevice in parsed_devices.items(): + # these are the properties from the merged device + pprops = pdevice.properties + # dump the associated single device + rpath = DeviceFileWriter.write(devices[pname], tmp_folder, lambda ids: ids.string) + # parse it again + rdevice_file = parser.parse(rpath) + rdevice = rdevice_file.get_devices() + assert(len(rdevice) == 1) + # these are the properties of the single device + rprops = rdevice[0].properties + ddiff = DeepDiff(rprops, pprops, ignore_order=True) + # assert that there is no difference between the two + assert(len(ddiff) == 0) diff --git a/tools/generator/raw-data-extractor/extract-nrf.py b/tools/generator/raw-data-extractor/extract-nrf.py new file mode 100644 index 00000000..7a1c8df6 --- /dev/null +++ b/tools/generator/raw-data-extractor/extract-nrf.py @@ -0,0 +1,36 @@ +from pathlib import Path +import urllib.request +import zipfile +import shutil +import io +import glob +import os + +packurl = "https://www.nordicsemi.com/-/media/Software-and-other-downloads/Desktop-software/nRF-MDK/sw/8-33-0/nRF_MDK_8_33_0_GCC_BSDLicense.zip" + +shutil.rmtree("../raw-device-data/nrf-devices", ignore_errors=True) +Path("../raw-device-data/nrf-devices/nrf").mkdir(exist_ok=True, parents=True) + +if __name__ == "__main__": + dest = "../raw-device-data/nrf-devices/nrf" + print("Downloading...") + with urllib.request.urlopen(packurl) as content: + z = zipfile.ZipFile(io.BytesIO(content.read())) + print("Extracting...") + # remove subfolders, some packs have several chips per pack + for zi in z.infolist(): + if zi.filename.endswith(".svd") or zi.filename.endswith(".ld"): + zi.filename = os.path.basename(zi.filename) + print(zi.filename) + z.extract(zi, dest) + + # dirty hack because af inconsistent part names in .svd files + os.rename(dest + '/nrf51.svd', dest + '/nrf51822.svd') + os.rename(dest + '/nrf52.svd', dest + '/nrf52832.svd') + + for f in glob.glob(dest + '/nrf51_*.ld'): + os.remove(f) + for f in glob.glob(dest + '/nrf52_*.ld'): + os.remove(f) + for f in glob.glob(dest + '/nrf_common.ld'): + os.remove(f)