3
\$\begingroup\$

There are no answers to this on the internet that I could find, and I've looked twice over the last 4 months.

In MPLab v8.88 using the Hi-Tech ANSI C Compiler, I have this line of code:

const   uint8 SUM_THRESHOLD_MIN = 15;   /* comment edited out   */

and I get the warning:

Warning [364] C:\*directory edited out* \ *filename_edited_out*.c; 273.35 attempt to modify object qualifed const

(excuse the edits, but I felt I should edit out personal yet superfluous details).

It is not my code, and I'd just use a #define, but others want to use a const (for those that don't know: using a const guarantees a proper typecast of a value, and can save you from some weird issues related to typecasting and data types; it's not my favorite way of doing it, but it's not a bad idea either).

There are several const initializations happening in the same block of code, and they all give me this warning. They are in a .c file, in a void function. I have other files with void functions where I initialize const uint8's and there are no warnings in those files. I searched globally, and found no other instance of the variable except where it gets used in the void function (so there aren't any issues with redefining or anything like that). To be clear, these const's are not part of any structure or anything strange, they are just declared in the void function in the .c file.

I have uint8 properly typedef'd, and not #define'd (see comments).

Can someone help me get rid of this warning?

EDIT: If I paste one of the const uint8's into another .c file directly after a const uint16 that doesn't throw the error, like this:

const uint16 rate_bias_time_constant[NUM_RATE_CHANNELS][RATE_BIAS_STEP_MAX] = 
    {30,120,480,960,  300,120,180,240,  300,120,180,240 }; // comment edited out
const   uint8 SUM_THRESHOLD_MIN = 15;   /* comment edited out   */

I get warning 364 in this file for this const uint8 but not for the const uint16. If I change SUM_THRESHOLD_MIN from a uint8 to a uint16, I still get the warning. For completeness, if I change it from all uppercase to all lower case, I still get the warning. If I change the line to, e.g.:

const uint8 SUM_THRESHOLD_MIN[2] = {15,2};  /* comment edited out   */

There is no warning.

\$\endgroup\$
  • \$\begingroup\$ Is uint8 a proper typedef or just a #define? \$\endgroup\$ – Dave Tweed Sep 24 '13 at 19:30
  • \$\begingroup\$ The code says: "typedef unsigned char uint8;" and in a different file there are const int16's and uint8's initialized the same way with no warnings. \$\endgroup\$ – Bob Sep 24 '13 at 19:34
  • \$\begingroup\$ Is that piece of code in a header (.h) file which maybe is included multiple times in a .c file? \$\endgroup\$ – m.Alin Sep 24 '13 at 19:52
  • \$\begingroup\$ Is the line of code inside a function or outside of a function? \$\endgroup\$ – Joe Hass Sep 24 '13 at 19:56
  • 1
    \$\begingroup\$ You should provide more info (the whole .c module) if you want good answers. \$\endgroup\$ – m.Alin Sep 24 '13 at 20:28
2
\$\begingroup\$

I got it, and thanks so much for everyone's help!

The declarations that are not throwing warnings are either arrays, or they are declared static const uint8/16's. For some reason, the Hi-Tech C compiler is fine with const int/char's, const uint8/16's that are arrays, but not const uint8/16's unless declared as static const uint8/16.

\$\endgroup\$
2
\$\begingroup\$

You should appreciate that due to the odd architecture of the PIC16/18, a "const" qualifier is an instruction to place that variable in Flash instead of RAM, not an instruction to tell the compiler that it's not allowed to be changed.

If you're trying to initialise the value of an auto variable that's local to a function then you ARE trying to change it at run-time because it's going to try to write that initialisation value to the variable (which is stored in Flash and is therefore not (easily) writable) every time the function executes. The reason it works when the variable is declared static is because static variables that are local to functions are only ever initialised once, so there is no logical inconsistency for the compiler to whine about. My guess is that the const arrays are being treated in the same way.

\$\endgroup\$
  • \$\begingroup\$ This doesn't explain why when you use a char or int as opposed to int16/8 or uint16/8 it doesn't throw the same warning, but does have the potential to explain why globally scoped const int16/8's weren't giving the error. It's a weird, compiler specific issue. Are you sure these are placed in flash? I keep wondering about that for the PIC, and went through some disassembly once, but never was 100% on it. I thought the Pics had code space and memory space, and instructions were 14 bits long or something weird like that... \$\endgroup\$ – Bob Sep 26 '13 at 12:21
  • 1
    \$\begingroup\$ PIC16's have 14-bit flash (6-bit opcode, 8-bit operand); PIC18's have 16-bit flash. Both store const variables in flash; some PIC16 compilers can be told to pack strings 2x7-bit into each 14-bit word, which can make it hard to read when debugging. Both families have completely seperate code and data spaces; read the memory chapters of any PIC16/18 datasheet for a good explanation. I can't explain the "int/char works, int8/int16 doesn't" problem, that doesn't make sense at all - however you choose to describe a char, the compiler should behave exactly the same way. \$\endgroup\$ – markt Sep 27 '13 at 7:44
  • \$\begingroup\$ It occurred to me that the reason the auto const arrays weren't throwing errors is because a const char[] is actually a const char *; the pointer resides in ram and the data it references resides in flash. The pointer can be re-written (to point to the same object in flash) every time the function executes without causing any issues. Also, you could try resolving the char-v-uint8 issue by using a #define instead of a typedef. \$\endgroup\$ – markt Sep 28 '13 at 21:53
0
\$\begingroup\$

I think the root problem is your expectation of how CONST works with this compiler on this processor. These things are not variables as you seem to be expecting from your description. They are very likely implemented as constants in program memory, which is essentially read-only. These things can't be changed at run time. The error you are getting is probably related to runtime code attempting to write to the CONST, not the definition of the CONST.

\$\endgroup\$
  • 1
    \$\begingroup\$ None of which explains why it works some places in his project, but not others. \$\endgroup\$ – Dave Tweed Sep 25 '13 at 13:53
  • 1
    \$\begingroup\$ He's not trying to change the value, though. You're allowed to initialize a const; it's rather useless if you couldn't. \$\endgroup\$ – user28910 Sep 25 '13 at 13:57
  • \$\begingroup\$ @Dave: It might be that he only tries to assign to the CONST at run time in the modules that fail. \$\endgroup\$ – Olin Lathrop Sep 25 '13 at 13:58
  • \$\begingroup\$ @user: It's not at all clear that he isn't trying to change the value at run time. \$\endgroup\$ – Olin Lathrop Sep 25 '13 at 13:59
  • 2
    \$\begingroup\$ We are not changing the value at run time. The warning points to a line of code, and that line is the declaration of the const. \$\endgroup\$ – Bob Sep 25 '13 at 14:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.