Storing data in RAM without avr-libc. How can I configure the proper memory sections using a custom linker script and initialization code?

StackOverflow https://stackoverflow.com/questions/17520413

  •  02-06-2022
  •  | 
  •  

Question

Here's my linker script:

MEMORY {

  text   (rx)   : ORIGIN = 0x000000, LENGTH = 64K

  data   (rw!x) : ORIGIN = 0x800100, LENGTH = 0xFFA0

}

SECTIONS {

    .vectors : AT (0x0000) { entry.o (.vectors); }

    .text    : AT (ADDR (.vectors) + SIZEOF(.vectors)) { * (.text.startup); * (.text); * (.progmem.data); _etext = .; }

    .data    : AT (ADDR (.text) + SIZEOF (.text)) { PROVIDE (__data_start = .); * (.data); * (.rodata); * (.rodata.str1.1); PROVIDE (__data_end = .); } > data

    .bss     : AT (ADDR (.bss)) { PROVIDE (__bss_start = .); * (.bss); PROVIDE (__bss_end = .); } > data

    __data_load_start = LOADADDR(.data);

    __data_load_end = __data_load_start + SIZEOF(.data);

}

And this is my initialization code. init is called at reset.

.section .text,"ax",@progbits

/* Handle low level hardware initialization. */

.global init

init:                       eor r1, r1

                            out 0x3f, r1

                            ldi r28, 0xFF

                            ldi r29, 0x02

                            out 0x3e, r29

                            out 0x3d, r28

                            rjmp __do_copy_data

                            rjmp __do_clear_bss

                            jmp main

/* Handle copying data into RAM. */

.global __do_copy_data

__do_copy_data:             ldi r17, hi8(__data_end)

                            ldi r26, lo8(__data_start)

                            ldi r27, hi8(__data_start)

                            ldi r30, lo8(__data_load_start)

                            ldi r31, hi8(__data_load_start)

                            rjmp .L__do_copy_data_start

.L__do_copy_data_loop:      lpm r0, Z+

                            st X+, r0

.L__do_copy_data_start:     cpi r26, lo8(__data_end)

                            cpc r27, r17

                            brne .L__do_copy_data_loop

                            rjmp main

/* Handle clearing the BSS. */

.global __do_clear_bss

__do_clear_bss:             ldi r17, hi8(__bss_end)

                            ldi r26, lo8(__bss_start)

                            ldi r27, hi8(__bss_start)

                            rjmp .L__do_clear_bss_start

.L__do_clear_bss_loop:      st X+, r1

.L__do_clear_bss_start:     cpi r26, lo8(__bss_end)

                            cpc r27, r17

                            brne .L__do_clear_bss_loop

The problem is that the initialization code hangs sometime during the copying process. Here's an edited dump of my symbol table, if it's helpful to anyone.

00000000 a __tmp_reg__
...
00000000 t reset
...
00000001 a __zero_reg__
...
0000003d a __SP_L__
...
00000074 T main
0000009a T init
000000ae T __do_copy_data
000000c6 T __do_clear_bss
...
00000446 A __data_load_start
00000446 T _etext
0000045b A __data_load_end
00800100 D __data_start
00800100 D myint
00800115 B __bss_start
00800115 D __data_end
00800115 b foobar.1671
00800135 B ticks
00800139 B __bss_end
Was it helpful?

Solution 3

I actually got it to work. All I had to do was enable reading from and writing to external RAM in the SREG. It was mindblowingly obvious and simple, I know, but it was buried in the data sheet and it was poorly documented.

This resource was helpful, but didn't have any documentation for my chip. If you're having this problem, look in the data sheet for your AVR and see how it is related. The process is not the same for all variations of AVRs.

How to use external RAM.

OTHER TIPS

C is designed to work on von Neumann architectures. AVR is Harvard based. This means that C expects strings to be in RAM. As a consequence, if you ever take a look at the disassembly for any elf binary that would eventually be copied as a hex to your AVR chip, you will see two sections: __do_copy_data and __do_clear_bss [when required]. These routines, which are added in the linking stages, take care of the basic needs of the C language. As a consequence, what you are seeing here with your pointers is likely that they are pointing to the wrong addresses. In other words, they are either pointing to an address in program space but you are reading from data space [different address bus]. Or you are purposely reading from data space but have not copied the strings over.

See:

avr/pgmspace.h FAQ: ROM Array and scroll down for strings and of course, the AVR instruction set as provided by Atmel, especifically, the instruction to copy program memory over to data memory

Edited to reflect new question and comment: Your assembly for both sections look ok to me. I will have to take a look at your linker scripts with closer scrutinity to check if there any funny businesses going on there. Since you are writing a bootloader, do you mind if I ask if you have taken a look at bootloader support on AVR-libc?

http://deans-avr-tutorials.googlecode.com/svn/trunk/Progmem/Output/Progmem.pdf This document may help to clarify the use of flash/ram memories of AVR.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top