const unsigned char changing value!

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

const unsigned char changing value!

2,099 Views
DRichards
Contributor III

Micro MC9S08LL8.

Using CodeWarrior 5.9.0

 

I have a program where a variable doesn't now need to change. If I leave the declaration as

 

     unsigned char proportional_band = 100;

 

then everything is fine and the value never changes. If I change the declaration to

 

     const unsigned char proportional_band = 100;

 

it starts off as 54, changes later to 123 and finally to 122.

Changing from char to short fixes the problem. What is going on?

Labels (1)
16 Replies

1,360 Views
pavel_sadek
NXP Employee
NXP Employee

HI

there is another option to place constant into flash memory - look into documentation of CW compiler

#pragma INTO_ROM

unsigned char proportional_band = 100;

This pragma forces the next (non-constant) variable definition to be const (together with the -Cc compiler option).

works for only one next variable as unsigned char proportional_band = 100; in this case

try it :smileyhappy:

Pavel

0 Kudos

1,361 Views
bigmac
Specialist III

Hello Pavel,

According to the compiler manual (CW 6.3), the pragma should actually be:

#pragma INTO_ROM

There are some additional associated notes -

"This pragma is only useful for the HIWARE object-file format (and not for ELF/DWARF)."

"...  This pragma was introduced to cheat the constant handling of the compiler, and shall not be used any longer.  It is supported for legacy reasons only."

Regards,

Mac

0 Kudos

1,361 Views
TICS_Fiona
NXP Employee
NXP Employee

Please open the MAP file and get the address of your const data 'proportional_band', it should locate in ROM. Then start debugging, and open Memory View and go to this address in ROM. Is the data at this address varying in debugger?

0 Kudos

1,361 Views
DRichards
Contributor III

Thank you all for responding.

@bigmac,

No, I do not get any warnings or errors.

There are three warnings disabled,

C2402:Variable <ident><State>

C3605: Runtime object'<Object>' is used at PC <PC>

C306: Initialising object '<Object>'

I believe these to be disabled by default. I did not disable them.

The variable is confined to main.c. There is no extern. Declaring it static makes no difference.

When not declared as const, the map file locates the variable in zero page.

When declared as const, the map file lists the variable under NOT USED VARIABLES in the UNUSED OBJECTS SECTION.

The debugger shows the address of the variable as 0x00. (Did not spot this before).

I tried making the variable a const short again and this time it didn't fix the problem.

@GUITTET JOEL

I first noticed the problem through the bad behaviour of the program. Then through debugging I found the value of the constant was changing in the debugger window.

@Jun Zhang

Sorry I cannot post any significant amount of code due to IP reasons.

I can understand the variable not showing up in RAM. After all I would expect it to be stored in ROM (being a constant). But, the program behaviour is showing that the value being used is wrong.

I already have a couple of look-up tables declared as const and these are under #pragma DATA_SEG DEFAULT i.e. not in zero page. Moving the variable from zero page to under the default RAM #pragma makes no difference though.

The look-up tables do have ROM addresses shown in the debugger.

Message was edited by: David Richards 26/6/13 09:04 Added information about look-up table locations.

0 Kudos

1,361 Views
bigmac
Specialist III

Hello,

David Richards wrote:

When not declared as const, the map file locates the variable in zero page.

When declared as const, the map file lists the variable under NOT USED VARIABLES in the UNUSED OBJECTS SECTION.

The debugger shows the address of the variable as 0x00. (Did not spot this before).

When the variable located in zero page RAM, unless you have specifically placed it there by means of a #pragma, this may indicate that your project is attempting to use the tiny memory model.  You should be using the small memory model.

For the const declaration case, an address of 0x0000 is certainly not within flash memory.  In fact it is the address of the Port A data register, and if this is what the debugger is monitoring, the value is obviously likely to change, depending on usage of Port A.

Even though the map file may list the variable as not (yet) used, the linker is likely to be allocating the variable, and its address needs to be confirmed.

Regards,

Mac

0 Kudos

1,361 Views
DRichards
Contributor III

The variable was placed in zero page by a #pragma, so this was expected. The small memory model is specified in the compiler command line arguments (-Ms).

prm file listed below.

------------------------------------------------------------------------------------------------------------------------------------------------------------

/* This is a linker parameter file for the mc9s08ll8 */

NAMES END /* CodeWarrior will pass all the needed files to the linker by command line. But here you may add your own files too. */

SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */
    NO_INIT_Z_RAM            =  NO_INIT      0x0060 TO 0x0061;
    Z_RAM                    =  READ_WRITE   0x0062 TO 0x00FF;
    RAM                      =  READ_WRITE   0x0100 TO 0x087F;
    ROM                      =  READ_ONLY    0xD800 TO 0xFFAD;
    ROM1                     =  READ_ONLY    0xFFC0 TO 0xFFD7;
/* INTVECTS                 =  READ_ONLY    0xFFD8 TO 0xFFFF; Reserved for Interrupt Vectors */
END

PLACEMENT /* Here all predefined and user segments are placed into the SEGMENTS defined above. */
    DEFAULT_RAM,                        /* non-zero page variables */
                                        INTO  RAM;

    _PRESTART,                          /* startup code */
    STARTUP,                            /* startup data structures */
    ROM_VAR,                            /* constant variables */
    STRINGS,                            /* string literals */
    VIRTUAL_TABLE_SEGMENT,              /* C++ virtual table segment */
    DEFAULT_ROM,
    COPY                                /* copy down information: how to initialize variables */
                                        INTO  ROM; /* ,ROM1: To use "ROM1" as well, pass the option -OnB=b to the compiler */

    NI_ZEROPAGE                         INTO  NO_INIT_Z_RAM;

    _DATA_ZEROPAGE,                     /* zero page variables */
    MY_ZEROPAGE                         INTO  Z_RAM;
END

ENTRIES
    credit  /* Force inclusion of unused variable */
END

STACKSIZE 0x50

VECTOR 0 _Startup /* Reset vector: this is the default entry point for an application. */

------------------------------------------------------------------------------------------------------------------------------------------------------------

I have two const unsigned char[] and one const unsigned short[] that are correctly being located in ROM.

From the map file,

     log_table                                 D892      22      34       5   .rodata    

     digit                                     D8B4       A      10       2   .rodata    

     credit                                    D8BE      2B      43       0   .rodata   

I have not run out of space. In fact I have recently reduced the code size by removing no longer needed functionality.

Also from the map file,

Summary of section sizes per section type:
READ_ONLY (R):        20CE (dec:     8398)
READ_WRITE (R/W):      118 (dec:      280)
NO_INIT (N/I):          9C (dec:      156)

It is just,

const unsigned char proportional_band = 100;

that is not getting alloccated anywhere.

bigmac wrote,

"Even though the map file may list the variable as not (yet) used, the linker is likely to be allocating the variable, and its address needs to be confirmed."

How can I tell if the linker is allocating the variable and where?

0 Kudos

1,361 Views
DRichards
Contributor III

I have just discovered that selecting "Disable CONST variable by constant replacement" (-OnCstVar) in the compiler options Optimisations menu allows for a correct compilation. This is strange as a replacement of a RAM variable that doesn't change with a ROM value shouldn't be a risky optimisation.

0 Kudos

1,361 Views
bigmac
Specialist III

Hello,

David Richards wrote:

I have just discovered that selecting "Disable CONST variable by constant replacement" (-OnCstVar) in the compiler options Optimisations menu allows for a correct compilation. This is strange as a replacement of a RAM variable that doesn't change with a ROM value shouldn't be a risky optimisation.

To quote from the ANSI-C Frontend section of the Compiler manual (CW 6.3) -

Constant-Variable Optimization

If a constant non-volatile variable is used in any expression, the Compiler replaces it by the constant value it holds.  This needs less code than taking the object itself.

The constant non-volatile object itself is removed if there is no expression taking the address of it.  ...  This results in using less memory space.

Global constant non-volatile variables are not removed.  Their use in expressions are replaced by the constant value they hold.

Constant non-volatile arrays are also optimised.

This may partly explain what you are observing, especially if the variable in question is declared within a function (perhaps main() ).  But it does not explain the corruption of your calculations - you may need to delve into the generated assembly code to see what is occurring.  Your use of the compiler option disable will be forcing the compiler to read the variable each time it is used, but should be unnecessary for correct operation.  If you globally define the constant variable, it should be listed within the map file.  Refer to "Object-allocation section" and "Object list sorted by address".

Your constant arrays are not removed presumably because they are globally defined.

Regards,

Mac

0 Kudos

1,361 Views
DRichards
Contributor III

The variable in question is declared in global space. I tried moving it to inside main, but this made no difference. The compiler will not allocate space and treats the variable as unused.

I now have two workarounds to the problem, remove the particular optimisation, or just don't declare the variable as const.

I am using CodeWarrior IDE version 5.9.0 as I am reworking a previous project and it doesn't make sense to update it. I hope the current version is OK. Thanks for all your help.

0 Kudos

1,361 Views
bigmac
Specialist III

Hello,

Yet another alternative would be to use a macro -

#define PROPORTIONAL_BAND  100

and then use PROPORTIONAL_BAND as required in each expression. (My personal preference is to use upper case for macro names to distinguish from variable names.)

Regards,

Mac

0 Kudos

1,361 Views
DRichards
Contributor III

Yes, this is the way I would do it starting from scratch. It was my laziness, not wanting to change all occurrances of proportional_band to PROPORTIONAL_BAND that caused me to try the const definition in the first place. By the way, the macro definition does work.

0 Kudos

1,361 Views
bigmac
Specialist III

Hello David,

The macro name may use upper or lower case - there is no compulsion to always use upper case.

If your macros were defined within a header file, another variation might be to use within that file -

#define PROPORTIONAL_BAND  100

Then at the beginning of any .c file where the constant was used, to incorporate the following -

#include macros.h

#define proportional_band  PROPORTIONAL_BAND

This should require minimal alteration to the project.

Regards,

Mac

0 Kudos

1,361 Views
DRichards
Contributor III

bigmac wrote:

Hello David,

The macro name may use upper or lower case - there is no compulsion to always use upper case.

Yes there is, company coding standards! :smileygrin:

0 Kudos

1,361 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

can you please upload your demo project so that we can work on it directly?

0 Kudos

1,361 Views
Joel69003
Contributor IV

Hi David,

Variable optimized out ? As said by bigmac, check map file.

When you are saying that the value is changing, how do you see it ? Is it throw the (bad) behavior of the application ? Or in the debugger (take care in this case, debugger issues are still possible :smileywink:) ?

Regards,

Joel Guittet

1,361 Views
bigmac
Specialist III

Hello,

Do you get any compiler or linker warnings, or error messages?  Does the variable also happen to be declared as an extern, within a header file?

Also check the map file for the project to confirm that the location of the variable is actually within flash memory. Then using the debugger, check the value at this location.


Regards,

Mac

0 Kudos