all: generate interrupt vector from .svd file

Этот коммит содержится в:
Ayke van Laethem 2018-09-21 14:45:32 +02:00
родитель 3c22f5731c
коммит 505b1f750d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
5 изменённых файлов: 128 добавлений и 9 удалений

1
.gitignore предоставленный
Просмотреть файл

@ -2,3 +2,4 @@ build
src/device/avr/*.go
src/device/avr/*.ld
src/device/nrf/*.go
src/device/nrf/*.s

Просмотреть файл

@ -5,18 +5,53 @@ package runtime
import (
"device/arm"
"device/nrf"
"unsafe"
)
type timeUnit int64
const tickMicros = 1024 * 32
//go:export _start
func _start() {
//go:linkname systemInit SystemInit
func systemInit()
//go:export Reset_Handler
func handleReset() {
systemInit()
main()
}
//go:extern _sbss
var _sbss unsafe.Pointer
//go:extern _ebss
var _ebss unsafe.Pointer
//go:extern _sdata
var _sdata unsafe.Pointer
//go:extern _sidata
var _sidata unsafe.Pointer
//go:extern _edata
var _edata unsafe.Pointer
func preinit() {
// Initialize .bss: zero-initialized global variables.
ptr := uintptr(unsafe.Pointer(&_sbss))
for ptr != uintptr(unsafe.Pointer(&_ebss)) {
*(*uint32)(unsafe.Pointer(ptr)) = 0
ptr += 4
}
// Initialize .data: global variables initialized from flash.
src := uintptr(unsafe.Pointer(&_sidata))
dst := uintptr(unsafe.Pointer(&_sdata))
for dst != uintptr(unsafe.Pointer(&_edata)) {
*(*uint32)(unsafe.Pointer(dst)) = *(*uint32)(unsafe.Pointer(src))
dst += 4
src += 4
}
}
func postinit() {
@ -119,7 +154,7 @@ func rtc_sleep(ticks uint32) {
}
//go:export RTC0_IRQHandler
func RTC0_IRQHandler() {
func handleRTC0() {
nrf.RTC0.INTENCLR = nrf.RTC0_INTENSET_COMPARE0_Msk
nrf.RTC0.EVENTS_COMPARE[0] = 0
rtc_wakeup = true

Просмотреть файл

@ -34,6 +34,8 @@ SECTIONS
__StackTop = .;
} >RAM
_sidata = LOADADDR(.data);
/* This is the initialized data section
The program executes knowing that the data is in the RAM
but the loader puts the initial values in the FLASH (inidata).

Просмотреть файл

@ -2,7 +2,7 @@
"llvm-target": "armv7em-none-eabi",
"build-tags": ["nrf", "nrf52", "nrf52832", "js", "wasm"],
"linker": "arm-none-eabi-gcc",
"pre-link-args": ["-nostdlib", "-nostartfiles", "-mcpu=cortex-m4", "-mthumb", "-T", "targets/arm.ld", "-Wl,--gc-sections", "-fno-exceptions", "-fno-unwind-tables", "-ffunction-sections", "-fdata-sections", "-Os", "-DNRF52832_XXAA", "-D__STARTUP_CLEAR_BSS", "-Ilib/CMSIS/CMSIS/Include", "lib/nrfx/mdk/gcc_startup_nrf52.S", "lib/nrfx/mdk/system_nrf52.c"],
"pre-link-args": ["-nostdlib", "-nostartfiles", "-mcpu=cortex-m4", "-mthumb", "-T", "targets/arm.ld", "-Wl,--gc-sections", "-fno-exceptions", "-fno-unwind-tables", "-ffunction-sections", "-fdata-sections", "-Os", "-DNRF52832_XXAA", "-Ilib/CMSIS/CMSIS/Include", "lib/nrfx/mdk/system_nrf52.c", "src/device/nrf/nrf52.s"],
"objcopy": "arm-none-eabi-objcopy",
"flash": "nrfjprog -f nrf52 --sectorerase --program {hex} --reset"
}

Просмотреть файл

@ -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__':