Pages: [1]   Go Down
Author Topic: [SOLVED] Data type confusion  (Read 493 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a question, I hope somebody could help me.
In the following code the program runs as I expect, but if I comment (//) the line: Serial.println(bufPos); inside the While(1) it never goes inside the if.

How is affecting Serial.println(bufPos) to bufPos variable and why it is changing If behavior?

Thanks in advance.

Code:
#include "pins_arduino.h"

// what to do with incoming data
byte command = 0;
byte compression = 0;
byte dataLengthLSB = 0;
byte dataLengthMSB = 0;
byte acknowledgeCode = 129;
byte statusCode = 0;

char buf [100];
byte bufPos;

void setup (void)
{
  // Serialdebugging
  Serial.begin (115200);  
  
  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // turn on interrupts
  SPCR |= _BV(SPIE);
  SPDR = 0;
  
  bufPos = 0;
  
  Serial.println("Setup done.");
  
}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte c = SPDR;
  if (bufPos < 100)
  {
  buf [bufPos++] = c;
  }  // end of room available

}  // end of interrupt service routine (ISR) SPI_STC_vect

void loop (void)
{
  while(1){
    Serial.println(bufPos);
    if (bufPos > 0) {
      Serial.println(buf [bufPos]);
      bufPos = bufPos -1;
    }
  }
}  // end of loop

« Last Edit: November 01, 2012, 12:44:01 pm by gism » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 480
Posts: 18732
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

bufPos needs to be declared volatile.

http://www.gammon.com.au/interrupts
Logged


Leeds, UK
Online Online
Edison Member
*
Karma: 80
Posts: 1726
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You are usingchanging bufPos and buf[] inside an ISR so they should be declared volatile:

Code:
volatile char buf [100];
volatile byte bufPos;

By declaring them as such, the compiler knows they can change at any time (because of an interrupt).
If you don't it doesn't know about the interrupts, sees 'bufPos' as Zero when it gets to the main loop (it is set as such at the end of setup) and decides "if (bufPos > 0)" will thus never be true as bufPos cannot as far as it is aware change, so it optimises it out.
By adding the Serial.print() statement to the loop, it has to read in bufPos from the SRAM to print it, and for all it knows the print() function could affect bufPos. The result is it cannot gaurantee that the value doesn't change, so the if statement doesn't get optimised out.

Declaring them as volatile should fix the problem.
Logged

~Tom~

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Tom, Nick,

Thanks for your fast reply. It sounds very good to me. I will try as soon as I can, I will comment.

I've been using volatile without criteria.
Is there any link to find more information about volatile? I haven't found it on arduino website.
What are the side effects of using volatile always?
My understanding is that processing ISR will take much longer but, the physical memory used will be the same, it isn't?

 
Logged

0
Offline Offline
Shannon Member
****
Karma: 206
Posts: 12070
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

buf doesn't actually need to be volatile, its not changing (its a pointer to chars, not the chars themselves).  Declaring volatile is good practice though as it marks those variables as being used in an interrupt routine (ie can change under your feet in the main body of the code).
Logged

[ I won't respond to messages, use the forum please ]

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 69
Posts: 2166
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Volatile prevents the compiler from applying certain optimisations that can be unsafe if used between contexts.

The cpu uses registers, so variables in ram are copied to a register for computation. This information isn't tracked, so which does the ISR use; the ram copy or the register. Volatile ensures the register is flushed to ram before it loses context.

So, yes your ISR can be slower as more instructions can be emitted for volatile data.
« Last Edit: October 31, 2012, 11:25:06 am by pYro_65 » Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

All you were right. It's working fine!
As MarkT said, there is no need to declare pointers as volatile.

Thanks.
Logged

Pages: [1]   Go Up
Jump to: