I would like to specify that certain data be located in Flash at a particular address. For functions, I see that I can use the _attribute_ capabilities to do this. It doesn't work for constants. I have been trying to accomplish this primarily using the linker, but the linker needs to see my data items in a distinct section (so far as I can tell). I started with the atmel-rom.ld file available in the lwIP demos, as my application is based on them. I changed the top of the file to: MEMORY { flash : ORIGIN = 0x00100000, LENGTH = 0x3F000 fixed : ORIGIN = 0x0013F000, LENGTH = 0x1000 ram : ORIGIN = 0x00200000, LENGTH = 64K } However, in order to make this work, I have to tell the linker which modules go into the "fixed" section. A standard declaration such as const unsigned char ieee_mac[6] = { 0x00, 0x30, 0x86, // Our IEEE OUI number OUI_MINE, // This product's code 0xFF, 0xFF}; // Assigned by chip burner is always going into .rodata, even though I may put an asm (" .section fixed") before it. I realize I could accomplish this brute-force using the same method as the declarations found in at91sam7x256.h (i.e, #define AT91C_PIOB_MDER ((AT91_REG *) 0xFFFFF650) ) but I would prefer something slightly more elegant. Any ideas? Thanks. Andy
A solution came to mind on the way to work. It takes several steps to explain, but in summary what I did was use inline assembly code for the particular constant instead of using just C. First, I added a line to my compiler flags to cause them to generate the assembly .lst file: -Wa,-adhlns=$(subst $(suffix $<),.lst,$<) \ (tacked onto the CFLAGS definition). Next, I did a make. This created .lst files for everything. The ones I needed I kept, the others I deleted. I edited those lst files to produce true ASM code. I could have put these into the makefile as assembly source, but I chose instead to embed them into the appropriate .C files. For instance, the declaration above > const unsigned char ieee_mac[6] = { > 0x00, 0x30, 0x86, // Our IEEE OUI number > OUI_MINE, // This product's code > 0xFF, 0xFF}; // Assigned by chip burner is now commented out, and the comparable assembly is inserted as a series of C asm() statements as shown below: // const unsigned char ieee_mac[6] = { // 0x00, 0x30, 0x86, // Our IEEE OUI number // OUI_MINE, // This product's code // 0xFF, 0xFF}; // Assigned by chip burner asm (" .global ieee_mac"); asm (" .section .fixed"); asm ("ieee_mac:"); asm (" .byte 0"); asm (" .byte 48"); asm (" .byte -122"); asm (" .byte 16"); asm (" .byte -1"); asm (" .byte -1"); Next, I had to update the linker file. I did it by inserting the .fixed section as the first one, then allowing it to work its regular stuff from there. MEMORY { flash : ORIGIN = 0x00100000, LENGTH = 0x3F000 fixed : ORIGIN = 0x0013F000, LENGTH = 0x1000 ram : ORIGIN = 0x00200000, LENGTH = 64K } _stack_end_ = 0x00200000 + 64K - 4; SECTIONS { . = 0x0013F000; .fixed : { _fixed_beg_ = .; *(.fixed) _fixed_end_ = .; } >fixed . = 0; startup : { *(.startup)} >flash ... I hope this helps others. Andy
Just an additional suggestion: Did you check the gcc variable-attribute section (see gcc-manual)? The (inline-)assembler-code can be avoided by assigning a inititialized constant C-structure/array to a "linker"-section using the section-attribute. I have just done some AVR-code with avr-gcc which uses this method. I have not tried the method on an ARM with arm-elf-gcc so far but it should work with every "GNU-toolchain". The basic idea: unsigned char data_table_fixed[] _attribute_ ((section (".fixed_table"))) = { 0xaa, 0x55, 0xff, 0x00 }; For AVR I have used the default linker-scripts (provided by the toolchain/avr-libc) and just passed the section-address as parameter to the linker: LDFLAGS += -Wl,--section-start=.fixed_table=0x2000 But of cause you could use a "DIY" linker-script the way you have already implemented it. I checked the locations and contents in a disassembly created with this target in the makefile: %.lss: %.elf [TAB] $(OBJDUMP) -D -h -S -C $< > $@ Remark on your linker-script: If you declare an extra MEMORY area for "fixed" the line . = 0x0013F000; should not be needed. Did you try to link without this line in the linker-script? Martin Thomas
Thanks for the reply, Martin. > Just an additional suggestion: Did you check the gcc variable-attribute > section (see gcc-manual)? The (inline-)assembler-code can be avoided by At the time I did this, I had not found the attributes for variables section yet. Use of the attribute on the variable would have been much more elegant. > Remark on your linker-script: If you declare an extra MEMORY area for > "fixed" the line . = 0x0013F000; should not be needed. Did you try to > link without this line in the linker-script? The reason for the separate section is because we will be putting a bootloader into the same area eventually. I do not want the possibility of application code being in the same region - I would prefer to have the linker tell me I ran out of memory first. I appreciate all you've done with this work. Your examples have been very helpful in understanding how to approach solutions to problems in several areas. Andy
Martin, I just implemented the code according to your example and it works fine. The extra MEMORY line is to force a specific load address for the data. It will be in a protected portion of memory shared with the bootloader. I didn't see another way to force it to the exact address I wanted. Thanks. Andy
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.