Louis
Louis

Reputation: 1

Infinite loop due to Pointers on Arduino Due

I implemented a buffer on Arduino Mega 2560 using Code of Dan Royer as a base. The code runs perfectly fine on the Mega, but I wanted to use the enhanced features and power of the Arduino Due (which uses an ARM instead of the standard Atmel microprocessor).

On the Due I always get into an infinite loop while processing the buffer content due to it not exiting when the end of the buffer is reached. Does anyone know why this might happen? And do you have ideas on how to prevent this?

The commands given would be GCodes such as : "G01 X20.5 Y30;"

This is how the buffer is filled:

char buffer[MAX_BUF];  // where we store the message until we get a ';'
int sofar;  // how much is in the buffer

while(Serial.available() > 0) {  // if something is available
  char c=Serial.read();  // get it
  if(sofar<MAX_BUF-1) buffer[sofar++]=c;  // store it
  if(c==';') {
    // entire message received
    // we got a message and it ends with a semicolon
    buffer[sofar]=0;  // end the buffer so string functions work right
    processCommand();  // do something with the command
  }

The processCommand() then calls a function that searches the buffer for specific characters and returns the float that is directly behind this character:

/**
 * Look for character /code/ in the buffer and read the float that immediately follows it.
 * @return the value found.  If nothing is found, /val/ is returned.
 * @input code the character to look for.
 * @input val the return value if /code/ is not found.
 **/
float parsenumber(char code,float val) {
  char *ptr=buffer;
  while(ptr && *ptr && ptr<buffer+sofar) {
    if(*ptr==code) { // if /code/ is found
      return atof(ptr+1); // return the float behind it
    }
    ptr=strchr(ptr,' ')+1; // else increment pointer to next char after a space
  }
  return val; // if the end of the buffer is reached, return the default value
} 

Now, this code works perfectly fine on the Arduino Mega, but on the Due the while loop is never exited for some reason.

This is how it works on the Mega:

GCode: G1;
Parsenumber: code:F val:288.46
####
ASCII Code at ptr: 71.00
String at ptr: G1;
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 0.00
String at ptr: 
String at buffer end: 
#####
End of Parse: return 288.46

But this is how it is on the Due:

GCode: G1;
Parsenumber: code:F val:288.46
#####
ASCII Code at ptr: 71.00
String at ptr: G1;
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 128.00
String at ptr: € q 
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 113.00
String at ptr: q 
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 8.00
String at ptr: 
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 128.00
String at ptr: € q 
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 113.00
String at ptr: q 
String at buffer end: 
#####

and so on...

Thus, it seems to me that the exit condition ptr<buffer+sofar is never met. Unfortunately I have not been able to print memory addresses with the Arduino. Does anyone know anything?

Upvotes: 0

Views: 328

Answers (2)

chux
chux

Reputation: 154169

Insure buffer is a valid string before the while loop. (Maybe arduino initializes values to 0 by default - IDK. C does not and an infinite loop may result and cause "while loop is never exited".)

char buffer[MAX_BUF];
// int sofar;
int sofar = 0;  // Initialize to 0. 

buffer[0] = 0;  // Add 

During the while loop, append a null character after each time a character is appended. This is especially important should a ; is not found or the buffer is long. Is is not posted what happens to buffer after the while loop.

if (sofar<MAX_BUF-1) {
  buffer[sofar++] = c;
  buffer[sofar] = 0; // Add
 }

Upvotes: 0

LPs
LPs

Reputation: 16243

I post my comment to allow to close the question:

Incrementing pointer with ptr=strchr(ptr,' ')+1; is undefined behaviour, because of strchr doesn't find the char it return NULL.

You should check strchr return, before to assign it to ptr.

Probably on Atmel platform, there is a 0x00 at address NULL+1 that make your code work well.

Another possibility (I'm very noob on Arduino) is that strchr implementation in Atmel library is not returning NULL if the char is not found. I saw strchr implementation where, in case of char not found, the returned value was last char of string.

Upvotes: 0

Related Questions