olikraus / u8g2

U8glib library for monochrome displays, version 2
Other
5.14k stars 1.05k forks source link

u8x8 drawString taking progmem? #782

Closed siochs closed 5 years ago

siochs commented 5 years ago

Thanks for sharing this great library! This is not an issue, it's a question about the API. I assumed that u8x8.drawString takes const char * from RAM. But it seems, that it works also with PROGMEM strings? I am on ESP32 and Arduino Framework:

static const char a_pgm_string[] PROGMEM = "From Flash";
U8X8_SSD1306_128X64_NONAME_SW_I2C display(/* clock=*/ OLED_SCL, /* data=*/ OLED_SDA, /* reset=*/ OLED_RST);

void testTheDisplay()
{
  display.setCursor(0, 0);
  display.printf_P(a_pgm_string); // works

  display.setCursor(0, 1);
  display.printf( PSTR(a_pgm_string) ); // works

  display.drawString(0, 2, PSTR(a_pgm_string)); // works too!
  display.drawString(0, 3, a_pgm_string ); // even this works!?
}

Maybe this question sounds noobish, but I am a little confused Which one is the correct use of the API now?

olikraus commented 5 years ago

On any ARM based system (Due, MKR), you will not have this problem at all. I can not speak for ESP systems. For AVR systems, the string must be located in RAM. As an alternative solution you could use display.print (not sure whether printf works, but u8g2 is derived from the Arduino print class, so everything what is supported with Arduino is also supported with u8g2)

Maybe this question sounds noobish, but I am a little confused Which one is the correct use of the API now?

There is no correct or incorrect way. The problem is, that every system behaves differently here. The only question is, whether you want to create portable code or not. If so you probably want to use the F() macro together with the print command (See Arduino spec for this). Otherwise, just use whatever works.

siochs commented 5 years ago

@olikraus thanks for enlightening me :-) Exactly, on AVR platforms, I used to place "strings" in PROGMEM. What I found in the web was a little confusing: In this thread, the const attribute is enough to keep data in flash (ESP-IDF). But in the Arduino docs it seems that this "feature" was ported. It reads as if PROGMEM is required for storing in flash when using Arduino framework and ESP-Platform!? In my case, I am not aiming to port the code to an other platform.

olikraus commented 5 years ago

It reads as if PROGMEM is required for storing in flash when using Arduino framework and ESP-Platform!?

Indeed, I think this is an AVR specific problem. I assume for ESP you can ignore the complete problem. Whether the string is placed in Flash or RAM does not matter.

siochs commented 5 years ago

Thanks. Really confusing all that. See also this gist.

olikraus commented 5 years ago

Yes indeed, for I should be more precise: For ESP32 you can ignore the problem.

Maybe to clarify your problem:

First problem: Some microcontrollers make a difference in accessing RAM or Flash. This means: The compiler must generate different code to access data, depending whether it is in RAM or Flash. This problem applies only to some controllers (ESP8266 and AVR to my knowledge, maybe others also)

Second Problem: We (as a programmer) have to tell, where the data (e.g. the string) has to be placed. The implementation often goes different ways here, but usually some kind of section command is used for this purpose. For the AVR port of the gcc the PROGMEM keyword was introduced. But actually this just resolves to something like attribute((section(".blablabla"))). Of course the blablabla will be different between each system.

Now in principle, gcc can generate different code (problem 1) based on the section where the data is located (problem 2), but this is not so easy, because, as a programmer of a sub procedure, you do not want to care where the argument is located, but in fact, this is not possible: We can not simply write code, which works for strings which are located in Flash and RAM on some systems. As a consequence, for example AVR has introduced two procedures for this task (with and without _P)

On other systems (like ARM), the first problem does not exist, because the code is identical for RAM and Flash access. So we can use all the standard string manipulation procedures. ARM type systems allow a nice simplification: They just use the const keyword to put the code into Flash and reuse all existing string procedures.

siochs commented 5 years ago

Thank you for clarification. Awesome. I close this issue now.

olikraus commented 5 years ago

ok :-)