diff options
author | Ayke van Laethem <[email protected]> | 2018-09-23 20:37:22 +0200 |
---|---|---|
committer | Ayke van Laethem <[email protected]> | 2018-09-23 20:37:22 +0200 |
commit | b9638315d2dbac253d1e867d4a61f689932f2d48 (patch) | |
tree | 494a7b39840fa350361d72e6123ea3dffe5a0ab1 | |
parent | 3850530c88e51c6cb023b5a53cf6f4a1e074e987 (diff) | |
download | tinygo-b9638315d2dbac253d1e867d4a61f689932f2d48.tar.gz tinygo-b9638315d2dbac253d1e867d4a61f689932f2d48.zip |
avr: automatically generate interrupt vectors
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | targets/arduino.json | 4 | ||||
-rw-r--r-- | targets/avr.S | 30 | ||||
-rw-r--r-- | targets/avr.ld | 4 | ||||
-rwxr-xr-x | tools/gen-device-avr.py | 37 |
5 files changed, 61 insertions, 15 deletions
diff --git a/.gitignore b/.gitignore index b3a998502..1d1db7fe7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build docs/_build src/device/avr/*.go src/device/avr/*.ld +src/device/avr/*.s src/device/nrf/*.go src/device/nrf/*.s src/device/stm32/*.go diff --git a/targets/arduino.json b/targets/arduino.json index 2b03b8fb5..978f5663c 100644 --- a/targets/arduino.json +++ b/targets/arduino.json @@ -1,8 +1,8 @@ { "llvm-target": "avr-atmel-none", - "build-tags": ["arduino", "atmega328p", "atmega", "avr8", "avr", "js", "wasm"], + "build-tags": ["arduino", "atmega328p", "atmega", "avr5", "avr", "js", "wasm"], "linker": "avr-gcc", - "pre-link-args": ["-nostartfiles", "-T", "targets/avr.ld", "-Wl,--gc-sections", "targets/avr.S"], + "pre-link-args": ["-nostartfiles", "-mmcu=avr5", "-T", "targets/avr.ld", "-Wl,--gc-sections", "targets/avr.S", "src/device/avr/atmega328p.s"], "objcopy": "avr-objcopy", "flash": "avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}" } diff --git a/targets/avr.S b/targets/avr.S index 9c5523153..1c32fa197 100644 --- a/targets/avr.S +++ b/targets/avr.S @@ -1,14 +1,11 @@ -.section .isr -isr: - rjmp reset - -.org 0x18 ; WDT - rjmp wdt +; This file provides common code across AVRs that cannot be implemented directly +; in Go. +; The reset vector is device-specific and is generated by tools/gen-device-avr.py. ; Startup code -.section .reset -.org 26 -reset: +.section .text.__vector_RESET +.global __vector_RESET +__vector_RESET: clr r1 ; r1 is expected to be 0 by the C calling convention ; Set up the stack pointer. @@ -41,10 +38,21 @@ init_data_end: ; need to jump. +; This is the default handler for interrupts, if triggered but not defined. +; Sleep inside so that an accidentally triggered interrupt won't drain the +; battery of a battery-powered device. +.section .text.__vector_default +.global __vector_default +__vector_default: + sleep + rjmp __vector_default + + ; The only thing this WDT handler really does is disable itself, to get out of ; sleep mode. -.section .text.wdt -wdt: +.section .text.__vector_WDT +.global __vector_WDT +__vector_WDT: push r16 clr r16 diff --git a/targets/avr.ld b/targets/avr.ld index 99d2f28b1..f2421c4b0 100644 --- a/targets/avr.ld +++ b/targets/avr.ld @@ -12,8 +12,8 @@ SECTIONS { .text : { - KEEP(*(.isr)) - KEEP(*(.reset)) + KEEP(*(.vectors)) + KEEP(*(.text.__vector_RESET)) KEEP(*(.text.main)) /* main must follow the reset handler */ *(.text.*) *(.rodata) diff --git a/tools/gen-device-avr.py b/tools/gen-device-avr.py index 1f5aa2b06..3517d868e 100755 --- a/tools/gen-device-avr.py +++ b/tools/gen-device-avr.py @@ -201,6 +201,42 @@ const ( out.write('\n') 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-avr.py from {file}, see {descriptorSource} + +; Avoid the need for repeated .weak and .set instructions. +.macro IRQ handler + .weak \\handler + .set \\handler, __vector_default +.endm + +; The interrupt vector of this device. Must be placed at address 0 by the linker. +.section .vectors +.global __vectors +'''.format(**device.metadata)) + num = 0 + for intr in device.interrupts: + if intr['index'] < num: + # Some devices have duplicate interrupts, probably for historical + # reasons. + continue + while intr['index'] > num: + out.write(' jmp __vector_default\n') + num += 1 + num += 1 + out.write(' jmp __vector_{name}\n'.format(**intr)) + + out.write(''' + ; Define default implementations for interrupts, redirecting to + ; __vector_default when not implemented. +''') + for intr in device.interrupts: + out.write(' IRQ __vector_{name}\n'.format(**intr)) + def writeLD(outdir, device): # Variables for the linker script. out = open(outdir + '/' + device.metadata['nameLower'] + '.ld', 'w') @@ -220,6 +256,7 @@ def generate(indir, outdir): print(filepath) device = readATDF(filepath) writeGo(outdir, device) + writeAsm(outdir, device) writeLD(outdir, device) |