IAR Compiler and Absolute Addresses

I would like to locate some things (a table in this case), at an absolute address. When I compile and link the following code segment, data shows up in flash as expected (looking at the map file). Although, not at the address I would like.

extern const uint16_t tblFlashTest[3] = {1,2,3};

It appears as if I should be able to specify the absolute address where the linker should put the table as shown below, but I get a variety of error messages. I have also tried adding the _no_init specifer in the definition, but then I get different errors.

#pragma location=0x0801FC00

extern const uint16_t tblFlashTest[3] = {1,2,3};

Does anyone have an experience with IAR compilers, and placing variables at fixed locations ?

gahelton:
extern const uint16_t tblFlashTest[3] = {1,2,3};

The problem with this is that it just declares that this variable exists somewhere but it allocates no space for it. (Which would certainly cause confusion with that pragma stating that you want to put unallocated storage in a specific location.) Since you claim that the program compiles then it must be declared (without the “extern”) somewhere else.

The best way to gain control over where things go is via the linker scripts. By using them you can place various segments exactly where you want them. If you put the allocation of this variable in an assembly file in its own segment, you could do that. (I don’t use IAR so I don’t know the details of how it does that but it should be in the documentation somewhere. Or look up a web page on bare metal ARM programming.)

I vaguely recall that IAR has a special syntax with an @ in it, for absolute addresses. Or you can struggle with the linker’s icf file syntax.

in C, you can just cast a constant to a memory address pointer to a byte or 32 bit value, right?

uint32_t *p32, n;

p32 = (uint32_t *) 0x12345;

n = *p32;

or

n = p32[1024];

Ugly yes. Easy yes too.

IAR used to have a feature for placing constants into absolute memory addresses in v4.xx, but deleted it for v5.xx - v6.20. But, added it back again for v6.30. However, there is a workaround for other users. By adding some information to the linker configuration file, and using the #pragma location=“SectionName”, you can force a constant table (or data) where you want it.

//***********************************************************************

//C Code to create constant table

//***********************************************************************

#pragma location = “FLASH_TEST”

__root const uint16_t tblFlashTest = {0,1,2, …, 511};

//***********************************************************************

//Here are the changes to the .icf file. The “ROM” block was shorted by one page (1024 bytes). Then the “FLASH_TEST” page was added as the last page of flash.

define symbol ICFEDIT_region_ROM_start = 0x08000000;

define symbol ICFEDIT_region_ROM_end = 0x0801FBFF;

define symbol FLASH_TEST_start = 0x0801FC00;

define symbol FLASH_TEST_end = 0x0801FFFF;

//Define the region:

define region FLASH_TEST_region = mem:[from FLASH_TEST_start to FLASH_TEST_end];

// Place the FLASH_TEST region in readonly memory

place in FLASH_TEST_region { readonly section FLASH_TEST };

This is loosely based on a tech note from IAR.