|
 UltimaSerial
Windaq Add-ons
UltimaWaterfall
XChart
FFT1024

Lessons |
|
Sometimes, it is necessary to force a section of codes into
a certain physical memory location.
Assume your project is named as MyProject and you've got
debug utilities imported so that you can use print_dbg_xxx
-
From: C:\Program Files\Atmel\AVR Tools\AVR32 Toolchain\avr32\lib\ldscripts,
locate the default linker script for the target MPU, for example, avr32elf_uc3a0512.x.
There are several other linker scripts based on the configuration of
your project, but we will use this one as our stepping stone
-
Copy it to the root of MyProject
-
Rename it to my_linker_script.lds
-
Modify it. Note: keep in mind that UC3A0512 has 512K
flash. If you are using a different MPU, you will need to adjust
accordingly and the output will also be different
-
In MEMORY, change FLASH (rxai!w) : ORIGIN =
0x80002000, LENGTH = 512K to FLASH (rxai!w) : ORIGIN =
0x80002000, LENGTH = 512K-10K-8K
-
All AVR32 project will be linked to
0x80002000 if no customized linker script presented!
-
The default linker script has a minor
mistake: it didn't take the size of the USB DFU bootloader
into account when it specifies the length, but this will
never cause a problem since you will need to create a huge
project to consume all 512K flash before you will fall into
this trap :)
-
In MEMORY, add FLASH2 (rxai!w) : ORIGIN =
0x80002000+512K-10K-8K, LENGTH = 10K
-
In SECTIONS, add .mytest_section : {*(mytest_section
)} >FLASH2 AT>FLASH2
-
Now the linker script should be like this:
MEMORY
{
FLASH (rxai!w) : ORIGIN = 0x80002000, LENGTH = 512K-10K-8K
FLASH2 (rxai!w) : ORIGIN = 0x80002000+512K-10K-8K, LENGTH = 10K
CPUSRAM (wxa!ri) : ORIGIN = 0x00000000, LENGTH = 64K
USERPAGE : ORIGIN = 0x80800000, LENGTH = 512
FACTORYPAGE : ORIGIN = 0x80800200, LENGTH = 512
}
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = 0x80000000); . = 0x80000000;
.mytest_section : {*(.mytest_section )} >FLASH2 AT>FLASH2
.interp : { *(.interp) } >FLASH AT>FLASH
.reset : { *(.reset) } >FLASH AT>FLASH
...
-
Save it
-
Side note: If you ever wonder what makes
the Atmel's USB DFU links to 0x80000000 instead of 0x80002000,
follow these steps to take a look at the linker script of USB
Bootloader example provided by AVR32 Studio.
-
Make sure you have AVR32 Studio 2.1 or
higher. Earlier AVR32 Studio doesn't provide the example.
-
Follow AVR32Studio -> File
-> New -> other -> AVR32 Example Project ->
UC3A0512 -> EVK1100->SERVICE->USB DFU ISP example.
-
Open the src folder and you
will find the linker script, link_at32uc3a-isp.lds
-
You may notice the linker
script is in a different location as recommended in
Atmel's application note. Don't worry, it is taken care
in the directive for the linker. Follow USB
DFU ISP example->Properties->Tool
Settings->AVR32/GNU C Linker->Miscellaneous, you will see the
directive of -T../src/link_at32uc3a-isp.lds
-
You will see its MEMORY is
different from the one above
MEMORY
{
FLASH (rxai!w) : ORIGIN = 0x80000000, LENGTH = 0x00080000
INTRAM (wxa!ri) : ORIGIN = 0x00000004, LENGTH = 0x0000FFFC
USERPAGE : ORIGIN = 0x80800000, LENGTH = 0x00000200
}
-
Please read http://atmel.com/dyn/resources/prod_documents/doc32131.pdf
for more detail regarding this AVR32 USB DFU ISP example
-
Follow MyProject->Properties->Tool
Settings->AVR32/GNU C Linker->Miscellaneous. and add "-T../my_linker_script.lds"
to Other options (-Xlinker [option])
-
Save it
-
In MyProject->src->main.c
-
Before the body of main(), add int test_call (void) __attribute__((__section__(".mytest_section
")));
-
Before the body of main(), add int test_call (void) {;}.
If you'd like you can add some meaningful codes to test it.
-
Inside the body of main (), after
the initialization codes, add print_dbg("\ntest_call
locates at: "); print_dbg_hex((long)test_call);
The purpose of this to print out the address of test_call.
-
Right after the above lines, add print_dbg("\nmain
locates at: "); print_dbg_hex((long)main); The
purpose of this to print out the address of main.
-
Save it
-
Build the project and run it
-
If you run HyperTerminal and connects PC's com port
to the com port of your EVK1100, you will see the output "test_call locates at
0x8007D800" then something like "main locates at
0x80020578"
-
Keep in mind that UC3A0512 has 512K flash.
If you are using a different MPU, you will need to adjust the linker
script accordingly and the output will also be different.
-
Do not assume main, which is the entry point of
the whole project, will be allocated to the very first address
of the code segment, 0x80002000! since FreeRTOS and other
initialization must take place before main() is invoked.
-
Simple math shows:
0x80002000+512K-10K-8K=0x80002000+0x80000-0x2800-0x2000=0x8007D800, so test_call () is allocated at the beginning of the last
10K of internal FLASH,
away from the rest of codes.
-
Note: If test_call needs to access some
FLASH-based constants, watch out, it may not be in this last
10K of the internal FLASH.
-
If you wish to learn more about
linker scripts, visit http://www.math.utah.edu/docs/info/ld_toc.html#SEC4
and http://www.davehylands.com/avi/linker_scripts.htm
-
Want to verify it in machine codes? Read on...
-
We use this command line to convert the .elf file to
.hex for easy reading, avr32-objcopy
-O ihex MyProject.elf MyProject.hex
-
If you are more familiar
with .bin file format, use command line avr32-objcopy
-O binary MyProject.elf
MyProject.bin
instead and skip the discussion
below.
-
Use Wiki as your reference to study Hex
file format
-
Open MyProject.hex with any text editor, the first line reads :0200000480007A.
-
With the help from Wiki, we know that 04 is the Extended
linear Address Record, and its address field is 8000, thus the
address in next line should be added with 0x8000000 to form a 32-bit address.
-
The second line something like :10200000E08F100000000000000000000000000051
-
Combining the extended linear address record of
0x80000000, we
know the actual codes starts at 0x80002000!
-
Now you see the very first line bypasses the regular
USB_DFU section
-
If you use ":02" as the keyword to search
the .hex file, you will find :02000004800179
-
This is where the codes has to move to a consecutive
memory location beyond 0x8000FFFF, starting at 0x80010000
-
You will even find :02000004800278,
when the codes have to cross 0x80020000
-
Somewhere down the .hex file, you will find a line like
this, :02000004800773
-
Aha, this is another Extended linear Address Record
(04),
indicating the address in next line should add 0x8007000 to form a
32-bit address
-
The very next line is something like this :10D80000EBCD40801A97203D1898EF68FFF83198CB
-
Simple math shows: 0xD800+0x80070000=0x8007D800
-
If you keep track of the addresses, you will
notice there is a gap between 0x8007D800 and the last used
address.
-
We caught the entry point of our test_call!
-
BTW, take a look at the line before the end of the
file, :040000058000200057, it
specifies the start address of 0x80002000
Last update:
05/04/10
|