diff --git a/data/registers/flash_f4.yaml b/data/registers/flash_f4.yaml new file mode 100644 index 0000000..103ff07 --- /dev/null +++ b/data/registers/flash_f4.yaml @@ -0,0 +1,352 @@ +--- +block/FLASH: + description: FLASH + items: + - name: ACR + description: Flash access control register + byte_offset: 0 + fieldset: ACR + - name: KEYR + description: Flash key register + byte_offset: 4 + access: Write + fieldset: KEYR + - name: OPTKEYR + description: Flash option key register + byte_offset: 8 + access: Write + fieldset: OPTKEYR + - name: SR + description: Status register + byte_offset: 12 + fieldset: SR + - name: CR + description: Control register + byte_offset: 16 + fieldset: CR + - name: OPTCR + description: Flash option control register + byte_offset: 20 + fieldset: OPTCR +fieldset/ACR: + description: Flash access control register + fields: + - name: LATENCY + description: Latency + bit_offset: 0 + bit_size: 3 + enum: LATENCY + - name: PRFTEN + description: Prefetch enable + bit_offset: 8 + bit_size: 1 + enum: PRFTEN + - name: ICEN + description: Instruction cache enable + bit_offset: 9 + bit_size: 1 + enum: ICEN + - name: DCEN + description: Data cache enable + bit_offset: 10 + bit_size: 1 + enum: DCEN + - name: ICRST + description: Instruction cache reset + bit_offset: 11 + bit_size: 1 + enum: ICRST + - name: DCRST + description: Data cache reset + bit_offset: 12 + bit_size: 1 + enum: DCRST +fieldset/CR: + description: Control register + fields: + - name: PG + description: Programming + bit_offset: 0 + bit_size: 1 + enum: PG + - name: SER + description: Sector Erase + bit_offset: 1 + bit_size: 1 + enum: SER + - name: MER + description: Mass Erase + bit_offset: 2 + bit_size: 1 + enum: MER + - name: SNB + description: Sector number + bit_offset: 3 + bit_size: 4 + - name: PSIZE + description: Program size + bit_offset: 8 + bit_size: 2 + enum: PSIZE + - name: STRT + description: Start + bit_offset: 16 + bit_size: 1 + enum: STRT + - name: EOPIE + description: End of operation interrupt enable + bit_offset: 24 + bit_size: 1 + enum: EOPIE + - name: ERRIE + description: Error interrupt enable + bit_offset: 25 + bit_size: 1 + enum: ERRIE + - name: LOCK + description: Lock + bit_offset: 31 + bit_size: 1 + enum: LOCK +fieldset/KEYR: + description: Flash key register + fields: + - name: KEY + description: FPEC key + bit_offset: 0 + bit_size: 32 +fieldset/OPTCR: + description: Flash option control register + fields: + - name: OPTLOCK + description: Option lock + bit_offset: 0 + bit_size: 1 + - name: OPTSTRT + description: Option start + bit_offset: 1 + bit_size: 1 + - name: BOR_LEV + description: BOR reset Level + bit_offset: 2 + bit_size: 2 + - name: WDG_SW + description: WDG_SW User option bytes + bit_offset: 5 + bit_size: 1 + - name: nRST_STOP + description: nRST_STOP User option bytes + bit_offset: 6 + bit_size: 1 + - name: nRST_STDBY + description: nRST_STDBY User option bytes + bit_offset: 7 + bit_size: 1 + - name: RDP + description: Read protect + bit_offset: 8 + bit_size: 8 + - name: nWRP + description: Not write protect + bit_offset: 16 + bit_size: 12 +fieldset/OPTKEYR: + description: Flash option key register + fields: + - name: OPTKEY + description: Option byte key + bit_offset: 0 + bit_size: 32 +fieldset/SR: + description: Status register + fields: + - name: EOP + description: End of operation + bit_offset: 0 + bit_size: 1 + - name: OPERR + description: Operation error + bit_offset: 1 + bit_size: 1 + - name: WRPERR + description: Write protection error + bit_offset: 4 + bit_size: 1 + - name: PGAERR + description: Programming alignment error + bit_offset: 5 + bit_size: 1 + - name: PGPERR + description: Programming parallelism error + bit_offset: 6 + bit_size: 1 + - name: PGSERR + description: Programming sequence error + bit_offset: 7 + bit_size: 1 + - name: BSY + description: Busy + bit_offset: 16 + bit_size: 1 +enum/DCEN: + bit_size: 1 + variants: + - name: Disabled + description: Data cache is disabled + value: 0 + - name: Enabled + description: Data cache is enabled + value: 1 +enum/DCRST: + bit_size: 1 + variants: + - name: NotReset + description: Data cache is not reset + value: 0 + - name: Reset + description: Data cache is reset + value: 1 +enum/EOPIE: + bit_size: 1 + variants: + - name: Disabled + description: End of operation interrupt disabled + value: 0 + - name: Enabled + description: End of operation interrupt enabled + value: 1 +enum/ERRIE: + bit_size: 1 + variants: + - name: Disabled + description: Error interrupt generation disabled + value: 0 + - name: Enabled + description: Error interrupt generation enabled + value: 1 +enum/ICEN: + bit_size: 1 + variants: + - name: Disabled + description: Instruction cache is disabled + value: 0 + - name: Enabled + description: Instruction cache is enabled + value: 1 +enum/ICRST: + bit_size: 1 + variants: + - name: NotReset + description: Instruction cache is not reset + value: 0 + - name: Reset + description: Instruction cache is reset + value: 1 +enum/LATENCY: + bit_size: 3 + variants: + - name: WS0 + description: 0 wait states + value: 0 + - name: WS1 + description: 1 wait states + value: 1 + - name: WS2 + description: 2 wait states + value: 2 + - name: WS3 + description: 3 wait states + value: 3 + - name: WS4 + description: 4 wait states + value: 4 + - name: WS5 + description: 5 wait states + value: 5 + - name: WS6 + description: 6 wait states + value: 6 + - name: WS7 + description: 7 wait states + value: 7 + - name: WS8 + description: 8 wait states + value: 8 + - name: WS9 + description: 9 wait states + value: 9 + - name: WS10 + description: 10 wait states + value: 10 + - name: WS11 + description: 11 wait states + value: 11 + - name: WS12 + description: 12 wait states + value: 12 + - name: WS13 + description: 13 wait states + value: 13 + - name: WS14 + description: 14 wait states + value: 14 + - name: WS15 + description: 15 wait states + value: 15 +enum/LOCK: + bit_size: 1 + variants: + - name: Unlocked + description: FLASH_CR register is unlocked + value: 0 + - name: Locked + description: FLASH_CR register is locked + value: 1 +enum/MER: + bit_size: 1 + variants: + - name: MassErase + description: Erase activated for all user sectors + value: 1 +enum/PG: + bit_size: 1 + variants: + - name: Program + description: Flash programming activated + value: 1 +enum/PRFTEN: + bit_size: 1 + variants: + - name: Disabled + description: Prefetch is disabled + value: 0 + - name: Enabled + description: Prefetch is enabled + value: 1 +enum/PSIZE: + bit_size: 2 + variants: + - name: PSIZE8 + description: Program x8 + value: 0 + - name: PSIZE16 + description: Program x16 + value: 1 + - name: PSIZE32 + description: Program x32 + value: 2 + - name: PSIZE64 + description: Program x64 + value: 3 +enum/SER: + bit_size: 1 + variants: + - name: SectorErase + description: Erase activated for selected sector + value: 1 +enum/STRT: + bit_size: 1 + variants: + - name: Start + description: Trigger an erase operation + value: 1 diff --git a/parse.py b/parse.py index 54e78ae..b9a5afc 100755 --- a/parse.py +++ b/parse.py @@ -333,6 +333,7 @@ perimap = [ ('.*:STM32H7_pwr_v1_0', 'pwr_h7smps/PWR'), ('.*:STM32H7_flash_v1_0', 'flash_h7/FLASH'), ('.*:STM32F0_flash_v1_0', 'flash_f0/FLASH'), + ('.*:STM32F4_flash_v1_0', 'flash_f4/FLASH'), ('.*TIM\d.*:gptimer.*', 'timer_v1/TIM_GP16'), ('.*ETH:ethermac110_v3_0', 'eth_v2/ETH'), @@ -363,6 +364,7 @@ perimap = [ ('.*:DMA', 'bdma_v1/DMA'), ] + def match_peri(peri): for r, block in perimap: if re.match('^'+r+'$', peri): @@ -442,6 +444,7 @@ def parse_headers(): headers_parsed[ff] = res + def chip_name_from_package_name(x): name_map = [ ('(STM32L1....).x([AX])', '\\1-\\2'), @@ -548,7 +551,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 + 'nvic': nvic # temporarily stashing it here }) chips[chip_name]['packages'].append(OrderedDict({ @@ -650,17 +653,17 @@ def parse_chips(): defines = h['defines'][core_name] core['interrupts'] = interrupts - + peris = {} for pname, pkind in chip['peripherals'].items(): addr = defines.get(pname) if addr is None: if pname == 'ADC_COMMON': - addr = defines.get('ADC1_COMMON') + addr = defines.get('ADC1_COMMON') + if addr is None: + addr = defines.get('ADC12_COMMON') if addr is None: - addr = defines.get('ADC12_COMMON') - if addr is None: - addr = defines.get('ADC123_COMMON') + addr = defines.get('ADC123_COMMON') if addr is None: continue @@ -682,7 +685,7 @@ 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'] = filter_interrupts( chip_interrupts[chip_nvic][pname], interrupts) + p['interrupts'] = filter_interrupts(chip_interrupts[chip_nvic][pname], interrupts) peris[pname] = p @@ -719,7 +722,7 @@ def parse_chips(): 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) + p['interrupts'] = filter_interrupts(chip_interrupts[chip_nvic][dma], interrupts) peris[dma] = p @@ -735,7 +738,6 @@ def parse_chips(): dbg_peri['block'] = block peris[dma] = dbg_peri - # EXTI is not in the cubedb XMLs if addr := defines.get('EXTI_BASE'): if chip_name.startswith("STM32WB55"): @@ -792,7 +794,6 @@ def parse_chips(): if (peri_clock := match_peri_clock(rcc_block, name)) is not None: core['peripherals'][name]['clock'] = peri_clock - # Process DMA channels chs = {} if chip_dma in dma_channels: @@ -812,7 +813,7 @@ 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 @@ -822,7 +823,6 @@ def parse_chips(): for req, req_chs in peri_chs.items() } - # remove all pins from the root of the chip before emitting. del chip['pins'] del chip['peripherals'] @@ -880,11 +880,12 @@ def parse_gpio_af(): dma_channels = {} + def parse_dma(): for f in glob('sources/cubedb/mcu/IP/*DMA-*Modes.xml'): is_explicitly_bdma = False ff = removeprefix(f, 'sources/cubedb/mcu/IP/') - if not ( ff.startswith('B') or ff.startswith( 'D' ) ): + if not (ff.startswith('B') or ff.startswith('D')): continue if ff.startswith("BDMA"): is_explicitly_bdma = True @@ -908,8 +909,10 @@ def parse_dma(): # ========== CHIP WITH DMAMUX dmamux_file = ff[5:7] - if ff.startswith('STM32L4P'): dmamux_file = 'L4PQ' - if ff.startswith('STM32L4S'): dmamux_file = 'L4RS' + if ff.startswith('STM32L4P'): + dmamux_file = 'L4PQ' + if ff.startswith('STM32L4S'): + dmamux_file = 'L4RS' for mf in glob('data/dmamux/{}_*.yaml'.format(dmamux_file)): with open(mf, 'r') as yaml_file: y = yaml.load(yaml_file, Loader=SafeLoader) @@ -935,7 +938,8 @@ def parse_dma(): }) dmamux = 'DMAMUX1' - if is_explicitly_bdma: dmamux = 'DMAMUX2' + if is_explicitly_bdma: + dmamux = 'DMAMUX2' dmamux_channel = 0 for n in dma_peri_name.split(","): @@ -1019,8 +1023,10 @@ def parse_dma(): dma_channels[ff] = chip_dma + clocks = {} + def parse_clocks(): for f in glob('sources/cubedb/mcu/IP/RCC-*rcc_v1_0_Modes.xml'): ff = removeprefix(f, 'sources/cubedb/mcu/IP/RCC-') @@ -1039,8 +1045,10 @@ def parse_clocks(): clocks[ff] = chip_clocks + peripheral_to_clock = {} + def parse_rcc_regs(): print("parsing RCC registers") for f in glob('data/registers/rcc_*'): @@ -1061,6 +1069,7 @@ def parse_rcc_regs(): family_clocks[peri] = clock peripheral_to_clock['rcc_' + ff + '/RCC'] = family_clocks + def match_peri_clock(rcc_block, peri_name): if rcc_block in peripheral_to_clock: family_clocks = peripheral_to_clock[rcc_block] @@ -1071,8 +1080,10 @@ 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'): @@ -1088,8 +1099,8 @@ def parse_interrupts(): peri_names = parts[2].split(',') 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] ] + 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: @@ -1097,6 +1108,7 @@ def parse_interrupts(): 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: @@ -1111,21 +1123,23 @@ def split_interrupts(peri_names, irq_name): return split + irq_signals_map = { - 'I2C': [ 'ER', 'EV'], - 'TIM': [ 'BRK', 'UP', 'TRG', 'COM'], - 'HRTIM': ['Master', 'TIMA', 'TIMB', 'TIMC', 'TIMD', 'TIME', 'TIMF' ] + '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.startswith('DMA') or peri_name.startswith('BDMA')) and irq_name.startswith(peri_name): - return { irq_name: irq_name } + return {irq_name: irq_name} if peri_name in irq_name: signals = {} start = irq_name.index(peri_name) - regexp = re.compile('(_[^_]+)'); + regexp = re.compile('(_[^_]+)') if match := regexp.findall(irq_name, start): for m in match: signal = removeprefix(m, '_').strip() @@ -1135,7 +1149,8 @@ def remap_interrupt_signals(peri_name, irq_name): signals = expand_all_irq_signals(peri_name, irq_name) return signals else: - return { 'GLOBAL': irq_name } + return {'GLOBAL': irq_name} + def is_valid_irq_signal(peri_name, signal): for prefix, signals in irq_signals_map.items(): @@ -1143,15 +1158,17 @@ def is_valid_irq_signal(peri_name, signal): 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]: + for s in irq_signals_map[prefix]: expanded[s] = irq_name return expanded - return {'GLOBAL': irq_name } + return {'GLOBAL': irq_name} + def filter_interrupts(peri_irqs, all_irqs): filtered = {} @@ -1165,7 +1182,6 @@ def filter_interrupts(peri_irqs, all_irqs): return filtered - parse_interrupts() parse_rcc_regs() parse_documentations()