Hello,
I am using CW Version: 10.2 (Build Id:120126) for MPC5604P. I am in a need to place a variable in an uninitialized separate memory segment(mode_flag). For this i made following changes in my linker file
MEMORY
{
resetvector: org = 0x00000000, len = 0x00000008
init: org = 0x00000020, len = 0x00000FE0
exception_handlers: org = 0x00001000, len = 0x00001000
internal_flash: org = 0x00002000, len = 0x0007E000
internal_ram: org = 0x40000000, len = 0x00008000
heap : org = 0x40008000, len = 0x00001000
stack : org = 0x40009000, len = 0x00000FFC
mode_flag : org = 0x40009FFC, len = 0x00000004
}
GROUP : {
.mode_flag ALIGN (0x4) : {}
} > mode_flag
& in c file
#pragma section RW "mode_flag" ".mode_flag"
__declspec (section "mode_flag") uint32_t RespModeFlag;
With this modifications i am able to place the variable within the uninitialized segment created.
in .MAP file
.mode_flag section layout
Starting Virtual File
address Size address offset
---------------------------------
00000000 000004 40009ffc 000038a8 1 .mode_flag Diag.obj
00000000 000004 40009ffc 000038a8 4 RespModeFlag Diag.obj
As mentioned earlier this is an uninitialized segment, but after power on this segment is initialized to zero in "__asm void INIT_Derivative()" function. When checked with this function, instruction "li r12,320" which loads a fixed count for a loop to initialize the RAM. When count changed from 320 to 319 it works (As uninitialized segment is placed at the top of RAM/ last 4 bytes of RAM), but then it gets initialized in one of the library function "__init_bss_section".
It will be a great help if anyone suggest how to proceed in order to not to initialize the RAM segment after Power up.
Thanks & Regards,
Shrikant
Hello shrikant.oak,
I've resolved this issue via Service Request. I'm posting the answer for others that might be facing same or similar issue.
Actually there are several things that may modify the RAM section:
By decreasing the counter from 320 to 319 it causes the 32x4 = 128 Bytes of SRAM (from top of the ram) are not initialized. In this case ECC check exception might occurs if in case ECC check does not match.
Other solution could be to initialize entire SRAM only in case you suspect SRAM content might be corrupted (e.g. RGM.DES != 0)
e.g.:
__asm void INIT_Derivative(void)
{
…
// if (RGM.DES.R) init SRAM;
e_lis r8,0xc3fe
e_lhz r0,16386(r8)
se_cmpi r0,0
se_beq dont_init
/* MPC5602P SRAM initialization code */
lis r11,L2SRAM_LOCATION@h /* Base of SRAM, 64-bit word aligned */
ori r11,r11,L2SRAM_LOCATION@l
li r12,256 /* Loops to cover 32K SRAM; 32k/4 bytes/32 GPRs = 384 */
mtctr r12
init_l2sram_loop:
stmw r0,0(r11) /* Write 32 GPRs to SRAM */
addi r11,r11,128 /* Inc the ram ptr; 32 GPRs * 4 bytes = 128B */
bdnz init_l2sram_loop /* Loop for 32k of SRAM */
dont_init:
blr
Also it would be good to service an ECC generated exception properly.
To avoid zeroing of the memory section you need to customize the startup routine __init_data(). Since __init_data() routine is part of the standard library you can copy&paste its source form __start.c from "c:\Freescale\CW MCU v10.2\MCU\PA_Support\ewl\EWL_Runtime\Runtime_PA\Source\__start.c" to your project source directory and adapt it. The __init_Data() is defined as a weak symbol so your customized version should be used by the linker instead of the library version.
Let's consider a linker section e.g.:
MEMORY
{
resetvector: org = 0x00000000, len = 0x00000008
...
my_uninit_ram : org = 0x40004F00, len = 0x00000100
}
SECTIONS
{
...
.do_not_init (BSS) : {} > my_uninit_ram
}
And use the custom uninited section in the code:
#pragma section RW ".dummy" ".do_not_init"
__declspec (section ".dummy") uint32_t RespModeFlag;
Then adapt the startup routine, __start.c e.g.:
extern char _f_do_not_init[]; //import the linker sybol - start address of .do_not_init
…
extern void __init_data(void)
{
__rom_copy_info *dci;
__bss_init_info *bii;
/* Copy from ROM to RAM: */
dci = _rom_copy_info;
while (1) {
if (dci->rom == 0 && dci->addr == 0 && dci->size == 0) break;
__copy_rom_section(dci->addr, dci->rom, dci->size);
dci++;
}
/* Initialize with zeros: */
bii = _bss_init_info;
while (1) {
if (bii->addr == 0 && bii->size == 0) break;
// do not init the ".do_not_init" section, zero all remaining bss sections
if (bii->addr != _f_do_not_init) __init_bss_section(bii->addr, bii->size);
bii++;
}
}
init_ram 0x40000000 0x5000
See below snippet of tcl. file:
#################################
# Initialization for MPC5602P
#################################
proc mpc5602P_init {} {
reset hard
# Explicitly stop the core
stop
# Disable SWT Watchdog Timer
mem v:0xfff38010 = 0x0000c520
mem v:0xfff38010 = 0x0000d928
mem v:0xfff38000 = 0xff00000A
# core init
init_e200z0h
# initialize MPC5602P ECC SRAM 20K: 0x40000000 - 0x40005000
# comment this line to avoid ram init by the debugger init_ram 0x40000000 0x5000
}
Stanish
Thank you very much for sharing the code!
Hello Stanislav Sliva,
I am observing a strange behavior with the change in the INIT_Derivative function. The changes has been made exactly same as suggested in prior conversation.
Behavior is as below:
Is there anything else we need to take care of? Please suggest.
Thanks & Regards,
Shrikant
Hello Stanish,
This is exactly what i was looking for, & it's working fine at my end.
Thanks for in deatail suggestion!!
Regards,
Shrikant
It appears that your flag variable is a global, correct? Per the ELF and C specification, those wind up in the .bss section and get initialzed to zero. The dead giveway is that __init_bss_section gets involved. You might want to force the flag variable into the .data section. See this thread at Stackoverflow for more info:
http://stackoverflow.com/questions/3532334/how-about-bss-section-not-zero-initialized
---Tom
First of all thanks for the reply!!
Actually i am looking for a variable which should be placed in an uninitialized memory as well as this variable also uninitialized. The intention is after power up this RAM variable is not initialized to zero instead it should retain it's previous value before SW RESET.
Thanks & Regards,
Shrikant
Hello
The ANSI C standard expects all uninitialized variables to be set to 0 when function main is reached.
So the startup code we are providing is performing this initialization.
If you do not want this to happen the startup code needs to be modified.
First question is do you want this to happen to all uninitialized variables or only some of them?
Also if you decide to go this way you need to make sure your application does not assume some of the
uninitialized variables are initialized with 0.
CrasyCat