Declaring persistent variables?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Declaring persistent variables?

3,647 Views
BasePointer
Contributor II
Hi,
 
I'm new at CW and using MC9S08LC60. I generated ANSI compatiable start08.c that initializes all my variables to zero at start-up for my first project.
 
I need some persistent variables that are uninitialized during start-up. How can I declare such as variables in CW?
 
Thanks.

Message Edited by BasePointer on 2006-12-2903:02 PM

Labels (1)
Tags (1)
0 Kudos
10 Replies

572 Views
Alban
Senior Contributor II
Hello,
 
You can keep a variable between non-memory damaging resets by:
- creating a specific area in your PRM file that you will declared as NO_INIT.
- placing the variable in that area with a #PRAGMA data...
 
Subject already talked about. The search engine at the bottom of Forum pages would have given you the link (it's what I've just used).
 
The variable is not initialized.
BUT if you had a Low Voltage or Power-On Reset, for instance, its content WILL be damaged !!!
 
Cheers,
Alban.
 
PS: Please post CodeWarrior questions in CodeWarrior board.

Message Edited by Alban on 2006-12-29 07:00 PM

0 Kudos

572 Views
BasePointer
Contributor II
Sorry for the wrong place.
 
Here is my orginal prm file:
SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */
   ROM                      =  READ_ONLY    0x8000 TO 0xFFAF;
   Z_RAM                    =  READ_WRITE   0x0060 TO 0x00FF;
   RAM                      =  READ_WRITE   0x0100 TO 0x105F;
   ROM1                     =  READ_ONLY    0xFFC0 TO 0xFFD1;
   ROM2                     =  READ_ONLY    0x1870 TO 0x7FFF;
   ROM3                     =  READ_ONLY    0x1060 TO 0x17FF;
END

I want to declare 1024 byte as non-initialized. Here is modified prm file:
SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */
   ROM                      =  READ_ONLY    0x8000 TO 0xFFAF;
   Z_RAM                    =  READ_WRITE   0x0060 TO 0x00FF;
   RAM                      =  READ_WRITE   0x0100 TO 0x0C5F;
   NO_INIT_RAM              =  NO_INIT      0x0C60 TO 0x105F;
   ROM1                     =  READ_ONLY    0xFFC0 TO 0xFFD1;
   ROM2                     =  READ_ONLY    0x1870 TO 0x7FFF;
   ROM3                     =  READ_ONLY    0x1060 TO 0x17FF;
END

 
And here is my variable declaration in "nvram.c" module:
 
#ifndef NVRAM_C
#define NVRAM_C

#pragma DATA_SEG NO_INIT_RAM
TNode RestorePoint;
TNVRAM     NV;
#pragma DATA_SEG DEFAULT
 
#endif
Are all them correct?
 
Thank you for the help.

Message Edited by BasePointer on 2006-12-3012:13 PM

0 Kudos

572 Views
Alban
Senior Contributor II
Hello,

It looks fine to me.

I think you can also use

TNode RestorePoint @ 0x0C60;
TNVRAM NV @ 0x????;

instead of

#pragma DATA_SEG NO_INIT_RAM
TNode RestorePoint;
TNVRAM NV;
#pragma DATA_SEG_DEFAULT

But it is less flexible when you hard code the address in the source.
Still, be careful not to read the data as always being REAL, as when a RESET occurs and depending on its source it can mean the RAM has been corrupted.
I know I insist on this, but...
You can add a checksum in the value itself, so if the checksum is not verified it means the data is not to be taken into account and the software needs to take default values.

Cheers,
Alban.
0 Kudos

572 Views
Lundin
Senior Contributor IV
Edit: just realized that the OP is using S08 where you don't have a separate COP reset vector. This was written with S12 in mind. Oh well... :smileyhappy:


In fact, the only time you can trust those RAM cells is when you have received a watchdog reset. I would advice to do like this:

#pragma DATA_SEG NO_INIT_RAM
Type x;
#pragma DATA_SEG DEFAULT

...
BOOL trust_x;

#pragma TRAP_PROC
void interrupt_por (void) /* From $FFFE:FF Reset */
{
x = 0;
trust_x = FALSE;
...
}

#pragma TRAP_PROC
void interrupt_wdog (void) /* From $FFFA:FB COP failure reset */
{
if(x == something)
trust_x = TRUE;

}

int main()
{
if(trust_x)
use(x);
}

Message Edited by Lundin on 2007-01-0210:14 AM

0 Kudos

572 Views
BasePointer
Contributor II
Hi Alban,
 
All my non initialized variables contain a lot of frame checksum bytes due to POR and asynchronous reset.
 
Thank you for your reply.
0 Kudos

572 Views
BasePointer
Contributor II
Code:
typedef struct{ unsigned char Year; unsigned char Month; unsigned char Day; unsigned char Hour; unsigned char Minute; unsigned char Second;} TDate;typedef struct{ char  DOW; TDate   Date;}  TRTC;#pragma DATA_SEG NO_INIT_RAM  TRTC  RTC;  volatile signed char internal_second;#pragma DATA_SEG  DEFAULT

 
Hi,
 
I defined RTC variable in NO_INIT_RAM segment. But It lose its content such as second, minute at every reset(via the reset pin of the mcu) and start with zero.  I don't know what I'm doing wrong...
0 Kudos

572 Views
CrasyCat
Specialist III
Hello
 
Can you provide me with your .PRM file and the .map file from the application?
I need to check how the variable is allocated.
CrasyCat
0 Kudos

572 Views
BasePointer
Contributor II
Here is my prm file:
 
Code:
/* This is a linker parameter file for the LC60 */NAMES END /* CodeWarrior will pass ... *//*SEGMENTS     ROM                      =  READ_ONLY    0x8000 TO 0xFFAF;    Z_RAM                    =  READ_WRITE   0x0060 TO 0x00FF;    RAM                      =  READ_WRITE   0x0100 TO 0x105F;    ROM1                     =  READ_ONLY    0xFFC0 TO 0xFFD1;    ROM2                     =  READ_ONLY    0x1870 TO 0x7FFF;    ROM3                     =  READ_ONLY    0x1060 TO 0x17FF;END*/SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */    ROM                      =  READ_ONLY    0x8000 TO 0xFFAF;    Z_RAM                    =  READ_WRITE   0x0060 TO 0x00FF;    RAM                      =  READ_WRITE   0x0100 TO 0x0C5F;    NO_INIT_RAM              =  NO_INIT      0x0C60 TO 0x105F;    ROM1                     =  READ_ONLY    0xFFC0 TO 0xFFD1;    ROM2                     =  READ_ONLY    0x1870 TO 0x7FFF;    ROM3                     =  READ_ONLY    0x1060 TO 0x17FF;ENDPLACEMENT /* Here all predefined and user segments are placed into the SEGMENTS defined above. */    DEFAULT_RAM                         INTO  RAM;    DEFAULT_ROM, ROM_VAR, STRINGS       INTO  ROM; /* ROM1,ROM2,ROM3 In case you want to ... */    _DATA_ZEROPAGE, MY_ZEROPAGE         INTO  Z_RAM;ENDSTACKSIZE 0x50VECTOR 0 _Startup /* Reset vector: this is the default entry point for an application. */

 

Message Edited by BasePointer on 2007-01-0401:55 PM

0 Kudos

572 Views
CrasyCat
Specialist III
Hello
 
OK get it.
The PRM file is not correct. The user defined section NO_INIT_RAM  should be specified in the PLACEMENT block and allocated in a NO_INIT segment.
You have to modify your PRM file as follows:
 
Code:
/* This is a linker parameter file for the LC60 */NAMES END /* CodeWarrior will pass ... */SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */    ROM                      =  READ_ONLY    0x8000 TO 0xFFAF;    Z_RAM                    =  READ_WRITE   0x0060 TO 0x00FF;    RAM                      =  READ_WRITE   0x0100 TO 0x0C5F;    NO_INIT_RAM_SEG          =  NO_INIT      0x0C60 TO 0x105F;    ROM1                     =  READ_ONLY    0xFFC0 TO 0xFFD1;    ROM2                     =  READ_ONLY    0x1870 TO 0x7FFF;    ROM3                     =  READ_ONLY    0x1060 TO 0x17FF;ENDPLACEMENT /* Here all predefined and user segments are placed into the SEGMENTS defined above. */    DEFAULT_RAM                         INTO  RAM;    DEFAULT_ROM, ROM_VAR, STRINGS       INTO  ROM; /* ROM1,ROM2,ROM3 In case you want to ... */    _DATA_ZEROPAGE, MY_ZEROPAGE         INTO  Z_RAM;    NO_INIT_RAM                         INTO  NO_INIT_RAM_SEG;ENDSTACKSIZE 0x50VECTOR 0 _Startup /* Reset vector: this is the default entry point for an application. */

 
That should do it.
 
CrasyCat
0 Kudos

572 Views
BasePointer
Contributor II
Thanks CrasyCat,
This worked for me :smileyhappy:
0 Kudos