Hello,
I really need your help.
I want to reinit all global initialized variables in my C-Sourcecode again after start of the S12P microcontroller (like "int example = 8").
I thought I would know how to do this, but I have lots of problems.
The only thing I need to know is the adress in ROM where the initial values are stored, right?
After I know that, I would be able to write a function to get these values again and reinitialize the variables any time I want to... thats my plan, if you have better suggestions tell me please.
I read the linker manual today and thought the adress of my global initialized data is representated by .copy, so the ELF name is COPY.
Problem: I always get a linker warning that there is no information about the segment COPY !?
My prm-file looks like:
PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */
_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_C000/*, ROM_1400, ROM_4000*/;
DEFAULT_ROM INTO PAGE_08, PAGE_09, PAGE_0A, PAGE_0B, PAGE_0C, PAGE_0C_A800, PAGE_0E ;
//.stackstart, /* eventually used for OSEK kernel awareness: Main-Stack Start */
SSTACK, /* allocate stack first to avoid overwriting variables on overflow */
//.stackend, /* eventually used for OSEK kernel awareness: Main-Stack End */
DEFAULT_RAM INTO RAM;
//.vectors INTO OSVECTORS; /* OSEK */
END
What I do in the Sourcecode (like the example in the linker manual):
char *test;
#define __SEG_START_REF(a) __SEG_START_ ## a
#define __SEG_START_DEF(a) extern char __SEG_START_REF(a) []
__SEG_START_DEF(COPY);
test= (char*)__SEG_START_REF(COPY); /* this should be the startaddress of the segment COPY! */
If I try to do the same with SSTACK instead of COPY, everythings ok and I DO get the begin of the stack at the address 0x2800!
Where's the failure???
Thanks for any hints!
fireas
Solved! Go to Solution.
I would recommend to export the Init method from start12.c and not to use the C implementation.
Having 2 implementations of the startup code just wastes memory. Also the start12.c version is optimized and the provided C version lacks to initialized zero initialized areas, that would need to be added.
About the warning, the struct has a different size depending on some macros.
In Start12.c I see:
> #define __NO_FLAGS_OFFSET /* we do not need the flags field in the startup data descriptor */
> #define __NO_MAIN_OFFSET /* we do not need the main field in the startup data descriptor */
> #define __NO_STACKOFFSET_OFFSET /* we do not need the stackOffset field in the startup data descriptor */
If those macros have to be consitently defined before start12.h is included as that file conditionally adds some fields. Make sure the _startupData is only defined once (keep the definition in start12.c). It is probably not the best idea to define those macros in a C file (start12.c) but I guess this was done to share the start12.h definition while allowing to define those fields per project. If you want to include start12.h from multiple files I would move those defines into a common header which then includes start12.h.
Daniel
Isn't it simplier and better to reset CPU (using COP reset or if available, illegal address access reset)? I'm not sure it is safe to reinitialize only variables.
Hi again,
thanks for all the posts, very good ideas!
The following days I will try what's the best solution for me and give you a feedback next week.
@ kef: It's simpler, but in my case the worst I could do...
"Why? That is how you do it no matter application. You reset the CPU. If the CPU for some reason can't be reseted, then the design is seriously flawed. Because any program can get a reset at any time: watchdog, low-power/powerloss, illegal instruction, clock failure, user reset, external reset signal, external noise etc etc.
You can't design with the assumption "my processor will never be reseted"."
Based on my description you can't assume that my processor will never be reseted.
It will be reseted in lots of cases (and if faults appear)!
To give you a simple example in which case variables have to be reinitialized again:
Think about various tests for example at startup. After some of them you can't ensure that the variables needed for the following application haven't been modified. So the only way to fix this is to get the values of the rom and initialize these variables again (if they are global and in different files it's not very practicable and also not safe to do this manually).
Further Questions or hints?
#include "start12.h" #pragma CODE_SEG CODE_ROM void copyDown (void) { _Copy* ptr = _startupData.toCopyDownBeg; while(ptr->size > 0) { unsigned char* dest = ptr->dest; unsigned char* source = (unsigned char*)(ptr+1); unsigned int i; for(i=0; isize; i++) { dest[i] = source[i]; } ((unsigned char*)ptr) = source + i; } } #pragma CODE_SEG DEFAULT
I tried all suggestions today, but the only working way is to misuse the Init() function from "start12.c" again before the application is running.
Thats not my preferred solution....
@ lundin: I also tried to do it like in your source-code. Something like this I also have found in the "build tools utilities manual", chapter 7 "program startup". But I have only problems:
Warning : C3801: Segment already used with different attributes
Warning : C4200: Other segment than in previous declaration
L1827: Symbol _startupData has different size in Start12.c.o (6 bytes) and main.c.o (12 bytes)
So, the struct has different bytes in the Init() function and if I use it in the main. Can someone explain whats wrong? Of course I could only use the first 6 byte (which have the same data but in another structure) but thats not the normal way, cause something seems to be wrong!?
Do I need other pragmas perhaps? I tried CODE_ROM and also NEAR_SEG STARTUP_DATA without improvement or other behaviour.
Thanks in advance
I only use the
#pragma CODE_SEG NON_BANKED
for ISRs, of course after them
#pragma CODE_SEG DEFAULT
I never had these warnings until trying to reinitialize the variables. So I thought perhaps the fault has to to with this fact.
The
extern _Copy* ptr = _startupData.toCopyDownBeg;
ends with errors.
struct _tagStartup _startupData; is enclosed in "startup12.c", I'd like to think that this is enough and I don't have to declare this again in my main.c? I already tried to to this (also with "extern") without improvement in behaviour.
bedevilled.
I would recommend to export the Init method from start12.c and not to use the C implementation.
Having 2 implementations of the startup code just wastes memory. Also the start12.c version is optimized and the provided C version lacks to initialized zero initialized areas, that would need to be added.
About the warning, the struct has a different size depending on some macros.
In Start12.c I see:
> #define __NO_FLAGS_OFFSET /* we do not need the flags field in the startup data descriptor */
> #define __NO_MAIN_OFFSET /* we do not need the main field in the startup data descriptor */
> #define __NO_STACKOFFSET_OFFSET /* we do not need the stackOffset field in the startup data descriptor */
If those macros have to be consitently defined before start12.h is included as that file conditionally adds some fields. Make sure the _startupData is only defined once (keep the definition in start12.c). It is probably not the best idea to define those macros in a C file (start12.c) but I guess this was done to share the start12.h definition while allowing to define those fields per project. If you want to include start12.h from multiple files I would move those defines into a common header which then includes start12.h.
Daniel
I think to use only a part of the start12.c file is in my case the happy medium
Thanks for the busy participation!
Hello fireas,
You can refer to startup structure "_startupData" in your code. It's initialized by the linker. See the "Build Tools Utilities" manual, section "Program Startup" for more information about this struct.
You have to import it form "start08.h"
Or you can call the startup function that inits variables "Init()" from Start08.c
In fact this function does:
1) zero out RAM-areas where data is allocated
2) init run-time data
3) copy initialization data from ROM to RAM
You have to change the function modifier (remove static) to use it in your module.
Stanish
Hi,
Take a look at the file Start12.c, there is a function inside
static void Init(void);
maybe this will help - this function already init your variables
at startup.
Regards,
IPA