aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2018-09-23 20:37:22 +0200
committerAyke van Laethem <[email protected]>2018-09-23 20:37:22 +0200
commitb9638315d2dbac253d1e867d4a61f689932f2d48 (patch)
tree494a7b39840fa350361d72e6123ea3dffe5a0ab1
parent3850530c88e51c6cb023b5a53cf6f4a1e074e987 (diff)
downloadtinygo-b9638315d2dbac253d1e867d4a61f689932f2d48.tar.gz
tinygo-b9638315d2dbac253d1e867d4a61f689932f2d48.zip
avr: automatically generate interrupt vectors
-rw-r--r--.gitignore1
-rw-r--r--targets/arduino.json4
-rw-r--r--targets/avr.S30
-rw-r--r--targets/avr.ld4
-rwxr-xr-xtools/gen-device-avr.py37
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)