Handling Constant Data In The Keil C166 C Compiler
|< back

In any embedded system, substantial amounts of constant data will be required. This can range from look-up tables to character strings used in printf ("Hello") statements. Naturally, constant data should be placed into ROM in a true embedded system.

Constant data can be near, far, huge and xhuge like variables and the memory model controls which is used in the same way. Thus a SMALL model program will have all its constant data placed into a near constant area and an HLARGE program have it in a huge constant area.

As with variables, it is possible to override the default placement of constants:

Example 1

#pragma LARGE int near const constant_data = 0x20 ; // Put this in the NCONST class

Example 2

#pragma SMALL int const huge constant_array[] = { 0x20,0x20,0x34,0x89... } ; // Put this in HCONST class

Example 3

#pragma SMALL int const xhuge constant_array[] = { 0x20,0x20,0x34,0x89... } ; // Put this in XCONST class

The most common use of const is to define constant strings and look-up tables. Note that any string in a printf("string") statement will end up in the near (NCONST) or huge (HCONST) area, depending on the memory model. This can have some unexpected side effects, particularly in the following situation:

#pragma SMALL char const *messages[] = {"hello", "guten tag","bonjour","gooday"} ;

Here, some constant strings are created and placed into the NCONST class, as would be expected under the SMALL memory model. An array of pointers to the strings are created in the default NDATA class and set to point at the strings.

In applications which have a great deal of constant strings like this, for example, where multiple languages have to be catered for on some sort of human interface, two problems may arise:

(i) The NCONST class is limited to a total size of 16kb
(ii) The pointers are created in RAM, which is not sensible as the strings are in EPROM and so unlikely to move at run time!
(iii) Each string will absorb two bytes of NDATA RAM. As NDATA is limited to 16k in size also, it would be very easy to use up this precious fast RAM.

Problem (iii) can be solved by making use of a little known backwater of the C language which says that the region between the asterisk and the pointer name specifies where the pointer itself with be located. Thus:

#pragma SMALL char const * const messages[] = {"hello", "guten tag","bonjour","gooday"} ;

Will move the pointers to the NCONST class, so freeing up NDATA RAM.

Problem (i) can be eliminated by changing the memory model to HLARGE so that the strings now move to the HCONST class, which has a theoretical size limit of 64K.

#pragma HLARGE char const huge * const huge messages[] = {"hello", "guten tag","bonjour","gooday"} ;|

The "huge" attribute is really superflouous here as the HLARGE memory model makes it the default attribute. Now, both the pointers and the strings are in the HCONST class.

A final point is that if the strings exceed 64k in total size, the pointers need to be given the attribute "xhuge":

#pragma HLARGE char const xhuge * const huge messages[] = {"hello", "guten tag","bonjour","gooday"} ;|

Now, both the pointers and the strings are the huge (HCONST) area but the pointers themselves are of type xhuge and so can point at any address. Therefore for programs with very large quantities of constant strings, this is the recommended approach.

Send me more information on the above