arduino / ArduinoCore-sam

81 stars 107 forks source link

[Due] pgm_read_ptr causes error #21

Open agdl opened 7 years ago

agdl commented 7 years ago

From @bobc on December 10, 2016 12:31

Arduino IDE 1.6.8 Arduino AVR Boards 1.6.10 Arduino SAM Boards 1.6.9

On Mega2560, the following sketch compiles OK:

void setup() {
  // put your setup code here, to run once:
  char str_debug_1[] PROGMEM = "ECHO";
  Serial.print((char*)pgm_read_ptr(&str_debug_1));
}

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

On Due, the same sketch has a compile error :

In file included from C:\Users\bob\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\cores\arduino/Arduino.h:31:0,

                 from C:\Users\bob\AppData\Local\Temp\build3a01f77cc023d803352a39f55ca441db.tmp\sketch\sketch_pgm_read_test.ino.cpp:1:

C:\Users\bob\Documents\Arduino\sketch_pgm_read_test\sketch_pgm_read_test.ino: In function 'void setup()':

C:\Users\bob\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\cores\arduino/avr/pgmspace.h:106:49: error: 'const void*' is not a pointer-to-object type

 #define pgm_read_ptr(addr) (*(const void *)(addr))

                                                 ^

C:\Users\bob\Documents\Arduino\sketch_pgm_read_test\sketch_pgm_read_test.ino:6:23: note: in expansion of macro 'pgm_read_ptr'

   Serial.print((char*)pgm_read_ptr(&str_debug_1));

                       ^

exit status 1
Error compiling for board Arduino Due (Programming Port).

Inspection of pgm_read_ptr (in avr/pgmspace.h) for Due shows : - #define pgm_read_ptr(addr) (*(const void *)(addr))

This macro casts the argument void , then tries to dereference a void , which is guaranteed to never work.

Probably, the cast to (void *) is not needed.

Copied from original issue: arduino/Arduino#5698

PaulStoffregen commented 7 years ago

On Mega2560, the following sketch compiles OK:

It may compile, but it certainly doesn't work. It has 3 fatal flaws:

1: There's no Serial.begin(), so it can't print anything 2: It doesn't actually store any pointers for pgm_read_ptr() to read. The array has 5 chars (including terminating zero), not a pointer to chars. 3: The array is local scope (stack allocated), which doesn't work with PROGMEM.

Here is a correct program which actually works when run on Uno or Mega (yes, I did just test both of them).

const char * const str_debug_1[] PROGMEM = {"ECHO", "ECHO2"};

void setup() {
  Serial.begin(9600);
  Serial.println("test pgm_read_ptr:");
  Serial.println((char*)pgm_read_ptr(&str_debug_1[0]));
  Serial.println((char*)pgm_read_ptr(&str_debug_1[1]));
}

void loop() {
}

This doesn't solve the issue on Arduino Due, but at least a working test case might be helpful?

bobc commented 7 years ago

There is no doubt that pgm_read_ptr works on AVR platforms, so it doesn't help at all, frankly. Creating a runnable test case for Due once the compile issue has been fixed is a trivial exercise.

Any thoughts on how to fix it?

PaulStoffregen commented 7 years ago

Use ((void const *)(addr))

https://github.com/arduino/ArduinoCore-samd/commit/4ffc9d2bdb557e1a0db2cc943aa9b3fef4ad71b1