View previous topic :: View next topic |
Author |
Message |
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
Is it possible to initialize a volatile struct ? |
Posted: Tue Jan 10, 2017 2:10 pm |
|
|
I want to initialize some variables in a struct, for example:
Code: |
volatile struct GPRS{
short Configurado=false;
short ChkError=false;
short Responder=false;
short Reset=true;
char Step=0;
char Time=10;
}GPRS_Status;
|
But the compiler does not accept that code, which I understand, in C is possible.
This is so? Is it a compiler limitation or am I making a mistake? _________________ Electric Blue |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19561
|
|
Posted: Tue Jan 10, 2017 2:46 pm |
|
|
The initialisation has to be after the declaration:
Code: |
struct GPRS{
short Configurado;
short ChkError;
short Responder;
short Reset;
char Step;
char Time;
}GPRS_Status = {FALSE, FALSE, FALSE, TRUE, 0, 10};
|
Volatile does nothing in CCS. There is no support for variable protection (volatile in some C's adds the protection against reading/writing, when another part of the code may update the value - in CCS _you_ have to do this). |
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Tue Jan 10, 2017 2:57 pm |
|
|
Thanks for your fast and clear answer and I'm sorry, I forgot to make the question in English, my bad.
Can I omit some variables by doing something like?
Code: | ...
GPRS_Status = {FALSE, , FALSE, TRUE, , 10}; |
_________________ Electric Blue |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Tue Jan 10, 2017 3:37 pm |
|
|
Ttelmah wrote: |
Volatile does nothing in CCS. There is no support for variable protection (volatile in some C's adds the protection against reading/writing, when another part of the code may update the value - in CCS _you_ have to do this). |
I've run into two cases where PCD optimized out a global variable write that it decided wasn't needed. It's not a repeatable thing, but in both cases the volatile specifier prevented the optimization. Very difficult bugs to track down.
Still though, a very rare occurrence given how long I have been using PCD. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19561
|
|
Posted: Wed Jan 11, 2017 8:28 am |
|
|
Yes, that is a good point. Though CCS doesn't have any of the protection to prevent partial writes, specifying as volatile does ensure that it treats the variable as 'required'.
It'd be rather strange to omit an item from an initialiser list at declaration.
The can be done in C++, when you are passing a variable and want to only overwrite some items where the variable has already been filled, but would not be done at initial declaration. It's not a C feature though. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9253 Location: Greensville,Ontario
|
|
Posted: Wed Jan 11, 2017 9:10 am |
|
|
One possible problem with not declaring a variable, is that the 1st time you use it, it can have ANYTHING in it unless the 'ram_zero' is used....? |
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Wed Jan 11, 2017 2:10 pm |
|
|
So, if a variable is not initialized when is declared the compiler doesn´t initialize that variable not even to zero or false.
Is it CCS compiler behavior or any C/C++ compiler will do the same? _________________ Electric Blue |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Wed Jan 11, 2017 2:22 pm |
|
|
E_Blue wrote: | So, if a variable is not initialized when is declared the compiler doesn´t initialize that variable not even to zero or false.
Is it CCS compiler behavior or any C/C++ compiler will do the same? |
In the "raw" sense, most compilers will actually do the same. However you normally get a compiler packaged with an IDE or software suite where the vendor automatically provides the configuration and code to initialize variables, usually in some place you don't typically see.
GCC for example will do even less than CCS does if you just grab it and compile code for an ARM micro. You have to provide the code to clear the BSS section (uninitialized vars) and to copy data from ROM into the initialized variables. However, if you get Atmel Studio (which uses GCC), Atmel already has the code setup to do that and their project creation process puts the code into your project without you actually seeing it.
CCS does some things for you. If you compile an empty main but provide some #use statements and #fuses, then if you look under main in the LST file, you'll see that CCS does put in some initialization code. It doesn't clear the BSS automatically though. That's a good thing as sometimes you want to have an uninitialized variable (like if you want to retain a value between chip resets caused by an intentional software reset).
If you declare an uninitialized variable as static, I think it sets it to 0 for your though.
CCS doesn't refer to the sections as text, data, and bss like GCC does, but see the following for the concepts. Note that someone has to provide the code to handle these sections correctly...it is usually a vendor or the programmer:
https://mcuoneclipse.com/2013/04/14/text-data-and-bss-code-and-data-size-explained/
https://en.wikipedia.org/wiki/.bss |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Wed Jan 11, 2017 2:42 pm |
|
|
Side note on the "volatile" topic:
One very scary thing I found out about the uses of volatile from the C standard perspective:
So given the code:
Code: |
unsigned int8 bgetc(){
unsigned int8 val;
if(next_in != next_out){
val = buffer[next_out++];
next_out = next_out % BUFFER_SIZE;
}
buffer_was_read = TRUE; //a flag to indicate the read is done
return val;
}
|
Not that I would do it this way but for the sake of having an example. The C standard allows for a compiler to do optimizations so that instruction cache (on chips that have it) can be filled efficiently before being sent. One of these optimizations is the ability to move unrelated code around. CCS does not do this that I have seen (no instruction cache, so not necessary), but I have seen GCC do something like the following:
Code: |
unsigned int8 bgetc(){
unsigned int8 val;
buffer_was_read = TRUE; //a flag to indicate the read is done
if(next_in != next_out){
val = buffer[next_out++];
next_out = next_out % BUFFER_SIZE;
}
return val;
|
It might do something like this because it reached the end of an instruction cache and the "buffer_was_read = TRUE" line was enough to finish off the current cache before starting another. It found that buffer_was_read did not depend on any of the for loop code at all, so the move should be fine. From the programmer's perspective it may not matter or might be a bad bug.
The reason this relates to volatile is the C standard also assigns another property to it. Volatile statements cannot be reordered. So if one of the variables in the For loop is volatile and buffer_was_read is marked volatile, then the compiler cannot make that move (though it is still free to move any statements without volatile sections around as it wants, even past the volatile statements around it).
Again, somewhat OT for CCS as it doesn't reorder statements like this that I have seen, but thought it was interesting. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9253 Location: Greensville,Ontario
|
|
Posted: Wed Jan 11, 2017 4:39 pm |
|
|
re:
So, if a variable is not initialized when is declared the compiler doesn't initialize that variable not even to zero or false.
CCS doesn't, can't say what others do. If you think about it, what the 'default' for a variable 'should' be depends upon the programmer and the program use.
CCS allows you to set every RAM location to zero. RAM by it's nature can be anything upon power up of the micro, therefore 'random' and unknown.
While some will say zero is 'proper', maybe my code desires 'startup' variable to be 'midpoint' (ie: bass and treble controls on amplifiers).
There is no 'correct' default, every program's different, every programmer too !
What IS important is that YOU say what variables must be at startup.
Jay |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1911
|
|
Posted: Wed Jan 11, 2017 7:44 pm |
|
|
I haven't had to use GCC that often but the few times that I have were enough to scare me away from it. I've found issues with how it treats variables smaller than the native width of the processor, and how it handles a continue statement, among other less distressing bugs.
And don't get me started on the Linux kernel..... |
|
|
|