avr: automatically generate interrupt vectors
Этот коммит содержится в:
родитель
3850530c88
коммит
b9638315d2
5 изменённых файлов: 61 добавлений и 15 удалений
1
.gitignore
предоставленный
1
.gitignore
предоставленный
|
@ -2,6 +2,7 @@ build
|
||||||
docs/_build
|
docs/_build
|
||||||
src/device/avr/*.go
|
src/device/avr/*.go
|
||||||
src/device/avr/*.ld
|
src/device/avr/*.ld
|
||||||
|
src/device/avr/*.s
|
||||||
src/device/nrf/*.go
|
src/device/nrf/*.go
|
||||||
src/device/nrf/*.s
|
src/device/nrf/*.s
|
||||||
src/device/stm32/*.go
|
src/device/stm32/*.go
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"llvm-target": "avr-atmel-none",
|
"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",
|
"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",
|
"objcopy": "avr-objcopy",
|
||||||
"flash": "avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}"
|
"flash": "avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
.section .isr
|
; This file provides common code across AVRs that cannot be implemented directly
|
||||||
isr:
|
; in Go.
|
||||||
rjmp reset
|
; The reset vector is device-specific and is generated by tools/gen-device-avr.py.
|
||||||
|
|
||||||
.org 0x18 ; WDT
|
|
||||||
rjmp wdt
|
|
||||||
|
|
||||||
; Startup code
|
; Startup code
|
||||||
.section .reset
|
.section .text.__vector_RESET
|
||||||
.org 26
|
.global __vector_RESET
|
||||||
reset:
|
__vector_RESET:
|
||||||
clr r1 ; r1 is expected to be 0 by the C calling convention
|
clr r1 ; r1 is expected to be 0 by the C calling convention
|
||||||
|
|
||||||
; Set up the stack pointer.
|
; Set up the stack pointer.
|
||||||
|
@ -41,10 +38,21 @@ init_data_end:
|
||||||
; need to jump.
|
; 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
|
; The only thing this WDT handler really does is disable itself, to get out of
|
||||||
; sleep mode.
|
; sleep mode.
|
||||||
.section .text.wdt
|
.section .text.__vector_WDT
|
||||||
wdt:
|
.global __vector_WDT
|
||||||
|
__vector_WDT:
|
||||||
push r16
|
push r16
|
||||||
|
|
||||||
clr r16
|
clr r16
|
||||||
|
|
|
@ -12,8 +12,8 @@ SECTIONS
|
||||||
{
|
{
|
||||||
.text :
|
.text :
|
||||||
{
|
{
|
||||||
KEEP(*(.isr))
|
KEEP(*(.vectors))
|
||||||
KEEP(*(.reset))
|
KEEP(*(.text.__vector_RESET))
|
||||||
KEEP(*(.text.main)) /* main must follow the reset handler */
|
KEEP(*(.text.main)) /* main must follow the reset handler */
|
||||||
*(.text.*)
|
*(.text.*)
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
|
|
|
@ -201,6 +201,42 @@ const (
|
||||||
out.write('\n')
|
out.write('\n')
|
||||||
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):
|
def writeLD(outdir, device):
|
||||||
# Variables for the linker script.
|
# Variables for the linker script.
|
||||||
out = open(outdir + '/' + device.metadata['nameLower'] + '.ld', 'w')
|
out = open(outdir + '/' + device.metadata['nameLower'] + '.ld', 'w')
|
||||||
|
@ -220,6 +256,7 @@ def generate(indir, outdir):
|
||||||
print(filepath)
|
print(filepath)
|
||||||
device = readATDF(filepath)
|
device = readATDF(filepath)
|
||||||
writeGo(outdir, device)
|
writeGo(outdir, device)
|
||||||
|
writeAsm(outdir, device)
|
||||||
writeLD(outdir, device)
|
writeLD(outdir, device)
|
||||||
|
|
||||||
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче