Reputation: 3255
OK, here's one file, tinyrom_2313.S
:
.text
.org 0
.global init
init:
rjmp main
.org 0x0020
.global main
main:
cli
// Disable watchdog timer
wdr
ldi r16, 0x00
out _SFR_IO_ADDR(MCUSR), r16
in r17, _SFR_IO_ADDR(WDTCSR)
ori r17, _BV(WDCE) | _BV(WDE)
out _SFR_IO_ADDR(WDTCSR), r17
out _SFR_IO_ADDR(WDTCSR), r16
// Disable input pullups
ldi r16, _BV(PUD)
out _SFR_IO_ADDR(MCUCR), r16
// Pin directions are all
// inputs on reset.
// Set pin directions:
// PA2 - PA0 are inputs
// PB7 - PB0 are inputs
// PD6 - PD0 are outputs
ldi r16, 0xFF
out _SFR_IO_ADDR(DDRD), r16
// We store the data table at 0x0100.
ldi ZH, 0x01
loop:
in ZL, _SFR_IO_ADDR(PINB)
lpm r0, Z
out _SFR_IO_ADDR(PORTD), r0
rjmp loop
And here's the second file, single_step_rom.S
:
.text
.org 0x0100
// / N H C
// H E O S U
// O X LRT R
// L T DUE R
// D___ ANP ___
.byte 0b00000000 // 000 000
.byte 0b00001010 // 000 001
.byte 0b00000011 // 000 010
.byte 0b00000011 // 000 011
.byte 0b00001101 // 000 100
.byte 0b00001110 // 000 101
.byte 0b00001110 // 000 110
.byte 0b00000011 // 000 111
.byte 0b00000001 // 001 000
.byte 0b00000001 // 001 001
.byte 0b00000011 // 001 010
.byte 0b00000011 // 001 011
.byte 0b00001101 // 001 100
.byte 0b00001110 // 001 101
.byte 0b00001111 // 001 110
.byte 0b00001111 // 001 111
.byte 0b00000100 // 010 000
.byte 0b00001010 // 010 001
.byte 0b00000011 // 010 010
.byte 0b00000011 // 010 011
.byte 0b00000100 // 010 100
.byte 0b00001110 // 010 101
.byte 0b00001110 // 010 110
.byte 0b00000011 // 010 111
.byte 0b00000001 // 011 000
.byte 0b00000001 // 011 001
.byte 0b00000011 // 011 010
.byte 0b00000011 // 011 011
.byte 0b00000100 // 011 100
.byte 0b00001110 // 011 101
.byte 0b00001111 // 011 110
.byte 0b00001111 // 011 111
.byte 0b00000000 // 100 000
.byte 0b00001010 // 100 001
.byte 0b00001010 // 100 010
.byte 0b00000000 // 100 011
.byte 0b00001101 // 100 100
.byte 0b00001101 // 100 101
.byte 0b00001110 // 100 110
.byte 0b00000011 // 100 111
.byte 0b00000001 // 101 000
.byte 0b00000001 // 101 001
.byte 0b00001010 // 101 010
.byte 0b00000000 // 101 011
.byte 0b00001101 // 101 100
.byte 0b00001101 // 101 101
.byte 0b00001111 // 101 110
.byte 0b00001111 // 101 111
.byte 0b00000100 // 110 000
.byte 0b00001010 // 110 001
.byte 0b00001010 // 110 010
.byte 0b00000000 // 110 011
.byte 0b00000100 // 110 100
.byte 0b00001101 // 110 101
.byte 0b00001110 // 110 110
.byte 0b00000011 // 110 111
.byte 0b00000001 // 111 000
.byte 0b00000001 // 111 001
.byte 0b00001010 // 111 010
.byte 0b00000000 // 111 011
.byte 0b00000100 // 111 100
.byte 0b00001101 // 111 101
.byte 0b00001111 // 111 110
.byte 0b00001111 // 111 111
Now, I compile:
avr-gcc -nostartfiles -mmcu=attiny2313 -Wl,-Map,map.txt -o single_step_rom.elf single_step_rom.S tinyrom_2313.S
I found that it put single_step_rom
properly at 0x0100
, but then it stuck tinyrom_2313
at 0x0140
. In other words, it looks like avr-gcc completely ignored the .org
directive in tinyrom_2313.S
.
Swapping the order of the .S files gives the opposite problem: tinyrom_2313
is properly at 0x0000
, but then single_step_rom
is placed at 0x0142
, as if avr-gcc is using .org 0x0100
as additive to where the previous file left off.
The description of .org
is:
.org new-lc, fill: Advance the location counter of the current section to new-lc. new-lc is either an absolute expression or an expression with the same section as the current subsection.
Clearly I'm not understanding what is meant by "advance to". Perhaps they meant "advance by". In any case, how do I get avr-gcc to place the code where specified? I'm hoping for a simpler solution than defining a script file and having to pass it via -Wl,-T
.
I'll accept a "yeah, you can't do it without a script file" answer as long as someone can explain to me what is meant by "advance to" in the description of the .org
directive.
Upvotes: 1
Views: 131
Reputation: 3918
There's an entity which describes the "current location" during locating step when linking. The value of it is the simple dot .
in the linker description file. Take for example this part of ./avr/lib/ldscripts/avr5.xn
which locates the static constructors and destructors and defines some symbols like __ctors_start
along with it:
__ctors_start = . ;
*(.ctors)
__ctors_end = . ;
__dtors_start = . ;
*(.dtors)
__dtors_end = . ;
One feature of .
is that it cannot be moved backwards.
Coming to your project, you are linking by means of
> avr-gcc ... single_step_rom.S tinyrom_2313.S
Due to the order of input files, the first thing that the linker/locator sees is
.text
.org 0x100
from single_step_rom.S
(or from respective .o) to be precise. Thus
.is advanced to 0x100, the data is put there, and then comes
tinyrom_2313.S`'s
.text
.org 0
As .
cannot be moved backwards, the effect of .org 0x0
is void.
Way 1: (Mis) use existing input sections.
The .text output section gathers many input sections, just have a look at the default linker description file for your device. For example, in my verion of binutils there is *(.hightext)
after *(.text*)
. So you can locate code to section .text
and table data to .hightext
, like in
.section .hightext, "a", @progbits
.balign 0x100
.global my_data
my_data:
.byte ...
and then load the address like so:
ldi ZH, hi8(my_data)
Notice that .org
will disappear altogether. Moreover, the first jump instruction would technically go to .vectors
, because it is the 1st vector (reset), and all other code would go to .text
.
Way 2: Use linker script augmentation
Use augmentation like
SECTIONS
{
.text :
{
. = ALIGN(0x100);
*(.my_data*)
}
}
INSERT AFTER .text
Then store this few lines as my_data.ld
and provide it by means of -T mydata.ld
during link. Put your table data into section .my_data
. To access it, define an appropriate symbol like in way 1.
Upvotes: 1