Global Variables

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

Global Variables

Jump to solution
4,169 Views
farhud
Contributor III

I have defined some global variables in my main function. I need the interrupt subroutine to have access to these variables once its called. When I define them in my main function there is no access to them in the ISR. How can define these variables so my main code and the ISR can have access to them. The ISR function is in the MCUInit.c file.

Labels (1)
0 Kudos
Reply
1 Solution
3,140 Views
admin
Specialist II

Try the following arrangement:

 

In my MAIN function (different file):

 

unsigned char SCIIniTx;

unsigned char SCIString[12]={'F','R','E','E','S','C','A','L','E',0xa,0xd,​'\0'};
unsigned char SCIStringMain[12]={'F','R','E','E','S','C','A','L','E',0xa,0xd,​'\0'};
unsigned char *SCIStringp;
unsigned char Stringcase;

 

In my MCUInit.c file that included the ISR:

 

extern unsigned char SCIIniTx;
//extern unsigned char SCIString[12]={'F','R','E','E','S','C','A','L','E',0xa,0xd,​'\0'};

extern unsigned char * SCIString;
extern unsigned char * SCIStringMain;

extern unsigned char *SCIStringp;
extern unsigned char Stringcase;

View solution in original post

0 Kudos
Reply
15 Replies
3,140 Views
admin
Specialist II

Go step-by-step.

1. Place the related code into the single file. The sequence: definition of the shared variable, then the main function, then the ISR.

2 After this arranging is debugged, move the ISR into the separate file. Define the shared variable as extern in the ISR file.

 

0 Kudos
Reply
3,140 Views
farhud
Contributor III

I put my global variables and the ISR in the MCUInit.c file. As you mentioned I declared the variables as "extern". In my main I just declared the as regular global variables. The debugger was still giving an error, stating that my SCIString variable is defined multiple times (in MCUInit.c and main.c). I just defined another string in my main file, called it SCIStringMain and kept the other one in the ISR file and it worked. The other variables worked just fine. Do you have any idea why? Here are my global variables:

 

In my MAIN function (different file):

 

unsigned char SCIIniTx;
unsigned char SCIStringMain[12]={'F','R','E','E','S','C','A','L','E',0xa,0xd,'\0'};
unsigned char *SCIStringp;
unsigned char Stringcase;

 

In my MCUInit.c file that included the ISR:

 

extern unsigned char SCIIniTx;
extern unsigned char SCIString[12]={'F','R','E','E','S','C','A','L','E',0xa,0xd,'\0'};
extern unsigned char *SCIStringp;
extern unsigned char Stringcase;

0 Kudos
Reply
3,141 Views
admin
Specialist II

Try the following arrangement:

 

In my MAIN function (different file):

 

unsigned char SCIIniTx;

unsigned char SCIString[12]={'F','R','E','E','S','C','A','L','E',0xa,0xd,​'\0'};
unsigned char SCIStringMain[12]={'F','R','E','E','S','C','A','L','E',0xa,0xd,​'\0'};
unsigned char *SCIStringp;
unsigned char Stringcase;

 

In my MCUInit.c file that included the ISR:

 

extern unsigned char SCIIniTx;
//extern unsigned char SCIString[12]={'F','R','E','E','S','C','A','L','E',0xa,0xd,​'\0'};

extern unsigned char * SCIString;
extern unsigned char * SCIStringMain;

extern unsigned char *SCIStringp;
extern unsigned char Stringcase;

0 Kudos
Reply
3,140 Views
CompilerGuru
NXP Employee
NXP Employee

That's not correct....

 

While the syntax using pointers and arrays is very similar, they are not the same. Declaring a variable as pointer and defining it as array is wrong, when only seeing the pointer declaration the compiler will read the first bytes of the array as address. Say pointer accesses will read from 'f'*0x100+'r', not what you want.

 

The issue why the extern alone does not work is that you left the initialization values. C causes the extern to be ignored if you initialize the variable.

Hence, the correct way is to use extern without the initialization value. Listing the size is optional, if provided it must be correct.

>extern unsigned char SCIString[];

 

If a string is never changed, make it const so it ends up in flash and does not waste RAM.

Also as general hint, I would also put all the declarations (extern...) into a header file and include that file into every module needing or defining any of the variables. With this setup the compiler warns about array vs pointer mixups.

 

So I would suggest to add a file main.h

 

 

#ifndef MAIN_H_#define MAIN_H_extern unsigned char SCIIniTx;extern /*ev const */unsigned char SCIString[/*ev 12*/];extern /*ev const */unsigned char SCIStringMain[];/* Is this an array? */ extern unsigned char *SCIStringp;extern unsigned char Stringcase;#endif MAIN_H_

 And then add a #include "main.h" in both main.c and in MCUInit.c

 

 

0 Kudos
Reply
3,140 Views
farhud
Contributor III

I am getting link error when I try your approach. As you said I made another file by the name "main.h" and added #include "main.h" in my Main file and MCUInit.c file. I get the following error:

 

Link Error : Undefined: "SCIString"

Referneced from main

......

Link Error

0 Kudos
Reply
3,140 Views
CompilerGuru
NXP Employee
NXP Employee

Are you using C or C++? Are you using const or not?

 

SCIString should be defined as in the initial post:

 

unsigned char SCIString[12]={'F','R','E','E','S','C','A','L','E',0xa,0xd,'\0'};

 

(well there are easier ways to type that....)

 

If SCIString is const and C++ is used then the declaration of SCIString must be visible, say the header file must have been included in the file defining the constant.

0 Kudos
Reply
3,140 Views
farhud
Contributor III

I am just a little confused here. If I write all my external variables in a different file and initialize them in my MAIN file, what happens if their value changes in my ISR? Will that value be visible in MAIN as well? Or is it going to be local to that ISR? I read some definitions for "external variable and const" from some where but I am still not clear.

0 Kudos
Reply
3,140 Views
CompilerGuru
NXP Employee
NXP Employee

>I am just a little confused here.

> If I write all my external variables in a different file and initialize them in my MAIN file,

> what happens if their value changes in my ISR?

 

There is only a single instance of global, non constant variables. Therefore if it changes for one file, the other files see the same change. If this is not wanted, then static has to be used (or non global variables).

Anyhow, I'm sure the net is full of good books explaining all these things :smileyhappy:.

 

Daniel

 

PS: If a global variable is used in interrupt handlers and in non interrupt code, then make it volatile. But this is independent on how the variable is declared or accessed from different source files, similar to if a variable is never changed, you should make it const to save RAM.

0 Kudos
Reply
3,140 Views
farhud
Contributor III

I am using C. For some reason the compiler does not like me creating "main.h" and declare it as you said. It gives link error. Maybe because I am using the "device initialization" option from CW. I don't know. When I declare my const and variables in Main and define them as "extern" in MCUInit.c file it works.

0 Kudos
Reply
3,140 Views
admin
Specialist II

CompilerGuru,

I agree with your post, except the following statement:

"Declaring a variable as pointer and defining it as array is wrong, when only seeing the pointer declaration the compiler will read the first bytes of the array as address. Say pointer accesses will read from 'f'*0x100+'r', not what you want."

 

Could you, please, explain the statement with an executable example?

 

My following code is compiled and executed without any issues:

 

extern "C" {
void f( unsigned char * arg );
}

void f( unsigned char * arg )
{
 printf( "Argument=%s.\n", arg);
}

 

extern "C" {
void UserMain(void * pd);
}

void UserMain(void * pd)
{
    /* Some nonrelated content is skipped. */
    unsigned char arg[ ] = { 'A', '\0' };
    f( arg );
}

 

0 Kudos
Reply
3,140 Views
CompilerGuru
NXP Employee
NXP Employee

In the new sample, the array is not externally declared at all, just a function.

Also it add's C++ to the mix. While C++ is very similar on many levels it has slithery different

rules for some things, for example global const variables are implicitely static if not declared extern. Well, for details any good C++ book Smiley Happy.

About the requested sample, here it is.

 

a.c:

 

 

unsigned char SCIString[]= "FREESCALE\xa\xd";unsigned char* PtrToSCIString = SCIString;extern void test(void);void main(void) {  for(;;) { test();  }}

 

 

b.c:

 

/* EXAMPLE of a WRONG usage. Don't do this! */extern unsigned char * SCIString;/* should have been:const unsigned char SCIString[];*/extern unsigned char* PtrToSCIString;void test(void){ while (PtrToSCIString != SCIString) {  // Error, should be the same. Is not because of wrong declaration of SCIString above! }}

 

To fix it, move all the declarations from b.c (everything with extern in this case) into a new file b.h, include b.h in both a.c and b.c, and then fix the compilation errors. The lesson to learn is that  having the declarations in a header file is not enforced by the language, but it is strongly recommended. It allows the compiler to verify the declarations against the definitions.

In C++, the language does part of that via its name mangling for functions, but for global variables this does not help.

 

Daniel

 

0 Kudos
Reply
3,140 Views
admin
Specialist II

CompilerGuru,

Thanks for the clear example on  your statement  "Declaring a variable as pointer and defining it as array is wrong, when only seeing the pointer declaration the compiler will read the first bytes of the array as address".

 

Could you, please, also explain, why my example of converting the array to the pointer is also correct?

0 Kudos
Reply
3,140 Views
CompilerGuru
NXP Employee
NXP Employee

You mean this code?

void UserMain(void * pd){    /* Some nonrelated content is skipped. */    unsigned char arg[ ] = { 'A', '\0' };    f( arg );}

This code is fine, it just does not contain the problematic setup.

First the bug in the other sample was that the declaration of a global variable did not match the definition, here there is no global variable, arg is local. Therefore there is also no declaration which could be wrong.

Second, when an array as arg in the sample is used it does get implicitly converted to a pointer to its first element.

Though this does not make it legal to declare an array as pointer, just (in many cases) to use it as if it was a pointer.

From most usages (sizeof being an exception), an array and a pointer to the first element of an array behave the same, so it is easy to mix the two representations up. But while their uses are so similar, arrays and pointers are not the same under the hood, the compiler has to generate very different code to get the desired behavior. So if an array is declared as pointer, then you basically lie to the compiler and the resulting code does not work.

 

Daniel

 

 

0 Kudos
Reply
3,140 Views
farhud
Contributor III

You found my bug. Thans. I shouldn't initializing my external variables in my ISR when i have already done that in my main. Cheers.

0 Kudos
Reply
3,140 Views
farhud
Contributor III

Now the code does not work properly. Any suggestions?

0 Kudos
Reply