From 39e3fe28db0db6ecc898fc56db06f47384d54499 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 16 Sep 2018 14:57:42 +0200 Subject: [PATCH] avr: convert initialization from asm to Go This increases code size by 1 instruction (2 bytes) because LLVM isn't yet smart enough to recognize that it doesn't need to clear a register to use 0: it can just use r1 which is always 0 according to the convention. It makes initialization a lot easier to read, however. --- src/runtime/runtime.go | 6 ++++++ src/runtime/runtime_avr.go | 20 ++++++++++++++++++++ src/runtime/runtime_nrf.go | 6 ++++++ src/runtime/runtime_unix.go | 6 ++++++ targets/avr.S | 18 ------------------ 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/runtime/runtime.go b/src/runtime/runtime.go index 233c34da..137a41a4 100644 --- a/src/runtime/runtime.go +++ b/src/runtime/runtime.go @@ -22,9 +22,15 @@ var hasScheduler bool // Entry point for Go. Initialize all packages and call main.main(). //go:export main func main() int { + // Initialize memory etc. + preinit() + // Run initializers of all packages. initAll() + // Enable interrupts etc. + postinit() + // This branch must be optimized away. Only one of the targets must remain, // or there will be link errors. if hasScheduler { diff --git a/src/runtime/runtime_avr.go b/src/runtime/runtime_avr.go index b94e86d2..958cd7cd 100644 --- a/src/runtime/runtime_avr.go +++ b/src/runtime/runtime_avr.go @@ -4,6 +4,7 @@ package runtime import ( "device/avr" + "unsafe" ) const BOARD = "arduino" @@ -28,6 +29,25 @@ const ( WDT_PERIOD_2S ) +var ( + _extern__sbss unsafe.Pointer // defined by the linker + _extern__ebss unsafe.Pointer // defined by the linker +) + +func preinit() { + // Initialize .bss: zero-initialized global variables. + ptr := uintptr(unsafe.Pointer(&_extern__sbss)) + for ptr != uintptr(unsafe.Pointer(&_extern__ebss)) { + *(*uint8)(unsafe.Pointer(ptr)) = 0 + ptr += 1 + } +} + +func postinit() { + // Enable interrupts after initialization. + avr.Asm("sei") +} + func init() { initUART() } diff --git a/src/runtime/runtime_nrf.go b/src/runtime/runtime_nrf.go index a359cef4..4cd337c3 100644 --- a/src/runtime/runtime_nrf.go +++ b/src/runtime/runtime_nrf.go @@ -16,6 +16,12 @@ func _start() { main() } +func preinit() { +} + +func postinit() { +} + func init() { initUART() initLFCLK() diff --git a/src/runtime/runtime_unix.go b/src/runtime/runtime_unix.go index 82937bb0..64c0ba3c 100644 --- a/src/runtime/runtime_unix.go +++ b/src/runtime/runtime_unix.go @@ -24,6 +24,12 @@ type timespec struct { const CLOCK_MONOTONIC_RAW = 4 +func preinit() { +} + +func postinit() { +} + func putchar(c byte) { _Cfunc_putchar(int(c)) } diff --git a/targets/avr.S b/targets/avr.S index 96252759..838fd784 100644 --- a/targets/avr.S +++ b/targets/avr.S @@ -11,30 +11,12 @@ isr: reset: clr r1 ; r1 is expected to be 0 by the C calling convention - ; Zero .bss -clear_bss: - ldi xl, lo8(_sbss) - ldi xh, hi8(_sbss) -clear_bss_loop: - ldi yl, lo8(_ebss) - ldi yh, hi8(_ebss) - cp xl, yl ; if x == y - cpc xh, yh - breq clear_bss_end - st x+, r1 ; zero byte in *x - rjmp clear_bss_loop -clear_bss_end: - ; Set up the stack pointer. ldi xl, lo8(_stack_top) ldi xh, hi8(_stack_top) out 0x3d, xl; SPL out 0x3e, xh; SPH - ; Enable interrupts. - ; TODO: make sure interrupts are started after all initializers have run. - sei - ; main will be placed right after here by the linker script so there's no ; need to jump.