From 2d38aad8617429da62c07e3e42f654e4eaa20cb9 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Thu, 29 Jul 2021 09:54:01 -0400 Subject: [PATCH 1/8] Include base addresses for flash and ram. Remove 'null' entries for datasheets/reference-manuals. --- parse.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/parse.py b/parse.py index 0b21927..595bad9 100755 --- a/parse.py +++ b/parse.py @@ -493,8 +493,14 @@ def parse_chips(): package_flashs = [package_flashs]*len(package_names) for package_i, package_name in enumerate(package_names): chip_name = chip_name_from_package_name(package_name) - flash = int(package_flashs[package_i]) - ram = int(package_rams[package_i]) + flash = OrderedDict( { + 'size': int(package_flashs[package_i]), + 'base': None, + } ) + ram = OrderedDict( { + 'size': int(package_rams[package_i]), + 'base': None, + } ) gpio_af = next(filter(lambda x: x['@Name'] == 'GPIO', r['IP']))['@Version'] gpio_af = removesuffix(gpio_af, '_gpio_v1_0') @@ -568,6 +574,11 @@ def parse_chips(): chips[chip_name]['reference-manual'] = rm[0] chips[chip_name]['application-notes'] = documents_for(chip_name, 'Application note') + if 'datasheet' in chips[chip_name] and chips[chip_name]['datasheet'] is None: + del chips[chip_name]['datasheet'] + if 'reference-manual' in chips[chip_name] and chips[chip_name]['reference-manual'] is None: + del chips[chip_name]['reference-manual'] + # Some packages have some peripehrals removed because the package had to # remove GPIOs useful for that peripheral. So we merge all peripherals from all packages. peris = chips[chip_name]['peripherals'] @@ -642,6 +653,15 @@ def parse_chips(): raise Exception("missing header for {}".format(chip_name)) h = headers_parsed[h] + chip['flash']['base'] = h['defines']['all']['FLASH_BASE'] + + if 'SRAM_BASE' in h['defines']['all']: + chip['ram']['base'] = h['defines']['all']['SRAM_BASE'] + elif 'SRAM1_BASE' in h['defines']['all']: + chip['ram']['base'] = h['defines']['all']['SRAM1_BASE'] + elif 'D1_AXISRAM_BASE' in h['defines']['all']: + chip['ram']['base'] = h['defines']['all']['D1_AXISRAM_BASE'] + # print("Got", len(chip['cores']), "cores") for core in chip['cores']: core_name = core['name'] From 2e7af6b8422f998f217566f156e1fe22c4f28a10 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Thu, 29 Jul 2021 15:44:44 -0400 Subject: [PATCH 2/8] Parse our memory location bases and name them well-ish. --- parse.py | 172 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 126 insertions(+), 46 deletions(-) diff --git a/parse.py b/parse.py index 595bad9..31b9e2a 100755 --- a/parse.py +++ b/parse.py @@ -3,6 +3,7 @@ import sys import xmltodict import yaml + try: from yaml import CSafeLoader as SafeLoader except ImportError: @@ -14,6 +15,24 @@ import os from collections import OrderedDict from glob import glob +class DecimalInt: + def __init__(self, val): + self.val = val + +def represent_decimal_int(dumper, data): + return dumper.represent_int(data.val) + +yaml.add_representer(DecimalInt, represent_decimal_int) + +class HexInt: + def __init__(self, val): + self.val = val + +def represent_hex_int(dumper, data): + return dumper.represent_int(hex(data.val)) + +yaml.add_representer(HexInt, represent_hex_int) + def removeprefix(value: str, prefix: str, /) -> str: if value.startswith(prefix): @@ -52,6 +71,7 @@ def represent_ordereddict(dumper, data): yaml.add_representer(OrderedDict, represent_ordereddict) + def hexint_presenter(dumper, data): if data > 0x10000: return dumper.represent_int(hex(data)) @@ -112,6 +132,7 @@ def paren_ok(val): return False return n == 0 + # warning: horrible abomination ahead @@ -167,21 +188,21 @@ def parse_header(f): cur_core = "cm" + str(m.group(1)) if m.group(2) != None: cur_core += "p" - #print("Cur core is ", cur_core, "matched", l) + # print("Cur core is ", cur_core, "matched", l) found = False for core in cores: if core == cur_core: found = True if not found: cores.append(cur_core) - #print("Switching to core", cur_core, "for", f) + # print("Switching to core", cur_core, "for", f) elif m := re.match('.*else.*', l): cur_core = "all" if m := re.match('.*else.*CORE_CM(\\d+)(PLUS)?.*', l): cur_core = "cm" + str(m.group(1)) if m.group(2) != None: cur_core += "p" - #print("Cur core is ", cur_core, "matched", l) + # print("Cur core is ", cur_core, "matched", l) elif len(cores) > 1: # Pick the second core assuming we've already parsed one cur_core = cores[1] @@ -192,19 +213,19 @@ def parse_header(f): found = True if not found: cores.append(cur_core) - #print("Switching to core", cur_core, "for", f) + # print("Switching to core", cur_core, "for", f) elif m := re.match('.*endif.*', l): - #print("Switching to common core for", f) + # print("Switching to common core for", f) cur_core = "all" if cur_core not in irqs: - #print("Registering new core", cur_core) + # print("Registering new core", cur_core) irqs[cur_core] = {} if cur_core not in defines: defines[cur_core] = {} if m := re.match('([a-zA-Z0-9_]+)_IRQn += (\\d+),? +/\\*!< (.*) \\*/', l): - #print("Found irq for", cur_core) + # print("Found irq for", cur_core) irqs[cur_core][m.group(1)] = int(m.group(2)) if m := re.match('#define +([0-9A-Za-z_]+)\\(', l): @@ -217,11 +238,11 @@ def parse_header(f): continue val = val.split('/*')[0].strip() val = parse_value(val, defines[cur_core]) - #print("Found define for", cur_core) + # print("Found define for", cur_core) defines[cur_core][name] = val - #print("Found", len(cores), "cores for", f) - #print("Found", len(irqs['all']), "shared interrupts for", f) + # print("Found", len(cores), "cores for", f) + # print("Found", len(irqs['all']), "shared interrupts for", f) if len(cores) == 0: cores.append("all") @@ -369,7 +390,7 @@ perimap = [ def match_peri(peri): for r, block in perimap: - if re.match('^'+r+'$', peri): + if re.match('^' + r + '$', peri): if block == '': return None return block @@ -462,11 +483,28 @@ def chip_name_from_package_name(x): ] for a, b in name_map: - r, n = re.subn('^'+a+'$', b, x) + r, n = re.subn('^' + a + '$', b, x) if n != 0: return r raise Exception("bad name: {}".format(x)) +memories_map = { + 'flash': [ + 'FLASH', 'FLASH_BANK1', 'FLASH_BANK2', + 'D1_AXIFLASH', 'D1_AXIICP', + ], + 'ram': [ + 'SRAM', 'SRAM1', 'SRAM2', + 'D1_AXISRAM', + 'D1_ITCMRAM', + 'D1_DTCMRAM', + 'D1_AHBSRAM', + 'D2_AXISRAM', + 'D3_BKPSRAM', + 'D3_SRAM' + ], +} + def parse_chips(): os.makedirs('data/chips', exist_ok=True) @@ -488,19 +526,19 @@ def parse_chips(): package_flashs = r['Flash'] die = r['Die'] if type(package_rams) != list: - package_rams = [package_rams]*len(package_names) + package_rams = [package_rams] * len(package_names) if type(package_flashs) != list: - package_flashs = [package_flashs]*len(package_names) + package_flashs = [package_flashs] * len(package_names) for package_i, package_name in enumerate(package_names): chip_name = chip_name_from_package_name(package_name) - flash = OrderedDict( { - 'size': int(package_flashs[package_i]), - 'base': None, - } ) - ram = OrderedDict( { - 'size': int(package_rams[package_i]), - 'base': None, - } ) + flash = OrderedDict({ + 'bytes': DecimalInt(int(package_flashs[package_i]) * 1024), + 'regions': [] + }) + ram = OrderedDict({ + 'bytes': DecimalInt(int(package_rams[package_i]) * 1024), + 'regions': [], + }) gpio_af = next(filter(lambda x: x['@Name'] == 'GPIO', r['IP']))['@Version'] gpio_af = removesuffix(gpio_af, '_gpio_v1_0') @@ -586,7 +624,7 @@ def parse_chips(): for ip in r['IP']: pname = ip['@InstanceName'] - pkind = ip['@Name']+':'+ip['@Version'] + pkind = ip['@Name'] + ':' + ip['@Version'] pkind = removesuffix(pkind, '_Cube') if pname == 'SYS': @@ -595,7 +633,7 @@ def parse_chips(): continue if pname.startswith('ADC'): if not 'ADC_COMMON' in peris: - peris['ADC_COMMON'] = 'ADC_COMMON:'+removesuffix(ip['@Version'], '_Cube') + peris['ADC_COMMON'] = 'ADC_COMMON:' + removesuffix(ip['@Version'], '_Cube') peris[pname] = pkind pins[pname] = [] @@ -653,14 +691,57 @@ def parse_chips(): raise Exception("missing header for {}".format(chip_name)) h = headers_parsed[h] - chip['flash']['base'] = h['defines']['all']['FLASH_BASE'] + found = [] + + for each in memories_map['flash']: + if each + '_BASE' in h['defines']['all']: + if each == 'FLASH': + key = 'BANK_1' + elif each == 'FLASH_BANK1': + key = 'BANK_1' + elif each == 'FLASH_BANK2': + key = 'BANK_2' + else: + key = each + + if key in found: + continue + + found.append(key) + + chip['flash']['regions'].append( + OrderedDict({ + key: { + 'base': HexInt(h['defines']['all'][each + '_BASE']), + } + }) + ) + + found = [] + + for each in memories_map['ram']: + if each + '_BASE' in h['defines']['all']: + if each == 'D1_AXISRAM': + key = 'SRAM' + elif each == 'SRAM1': + key = 'SRAM' + else: + key = each + + if key in found: + continue + + found.append(key) + + chip['ram']['regions'].append( + OrderedDict({ + key: { + 'base': HexInt(h['defines']['all'][each + '_BASE']) + } + }) + ) + - if 'SRAM_BASE' in h['defines']['all']: - chip['ram']['base'] = h['defines']['all']['SRAM_BASE'] - elif 'SRAM1_BASE' in h['defines']['all']: - chip['ram']['base'] = h['defines']['all']['SRAM1_BASE'] - elif 'D1_AXISRAM_BASE' in h['defines']['all']: - chip['ram']['base'] = h['defines']['all']['D1_AXISRAM_BASE'] # print("Got", len(chip['cores']), "cores") for core in chip['cores']: @@ -672,7 +753,7 @@ def parse_chips(): if not core_name in h['interrupts'] or not core_name in h['defines']: core_name = 'all' - #print("Defining for core", core_name) + # print("Defining for core", core_name) # Gather all interrupts and defines for this core @@ -702,7 +783,7 @@ def parse_chips(): if pname in clocks[rcc]: p['clock'] = clocks[rcc][pname] - if block := match_peri(chip_name+':'+pname+':'+pkind): + if block := match_peri(chip_name + ':' + pname + ':' + pkind): p['block'] = block if pname in chip['pins']: @@ -725,7 +806,7 @@ def parse_chips(): # Handle GPIO specially. for p in range(20): - port = 'GPIO' + chr(ord('A')+p) + port = 'GPIO' + chr(ord('A') + p) if addr := defines.get(port + '_BASE'): block = 'gpio_v2/GPIO' if chip['family'] == 'STM32F1': @@ -743,7 +824,7 @@ def parse_chips(): p = OrderedDict({ 'address': addr, }) - if block := match_peri(chip_name+':'+dma+':DMA'): + if block := match_peri(chip_name + ':' + dma + ':DMA'): p['block'] = block if chip_nvic in chip_interrupts: @@ -755,13 +836,13 @@ def parse_chips(): # DMAMUX is not in the cubedb XMLs for dma in ('DMAMUX', 'DMAMUX1', "DMAMUX2"): - if addr := defines.get(dma+'_BASE'): + if addr := defines.get(dma + '_BASE'): kind = 'DMAMUX:v1' dbg_peri = OrderedDict({ 'address': addr, 'kind': kind, }) - if block := match_peri(chip_name+':'+dma+':'+kind): + if block := match_peri(chip_name + ':' + dma + ':' + kind): dbg_peri['block'] = block peris[dma] = dbg_peri @@ -852,7 +933,6 @@ def parse_chips(): # Process peripheral - DMA channel associations for pname, p in peris.items(): if (peri_chs := dma_channels[chip_dma]['peripherals'].get(pname)) is not None: - p['dma_channels'] = { req: [ ch @@ -866,7 +946,7 @@ def parse_chips(): del chip['pins'] del chip['peripherals'] - with open('data/chips/'+chip_name+'.yaml', 'w') as f: + with open('data/chips/' + chip_name + '.yaml', 'w') as f: f.write(yaml.dump(chip, width=500)) @@ -874,7 +954,7 @@ af = {} def parse_gpio_af(): - #os.makedirs('data/gpio_af', exist_ok=True) + # os.makedirs('data/gpio_af', exist_ok=True) for f in glob('sources/cubedb/mcu/IP/GPIO-*_gpio_v1_0_Modes.xml'): if 'STM32F1' in f: continue @@ -912,7 +992,7 @@ def parse_gpio_af(): pins[pin_name] = afs # with open('data/gpio_af/'+ff+'.yaml', 'w') as f: - # f.write(yaml.dump(pins)) + # f.write(yaml.dump(pins)) af[ff] = pins @@ -932,7 +1012,7 @@ def parse_dma(): ff = removeprefix(ff, 'BDMA-') ff = removesuffix(ff, '_Modes.xml') - r = xmltodict.parse(open(f, 'rb'), force_list={'Mode', 'RefMode'}) + r = xmltodict.parse(open(f, 'rb'), force_list={'Mode', 'RefMode'}) chip_dma = { 'channels': {}, @@ -956,7 +1036,7 @@ def parse_dma(): with open(mf, 'r') as yaml_file: y = yaml.load(yaml_file, Loader=SafeLoader) mf = removesuffix(mf, '.yaml') - dmamux = mf[mf.index('_')+1:] # DMAMUX1 or DMAMUX2 + dmamux = mf[mf.index('_') + 1:] # DMAMUX1 or DMAMUX2 for (request_name, request_num) in y.items(): parts = request_name.split('_') @@ -990,8 +1070,8 @@ def parse_dma(): if low == 1: low -= 1 high -= 1 - for i in range(low, high+1): - chip_dma['channels'][n+'_CH'+str(i)] = OrderedDict({ + for i in range(low, high + 1): + chip_dma['channels'][n + '_CH' + str(i)] = OrderedDict({ 'dma': n, 'channel': i, 'dmamux': dmamux, @@ -1114,7 +1194,7 @@ def match_peri_clock(rcc_block, peri_name): family_clocks = peripheral_to_clock[rcc_block] if peri_name in family_clocks: return family_clocks[peri_name] - #print("found no clock for ", peri_name) + # print("found no clock for ", peri_name) if peri_name.endswith("1"): return match_peri_clock(rcc_block, removesuffix(peri_name, "1")) return None From 99cd26c33f33017c0f8b541c39e229b7acff5b3f Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Fri, 30 Jul 2021 13:53:38 -0400 Subject: [PATCH 3/8] Parse memory layouts for actual region sizes. --- data/memories.yaml | 702 +++++++++++++++++++++++++++++++++++++++++++ parse.py | 73 +++-- parse_memory.py | 0 util/parse_memory.py | 119 ++++++++ 4 files changed, 876 insertions(+), 18 deletions(-) create mode 100644 data/memories.yaml create mode 100644 parse_memory.py create mode 100644 util/parse_memory.py diff --git a/data/memories.yaml b/data/memories.yaml new file mode 100644 index 0000000..88ee797 --- /dev/null +++ b/data/memories.yaml @@ -0,0 +1,702 @@ +- device-id: 0x410 + names: + - STM32F101 + - STM32F102 + - STM32F103 + ram: + address: 0x20000000 + bytes: 0x5000 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x411 + names: + - STM32F2xx + ram: + address: 0x20000000 + bytes: 0x20000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x412 + names: + - STM32F101 + - STM32F102 + - STM32F103 + ram: + address: 0x20000000 + bytes: 0x2800 + flash: + address: 0x8000000 + bytes: 0x8000 +- device-id: 0x413 + names: + - STM32F405xx + - STM32F407xx + - STM32F415xx + - STM32F417xx + ram: + address: 0x20000000 + bytes: 0x20000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x414 + names: + - STM32F101 + - STM32F103 + ram: + address: 0x20000000 + bytes: 0x10000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x415 + names: + - STM32L4x1 + - STM32L475xx + - STM32L476xx + - STM32L486xx + ram: + address: 0x20000000 + bytes: 0x18000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x416 + names: + - STM32L100x8 + - STM32L100xB + - STM32L15xx6 + - STM32L15xx8 + - STM32L15xxB + ram: + address: 0x20000000 + bytes: 0x2800 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x417 + names: + - STM32L05x + - STM32L06x + - STM32L010 + ram: + address: 0x20000000 + bytes: 0x2000 + flash: + address: 0x8000000 + bytes: 0x10000 +- device-id: 0x418 + names: + - STM32F105 + - STM32F107 + ram: + address: 0x20000000 + bytes: 0x10000 + flash: + address: 0x8000000 + bytes: 0x40000 +- device-id: 0x419 + names: + - STM32F42xxx + - STM32F43xxx + ram: + address: 0x20000000 + bytes: 0x30000 + flash: + address: 0x8000000 + bytes: 0x200000 +- device-id: 0x420 + names: + - STM32F100 + - STMMedium + ram: + address: 0x20000000 + bytes: 0x2000 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x421 + names: + - STM32F446xx + ram: + address: 0x20000000 + bytes: 0x20000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x422 + names: + - STM32F302xB + - STM32F302xC + - STM32F303xB + - STM32F303xC + - STM32F358xx + ram: + address: 0x20000000 + bytes: 0xa000 + flash: + address: 0x8000000 + bytes: 0x40000 +- device-id: 0x423 + names: + - STM32F401xB + - STM32F401xC + ram: + address: 0x20000000 + bytes: 0x10000 + flash: + address: 0x8000000 + bytes: 0x40000 +- device-id: 0x425 + names: + - STM32L03x + - STM32L04x + - STM32L010 + ram: + address: 0x20000000 + bytes: 0x2000 + flash: + address: 0x8000000 + bytes: 0x8000 +- device-id: 0x427 + names: + - STM32L100xC + - STM32L15xxC + - STM32L162xC + ram: + address: 0x20000000 + bytes: 0x8000 + flash: + address: 0x8000000 + bytes: 0x40000 +- device-id: 0x428 + names: + - STM32F100 + ram: + address: 0x20000000 + bytes: 0x8000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x429 + names: + - STM32L100x6xxA + - STM32L100x8xxA + - STM32L100xBxxA + - STM32L15xx6xxA + - STM32L15xx8xxA + - STM32L15xxBxxA + ram: + address: 0x20000000 + bytes: 0x4000 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x430 + names: + - STM32F101 + - STM32F103 + ram: + address: 0x20000000 + bytes: 0x18000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x431 + names: + - STM32F411xC + - STM32F411xE + ram: + address: 0x20000000 + bytes: 0x10000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x432 + names: + - STM32F37xx + ram: + address: 0x20000000 + bytes: 0x8000 + flash: + address: 0x8000000 + bytes: 0x40000 +- device-id: 0x433 + names: + - STM32F401xD + - STM32F401xE + ram: + address: 0x20000000 + bytes: 0x10000 + flash: + address: 0x8000000 + bytes: 0x800000 +- device-id: 0x434 + names: + - STM32F469xx + - STM32F467xx + ram: + address: 0x20000000 + bytes: 0x50000 + flash: + address: 0x8000000 + bytes: 0x200000 +- device-id: 0x435 + names: + - STM32L43xxx + - STM32L44xxx + ram: + address: 0x20000000 + bytes: 0xc000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x436 + names: + - STM32L15xxD + - STM32L162xD + ram: + address: 0x20000000 + bytes: 0xc000 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x437 + names: + - STM32L15xxE + - STM32L162xE + ram: + address: 0x20000000 + bytes: 0x14000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x438 + names: + - STM32F303x4 + - STM32F303x6 + - STM32F303x8 + - STM32F328xx + - STM32F334xx + ram: + address: 0x20000000 + bytes: 0x3000 + flash: + address: 0x8000000 + bytes: 0x10000 +- device-id: 0x439 + names: + - STM32F301x4 + - STM32F301x6 + - STM32F301x8 + - STM32F302x4 + - STM32F302x6 + - STM32F302x8 + - STM32F318xx + ram: + address: 0x20000000 + bytes: 0x4000 + flash: + address: 0x8000000 + bytes: 0x10000 +- device-id: 0x440 + names: + - STM32F05x + - STMF030x8 + ram: + address: 0x20000000 + bytes: 0x1ff8 + flash: + address: 0x8000000 + bytes: 0x10000 +- device-id: 0x441 + names: + - STM32F412 + ram: + address: 0x20000000 + bytes: 0x40000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x442 + names: + - STM32F09x + - STMF030xC + ram: + address: 0x20000000 + bytes: 0x8000 + flash: + address: 0x8000000 + bytes: 0x40000 +- device-id: 0x443 + names: + - STM32C01x + ram: + address: 0x20000000 + bytes: 0x1800 + flash: + address: 0x8000000 + bytes: 0x8000 +- device-id: 0x444 + names: + - STM32F03x + ram: + address: 0x20000000 + bytes: 0x1000 + flash: + address: 0x8000000 + bytes: 0x8000 +- device-id: 0x445 + names: + - STM32F04x + - STMF070x6 + ram: + address: 0x20000000 + bytes: 0x1800 + flash: + address: 0x8000000 + bytes: 0x8000 +- device-id: 0x446 + names: + - STM32F302xE + - STM32F303xE + - STM32F398xx + ram: + address: 0x20000000 + bytes: 0x10000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x447 + names: + - STM32L07x + - STM32L08x + - STM32L010 + ram: + address: 0x20000000 + bytes: 0x5000 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x448 + names: + - STM32F07x + ram: + address: 0x20000000 + bytes: 0x4000 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x449 + names: + - STM32F74x + - STM32F75x + ram: + address: 0x20000000 + bytes: 0x50000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x450 + names: + - STM32H7xx + ram: + address: 0x24000000 + bytes: 0x80000 + flash: + address: 0x8000000 + bytes: 0x200000 +- device-id: 0x451 + names: + - STM32F76x + - STM32F77x + ram: + address: 0x20000000 + bytes: 0x80000 + flash: + address: 0x8000000 + bytes: 0x200000 +- device-id: 0x452 + names: + - STM32F72x + - STM32F73x + ram: + address: 0x20000000 + bytes: 0x40000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x453 + names: + - STM32C0 + ram: + address: 0x20000000 + bytes: 0x1800 + flash: + address: 0x8000000 + bytes: 0x8000 +- device-id: 0x456 + names: + - STM32G051 + - STM32G061 + ram: + address: 0x20000000 + bytes: 0x4000 + flash: + address: 0x8000000 + bytes: 0x10000 +- device-id: 0x457 + names: + - STM32L01x + - STM32L02x + ram: + address: 0x20000000 + bytes: 0x800 + flash: + address: 0x8000000 + bytes: 0x4000 +- device-id: 0x458 + names: + - STM32F410 + ram: + address: 0x20000000 + bytes: 0x8000 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x460 + names: + - STM32G07x + - STM32G08x + ram: + address: 0x20000000 + bytes: 0x8000 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x461 + names: + - STM32L496xx + - STM32L4A6xx + ram: + address: 0x20000000 + bytes: 0x40000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x462 + names: + - STM32L45x + - STM32L46x + ram: + address: 0x20000000 + bytes: 0x20000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x463 + names: + - STM32F413 + - STM32F423 + ram: + address: 0x20000000 + bytes: 0x50000 + flash: + address: 0x8000000 + bytes: 0x180000 +- device-id: 0x464 + names: + - STM32L41x + ram: + address: 0x20000000 + bytes: 0xa000 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x466 + names: + - STM32G03x + - STM32G04x + ram: + address: 0x20000000 + bytes: 0x2000 + flash: + address: 0x8000000 + bytes: 0x10000 +- device-id: 0x467 + names: + - STM32G0B1xx + - STM32G0C1xx + ram: + address: 0x20000000 + bytes: 0x20000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x468 + names: + - STM32G43x + - STM32G44x + ram: + address: 0x20000000 + bytes: 0x5000 + flash: + address: 0x8000000 + bytes: 0x20000 +- device-id: 0x469 + names: + - STM32G47x + - STM32G48x + ram: + address: 0x20000000 + bytes: 0x18000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x470 + names: + - STM32L4Rxxx + - STM32L4Sxxx + ram: + address: 0x20000000 + bytes: 0x30000 + flash: + address: 0x8000000 + bytes: 0x200000 +- device-id: 0x471 + names: + - STM32L4Pxxx + - STM32L4Qxxx + ram: + address: 0x20000000 + bytes: 0x30000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x472 + names: + - STM32L5xx + ram: + address: 0x20000000 + bytes: 0x40000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x479 + names: + - STM32G491xC + - STM32G491xE + ram: + address: 0x20000000 + bytes: 0x8000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x480 + names: + - STM32H7A + - STM32H7B + ram: + address: 0x24000000 + bytes: 0x100000 + flash: + address: 0x8000000 + bytes: 0x200000 +- device-id: 0x481 + names: + - STM32U5xx + ram: + address: 0x20000000 + bytes: 0x8000 + flash: + address: 0x8000000 + bytes: 0x400000 +- device-id: 0x482 + names: + - STM32U575 + - STM32U585 + ram: + address: 0x20000000 + bytes: 0xc0000 + flash: + address: 0x8000000 + bytes: 0x200000 +- device-id: 0x483 + names: + - STM32H72x + - STM32H73x + ram: + address: 0x24000000 + bytes: 0x20000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x484 + names: + - STM32H5xx + ram: + address: 0x20000000 + bytes: 0x40000 + flash: + address: 0x8000000 + bytes: 0x200000 +- device-id: 0x492 + names: + - STM32WBA55 + - STM32WBA54 + ram: + address: 0x20000000 + bytes: 0x10000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x494 + names: + - STM32WB1xxx + ram: + address: 0x20000000 + bytes: 0x3000 + flash: + address: 0x8000000 + bytes: 0x50000 +- device-id: 0x495 + names: + - STM32WB5x + ram: + address: 0x20000000 + bytes: 0x30000 + flash: + address: 0x8000000 + bytes: 0x100000 +- device-id: 0x496 + names: + - STM32WB35xx + ram: + address: 0x20000000 + bytes: 0x8000 + flash: + address: 0x8000000 + bytes: 0x80000 +- device-id: 0x497 + names: + - STM32WLxx + ram: + address: 0x20000000 + bytes: 0x3000 + flash: + address: 0x8000000 + bytes: 0x40000 +- device-id: 0x500 + names: + - STM32MP1 + ram: + address: 0x10000000 + bytes: 0x20000 +- device-id: 0x501 + names: + - STM32MP13xx + ram: + address: 0x10000000 + bytes: 0x20000 diff --git a/parse.py b/parse.py index 31b9e2a..8ccf9f8 100755 --- a/parse.py +++ b/parse.py @@ -15,22 +15,28 @@ import os from collections import OrderedDict from glob import glob + class DecimalInt: def __init__(self, val): self.val = val + def represent_decimal_int(dumper, data): return dumper.represent_int(data.val) + yaml.add_representer(DecimalInt, represent_decimal_int) + class HexInt: def __init__(self, val): self.val = val + def represent_hex_int(dumper, data): return dumper.represent_int(hex(data.val)) + yaml.add_representer(HexInt, represent_hex_int) @@ -71,7 +77,6 @@ def represent_ordereddict(dumper, data): yaml.add_representer(OrderedDict, represent_ordereddict) - def hexint_presenter(dumper, data): if data > 0x10000: return dumper.represent_int(hex(data)) @@ -488,6 +493,7 @@ def chip_name_from_package_name(x): return r raise Exception("bad name: {}".format(x)) + memories_map = { 'flash': [ 'FLASH', 'FLASH_BANK1', 'FLASH_BANK2', @@ -533,11 +539,11 @@ def parse_chips(): chip_name = chip_name_from_package_name(package_name) flash = OrderedDict({ 'bytes': DecimalInt(int(package_flashs[package_i]) * 1024), - 'regions': [] + 'regions': {}, }) ram = OrderedDict({ 'bytes': DecimalInt(int(package_rams[package_i]) * 1024), - 'regions': [], + 'regions': {}, }) gpio_af = next(filter(lambda x: x['@Name'] == 'GPIO', r['IP']))['@Version'] gpio_af = removesuffix(gpio_af, '_gpio_v1_0') @@ -709,13 +715,14 @@ def parse_chips(): found.append(key) - chip['flash']['regions'].append( - OrderedDict({ - key: { - 'base': HexInt(h['defines']['all'][each + '_BASE']), - } - }) - ) + chip['flash']['regions'][key] = OrderedDict( { + 'base': HexInt(h['defines']['all'][each + '_BASE']) + } ) + + if key == 'BANK_1' or key == 'BANK_2': + flash_size = determine_flash_size(chip_name) + if flash_size is not None: + chip['flash']['regions'][key]['bytes'] = DecimalInt(flash_size) found = [] @@ -733,15 +740,14 @@ def parse_chips(): found.append(key) - chip['ram']['regions'].append( - OrderedDict({ - key: { - 'base': HexInt(h['defines']['all'][each + '_BASE']) - } - }) - ) - + chip['ram']['regions'][key] = OrderedDict( { + 'base': HexInt(h['defines']['all'][each + '_BASE']) + } ) + if key == 'SRAM': + ram_size = determine_ram_size(chip_name) + if ram_size is not None: + chip['ram']['regions'][key]['bytes'] = DecimalInt(ram_size) # print("Got", len(chip['cores']), "cores") for core in chip['cores']: @@ -1310,7 +1316,38 @@ def filter_interrupts(peri_irqs, all_irqs): return filtered +memories = [] +def parse_memories(): + with open('data/memories.yaml', 'r') as yaml_file: + m = yaml.load(yaml_file, Loader=SafeLoader) + for each in m: + memories.append(each) + + +def determine_ram_size(chip_name): + for each in memories: + for name in each['names']: + if is_chip_name_match(name, chip_name): + return each['ram']['bytes'] + + return None + +def determine_flash_size(chip_name): + for each in memories: + for name in each['names']: + if is_chip_name_match(name, chip_name): + return each['flash']['bytes'] + + return None + +def is_chip_name_match(pattern, chip_name): + pattern = pattern.replace('x', '.') + return re.match(pattern + ".*", chip_name) + + + +parse_memories() parse_interrupts() parse_rcc_regs() parse_documentations() diff --git a/parse_memory.py b/parse_memory.py new file mode 100644 index 0000000..e69de29 diff --git a/util/parse_memory.py b/util/parse_memory.py new file mode 100644 index 0000000..2331c63 --- /dev/null +++ b/util/parse_memory.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 + +import sys +import xmltodict +import yaml +from collections import OrderedDict +from glob import glob + +try: + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeLoader + + +def represent_ordereddict(dumper, data): + value = [] + + for item_key, item_value in data.items(): + node_key = dumper.represent_data(item_key) + node_value = dumper.represent_data(item_value) + + value.append((node_key, node_value)) + + return yaml.nodes.MappingNode(u'tag:yaml.org,2002:map', value) + +yaml.add_representer(OrderedDict, represent_ordereddict) + +def represent_int(dumper, data): + return dumper.represent_int(hex(data)) + +yaml.add_representer(int, represent_int) + +def splat_names(base, parts): + names = [] + for part in parts: + if part.startswith("STM32"): + names.append( base ) + else: + names.append( base[0: len(base) - len(part)] + part) + + return names + + +def split_names(str): + cleaned = [] + names = str.split("/") + current_base = None + for name in names: + name = name.split(' ')[0].strip() + if '-' in name: + parts = name.split('-') + current_base = parts[0] + splatted = splat_names(current_base, parts ) + current_base = splatted[0] + cleaned = cleaned + splatted + elif name.startswith("STM32"): + current_base = name + cleaned.append(name) + else: + cleaned.append( current_base[0: len(current_base) - len(name)] + name) + return cleaned + +memories = [] + +def parse_files(dir): + for f in sorted(glob(dir + '/*.xml')): + #print("parsing ", f); + device = xmltodict.parse(open(f, 'rb'))['Root']['Device'] + device_id = device['DeviceID'] + name = device['Name'] + names = split_names(name) + flash_size = None + flash_addr = None + ram_size = None + ram_addr = None + + for peripheral in device['Peripherals']['Peripheral']: + if peripheral['Name'] == 'Embedded SRAM' and ram_size is None: + configs = peripheral['Configuration'] + if type(configs) != list: + configs = [ configs ] + ram_addr = int(configs[0]['Parameters']['@address'], 16) + ram_size = int(configs[0]['Parameters']['@size'], 16) + #print( f'ram {addr} {size}') + if peripheral['Name'] == 'Embedded Flash' and flash_size is None: + configs = peripheral['Configuration'] + if type(configs) != list: + configs = [ configs ] + flash_addr = int(configs[0]['Parameters']['@address'], 16) + flash_size = int(configs[0]['Parameters']['@size'], 16) + #print( f'flash {addr} {size}') + + chunk = OrderedDict( { + 'device-id': int(device_id, 16), + 'names': names, + }) + + if ram_size is not None: + chunk['ram'] = OrderedDict( { + 'address': ram_addr, + 'bytes': ram_size, + }) + + if flash_size is not None: + chunk['flash'] = OrderedDict( { + 'address': flash_addr, + 'bytes': flash_size, + }) + + memories.append( chunk ) + +dir = sys.argv[1] + +parse_files(dir) + +with open('data/memories.yaml', 'w') as f: + f.write(yaml.dump(memories, width=500)) + +#print(yaml.dump(memories, width=500)) \ No newline at end of file From 72478d1bc5968e0e0c292c046e3a36da6003d391 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Fri, 30 Jul 2021 13:53:53 -0400 Subject: [PATCH 4/8] Reparse to include memory sizes. --- parse_memory.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 parse_memory.py diff --git a/parse_memory.py b/parse_memory.py deleted file mode 100644 index e69de29..0000000 From 83f5b39ecb358b94e5b93db1fd003e793853bfe8 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Fri, 30 Jul 2021 13:58:54 -0400 Subject: [PATCH 5/8] Parse memory names slightly better from the XML. --- data/memories.yaml | 6 +++--- util/parse_memory.py | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/data/memories.yaml b/data/memories.yaml index 88ee797..5d51f8b 100644 --- a/data/memories.yaml +++ b/data/memories.yaml @@ -304,7 +304,7 @@ - device-id: 0x440 names: - STM32F05x - - STMF030x8 + - STM32F030x8 ram: address: 0x20000000 bytes: 0x1ff8 @@ -323,7 +323,7 @@ - device-id: 0x442 names: - STM32F09x - - STMF030xC + - STM32F030xC ram: address: 0x20000000 bytes: 0x8000 @@ -351,7 +351,7 @@ - device-id: 0x445 names: - STM32F04x - - STMF070x6 + - STM32F070x6 ram: address: 0x20000000 bytes: 0x1800 diff --git a/util/parse_memory.py b/util/parse_memory.py index 2331c63..661e961 100644 --- a/util/parse_memory.py +++ b/util/parse_memory.py @@ -35,6 +35,8 @@ def splat_names(base, parts): for part in parts: if part.startswith("STM32"): names.append( base ) + elif part.startswith( base[5]): + names.append('STM32' + part) else: names.append( base[0: len(base) - len(part)] + part) @@ -56,6 +58,8 @@ def split_names(str): elif name.startswith("STM32"): current_base = name cleaned.append(name) + elif name.startswith( current_base[5]): + names.append('STM32' + name) else: cleaned.append( current_base[0: len(current_base) - len(name)] + name) return cleaned From 93490bc42f243ed7140a112582fbd91a5d080d9d Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Mon, 2 Aug 2021 09:48:30 -0400 Subject: [PATCH 6/8] Ensure that any bank is not larger than the total from the SVD. --- parse.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/parse.py b/parse.py index 8ccf9f8..37435b3 100755 --- a/parse.py +++ b/parse.py @@ -692,6 +692,10 @@ def parse_chips(): chip_nvic = chip['nvic'] del chip['nvic'] + device_id = determine_device_id(chip_name) + if device_id is not None: + chip['device-id'] = device_id + h = find_header(chip_name) if h is None: raise Exception("missing header for {}".format(chip_name)) @@ -722,6 +726,8 @@ def parse_chips(): if key == 'BANK_1' or key == 'BANK_2': flash_size = determine_flash_size(chip_name) if flash_size is not None: + if flash_size > chip['flash']['bytes'].val: + flash_size = chip['flash']['bytes'].val chip['flash']['regions'][key]['bytes'] = DecimalInt(flash_size) found = [] @@ -1341,6 +1347,13 @@ def determine_flash_size(chip_name): return None +def determine_device_id(chip_name): + for each in memories: + for name in each['names']: + if is_chip_name_match(name, chip_name): + return each['device-id'] + return None + def is_chip_name_match(pattern, chip_name): pattern = pattern.replace('x', '.') return re.match(pattern + ".*", chip_name) From 4a67203c866fd105fb686face7b4f0bc7098cb1f Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Mon, 2 Aug 2021 09:58:31 -0400 Subject: [PATCH 7/8] Keep device-id as hex. --- parse.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/parse.py b/parse.py index 37435b3..91ef4a1 100755 --- a/parse.py +++ b/parse.py @@ -591,6 +591,7 @@ def parse_chips(): 'family': family, 'line': r['@Line'], 'die': die, + 'device-id': None, 'packages': [], 'datasheet': None, 'reference-manual': None, @@ -694,7 +695,9 @@ def parse_chips(): device_id = determine_device_id(chip_name) if device_id is not None: - chip['device-id'] = device_id + chip['device-id'] = HexInt(device_id) + else: + del chip['device-id'] h = find_header(chip_name) if h is None: From cd939ee5538392059d68647e6d423c417b2b0b9f Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Mon, 2 Aug 2021 11:05:50 -0400 Subject: [PATCH 8/8] Download cubeprogdb and point the parser to that. --- d | 5 +++++ util/parse_memory.py | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/d b/d index e2ac187..9884a6c 100755 --- a/d +++ b/d @@ -18,6 +18,7 @@ case "$CMD" in ./d download-svd ./d download-headers ./d download-cubedb + ./d download-cubeprogdb ;; download-mcufinder) mkdir -p sources/mcufinder @@ -53,6 +54,10 @@ case "$CMD" in rm -rf sources/cubedb git clone --depth 1 https://github.com/embassy-rs/stm32cube-database.git sources/cubedb ;; + download-cubeprogdb) + rm -rf sources/cubeprogdb + git clone --depth 1 https://github.com/embassy-rs/stm32cubeprog-database.git sources/cubeprogdb + ;; install-chiptool) cargo install --git https://github.com/embassy-rs/chiptool ;; diff --git a/util/parse_memory.py b/util/parse_memory.py index 661e961..3146414 100644 --- a/util/parse_memory.py +++ b/util/parse_memory.py @@ -113,11 +113,11 @@ def parse_files(dir): memories.append( chunk ) -dir = sys.argv[1] +dir = "sources/cubeprogdb/db" parse_files(dir) with open('data/memories.yaml', 'w') as f: f.write(yaml.dump(memories, width=500)) -#print(yaml.dump(memories, width=500)) \ No newline at end of file +#print(yaml.dump(memories, width=500))