Go Down

Topic: Issues with strstr_P (PROGMEM) (Read 1 time) previous topic - next topic

SwissPotato

Hi !

I try to use strstr_P in a big project and can't have it working. My goal is to search in a (RAM) buffer for a string (char*) located in FLASH with PROGMEM.  I did write a little and simple sketch which shows the problem, here it is :

Code: [Select]
void setup() {
  //WITH PROGMEM
  char *foo1 = "With PROGMEM is not working";
  char *foo2 PROGMEM = "is";
  char *foo3 = strstr_P(foo1, foo2);
 
  //WITHOUT PROGMEM
  char *foo4 = "Without PROGMEM is working";
  char *foo5 = "is";
  char *foo6 = strstr(foo4, foo5);
 
  Serial.begin(9600);
 
  //RESULT
  Serial.println(foo3);
  Serial.println(foo6);
 
}

void loop() {
  // put your main code here, to run repeatedly:

}


And here is what I see on the terminal :

Code: [Select]

is working


I use an Arduino Uno and my IDE is Arduino 1.5.6-r2.

I don't understand why the PROGMEM version doesn't work. The documentation says :
Quote
The strstr_P() function finds the first occurrence of the substring s2 in the string s1. [...] The strstr_P() function is similar to strstr() except that s2 is pointer to a string in program space.

Source : http://www.stmental.net/~dfoster/avr-libc-user-manual-1.6.5/group__avr__pgmspace.html#g36c9c2de19d7e23c4a6bf63eee608af3

Then... Why ? :/

Coding Badly


Try this...
Code: [Select]

void setup() {
  //WITH PROGMEM
  static char foo1[] = "With PROGMEM is not working";
  static char foo2[] PROGMEM = "is";
  char *foo3 = strstr_P(foo1, foo2);
 
  //WITHOUT PROGMEM
  char *foo4 = "Without PROGMEM is working";
  char *foo5 = "is";
  char *foo6 = strstr(foo4, foo5);
 
  Serial.begin(9600);
 
  //RESULT
  if ( foo3 != NULL )
    Serial.println( foo3 );
  else
    Serial.println( F( "NULL" ) );
 
  Serial.println(foo6);
 
}

void loop() {
  // put your main code here, to run repeatedly:

}

SwissPotato

#2
Sep 01, 2014, 11:08 am Last Edit: Sep 01, 2014, 11:16 am by SwissPotato Reason: 1
Your version works fine, thanks !

Can you explain me why is the "static" keyword important here ?

Actually, I thought that all PROGMEM var (in FLASH) were static, since the FLASH isn't written during the execution of the program.

I still can't do it with my program anyway because I have a few differences between what I really use in my code and this sketch. Here's a version muc longer but corresponding with what I use :

main sketch .ino
Code: [Select]
#include "file.h"

static const char *foo PROGMEM = "is";

void setup() {
 // put your setup code here, to run once:
 Serial.begin(9600);
}

void loop() {
 // put your main code here, to run repeatedly:
 if (Serial.available() > 0)
 {
   char *foo2;
   ble_readSerial();
   Serial.print("Read : ");
   Serial.println(strBleCommand);
   foo2 = strstr_P(strBleCommand, foo);
   Serial.println(foo2);
 }
}


file.cpp
Code: [Select]
#include "file.h"
#include <Arduino.h>
//VAR
char strBleCommand[BLE_BUFFER_SIZE + 1];

unsigned char ble_readSerial(void)
{
 unsigned char i = 0;
 unsigned long iTime = millis();

 ble_cleanBuffer();

 while (millis() - iTime < 1000 or i >= BLE_BUFFER_SIZE)
 {
   while (Serial.available() > 0)
   {
     char inChar = Serial.read();
     if (inChar == '$')
     {
       strBleCommand[i] = '$';
       return 0;
     }
     else if (inChar != '$' and i <= BLE_BUFFER_SIZE)
     {
       strBleCommand[i] = inChar;
       i++;
     }
     else
     {
       return -1;
     }
   }
 }
 return -1;
}

void ble_cleanBuffer(void)
{
 unsigned char i;
 for (i = 0; i < BLE_BUFFER_SIZE; i++)
 {
   strBleCommand[i] = ' ';
 }
}


file.h
Code: [Select]
#define BLE_BUFFER_SIZE 30

//VAR
extern char strBleCommand[BLE_BUFFER_SIZE + 1];

unsigned char ble_readSerial(void);
void ble_cleanBuffer(void);


The functions in the .c files are not relevant imo, just some reading and putting in the buffer methods for the Serial. I don't understand why there's nothing in the foo2 var...

Coding Badly

Quote
static const char *foo PROGMEM = "is";


...stores the pointer to the string in Flash.  The string is stored in SRAM.

Quote
static const char foo[] PROGMEM = "is";


...stores the string in Flash.  The pointer only exists in the compiler's head.

See the difference?

Coding Badly

Can you explain me why is the "static" keyword important here ?


Without it the foos exist on the stack.

Quote
Actually, I thought that all PROGMEM var (in FLASH) were static, since the FLASH isn't written during the execution of the program


We are discussing a C++ program which means C++ rules still apply.  Without the static they are automatic variables which puts them on the stack.

Go Up