From bb5050a50d1efaa28f1dcd84056a50e845cfacf6 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 7 Nov 2022 19:29:35 +0100 Subject: [PATCH] avr: fix .data initialization for binaries over 64kB I found that .data is not correctly initialized with firmware images that use over 64kB of flash. The problem is that the data in .data (which is stored in flash, and copied to RAM at reset) is beyond the 64kB limit and must therefore be loaded using the elpm instruction instead of the lpm instruction. I encountered this issue while getting testdata/math.go to work for AVR. The following command mostly works with this patch, while it prints garbage withtout it: tinygo run -target=simavr -size=short -scheduler=none ./testdata/math.go (This also requires a patch to picolibc to work, see https://github.com/picolibc/picolibc/pull/371) It still doesn't work entirely with this patch: some of the math operations have an incorrect result. But at least it's an improvement as it won't print garbage anymore. --- targets/avr.S | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/targets/avr.S b/targets/avr.S index 986f18ea..568ae6ae 100644 --- a/targets/avr.S +++ b/targets/avr.S @@ -11,6 +11,11 @@ #define zl r30 #define zh r31 +; Ugly hack until https://reviews.llvm.org/D137572 is merged. +#if !defined(__AVR_HAVE_ELPM__) && defined(__flash1) +#define __AVR_HAVE_ELPM__ +#endif + ; Startup code .section .text.__vector_RESET .global __vector_RESET @@ -34,11 +39,19 @@ init_data: ldi yh, hi8(_edata) ldi zl, lo8(_sidata) ldi zh, hi8(_sidata) +#ifdef __AVR_HAVE_ELPM__ + ldi r16, hh8(_sidata) ; RAMPZ = hh8(_sidata) + out 0x3b, r16 +#endif init_data_loop: cp xl, yl ; if x == y cpc xh, yh breq init_data_end ; goto main +#ifdef __AVR_HAVE_ELPM__ + elpm r0, Z+ ; r0 = *(z++) +#else lpm r0, Z+ ; r0 = *(z++) +#endif st X+, r0 ; *(x++) = r0 rjmp init_data_loop ; goto init_data_loop init_data_end: