1

I have defined a global variable named "ledFlag" in one source file, this source file also has a ISR for push button connect to Interupt pin. The ledFlag variable will be set in ISR once the push button is pressed. Since the main application is in another source file i have decalred the ledFlag as extern in the application file. But i get undfefined reference to the variable error. How can i fix it? I am using Source Insight for editing the source files.

Source file 1:

UINT32 ledFlag=0;
void ISR()
{
   status = readGpio...
   if (status == High)
   {
     ledFlag = 1;
   }
   else
   {}
}

Source file 2:

extern UINT32 ledFlag;
main()
{
  if (ledFlag)
      dothis;
}

//rough illustration.

clearlight
  • 12,255
  • 11
  • 57
  • 75
Ali
  • 39
  • 7
  • 4
    Can you please confirm that Source File 1 which contains the ISR is added to the project and is getting compiled? – Vishal Sagar Oct 06 '15 at 10:39
  • This will not work anyway; at least once you enable optimisations. Read about `volatile` – too honest for this site Oct 06 '15 at 10:52
  • @Vishal..yes, like i said its part of a source insight editor project..so it doesn't seem to be a linking error. – Ali Oct 06 '15 at 10:54
  • @Olaf Care to elaborate? Which part of the code will be effected by optimization. I know what volatile keyword does but where do you see the need for it here? – Ali Oct 06 '15 at 10:57
  • What if the error message concerns another variable or symbol instead of ledFlag? – A.S.H Oct 06 '15 at 11:00
  • Please do some research on yourself. For a starter: C does not have a concept of concurrent threads. And provide full description, including error message and exact line. – too honest for this site Oct 06 '15 at 11:01
  • @Olaf..First of all..I didn't say a single thing about concurrent threads. Second, you haven't answered about the optimization problem you were talking about. Lastly, The description is enough for people who want to help. – Ali Oct 06 '15 at 11:06
  • A.S.H..the error goes away when i comment out the ledFlag Variable. – Ali Oct 06 '15 at 11:07
  • 2
    @Ali The problem is that the compiler can't determine at compile-time when/if an interrupt gets called. Traditionally, embedded compilers have therefore made stupid assumptions about variables shared with interrupt service routines. The compiler may stupidly assume that the shared variable is never changed anywhere, so it thinks it is allowed to optimize it away code which makes assumptions about that variable. Which in turn creates incredibly nasty, hard-to-find bugs. To avoid such bugs caused by oblivious compilers, always declares variables shared with an ISR as `volatile`. – Lundin Oct 06 '15 at 11:10
  • That's not the only reason to mark it as volatile. Volatile enforces that the variable is always read before evaluating, and in many environments causes a memory fence/barrier that ensures all writes have posted before reading the variable, and all writes to it post before continuing. Granted, the memory fence thing isn't as applicable when you're referring to a variable (and not a memory mapped register)... – Russ Schultz Oct 06 '15 at 11:20
  • 1
    @RussSchultz There is no guarantee that volatile will yield a memory barrier. It may or may not do that, it is implementation-specific. – Lundin Oct 06 '15 at 11:27
  • `volatile` and 'optimizing away' has nothing to do with this problem. The compiler must always create the global variable in the declaring module as it doesn't know if another module is using it. Likewise, volatility has nothing to with whether the variable is created in the declaring module: it must. – Paul Ogilvie Oct 06 '15 at 11:46
  • @lundin yes, that's why I said "in many environments' – Russ Schultz Oct 06 '15 at 12:14
  • 1
    Only way is that two files are not both compiled. Check your makefile. Try to clean your project and see if both files are re-compiled. – LPs Oct 06 '15 at 13:13
  • 1
    Ali, the code that you have shown looks OK, so the problem seems to be in something that you _haven't_ shown. Please provide a complete, but very small, example, and show us the exact source for it, and the exact error message that you get. Otherwise we are stuck guessing. You may want to look at the instructions about a "Minimal, Complete, and Verifiable example" here: http://stackoverflow.com/help/mcve – Thomas Padron-McCarthy Oct 06 '15 at 13:27
  • Unfortunately, The Volatile keyword doesn't solve the problem. So it comes down to if the file is part of the project and being linked properly? I have checked that the file is already part of the project. Source insight already has both of the files in the project. Do they have to be in the same directory too? Also how can i check if both of them are getting compiled? I am using command shell to compile the project. Sorry my Question might sound naive, I am a noob. This is the exact error i see : undefined reference to 'ledFlag'. – Ali Oct 08 '15 at 03:33

1 Answers1

0

Firstly check that both files are getting properly compiled together and that both are added to the project.

Secondly: Your compiler is most likely optimising the variable call away, making false assumptions about what it can't and can shorten.

To prevent this, do something like this:

Source File 1

volatile UINT32 ledFlag=0;
void ISR()
{
   status = readGpio...
   if (status == High)
   {
     ledFlag = 1;
   }
   else
   {}
} 

Source File 2:

volatile extern UINT32 ledFlag;
main()
{
  if (ledFlag)
      dothis;
}
Magisch
  • 7,312
  • 9
  • 36
  • 52
  • Unfortunately, The Volatile keyword doesn't solve the problem. So it comes down to if the file is part of the project and being linked properly? I have checked that the file is already part of the project. Source insight already has both of the files in the project. Do they have to be in the same directory too? Also how can i check if both of them are getting compiled? I am using command shell to compile the project. Sorry my Question might sound naive, I am a noob. This is the exact error i see : undefined reference to 'ledFlag'. – Ali Oct 08 '15 at 03:26