From 505b1f750de1933501b1924a50110ea3b2b68fd9 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Fri, 21 Sep 2018 14:45:32 +0200 Subject: all: generate interrupt vector from .svd file --- tools/gen-device-svd.py | 91 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/gen-device-svd.py b/tools/gen-device-svd.py index 3103ad621..b2e86ebba 100755 --- a/tools/gen-device-svd.py +++ b/tools/gen-device-svd.py @@ -35,7 +35,7 @@ def readSVD(path): xml = minidom.parse(path) root = xml.getElementsByTagName('device')[0] deviceName = getText(root.getElementsByTagName('name')[0]) - deviceDescription = getText(root.getElementsByTagName('description')[0]) + deviceDescription = getText(root.getElementsByTagName('description')[0]).strip() licenseText = formatText(getText(root.getElementsByTagName('licenseText')[0])) cpu = root.getElementsByTagName('cpu')[0] cpuName = getText(cpu.getElementsByTagName('name')[0]) @@ -87,14 +87,16 @@ def readSVD(path): else: continue - device.interrupts = interrupts.values() # TODO: sort by index + device.interrupts = sorted(interrupts.values(), key=lambda v: v['index']) + licenseBlock = '// ' + licenseText.replace('\n', '\n// ') + licenseBlock = '\n'.join(map(str.rstrip, licenseBlock.split('\n'))) # strip trailing whitespace device.metadata = { 'file': os.path.basename(path), 'descriptorSource': 'https://github.com/NordicSemiconductor/nrfx/tree/master/mdk', 'name': deviceName, 'nameLower': deviceName.lower(), 'description': deviceDescription, - 'licenseBlock': '\n// ' + licenseText.replace('\n', '\n// '), + 'licenseBlock': licenseBlock, 'arch': ARM_ARCHS[cpuName], 'family': getText(root.getElementsByTagName('series')[0]), } @@ -164,7 +166,8 @@ def writeGo(outdir, device): // +build {pkgName},{nameLower} // {description} -// {licenseBlock} +// +{licenseBlock} package {pkgName} import "unsafe" @@ -183,7 +186,7 @@ const ( ) '''.format(pkgName=pkgName, **device.metadata)) - out.write('\n// Interrupts\nconst (\n') + out.write('\n// Interrupt numbers\nconst (\n') for intr in device.interrupts: out.write('\tIRQ_{name} = {index} // {description}\n'.format(**intr)) intrMax = max(map(lambda intr: intr['index'], device.interrupts)) @@ -244,11 +247,89 @@ const ( out.write(')\n') +def writeAsm(outdir, device): + # The interrupt vector, which is hard to write directly in Go. + out = open(outdir + '/' + device.metadata['nameLower'] + '.s', 'w') + out.write('''\ +// Automatically generated file. DO NOT EDIT. +// Generated by gen-device.py from {file}, see {descriptorSource} + +// {description} +// +{licenseBlock} + +.syntax unified + +// This is the default handler for interrupts, if triggered but not defined. +.section .text.Default_Handler +.global Default_Handler +.type Default_Handler, %function +Default_Handler: + wfe + b Default_Handler + +// Avoid the need for repeated .weak and .set instructions. +.macro IRQ handler +.weak \\handler +.set \\handler, Default_Handler +.endm + +.section .isr_vector +.global __isr_vector + // Interrupt vector as defined by Cortex-M, starting with the stack top. + // On reset, SP is initialized with *0x0 and PC is loaded with *0x4, loading + // __StackTop and Reset_Handler. + .long __StackTop + .long Reset_Handler + .long NMI_Handler + .long HardFault_Handler + .long MemoryManagement_Handler + .long BusFault_Handler + .long UsageFault_Handler + .long 0 + .long 0 + .long 0 + .long 0 + .long SVC_Handler + .long DebugMon_Handler + .long 0 + .long PendSV_Handler + .long SysTick_Handler + + // Extra interrupts for peripherals defined by the hardware vendor. +'''.format(**device.metadata)) + num = 0 + for intr in device.interrupts: + if intr['index'] < num: + raise ValueError('interrupt numbers are not sorted or contain a duplicate') + while intr['index'] > num: + out.write(' .long 0\n') + num += 1 + num += 1 + out.write(' .long {name}_IRQHandler\n'.format(**intr)) + + out.write(''' + // Define default implementations for interrupts, redirecting to + // Default_Handler when not implemented. + IRQ NMI_Handler + IRQ HardFault_Handler + IRQ MemoryManagement_Handler + IRQ BusFault_Handler + IRQ UsageFault_Handler + IRQ SVC_Handler + IRQ DebugMon_Handler + IRQ PendSV_Handler + IRQ SysTick_Handler +''') + for intr in device.interrupts: + out.write(' IRQ {name}_IRQHandler\n'.format(**intr)) + def generate(indir, outdir): for filepath in sorted(glob(indir + '/*.svd')): print(filepath) device = readSVD(filepath) writeGo(outdir, device) + writeAsm(outdir, device) if __name__ == '__main__': -- cgit v1.2.3