all: generate interrupt vector from .svd file

This commit is contained in:
Ayke van Laethem
2018-09-21 14:45:32 +02:00
parent 3c22f5731c
commit 505b1f750d
5 changed files with 128 additions and 9 deletions
+86 -5
View File
@@ -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__':