Nick Williams
Nick Williams

Reputation: 253

Embedded C: AVR; variable in header cannot be evaluated in main

thank you for taking the time to read.

Problem I'm seeing

I have:

main.h 

that declares:

uint8_t u_newVar

I also have

foo.h 

that writes:

extern uint8_t u_newVar

The application sits in a infinite while loop in main.c until an ISR occurs.

In the foo.c, said ISR calls a function within foo.c.

In that function (foo_function() if you will): 0x01 is written to the u_newVar.

Finally, after returning from the interrupt and back into the infinite while, there is a single "if" statement:

while(1){
  if(u_newVar == 0x01){
    uartTX_sendArray(st_uartRX_MessageContents->u_command, (sizeof st_uartRX_MessageContents->u_command));
    uartTX_sendButtonPressData(st_uartRX_MessageContents->u32_value);    
    u_newVar = 0x00;
  }
}

However, the application never enters the if. This "if" block will work if it is in foo.c, after the

u_newVar = 0x01;

line.

Stuff I tried

I looked at the compiled assembly, and what I found kind of stumps me.

If I look at the "if" in main, this is what I see:

enter image description here

So it loads the value from address: 0x011D from SRAM, which I can confirm is 0x01.

Then "CPI" to compare R24 directly to 0x01, which should obviously work.

Then "BREQ", branch if equal, and increment program counter twice to the uart function below. Also makes sense.

However this part is weird. Otherwise, use "RJMP" to jump to the instruction which it is currently at. Unless I'm mistaken, this would lock here for eternity?

So, remember when I mentioned that when I put the if block into the foo.c after the write to u_newVar? Yeah, that's not too interesting:

enter image description here

The "if" is supposed to be after "u_newVar = 0x01", but the compiler is too smart and optimizes it how. Which is why it always works there.

Upvotes: 0

Views: 76

Answers (2)

user3629249
user3629249

Reputation: 16540

what your looking at is the output from the assembler, not the linked code.

The linker has info in the relocation table for that offset in the code (the data byte(s) of the instruction and what the actual target offset is. during the linking process (or for certain environments during the load processing) those data bytes will be updated to contain the correct value

Upvotes: -1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798814

You forgot to tell the compiler that the variable might be modified asynchronously. Such as in a ISR.

volatile uint8_t u_newVar;

Upvotes: 8

Related Questions