aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2018-09-21 14:45:32 +0200
committerAyke van Laethem <[email protected]>2018-09-21 15:38:28 +0200
commit505b1f750de1933501b1924a50110ea3b2b68fd9 (patch)
treecf5e9f95592d130f5c52ce0ba27ae16753b52ca9 /tools
parent3c22f5731cb60eb20384261a6a28f790972d90b3 (diff)
downloadtinygo-505b1f750de1933501b1924a50110ea3b2b68fd9.tar.gz
tinygo-505b1f750de1933501b1924a50110ea3b2b68fd9.zip
all: generate interrupt vector from .svd file
Diffstat (limited to 'tools')
-rwxr-xr-xtools/gen-device-svd.py91
1 files changed, 86 insertions, 5 deletions
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__':