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.
Этот коммит содержится в:
Ayke van Laethem 2018-09-16 14:57:42 +02:00
родитель 0d8a7e1666
коммит 39e3fe28db
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
5 изменённых файлов: 38 добавлений и 18 удалений

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

@ -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 {

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

@ -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()
}

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

@ -16,6 +16,12 @@ func _start() {
main()
}
func preinit() {
}
func postinit() {
}
func init() {
initUART()
initLFCLK()

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

@ -24,6 +24,12 @@ type timespec struct {
const CLOCK_MONOTONIC_RAW = 4
func preinit() {
}
func postinit() {
}
func putchar(c byte) {
_Cfunc_putchar(int(c))
}

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

@ -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.