Linker Script Issue When Porting To CC2538


Tidy(ChunHua) Jiang <tidyjiang@...>
 

Hello,

I'm porting zephyr to TI's CC2538 device family, but there is a special user case —— customer
configuration area(CCA/CCFG). CCA is placed in the uppermost flash page, so the linker script
would like this:

MEMORY
{
FLASH (rx) : ORIGIN = 0x00200000, LENGTH = 0x0007FFD4
FLASH_CCA (rx) : ORIGIN = 0x0027FFD4, LENGTH = 0x2C
SRAM (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE
SYSTEM_CONTROL_SPACE (wx) : ORIGIN = 0xE000E000, LENGTH = 4K
SYSTEM_CONTROL_PERIPH (wx) : ORIGIN = 0x400FE000, LENGTH = 4K
}

ENTRY(flash_cca_lock_page)

...
GROUP_START(FLASH_CCA)
SECTION_PROLOGUE(.flash_cca,,)
{
KEEP(*(.flash_cca))

} GROUP_LINK_IN(FLASH_CCA)
GROUP_END(FLASH_CCA)
...

Please ignore the numerical hard-code.
How can I compatibly place this code to the original link script?
Does this ok:?

SECTIONS
{
GROUP_START(ROMABLE_REGION)
...
#ifdef CONFIG_CC2538_CCA_XXXXX
SECTION_PROLOGUE(.flash_cca,,)
{
. = 0x0027FFD4
KEEP(*(.flash_cca))
} GROUP_LINK_IN(ROMABLE_REGION)
#endif // CONFIG_CC2538_CCA_XXXXX
GROUP_END(ROMABLE_REGION)
...
}
Please ignore the numerical hard-code too.
Best Regards,
tidyjiang.


Andy Ross
 

Tidy(chunhua) Jiang <tidyjiang(a)163.com> wrote (on Tuesday, January 03, 2017 10:59PM):
I'm porting zephyr to TI's CC2538 device family, but there is a
special user case —— customer configuration area(CCA/CCFG). CCA is
placed in the uppermost flash page, so the linker script would like
this:

MEMORY
{
FLASH (rx) : ORIGIN = 0x00200000, LENGTH = 0x0007FFD4
*FLASH_CCA (rx) : ORIGIN = 0x0027FFD4, LENGTH = 0x2C*
SRAM (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE
SYSTEM_CONTROL_SPACE (wx) : ORIGIN = 0xE000E000, LENGTH = 4K
SYSTEM_CONTROL_PERIPH (wx) : ORIGIN = 0x400FE000, LENGTH = 4K
}

Zephyr doesn't really have a facility for device-specific
modifications to linker scripts at the moment. The script that you
would need to modify is in
include/arch/arm/cortex_m/scripts/linker.ld. This is passed through
the C preprocessor and has access to all Kconfig symbols, so if you
had to you could #ifdef your changes there and submit them, but it
would be a little ugly and we should probably come up with something
cleaner.

Do you really need to do this with the linker? What are you trying to
place in this region? If it's a fixed set of data you could just do it
something like:

struct cca_rec {
int my_field1;
char my_field2[128];
/* ... */
};

#define CCA_REC ((struct cca_rec *)0x0027ffd4)

And then just dereference the symbols you would have put in that
region with CCA_REC->my_field1, etc...

It's much simpler to implement, and might do what you want without
requiring immediate surgery to our linker script generation.

Andy


Chuck Jordan <Chuck.Jordan@...>
 

Btw, with the device-tree stuff being added, it might be possible to auto-generate the MEMORY { } part of a linker command file, using information from the device-tree.
BUT, the MEMORY {} part should hold ONLY simple memories in this scheme -- and not express custom areas within memories.
The custom areas within memories can be done using bottom portion of the linker command-file.

That would be a good coding practice going forward in that it
* keeps things SIMPLE and understandable
* MEMORY {} expresses true HARDWARE aspects of the memory map
* allows for auto-generate of MEMORY {} declaration under some circumstances (I suppose this could be overridden if it's a problem)

I know this is an individual choice, and I have certainly seen people go overboard within the MEMORY {} declaration, defining all sorts of custom regions.
One common usage for this is when its multi-core and you want to express only a PORTION of DRAM or SRAM as a shared region.
But even that could be done in the lower portion OUTSIDE the MEMORY {} declaration.

-Chuck J.

-----Original Message-----
From: Andy Ross [mailto:andrew.j.ross(a)intel.com]
Sent: Wednesday, January 04, 2017 9:04 AM
To: Tidy(ChunHua) Jiang <tidyjiang(a)163.com>; devel(a)lists.zephyrproject.org
Subject: [devel] Re: Linker Script Issue When Porting To CC2538

Tidy(chunhua) Jiang <tidyjiang(a)163.com> wrote (on Tuesday, January 03, 2017 10:59PM):
I'm porting zephyr to TI's CC2538 device family, but there is a
special user case -- customer configuration area(CCA/CCFG). CCA is
placed in the uppermost flash page, so the linker script would like
this:

MEMORY
{
FLASH (rx) : ORIGIN = 0x00200000, LENGTH = 0x0007FFD4
*FLASH_CCA (rx) : ORIGIN = 0x0027FFD4, LENGTH = 0x2C*
SRAM (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE
SYSTEM_CONTROL_SPACE (wx) : ORIGIN = 0xE000E000, LENGTH = 4K
SYSTEM_CONTROL_PERIPH (wx) : ORIGIN = 0x400FE000, LENGTH = 4K
}

Zephyr doesn't really have a facility for device-specific modifications to linker scripts at the moment. The script that you would need to modify is in include/arch/arm/cortex_m/scripts/linker.ld. This is passed through the C preprocessor and has access to all Kconfig symbols, so if you had to you could #ifdef your changes there and submit them, but it would be a little ugly and we should probably come up with something cleaner.

Do you really need to do this with the linker? What are you trying to place in this region? If it's a fixed set of data you could just do it something like:

struct cca_rec {
int my_field1;
char my_field2[128];
/* ... */
};

#define CCA_REC ((struct cca_rec *)0x0027ffd4)

And then just dereference the symbols you would have put in that region with CCA_REC->my_field1, etc...

It's much simpler to implement, and might do what you want without requiring immediate surgery to our linker script generation.

Andy


Tidy(ChunHua) Jiang <tidyjiang@...>
 

Hi Andy,

Yes, your idea might ok, I'll try it this night.

Do you really need to do this with the linker? What are you trying to place in this region? If it's a fixed set of data you could just do it something like:

struct cca_rec {
int my_field1;
char my_field2[128];
/* ... */
};

#define CCA_REC ((struct cca_rec *)0x0027ffd4)

Hi Chuck,
Thanks for your information.


Best Regards,
Tidy.