Rp2040 progmem arrays

has any one gotten this to work? if you say look at the documentation i cant find any for the official and the earl core isnt a option. mbed os documentation is not revolving around arduino and has no references. in fact it looked like its the worst least loved way to program anything ever their website has this not maintained feel and a mention of old obsolete examples to learn from (their words). why not just make every one learn turbo express while your at it arduino people

if i cant do it i guess thats fine but it seems crazy for it to not be able to do it. its basic and its arm stuff so wtf. nothing will run even if it loads the sketch. adafruit library canvas wont do anything. white bootloader screen and i loaded the gfx test for the ili9341 and its fine before and after the failed canvas example

honestly it would be nice if i could use arduino classic on this thing and just give up all new functions.

in String.h (Arduino package) there is
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
which suggest PSTR works
BUT in progspace

#define PROGMEM
#define PGM_P  const char *
#define PSTR(str) (str)

so no, no PROGMEM it is a NOOP to the compiler

PROGMEM is used when the flash memory (program memory) is in a different address space than the RAM, because the processor uses different instructions to access that memory, and the compiler needs to know to use those specific instructions. On a processor with a single address space PROGMEM is meaningless. The complications come with getting the compiler to properly compile code that uses PROGMEM for a processor that does not need it, there are likely still some bugs for the RP2040 since it is so recent, and it is possible the library needs some changes to be compatible (it is common for a library to check for different processor types and vary the code based on that, but being written prior to the existence of the RP2040 there is no check for that particular processor type). You may want to check the bug reports for the core used with the RP2040 and the problematic libraries to see if anyone else has encountered a similar problem.

thanks for the replies and i guess i can stop looking. i guess they expect us to just load it into ram instead of keeping it in flash since we got more ram but for graphics its sort of going to bog everything down. you could have something you could store in flash that cant load into ram. 2mb -16mb for rp2040 boards. only 264 kb ram.

well i guess i can give up on that and move onto trying to do curved line draw or a matrix of pixles to do it

On a processor with a single address space, declaring a variable as const should be enough for the compiler to store it in flash, the same machine instruction is used to access both flash and RAM. A processor with separate address spaces for flash and RAM uses a different machine instruction for each address space, hence the need for the PROGMEM declaration.

yea but without progmem i cant stream stuff into ram instead of it trying to load it all up at 1 time. also board frequency seems to be bugged or something. no changes seem to affect anything. i basically have only 264 kb of dynamic memory to make it work and flash space is meaningless

i think they rushed official support because of the unofficial cores and decided 264 kb is plenty of space despite having a product on the market that could be considered as being marketed as less than accurately labeled by some customers.

i dont want to be that guy but i tend to be. and there are many like me. im sure that enough dissappointment with the rp2040 boards has set in and the reality that the trade off errorred on the side of overpriced atmega644s linked spi would have been a better buy but then again so would a nintendo switch thats jail broken and can run java or what ever at that pricing

i guess they expect us to just load it into ram instead of keeping it in flash

It works fine with "const":

const char PROGMEM foo[1000] = "  Prints out byte values in all possible formats:\n" ;
void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
    Serial.println(foo);
  }
}
/usr/local/gcc-arm-8-2019-q3/bin/arm-none-eabi-nm -SC *.elf|grep foo
1000fd28 000003e8 r foo

(note that XIP flash starts at 0x10000000, and RAM at 0x20000000, so the string IS in flash.)

Also note that even on AVR, you've needed both "const" and "PROGMEM" for quite few versions now...

(This is about the same thing that david_2018 said back in reply #3. I don't know why you latched on to DRMPF's comment that "it's a no-op" as an indication that it doesn't work. It IS a no-op, but that doesn't matter.)

While that is true, I don't think that is doing what you expect.
see GCC and the PROGMEM Attribute

"Common sense and intuition would dictate that the compiler would store the string in the program memory, and read it out byte-by-byte inside the LCD_puts routine. But this is not what happens.

"Because the LCD_puts routine (or other string routines) are designed to work with strings in RAM, the compiler is forced to read out the entire string constant from program memory into RAM, and then pass the string's RAM pointer to the routine (in this case LCD_puts)."

I think was was wanted here was for the string to read directly from flash without creating a ram version first. This is what the F( ) normally does.

Also see Gammon Forum : Electronics : Microprocessors : Putting constant data into program memory (PROGMEM)
"The problem with constants in general (including string constants like "hello") is that the compiler generates code to copy them into RAM at program startup, because most C functions do not expect to find data in PROGMEM."

Um. I guess that would depend on how LCD_puts() is implemented. The tutorial you quote is from 2004 and refers to non-Arduino code.
It's also misleading in that it implies that the copy is done in LCD_puts(), when what actually happens in that the C/C++ startup code (on AVR) copies all of the initialized data from flash into RAM. (ARM startup code only copies non-read-only data into RAM - since there is a unified address space, and flash behaves just like RAM as far as reading is concerned, it doesn't need to do the copy.)

The current Arduino print() code (that most character output devices inherit from) reads FlashStringHelper strings one byte at a time.

(and it turns out that write() doesn't directly support flashStringHelper anyway.)

Edit: (adding)
I don't know why OP is having trouble with the GFX library on rp2040 (and the Arduino libraries seem to be broken at the moment), but I'm pretty sure it has nothing to do with "PROGMEM."

You are correct the const makes all the difference.
The PROGMEM does nothing.
You just increase my knowledge of ARM :slight_smile:
So bottom line just making any char[ ], a const char[ ] will save both global variable usage AND reduce the sketch size by the same amount, as well

Literal strings are also left in flash on ARM.
PROGMEM, PSTR, flashStringHelper, and etc are unnecessary, but are defined anyway so that sketches can be compatible with both AVR and "unified address space" architectures.

IIRC, ESP8266 has a weird memory architecture, and copies flash strings into RAM within print(), but it looks like it does a chunk at a time, so it's not that awful (?)

ESP32 seems to be better?

ok i will grant you that progmem survives in a form but its been crippled and even adafruit cant fix it. their cavas that was in the gfx library that was updated cant display the dragon. they got a cheat sheet with syntax changes. you know they did. because arduino cant be bothered to do any of that

i dont claim to be the worlds greatest anything but it looks like promem is nothing more that a struct form now and is disconnected from its full range . just in a comparison between what survived and whats dead. mbed has documentation about how poorly it handles images. im pretty sure thats why it was chosen

interestingly enough a old arduino library for a 3d engine that was terrible works . it was made in 2016. no changes. almost nothing else seems to work. even fancy blink sketches are subject to fail now. maybe i have to make a raycast system just to display 2d images. the 3d engine is like 1/3 of the way there. then others may play doom on pi pico and connect much to the dismay of the evil doers at arduino

Could you please give a specific example of code that exhibits the problem? Descriptions such as "the gfx library that was updated cant display the dragon" is totally meaningless out of context.

adafruit gfx library. canvas example. everything else was updated but that thing. since there is so little updated and almost all of it has to do with wifi or ethernet this is one of the only examples i can site that every one could download. there was a update 2 days ago but i didnt observe a change

at this point it looks like i have to do line draw arrays to make basic graphics which is god awful and requires processing power and time for something that wont even look better than its bitmap equivalent.

considering the libraries are so terrible for tft screens with refresh rate people have tried to solve refresh problems in the past. each time the library is deprecated . there is a flappy bird clone from 2019 that only compiles on avr boards. it used pixle draw with push color to draw the stupid bird and pipes faster. doesnt work now. there is a history of this and i think they just decided to use the worst graphical proccessing platform (mbed according to the company that developed it) and killed progmem arrays being used in varying degrees of usage

the tft companies won a legal battle that claimed their product doesnt actually work at the specified frequencies to deliver 70 hrz refresh rates. at a meager 63.5mhz it should be well past 60 fps. but alas its not even 4 fps. so the blame falls on either arduino or adafruit ...and now this. just make a official public statement that you dont like money and want people to buy raspberry pis and not picos no rasberry pi 3 and up.

The canvas example does not appear to use PROGMEM except for the fonts? Nor the sort of "transfer the whole image" sort of thing that I thought you were talking about... (Am I looking at the right code? Examples/Adafruit GFX Library/GFXCavnas ? It doesn't look like it does anything like what you describe you're trying to do...)

I am willing to help debug this, from the Pico/Mbed/SPI/whatever point of view, but I have no experience with TFT displays or their use, so my input is going to be largely "theoretical" and require significant input from your side... (or: "Will write code for toys." The last time I did this was quite a while ago ( Arduino to 384 LED display module (MCU Interface) - #4 by westfw ), but it went pretty well...)

What actual display are you using (ILI9341?), and how is it connected? (how does the canvas demo figure this out?) The GFX example will also need the hardware driver for the particular display linked in somehow, right? How is that happening (how does the GFXCanvas example even COMPILE without me specifying a particular display??)

considering the libraries are so terrible for tft screens with refresh rate
Yes, the library is full of special optimization for particular processors, designed to eke out the best performance possible. And there isn't any such optimized code for the rp2040. (and it's entirely possible that having an mBed layer interferes with performance as well.)

But that's a distraction. "Not as fast as I want it to be" is not at all the same thing as "doesn't work at all." If you're going to get anywhere (other than re-writing your code as you've described, which is undesirable and OUGHT to be unnecessary), you need to focus on one problem at a time (and the most serious problem first.)

Yes, it's unfortunate that a product can get released without everything working perfectly. But that's reality, and things will go better for everyone if you aim at helping to make the broken things work instead of just complaining, or even doing your own "work-arounds."


at a meager 63.5mhz it should be well past 60 fps.

(I know I said not to get distracted by performance issues, but... 320x240x24 is ~1.8Mb. At 63.5Mbps, I don't see how you can expect more than about 30fps, and that would need "zero overhead" in the transfer...)

its not even about 30 fps. its about getting 5fps even. adafruits library cant do it. bodmers doesnt work regardless of his nonsense and the tft companies proved that a datastream at their specified rates would be sufficient for 70 hrz fps.

now the datasheet for ili9341 says 6.35 mhz is whats needed but the arduino code has to be run to process things. even at 10 clock cycles for every 1 spi it shouldnt even need a real buffer since the screen has one. 170kb of ram on the screen. so as long as it sends the data for 1 pixle every 10 clock cycle it should be able to do it at stock clock speed (arduino thinks its 125 mhz)

i dont think arduino runs spi at the clock speed it claims. i think only 12c runs at the claimed speed and every thing else has some kind of throttling in the ide

*added a quick google search shows arduino spi locked at 16mhz regardless of any settings. this means there should be some kind of disclaimer for all arduino boards especially the rp2040 connect. its not even a usable speed for practically anything and why even have a 32 bit processor board if its going to act like a 8bit one

There is an Arduino API default SPI speed that is supposed to be 4MHz, but it looks like the RP2040 SPI only runs at 1MHz by default:

You can up the speed using SPI.beginTransaction with a new SPISettings value.

that is pretty useful thnx. yea i was thinking it was going slower than listed

BTW, I suspect that the RP2040 could use it's "PIO" state machines to drive an ILI9341 display in "parallel IO mode" at probably 8x the speed it's capable of doing on SPI.
But that would be a pretty significant development effort.

BTW, here's some code that will allow you to determine the actual SPI Speed that the rp2040 hardware is configured for. Just stick it at the top of your sketch:

#ifdef ARDUINO_ARCH_MBED
#include <clocks.h>
#endif
long getHWSPISpeed() {
  return clock_get_hz(clk_peri) / ((long)spi0_hw->cpsr * ((spi0_hw->cr0 >> 8) + 1));
}

It should work with both the Arduino MBed Core and Earle's SDK-based core...