Skip to main content
Added update text
Source Link
Casey
  • 151
  • 6

Is it possible for a function/method to know if a constant array that has been passed in is in flash or RAM?

If I have a method or function that receives a constant array that is in RAM, the array is declared like this: const uint8_t MY_ARRAY[] = { 1, 2, 3, 4 };

gets passed into a method or function like this: MyFunction(MY_ARRAY);

and the method or function can handle it like this:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = MY_ARRAY[1];
     ...

However, if the array is in Flash (because it's a constant array, so that's where it should go), then the declaration adds PROGMEM: const uint8_t PROGMEM MY_ARRAY[] = { 1, 2, 3, 4 };

The pass looks the same: MyFunction(MY_ARRAY);

And the function declaration looks the same but it needs to use pgm_read_byte_near to get the correct values back:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = pgm_read_byte_near(MY_ARRAY+1);
     ...

How can the receiving method know if the array is in flash (PROGMEM) or RAM (no PROGMEM) so it knows to use pgm_read_byte_near or not? Ideally I'd like a compiler error, but the type is the same (both are const arrays of uint8_t).

If pgm_read_byte_near is used when it shouldn't be, or it's not used when it should be, the results are garbage.

Some relevant questions: How to pass a static const (progmem) array to a function

RAM usage question: PROGMEM vs const vs #define

Storing array in PROGMEM

PROGMEM: do I have to copy data from flash to RAM for reading?

UPDATE: It looks like what I want to do is not possible. The responses below are very interesting options though: using __flash in plain C, using OOP to make PROGMEM and non-PROGMEM data holders or trying to (somehow?) use non-deprecated progmem specific data types from avr/gpmspace.h.

The best answer to my original question is that the method can not make this determination. The best solution, from a comment by Delta_G, is to create regular (ram) and "_P" (flash/ progmem) versions of the functions and to be as obvious as possible in the naming of those functions.

Is it possible for a function/method to know if a constant array that has been passed in is in flash or RAM?

If I have a method or function that receives a constant array that is in RAM, the array is declared like this: const uint8_t MY_ARRAY[] = { 1, 2, 3, 4 };

gets passed into a method or function like this: MyFunction(MY_ARRAY);

and the method or function can handle it like this:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = MY_ARRAY[1];
     ...

However, if the array is in Flash (because it's a constant array, so that's where it should go), then the declaration adds PROGMEM: const uint8_t PROGMEM MY_ARRAY[] = { 1, 2, 3, 4 };

The pass looks the same: MyFunction(MY_ARRAY);

And the function declaration looks the same but it needs to use pgm_read_byte_near to get the correct values back:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = pgm_read_byte_near(MY_ARRAY+1);
     ...

How can the receiving method know if the array is in flash (PROGMEM) or RAM (no PROGMEM) so it knows to use pgm_read_byte_near or not? Ideally I'd like a compiler error, but the type is the same (both are const arrays of uint8_t).

If pgm_read_byte_near is used when it shouldn't be, or it's not used when it should be, the results are garbage.

Some relevant questions: How to pass a static const (progmem) array to a function

RAM usage question: PROGMEM vs const vs #define

Storing array in PROGMEM

PROGMEM: do I have to copy data from flash to RAM for reading?

UPDATE: It looks like what I want to do is not possible. The responses below are very interesting options though: using __flash in plain C, using OOP to make PROGMEM and non-PROGMEM data holders or trying to (somehow?) use non-deprecated progmem specific data types from avr/gpmspace.h.

Is it possible for a function/method to know if a constant array that has been passed in is in flash or RAM?

If I have a method or function that receives a constant array that is in RAM, the array is declared like this: const uint8_t MY_ARRAY[] = { 1, 2, 3, 4 };

gets passed into a method or function like this: MyFunction(MY_ARRAY);

and the method or function can handle it like this:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = MY_ARRAY[1];
     ...

However, if the array is in Flash (because it's a constant array, so that's where it should go), then the declaration adds PROGMEM: const uint8_t PROGMEM MY_ARRAY[] = { 1, 2, 3, 4 };

The pass looks the same: MyFunction(MY_ARRAY);

And the function declaration looks the same but it needs to use pgm_read_byte_near to get the correct values back:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = pgm_read_byte_near(MY_ARRAY+1);
     ...

How can the receiving method know if the array is in flash (PROGMEM) or RAM (no PROGMEM) so it knows to use pgm_read_byte_near or not? Ideally I'd like a compiler error, but the type is the same (both are const arrays of uint8_t).

If pgm_read_byte_near is used when it shouldn't be, or it's not used when it should be, the results are garbage.

Some relevant questions: How to pass a static const (progmem) array to a function

RAM usage question: PROGMEM vs const vs #define

Storing array in PROGMEM

PROGMEM: do I have to copy data from flash to RAM for reading?

UPDATE: It looks like what I want to do is not possible. The responses below are very interesting options though: using __flash in plain C, using OOP to make PROGMEM and non-PROGMEM data holders or trying to (somehow?) use non-deprecated progmem specific data types from avr/gpmspace.h.

The best answer to my original question is that the method can not make this determination. The best solution, from a comment by Delta_G, is to create regular (ram) and "_P" (flash/ progmem) versions of the functions and to be as obvious as possible in the naming of those functions.

Added update text
Source Link
Casey
  • 151
  • 6

Is it possible for a function/method to know if a constant array that has been passed in is in flash or RAM?

If I have a method or function that receives a constant array that is in RAM, the array is declared like this: const uint8_t MY_ARRAY[] = { 1, 2, 3, 4 };

gets passed into a method or function like this: MyFunction(MY_ARRAY);

and the method or function can handle it like this:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = MY_ARRAY[1];
     ...

However, if the array is in Flash (because it's a constant array, so that's where it should go), then the declaration adds PROGMEM: const uint8_t PROGMEM MY_ARRAY[] = { 1, 2, 3, 4 };

The pass looks the same: MyFunction(MY_ARRAY);

And the function declaration looks the same but it needs to use pgm_read_byte_near to get the correct values back:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = pgm_read_byte_near(MY_ARRAY+1);
     ...

How can the receiving method know if the array is in flash (PROGMEM) or RAM (no PROGMEM) so it knows to use pgm_read_byte_near or not? Ideally I'd like a compiler error, but the type is the same (both are const arrays of uint8_t).

If pgm_read_byte_near is used when it shouldn't be, or it's not used when it should be, the results are garbage.

Some relevant questions: How to pass a static const (progmem) array to a function

RAM usage question: PROGMEM vs const vs #define

Storing array in PROGMEM

PROGMEM: do I have to copy data from flash to RAM for reading?

UPDATE: It looks like what I want to do is not possible. The responses below are very interesting options though: using __flash in plain C, using OOP to make PROGMEM and non-PROGMEM data holders or trying to (somehow?) use non-deprecated progmem specific data types from avr/gpmspace.h.

Is it possible for a function/method to know if a constant array that has been passed in is in flash or RAM?

If I have a method or function that receives a constant array that is in RAM, the array is declared like this: const uint8_t MY_ARRAY[] = { 1, 2, 3, 4 };

gets passed into a method or function like this: MyFunction(MY_ARRAY);

and the method or function can handle it like this:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = MY_ARRAY[1];
     ...

However, if the array is in Flash (because it's a constant array, so that's where it should go), then the declaration adds PROGMEM: const uint8_t PROGMEM MY_ARRAY[] = { 1, 2, 3, 4 };

The pass looks the same: MyFunction(MY_ARRAY);

And the function declaration looks the same but it needs to use pgm_read_byte_near to get the correct values back:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = pgm_read_byte_near(MY_ARRAY+1);
     ...

How can the receiving method know if the array is in flash (PROGMEM) or RAM (no PROGMEM) so it knows to use pgm_read_byte_near or not? Ideally I'd like a compiler error, but the type is the same (both are const arrays of uint8_t).

If pgm_read_byte_near is used when it shouldn't be, or it's not used when it should be, the results are garbage.

Some relevant questions: How to pass a static const (progmem) array to a function

RAM usage question: PROGMEM vs const vs #define

Storing array in PROGMEM

PROGMEM: do I have to copy data from flash to RAM for reading?

Is it possible for a function/method to know if a constant array that has been passed in is in flash or RAM?

If I have a method or function that receives a constant array that is in RAM, the array is declared like this: const uint8_t MY_ARRAY[] = { 1, 2, 3, 4 };

gets passed into a method or function like this: MyFunction(MY_ARRAY);

and the method or function can handle it like this:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = MY_ARRAY[1];
     ...

However, if the array is in Flash (because it's a constant array, so that's where it should go), then the declaration adds PROGMEM: const uint8_t PROGMEM MY_ARRAY[] = { 1, 2, 3, 4 };

The pass looks the same: MyFunction(MY_ARRAY);

And the function declaration looks the same but it needs to use pgm_read_byte_near to get the correct values back:

void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = pgm_read_byte_near(MY_ARRAY+1);
     ...

How can the receiving method know if the array is in flash (PROGMEM) or RAM (no PROGMEM) so it knows to use pgm_read_byte_near or not? Ideally I'd like a compiler error, but the type is the same (both are const arrays of uint8_t).

If pgm_read_byte_near is used when it shouldn't be, or it's not used when it should be, the results are garbage.

Some relevant questions: How to pass a static const (progmem) array to a function

RAM usage question: PROGMEM vs const vs #define

Storing array in PROGMEM

PROGMEM: do I have to copy data from flash to RAM for reading?

UPDATE: It looks like what I want to do is not possible. The responses below are very interesting options though: using __flash in plain C, using OOP to make PROGMEM and non-PROGMEM data holders or trying to (somehow?) use non-deprecated progmem specific data types from avr/gpmspace.h.

Tweeted twitter.com/StackArduino/status/1261944570721587200
edited tags
Link
Juraj
  • 18.2k
  • 4
  • 30
  • 49
Became Hot Network Question
Source Link
Casey
  • 151
  • 6
Loading