CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

const and extern

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
allenhuffman



Joined: 17 Jun 2019
Posts: 552
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

const and extern
PostPosted: Fri Feb 26, 2021 1:39 pm     Reply with quote

I recently ran in to a bug where a memcpy() was doing things in the wrong order, such as:

Code:

memcpy (&defaultData, myData, sizeof(myData));


It looks like the code's intent was to copy default values over into a working structure, but the destination/source was reversed so it was overwriting the defaults.

Using the const keyword can make compilers catch such accidents, but I get a linker error when trying to extern the const in a header file, such as:

Code:

HEADER FILE:

typedef struct
{
     int a,b,c;
} MyStruct;
...

extern const MyStruct defaultData;


SOURCE FILE:

const MyStruct defaultData=
{
   1, 2, 3
};


But I get a linker error on the CCS compiler, in my case complaining about "const1464" (did not appear anywhere in the map/list file). I feel like I've been down this path before, since I found I already had a C test program called ExternConst where I was doing this on a PC using GCC.
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Sat Feb 27, 2021 2:31 am     Reply with quote

Thing is that const in CCS has a fundamentally different meaning to
const in GCC.

Const in ANSI C implies a standard variable that is designed so it should
not allow writes to it. So defining as const still has you using what is a RAM
based variable.
Const in CCS implies a 'variable' stored in the program memory, which in the
PIC is a different memory space to the RAM.

I'd have expected what you want to work, provided you select ANSI mode, or
CONST=READ_ONLY which should switch const to behaving like the ANSI
form.
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Sat Feb 27, 2021 5:39 am     Reply with quote

And if you need "const" for actual constant data somewhere else, you can alternatively use the _readonly keyword as a replacement for the const you are normally used to.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Feb 27, 2021 10:56 am     Reply with quote

I've always wondered how much 'overhead' is involved in making any variable like RAM or EEPROM 'read only' aka 'constant' ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Sun Feb 28, 2021 1:49 am     Reply with quote

I think it depends enormously on what chip is involved.
On most compilers, the 'const' declaration only affects the compile, not
the running code. It simply sets a flag so that if at any point in the code,
a call is made that potentially writes to the 'const', it raises an error for this.
Most don't/can't go further than this.
You can actually do things like pointer accesses and change a const,
on a lot of compilers.
Now a few chips do have hardware that can physically protect areas of
memory, and in some cases the const declaration instead uses this. This
does impose in some cases a lot of overhead.
Now the different CCS usage, is not a case of CCS being awkward. They used
const for the ROM, long before ANSI C used it. It is perhaps a pity that
the ANSI committee didn't elect to use a different keyword, like 'protected'
(which would better describe what const involves in this language), or
'unwritable'.
In the CCS 'const' use, the overhead depends on the chip version. On
the PIC16's, the program memory, only supports 14bit, so storing values
as const, adds extra maths to calculate where you are actually talking to,
and performing either RETLW instructions (which is a very efficient way
of retrieving simple values on these - on the early chips, the only way
of doing this), or the program memory read operation (which involves
several instructions more than a simple RAM read). On the PIC18's things
get easier. Unfortunately things get harder again on the PIC24/30/33,
though using PSV gets rid of this overhead (though there is a timing cost),
but restricts how much data can be stored, and uses more ROM space.
allenhuffman



Joined: 17 Jun 2019
Posts: 552
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Mar 02, 2021 10:11 am     Reply with quote

Ttelmah wrote:

On most compilers, the 'const' declaration only affects the compile, not
the running code. It simply sets a flag so that if at any point in the code,
a call is made that potentially writes to the 'const', it raises an error for this.


This is exactly what I wanted this for. To catch an attempt to memcpy to data that was supposed to be the source. Smile
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
allenhuffman



Joined: 17 Jun 2019
Posts: 552
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Fri Apr 30, 2021 9:19 am     Reply with quote

temtronic wrote:
I've always wondered how much 'overhead' is involved in making any variable like RAM or EEPROM 'read only' aka 'constant' ?


I am curious too. Arduino has the "PROGMEM" stuff which puts variables in program space, and generates special code to access them (I dove in to these on a blog post one - https://subethasoftware.com/2014/02/20/arduino-memory-and-optimizations/).

Ideally I'd like constant data to be in program space, but it looks like I can't pass them in to functions (?) without the trick that copies them into RAM. Is there some kind of ROM Ptr equivalent in this CCS PIC world?

In my case, we have a runtime structure like this:

Code:

typedef struct
{
     int Setting1;
     int Setting2;
} RuntimeStruct;


And we have an image in memory declared like this:

Code:

RuntimeStruct g_Runtime =
{
   0,
   0
};


But if that needs to be reset to defaults, we also have a default declaration like:

Code:

RuntimeStruct g_RuntimeDefaults =
{
   42,
   1955
};


When that needs to be reset, there is a memcpy (&g_Runtime, &g_RuntimeDefaults, sizeof(g_Runtime));

I was looking for a simple way to make g_RuntimeDefaults const so it could not be changed, since the original code bug I found had those src/dst parameters reversed and it was wiping out the default values instead of restoring to defaults.
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 30, 2021 10:51 am     Reply with quote

allenhuffman wrote:
Is there some kind of ROM Ptr equivalent in this CCS PIC world?

It's in the CCS manual:
Quote:

Type Qualifiers (page 44):

rom - Forces data into program memory. Pointers may be
used to this data but they can not be mixed with RAM pointers.

[PCD] roml - Same as rom except only the even program memory locations are used.

and:
Quote:

Using Program Memory for Data (page 48):

A special method allows the use of pointers to ROM. This method
does not contain extra code at the start of the structure, as does const.
For example:
char rom commands[] = {“put|get|status|shutdown”};

[PCD] ROML may be used instead of ROM if you only to use even memory locations.

CCS manual:
https://www.ccsinfo.com/downloads/ccs_c_manual.pdf
allenhuffman



Joined: 17 Jun 2019
Posts: 552
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Fri Apr 30, 2021 12:40 pm     Reply with quote

Thanks -- I did quite a bit of experimenting with those last year. In case anyone else pops in to this, here's a test program I wrote testing rom versus const and such. It showed how to make a RAM variable (structure) that could contain pointer to constant data, and pass that around, and read that constant data in the function.

Is there a better approach?

Code:
#include <main.h>

#include <stdint.h>

rom BYTE TABLE1[10] = {1,2,3,4,5,6,7,8,9,10};
rom BYTE TABLE2[10] = {11,12,13,14,15,16,17,18,19,20};
rom BYTE TABLE3[10] = {21,22,23,24,25,26,27,28,29,30};


const uint8_t data1[] = { 1,2,3,4,5,6,7,8,9,10 };
const uint8_t data2[] = { 11,12,13,14,15,16,17,18,19,20 };

typedef struct
{
   int x,y;
   const uint8_t *ptr;
} MyStruct;

MyStruct one = { 1, 2, data1 };
MyStruct two = { 3, 4, data2 };


void show(MyStruct temp)
{
   printf ("%d, %d - ", temp.x, temp.y);
   for (int i=0; i<10; i++)
   {
      unsigned int value = temp.ptr[i];
      printf ("%u ", value);
   }
   printf ("\r\n");
}


const int Test[] = { 1, 2, 3, 4, 5 };

void main()
{
   printf (__DATE__" "__TIME__"\r\n");

   printf ("&data1  = 0x%x\r\n", &data1);
   printf ("&data2  = 0x%x\r\n", &data2);

   printf ("one.ptr = 0x%x\r\n", one.ptr);
   printf ("two.ptr = 0x%x\r\n", two.ptr);
   

   show(one);
   show(two);

   printf ("sizeof(Test) = %u\r\n", sizeof(Test));
   
   while(TRUE);

   // SECOND TEST - edit as needed.

   printf ("&TABLE1 = 0x%x\r\n", &TABLE1);
   printf ("&TABLE2 = 0x%x\r\n", &TABLE2);
   printf ("&TABLE3 = 0x%x\r\n", &TABLE3);

   rom BYTE *Ptr = &TABLE2;

   printf ("Ptr      = 0x%x\r\n", Ptr);

   for (int idx=0; idx<10; idx++)
   {
      unsigned int value = Ptr[idx];
      printf("%d. %u\r\n", idx, value);
   }

   while(TRUE); // CCS compiler #define
}

// End of main.c

_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
allenhuffman



Joined: 17 Jun 2019
Posts: 552
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Fri Apr 30, 2021 12:45 pm     Reply with quote

And for future reference -- this was a test program showing how to pass a ROM pointer in to a function:

Code:
#include <main.h>
#include <stddef.h> // NULL

#if 1
// Store this in ROM.
const int8 data1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
const int8 data2[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
#else
extern const int8 data1[];
extern const int8 data2[];
#endif


void function(rom int8 *ptr, int size)
{
   printf ("function( 0x%x, %d)\r\n", ptr, size);
   
   if (ptr != NULL)
   {
      for (int idx=0; idx < size; idx++)
      {
         // Load value from ROM.
         int8 value = ptr[idx];
         printf ("%d ", value);
      }
      printf ("\r\n");
   }
}

void main()
{
   printf (__DATE__" "__TIME__"\r\n");

   // Show direct data.
   printf ("data1 at 0x%x:\r\n", data1);
   for (int idx=0; idx < sizeof(data1); idx++)
   {
      printf ("%d ", data1[idx]);
   }
   printf ("\r\n");

   printf ("data2 at 0x%x:\r\n", data2);
   for (int idx=0; idx < sizeof(data2); idx++)
   {
      printf ("%d ", data2[idx]);
   }
   printf ("\r\n");


   // Call function.
   function (data1, 10);

   function (data2, 10);

   while(TRUE) // CCS compiler #define
   {
      //TODO: User Code
   }
}

// End of main.c


_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group