Go Down

Topic: PROGMEM Issue I read all other PROGMEM posts (Read 5485 times) previous topic - next topic

jl-p

Apr 04, 2014, 08:38 pm Last Edit: Apr 04, 2014, 09:47 pm by jl-p Reason: 1
Hi,,

I read all other progmem related topics but none of these works for me

I have a pretty big program which should still be uploaded to a mega and in the future to the due. so i hope to have only one source instead of two.
Because my complete menu which is a static list and never change without a new upload i created the menu structure in progmem which i filter out with sscanf_p

here 10 of the 1000 lines
Code: [Select]

prog_char MenuNL_0[] PROGMEM = "0 1 H Menu Hoofdmenu 0 0 0 0 0";
prog_char MenuEN_0[] PROGMEM = "0 1 H Menu Hoofdmenu 0 0 0 0 0 ";
prog_char MenuNL_1[] PROGMEM = "1 1 S Instellingen SubMenu 0 0 0 0 1";
prog_char MenuEN_1[] PROGMEM = "1 1 S Settings SubMenu 0 0 0 0 1 ";
prog_char MenuNL_2[] PROGMEM = "2 1 B Status SubMenu 0 0 0 0 2";
prog_char MenuEN_2[] PROGMEM = "2 1 B Status SubMenu 0 0 0 0 2 ";
prog_char MenuNL_3[] PROGMEM = "3 1 S Acties SubMenu 0 0 0 0 3";
prog_char MenuEN_3[] PROGMEM = "3 1 S Actions SubMenu 0 0 0 0 3 ";
prog_char MenuNL_4[] PROGMEM = "4 1 S Logs SubMenu 0 0 0 0 4";
prog_char MenuEN_4[] PROGMEM = "4 1 S Logs SubMenu 0 0 0 0 4 ";


I still don't know if these are translated properly but i know the next lines won't work

i also use a lot of
Code: [Select]

n=sprintf_P(Tekst, PSTR("SD Card Initialized"));
myGLCD.print(Tekst, CENTER, 32);
Log(Tekst,2,6);


so i added the following code as described in the other progmem topics but still the same error

Code: [Select]
#if defined(__SAM3X8E__)
   #define PROGMEM
   #define pgm_read_byte(x)        (*((char *)x))
//  #define pgm_read_word(x)        (*((short *)(x & 0xfffffffe)))
   #define pgm_read_word(x)        ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
   #define pgm_read_byte_near(x)   (*((char *)x))
   #define pgm_read_byte_far(x)    (*((char *)x))
//  #define pgm_read_word_near(x)   (*((short *)(x & 0xfffffffe))
//  #define pgm_read_word_far(x)    (*((short *)(x & 0xfffffffe)))
   #define pgm_read_word_near(x)   ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
   #define pgm_read_word_far(x)    ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x))))
   #define PSTR(x)  x
 #if defined F
   #undef F
 #endif
 #define F(X) (X)
#endif



Code: [Select]

1_Setup:49: error: expected primary-expression before ')' token        
1_Setup:54: error: expected primary-expression before ')' token
1_Setup:59: error: expected primary-expression before ')' token
1_Setup:64: error: expected primary-expression before ')' token
1_Setup:69: error: expected primary-expression before ')' token


All of the mentioned lines  start with n=sprintf_P(Tekst, PSTR("

so how do i change it during the compilation without rewriting every line


Kind regards

Johan

MarkT

Due doesn't have PROGMEM.  You can't read flash memory at all, you can only execute
it as code, this is a basic security measure on the chip.  From outside the chip you can't
read the flash either, you can only erase it totally then write it I believe.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

pjrc


You can't read flash memory at all, you can only execute
it as code, this is a basic security measure on the chip.


Are you sure about that?

gogol


Due doesn't have PROGMEM. 


And because of that, the thread owner is using all those preprocessor macros, to make PROGMEM and the corresponding functions disappear!
And of course, you can read flash memory! You can store constant data there!  In the AVR world it is tricky, so PROGMEM was introduced. In the ARM world, such tricks are not needed.

The poster tries now to write compatible code, which can be translated for the AVR world and the DUE, so he needs those macros!

However the thread owner needs to post more of his code, as it looks like just as an preprocessor issue.
When he writes:
Quote

All of the mentioned lines  start with n=sprintf_P(Tekst, PSTR("

he has cutted of the more important piece with the closing bracket, which is mentioned in the error message.



jl-p

Gogol i right thats what i need. 

but  I did post one of the lines which has the error completely

Quote

n=sprintf_P(Tekst, PSTR("SD Card Initialized"));
myGLCD.print(Tekst, CENTER, 32);
Log(Tekst,2,6);


some others

Code: [Select]

Log(Tekst,2,6);sprintf(Tekst, (PGM_P) pgm_read_word(&Teksten[1][Taal]));
myGLCD.print(Tekst, 5, 150);

n=sprintf_P(Tekst, PSTR("Spoelen Tijden[0] = %lu Spoeltijden[%lu-1] = %lu"),Spoeltijden[0],AantalSpoelBeurten,Spoeltijden[AantalSpoelBeurten-1]);
  Log(Tekst,1,1);
  n=sprintf_P(Tekst, PSTR("AantalMinutenSpoelBeurten*60 = %lu * 60 = %lu"),AantalMinutenSpoelBeurten,AantalMinutenSpoelBeurten*60);
  Log(Tekst,1,1);




everything i send to the serial port, log to a  file or show on the tft screen is now declared as progmem.

or with the PSTR or with the prog_char   command

And because i also want to use this code to upload to a mega i don't want to delete all progmem defenitions from my code.because then i need to write every change , fix or new feature twice.

I understand that if  i delete everything  and declare it as a normal constants it works but then i cannot upload it to a mega anymore.

if you need more or something else just say it and i will send it.


Johan

stimmer

Just spotted this:
Code: [Select]
    #define pgm_read_word_near(x)   ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
    #define pgm_read_word_far(x)    ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x))))

One of these must obviously be wrong!
Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html

jl-p

as far as i know the compiler already change these lines if you compile for a due.
But the PSTR things are the biggest issue .
whatever i try it keep failing on that one

jl-p

#7
Apr 06, 2014, 09:44 am Last Edit: Apr 06, 2014, 09:50 am by jl-p Reason: 1
here a simple complete program which runs on the mega but even i added all the #define lines not on the DUE


Code: [Select]

char Tekst[100];
int n;
int Taal=0;
char Omschrijving[150];


#if defined(__SAM3X8E__)
   #define PROGMEM
   #define pgm_read_byte(x)        (*((char *)x))
//  #define pgm_read_word(x)        (*((short *)(x & 0xfffffffe)))
   #define pgm_read_word(x)        ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
   #define pgm_read_byte_near(x)   (*((char *)x))
   #define pgm_read_byte_far(x)    (*((char *)x))
//  #define pgm_read_word_near(x)   (*((short *)(x & 0xfffffffe))
//  #define pgm_read_word_far(x)    (*((short *)(x & 0xfffffffe)))
   #define pgm_read_word_near(x)   ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
   #define pgm_read_word_far(x)    ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x))))
   #define PSTR(x)  x
   #define _P
   
 #if defined F
   #undef F
 #endif
 #define F(X) (X)
#endif

prog_char MenuNL_0[] PROGMEM = "0 1 H Menu Hoofdmenu 0 0 0 0 0";
prog_char MenuEN_0[] PROGMEM = "0 1 H Menu Hoofdmenu 0 0 0 0 0 ";

PGM_P Menu[][2] PROGMEM =
{
 MenuNL_0, MenuEN_0};
 
 
void setup() {
  Serial.begin(115200);
n=sprintf_P(Tekst, PSTR("Version 1.1"));
Serial.println(Tekst);
sprintf_P(Tekst, (PGM_P) pgm_read_word(&Menu[0][Taal]));
Serial.println(Tekst);

sscanf_P(Tekst,PSTR("%*u\t%*d\t%*c\t%*15[a-zA-Z0-9().;,:><= ]\t%90[a-zA-Z0-9().;,:><= ]\t%*u\t%*u\t%*u\t%*u\t%*u"),Omschrijving);
Serial.println(Omschrijving);


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

}

stimmer

Thanks for the simplified example code, it really does make debugging these problems much easier.

Firstly the PROGMEM compatibility code is already in avr/pgmspace.h which is automatically included, so you don't need most of the big #if block. The problem is that there are two bugs in pgmspace.h:

1) sprintf_P only works if there are 3 or more arguments. There's not much point using sprintf with only 2 arguments (strcpy is better), however I think for consistency it should work.

2) sscanf_P isn't there at all!

To work around this, change the #if block to just contain the following:
Code: [Select]

#if defined(__SAM3X8E__)
  #define sprintf_P sprintf
  #define sscanf_P sscanf
#endif

Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html

gogol

Hello Stimmer,

thanks for that information.  Comparing pgmspace.h with the defines posted above, I see only one more difference:
[font=Courier]#define F(X) (X)[/font][/b] should also be included.

I think, that this should be included in pgmspace.h. 

I see no advantage of the current define:
[font=Courier]#define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__)[/font][/b]
compared to your pragmatic
[font=Courier]#define sprintf_P sprintf[/font][/b]

or does the pragmatic way break some other stuff?




jl-p

#10
Apr 07, 2014, 01:48 pm Last Edit: Apr 07, 2014, 05:23 pm by jl-p Reason: 1
I added them,
compiling runs without errors
But when i run the program on the due (test code)  i only receive one line of text in my output instead of three
The first is perfect but something is still missing in de defines (i think) for the other lines


Kind regards

Johan

stimmer

You are using pgm_read_word to read an address, but pgm_read_word is only 16-bits. That might work on a Mega (and even then only for 'near' addresses) but it won't work on a Due, which uses 32 bit addresses.
Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html

jl-p

stimmer,

I understand that part but is there any way to convert the during compile time. because i have a lot of these

Kind regards

Johan

MarkT



You can't read flash memory at all, you can only execute
it as code, this is a basic security measure on the chip.


Are you sure about that?


Ah, I am wrong  :( (but right in some weaker sense).

The chip does support this security model where the flash cannot be read, but there
is a control bit that enables it - section 9.1.3.5 "Security bit feature" - I clearly rememberd
the description of the mechanism but not that it was optional.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

gogol


Ah, I am wrong  :( (but right in some weaker sense).
The chip does support this security model where the flash cannot be read, but there
is a control bit that enables it - section 9.1.3.5 "Security bit feature" - I clearly rememberd
the description of the mechanism but not that it was optional.


I think, that you are still wrong with that.  This is a mechanism to protect your code from being read out by external programmers, JTAG devices etc., but not from preventing you, to initialize variables in the flash.  The ARM architecture is here little bit different from the AVR architecture.

Go Up