Browse Source

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.
pull/3291/head
Ayke van Laethem 2 years ago
committed by Ron Evans
parent
commit
bb5050a50d
  1. 13
      targets/avr.S

13
targets/avr.S

@ -11,6 +11,11 @@
#define zl r30 #define zl r30
#define zh r31 #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 ; Startup code
.section .text.__vector_RESET .section .text.__vector_RESET
.global __vector_RESET .global __vector_RESET
@ -34,11 +39,19 @@ init_data:
ldi yh, hi8(_edata) ldi yh, hi8(_edata)
ldi zl, lo8(_sidata) ldi zl, lo8(_sidata)
ldi zh, hi8(_sidata) ldi zh, hi8(_sidata)
#ifdef __AVR_HAVE_ELPM__
ldi r16, hh8(_sidata) ; RAMPZ = hh8(_sidata)
out 0x3b, r16
#endif
init_data_loop: init_data_loop:
cp xl, yl ; if x == y cp xl, yl ; if x == y
cpc xh, yh cpc xh, yh
breq init_data_end ; goto main breq init_data_end ; goto main
#ifdef __AVR_HAVE_ELPM__
elpm r0, Z+ ; r0 = *(z++)
#else
lpm r0, Z+ ; r0 = *(z++) lpm r0, Z+ ; r0 = *(z++)
#endif
st X+, r0 ; *(x++) = r0 st X+, r0 ; *(x++) = r0
rjmp init_data_loop ; goto init_data_loop rjmp init_data_loop ; goto init_data_loop
init_data_end: init_data_end:

Loading…
Cancel
Save