From 38c403f205ffd8e981e0b82cdd80f52ba67c2cd9 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Fri, 23 Jul 2021 14:48:45 -0400 Subject: [PATCH 1/3] Fixes #9 Adds per-peripheral interrupts. Simple list, functionality not otherwise described. --- parse.py | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/parse.py b/parse.py index 796dea1..33799af 100755 --- a/parse.py +++ b/parse.py @@ -480,6 +480,7 @@ def parse_chips(): package_names = expand_name(r['@RefName']) package_rams = r['Ram'] package_flashs = r['Flash'] + die = r['Die'] if type(package_rams) != list: package_rams = [package_rams]*len(package_names) if type(package_flashs) != list: @@ -493,13 +494,17 @@ def parse_chips(): dma = next(filter(lambda x: x['@Name'] == 'DMA', r['IP']), None) bdma = next(filter(lambda x: x['@Name'] == 'BDMA', r['IP']), None) + nvic = next(filter(lambda x: x['@Name'] == 'NVIC', r['IP']), None) + + if nvic is None: + nvic = next(filter(lambda x: x['@Name'] == 'NVIC1', r['IP']), None) + + nvic = nvic['@Version'] if dma is not None: dma = dma['@Version'] if bdma is not None: bdma = bdma['@Version'] - #dma = next(filter(lambda x: x['@Name'] == 'DMA', r['IP']), None)['@Version'] - #bdma = next(filter(lambda x: x['@Name'] == 'BDMA', r['IP']), None)['@Version'] rcc = next(filter(lambda x: x['@Name'] == 'RCC', r['IP']))['@Version'] @@ -529,6 +534,7 @@ def parse_chips(): 'name': chip_name, 'family': family, 'line': r['@Line'], + 'die': die, 'packages': [], 'datasheet': None, 'reference-manual': None, @@ -541,6 +547,7 @@ def parse_chips(): 'rcc': rcc, # temporarily stashing it here 'dma': dma, # temporarily stashing it here 'bdma': bdma, # temporarily stashing it here + 'nvic': nvic # temporarily stashing it here }) chips[chip_name]['packages'].append(OrderedDict({ @@ -621,6 +628,9 @@ def parse_chips(): chip_bdma = chip['bdma'] del chip['bdma'] + chip_nvic = chip['nvic'] + del chip['nvic'] + h = find_header(chip_name) if h is None: raise Exception("missing header for {}".format(chip_name)) @@ -668,6 +678,11 @@ def parse_chips(): if len(chip['pins'][pname]) > 0: p['pins'] = chip['pins'][pname] + if chip_nvic in chip_interrupts: + if pname in chip_interrupts[chip_nvic]: + # filter by available, because some are conditioned on + p['interrupts'] = [ v for v in chip_interrupts[chip_nvic][pname] if v in interrupts ] + peris[pname] = p family_extra = "data/extra/family/" + chip['family'] + ".yaml" @@ -1050,6 +1065,32 @@ def match_peri_clock(rcc_block, peri_name): return match_peri_clock(rcc_block, removesuffix(peri_name, "1")) return None +chip_interrupts = {} + +def parse_interrupts(): + print("parsing interrupts") + for f in glob('sources/cubedb/mcu/IP/NVIC-*_Modes.xml'): + ff = removeprefix(f, 'sources/cubedb/mcu/IP/NVIC-') + ff = removesuffix(ff, '_Modes.xml') + chip_irqs = {} + r = xmltodict.parse(open(f, 'rb')) + print(f) + irqs = next(filter(lambda x: x['@Name'] == 'IRQn', r['IP']['RefParameter'])) + for irq in irqs['PossibleValue']: + value = irq['@Value'] + parts = value.split(':') + irq_name = removesuffix(parts[0], "_IRQn") + peri_names = parts[2].split(',') + if len(peri_names) == 1 and peri_names[0] == '': + continue + print(f'{peri_names} -> {irq_name}') + for p in peri_names: + if p not in chip_irqs: + chip_irqs[p] = [] + chip_irqs[p].append( irq_name ) + chip_interrupts[ff] = chip_irqs + +parse_interrupts() parse_rcc_regs() parse_documentations() parse_dma() From 2618ec3a942c835bcf5b443f0b73ecc5bdc455a9 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Mon, 26 Jul 2021 13:33:36 -0400 Subject: [PATCH 2/3] Be fancier on parsing peripheral IRQs. --- parse.py | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/parse.py b/parse.py index 33799af..40711c3 100755 --- a/parse.py +++ b/parse.py @@ -681,7 +681,8 @@ def parse_chips(): if chip_nvic in chip_interrupts: if pname in chip_interrupts[chip_nvic]: # filter by available, because some are conditioned on - p['interrupts'] = [ v for v in chip_interrupts[chip_nvic][pname] if v in interrupts ] + #p['interrupts'] = [ v for v in chip_interrupts[chip_nvic][pname] if v in interrupts ] + p['interrupts'] = filter_interrupts( chip_interrupts[chip_nvic][pname], interrupts) peris[pname] = p @@ -1074,22 +1075,88 @@ def parse_interrupts(): ff = removesuffix(ff, '_Modes.xml') chip_irqs = {} r = xmltodict.parse(open(f, 'rb')) - print(f) irqs = next(filter(lambda x: x['@Name'] == 'IRQn', r['IP']['RefParameter'])) for irq in irqs['PossibleValue']: value = irq['@Value'] parts = value.split(':') irq_name = removesuffix(parts[0], "_IRQn") peri_names = parts[2].split(',') + split = split_interrupts(peri_names, irq_name) if len(peri_names) == 1 and peri_names[0] == '': continue - print(f'{peri_names} -> {irq_name}') for p in peri_names: if p not in chip_irqs: - chip_irqs[p] = [] - chip_irqs[p].append( irq_name ) + chip_irqs[p] = {} + merge_peri_irq_signals(chip_irqs[p], split[p]) chip_interrupts[ff] = chip_irqs +def merge_peri_irq_signals(peri_irqs, additional): + for key, value in additional.items(): + if key not in peri_irqs: + peri_irqs[key] = [] + peri_irqs[key].append(value) + + +def split_interrupts(peri_names, irq_name): + split = {} + for p in peri_names: + split[p] = remap_interrupt_signals(p, irq_name) + + return split + +irq_signals_map = { + 'I2C': [ 'ER', 'EV'], + 'TIM': [ 'BRK', 'UP', 'TRG', 'COM'], + 'HRTIM': ['Master', 'TIMA', 'TIMB', 'TIMC', 'TIMD', 'TIME', 'TIMF' ] +} + +def remap_interrupt_signals(peri_name, irq_name): + if peri_name == irq_name: + return expand_all_irq_signals(peri_name, irq_name) + if peri_name in irq_name: + signals = {} + start = irq_name.index(peri_name) + regexp = re.compile('(_[^_]+)'); + if match := regexp.findall(irq_name, start): + for m in match: + signal = removeprefix(m, '_').strip() + if is_valid_irq_signal(peri_name, signal): + signals[signal] = irq_name + else: + signals = expand_all_irq_signals(peri_name, irq_name) + return signals + else: + return { 'GLOBAL': irq_name } + +def is_valid_irq_signal(peri_name, signal): + for prefix, signals in irq_signals_map.items(): + if peri_name.startswith(prefix): + return signal in signals + return False + +def expand_all_irq_signals(peri_name, irq_name): + expanded = {} + for prefix, signals in irq_signals_map.items(): + if peri_name.startswith(prefix): + for s in irq_signals_map[prefix]: + expanded[s] = irq_name + return expanded + + return {'GLOBAL': irq_name } + +def filter_interrupts(peri_irqs, all_irqs): + filtered = {} + + for signal, irqs in peri_irqs.items(): + for irq in all_irqs: + if irq in irqs: + filtered[signal] = irq + break + + return filtered + + + parse_interrupts() parse_rcc_regs() parse_documentations() From 3f583ec196dfe4de482d2ec0e3e02503762a9dca Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Mon, 26 Jul 2021 14:10:25 -0400 Subject: [PATCH 3/3] Scrape our (B)DMA interrupts per peripheral also. --- parse.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/parse.py b/parse.py index 40711c3..baa823c 100755 --- a/parse.py +++ b/parse.py @@ -681,7 +681,6 @@ def parse_chips(): if chip_nvic in chip_interrupts: if pname in chip_interrupts[chip_nvic]: # filter by available, because some are conditioned on - #p['interrupts'] = [ v for v in chip_interrupts[chip_nvic][pname] if v in interrupts ] p['interrupts'] = filter_interrupts( chip_interrupts[chip_nvic][pname], interrupts) peris[pname] = p @@ -716,6 +715,11 @@ def parse_chips(): if block := match_peri(chip_name+':'+dma+':DMA'): p['block'] = block + if chip_nvic in chip_interrupts: + if dma in chip_interrupts[chip_nvic]: + # filter by available, because some are conditioned on + p['interrupts'] = filter_interrupts( chip_interrupts[chip_nvic][dma], interrupts) + peris[dma] = p # DMAMUX is not in the cubedb XMLs @@ -1081,9 +1085,11 @@ def parse_interrupts(): parts = value.split(':') irq_name = removesuffix(parts[0], "_IRQn") peri_names = parts[2].split(',') - split = split_interrupts(peri_names, irq_name) if len(peri_names) == 1 and peri_names[0] == '': continue + elif len(peri_names) == 1 and ( peri_names[0] == 'DMA' or peri_names[0].startswith("DMAL")): + peri_names = [ parts[3] ] + split = split_interrupts(peri_names, irq_name) for p in peri_names: if p not in chip_irqs: chip_irqs[p] = {} @@ -1113,6 +1119,8 @@ irq_signals_map = { def remap_interrupt_signals(peri_name, irq_name): if peri_name == irq_name: return expand_all_irq_signals(peri_name, irq_name) + if (peri_name.startswith('DMA') or peri_name.startswith('BDMA')) and irq_name.startswith(peri_name): + return { irq_name: irq_name } if peri_name in irq_name: signals = {} start = irq_name.index(peri_name)