Hello Freescale,
I have a question as title. Here is my case, in S12 PRM file, a flash section is allocated at 0xC000 area, and in code, I want to do a flash checksum checking using the address. I think the compiler can use a symbol in C code to refer or extern to the absolute address in PRM file, in stead of re-define this address in C code. I see TI MCU compiler has this usage, an address symbol can be defined in its memory control file, and it can be used in C.
In following example, how to reference ROM_C000_Start, ROM_C000_End and Rom_Cs_Word?
project.prm:
SEGMENTS
... ...
ROM_CS = READ_ONLY 0xC000 TO 0xC001;
ROM_C000 = READ_ONLY 0xC002 TO 0xEFFF;
... ...
END
PLACEMENT
... ...
APP_ROM INTO ROM_C000
... ...
END
C code:
void Startup (void)
{
U16 cs;
cs = Checksum_CheckAreaWordAdd (ROM_C000_Start, ROM_C000_End);
if (cs != *(U16 *) Rom_Cs_Word)
{
for(;;);
}
... ...
}
Regards,
dp
There are linker predefined symbols __SEG_STARTxxxx and __SEG_ENDxxxx. But these don't work with entries from SEGMENTS. They work with entries from PLACEMENT
extern char __SEG_START_APP_ROM[]; // have to be extern array of charss
extern char __SEG_END_APP_ROM[]; // -"-
void *start, *end;
start = &__SEG_START_APP_ROM; // yes, address of "address"
end = &__SEG_END_APP_ROM; // -"-
start and end will be NULL, if there's no APP_ROM PLACEMENT, or if there's nothing placed to APP_ROM.
Thanks Edward, your answer partly helped me, but not completely.
in my project, I have a ROM header table allocated in application code, but used in bootloader project for power on flash test.
see below to know the table content:
PRM file:
SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */
/* non-paged FLASHs */
ROM_CS = READ_ONLY 0x1400 TO 0x1401; // App code checksum
ROM_1400 = READ_ONLY 0x1402 TO 0x1FFF;
ROM_4000 = READ_ONLY 0x4000 TO 0x7FFF;
ROM_ENTRY = READ_ONLY 0xC000 TO 0xC06F;
ROM_VECTORS = READ_ONLY 0xC070 TO 0xC0FF;
ROM_C000 = READ_ONLY 0xC100 TO 0xEFFF;
ROM_F000 = READ_ONLY 0xF000 TO 0xFEFF; /* Bootloader preserved */
END
PLACEMENT
_PRESTART, /* Used in HIWARE format: jump to _Startup at the code start */
STARTUP, /* startup data structures */
ROM_VAR, /* constant variables */
STRINGS, /* string literals */
VIRTUAL_TABLE_SEGMENT, /* C++ virtual table segment */
//.ostext, /* OSEK */
NON_BANKED, /* runtime routines which must not be banked */
COPY /* copy down information: how to initialize variables */
/* in case you want to use ROM_4000 here as well, make sure
that all files (incl. library files) are compiled with the
option: -OnB=b */
INTO ROM_1400, ROM_4000;
DEFAULT_ROM INTO ROM_C000, PAGE_08, PAGE_09, PAGE_0A, PAGE_0B, PAGE_0C, PAGE_0C_A000, PAGE_0E;
END
CHECKSUM
CHECKSUM_ENTRY
METHOD_ADD
OF READ_ONLY 0x4000 TO 0x7FFF /* ROM_4000 */
OF READ_ONLY 0xC000 TO 0xEFFF /* ROM_C000 */
//OF READ_ONLY 0x88000 TO 0x8bfff /* PAGE_08 */
INTO READ_ONLY 0x1400 SIZE 2
UNDEFINED 0xff
END
END
in Application code, main.c, the ROM header structure is defined as below,
typedef struct SECTION_HEADER_TYPE_TAG{
//U32 Startup; /* _Startup entry address, must be in local flash */
U32 Rom_Begin; /* ROM beginning address to calculate checksum */
U32 Rom_End; /* ROM end address to calculate checksum */
U16 Rom_Cs_Addr; /* ROM checksum address, local flash */
struct SECTION_HEADER_TYPE_TAG const* Next_Section_Header;
}SECTION_HEADER_TYPE;
#pragma CONST_SEG APP_ROM_ENTRY
extern char __SEG_START__PRESTART[];
extern char __SEG_END_DEFAULT_ROM[];
#define ROM_SECTION_1400_START 0x1400UL
#define APP_ROM_CS_ADDR ROM_SECTION_1400_START
const SECTION_HEADER_TYPE App_Section_Header /*@ROM_SECTION_C000_START*/ =
{
(U32)__SEG_START__PRESTART,
(U32)__SEG_END_DEFAULT_ROM,
APP_ROM_CS_ADDR,
NULL,
};
in the map file, I can see the address lables generated as below:
- LABELS:
__SEG_START__PRESTART 1402 0 0 2
__SEG_END_DEFAULT_ROM C410 0 0 2
as you see, I can resolve Rom_Begin, but for Rom_End, I want it at 0xEFFF, as it defined in CHECKSUm, but compiler gives it the dynamic address decided by code size,
also it can't resolve Rom_Cs_Addr, because it's not used in App code, there is no placement name for it.
I knew __SEG_xxx won't help you. Unfortunately CW doesn't have means to determine in the code the start and end of particular PRM SEGMENT, only start and end of PLACEMENT, where end depends on the size of placed stuff.
This is also why I'm not using PRM CHECKSUM feature. Looks great until you try to use it for anything else than code checksum. I think that either CHECKSUM should be able to crc from __SEG_START to __SEG_END, or there need to be some other linker defined symbols for start and end of PRM SEGMENT or PRM defined top of PLACEMENT. If you need this feature, then you may like to make service request asking for this feature.
Regards
Edward