Skip to main content
-Waddr-space-convert is needed only for getting warnings.
Source Link
Edgar Bonet
  • 44.3k
  • 4
  • 41
  • 79

I am afraid there is no good solution to this problem. One option I do like is to use the __flash qualifier instead of PROGMEM:

const uint8_t ram_array[] = { 1, 2, 3, 4 };
__flash const uint8_t flash_array[] = { 5, 6, 7, 8 };

void function_reading_ram(const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

void function_reading_flash(__flash const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

int main(void)
{
    function_reading_ram(ram_array);      // OK
    function_reading_flash(flash_array);  // OK
    function_reading_ram(flash_array);    // Warning
    function_reading_flash(ram_array);    // Warning
}

Note that, with __flash, you don't need pgm_read_byte_near() or anything similar. You just use the array like you would use any regular array, and the compiler is smart enough to generate the code required to access the Flash memory.

The warnings generated by gcc are:

warning: conversion from address space ‘__flash’ to address space ‘generic’ [-Waddr-space-convert]
     function_reading_ram(flash_array);
     ^
warning: conversion from address space ‘generic’ to address space ‘__flash’ [-Waddr-space-convert]
     function_reading_flash(ram_array);
     ^

Given how nice this solution is, you may wonder why I wrote “there is no good solution”. Well, this comes with two caveats, one small and one huge. The small caveat is that you need to explicitly pass the option -Waddr-space-convert to the compiler if you want it to generate the warnings. It It is not implied even with -Wall -Wextra. The huge caveat is that this only works in plain C. If you try to use this trick in C++ you get:

error: ‘__flash’ does not name a type

This is an implementation of the “named address spaces” extension to the standard C. Since nothing like this is standardized in C++, the authors of gcc assumed it would not be useful to users of C++. :-( You can mix C and C++ sources in Arduino, but you can't call class methods from C.

I am afraid there is no good solution to this problem. One option I do like is to use the __flash qualifier instead of PROGMEM:

const uint8_t ram_array[] = { 1, 2, 3, 4 };
__flash const uint8_t flash_array[] = { 5, 6, 7, 8 };

void function_reading_ram(const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

void function_reading_flash(__flash const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

int main(void)
{
    function_reading_ram(ram_array);      // OK
    function_reading_flash(flash_array);  // OK
    function_reading_ram(flash_array);    // Warning
    function_reading_flash(ram_array);    // Warning
}

Note that, with __flash, you don't need pgm_read_byte_near() or anything similar. You just use the array like you would use any regular array, and the compiler is smart enough to generate the code required to access the Flash memory.

The warnings generated by gcc are:

warning: conversion from address space ‘__flash’ to address space ‘generic’ [-Waddr-space-convert]
     function_reading_ram(flash_array);
     ^
warning: conversion from address space ‘generic’ to address space ‘__flash’ [-Waddr-space-convert]
     function_reading_flash(ram_array);
     ^

Given how nice this solution is, you may wonder why I wrote “there is no good solution”. Well, this comes with two caveats, one small and one huge. The small caveat is that you need to explicitly pass the option -Waddr-space-convert to the compiler. It is not implied even with -Wall -Wextra. The huge caveat is that this only works in plain C. If you try to use this trick in C++ you get:

error: ‘__flash’ does not name a type

This is an implementation of the “named address spaces” extension to the standard C. Since nothing like this is standardized in C++, the authors of gcc assumed it would not be useful to users of C++. :-( You can mix C and C++ sources in Arduino, but you can't call class methods from C.

I am afraid there is no good solution to this problem. One option I do like is to use the __flash qualifier instead of PROGMEM:

const uint8_t ram_array[] = { 1, 2, 3, 4 };
__flash const uint8_t flash_array[] = { 5, 6, 7, 8 };

void function_reading_ram(const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

void function_reading_flash(__flash const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

int main(void)
{
    function_reading_ram(ram_array);      // OK
    function_reading_flash(flash_array);  // OK
    function_reading_ram(flash_array);    // Warning
    function_reading_flash(ram_array);    // Warning
}

Note that, with __flash, you don't need pgm_read_byte_near() or anything similar. You just use the array like you would use any regular array, and the compiler is smart enough to generate the code required to access the Flash memory.

The warnings generated by gcc are:

warning: conversion from address space ‘__flash’ to address space ‘generic’ [-Waddr-space-convert]
     function_reading_ram(flash_array);
     ^
warning: conversion from address space ‘generic’ to address space ‘__flash’ [-Waddr-space-convert]
     function_reading_flash(ram_array);
     ^

Given how nice this solution is, you may wonder why I wrote “there is no good solution”. Well, this comes with two caveats, one small and one huge. The small caveat is that you need to explicitly pass the option -Waddr-space-convert to the compiler if you want it to generate the warnings. It is not implied even with -Wall -Wextra. The huge caveat is that this only works in plain C. If you try to use this trick in C++ you get:

error: ‘__flash’ does not name a type

This is an implementation of the “named address spaces” extension to the standard C. Since nothing like this is standardized in C++, the authors of gcc assumed it would not be useful to users of C++. :-( You can mix C and C++ sources in Arduino, but you can't call class methods from C.

Source Link
Edgar Bonet
  • 44.3k
  • 4
  • 41
  • 79

I am afraid there is no good solution to this problem. One option I do like is to use the __flash qualifier instead of PROGMEM:

const uint8_t ram_array[] = { 1, 2, 3, 4 };
__flash const uint8_t flash_array[] = { 5, 6, 7, 8 };

void function_reading_ram(const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

void function_reading_flash(__flash const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

int main(void)
{
    function_reading_ram(ram_array);      // OK
    function_reading_flash(flash_array);  // OK
    function_reading_ram(flash_array);    // Warning
    function_reading_flash(ram_array);    // Warning
}

Note that, with __flash, you don't need pgm_read_byte_near() or anything similar. You just use the array like you would use any regular array, and the compiler is smart enough to generate the code required to access the Flash memory.

The warnings generated by gcc are:

warning: conversion from address space ‘__flash’ to address space ‘generic’ [-Waddr-space-convert]
     function_reading_ram(flash_array);
     ^
warning: conversion from address space ‘generic’ to address space ‘__flash’ [-Waddr-space-convert]
     function_reading_flash(ram_array);
     ^

Given how nice this solution is, you may wonder why I wrote “there is no good solution”. Well, this comes with two caveats, one small and one huge. The small caveat is that you need to explicitly pass the option -Waddr-space-convert to the compiler. It is not implied even with -Wall -Wextra. The huge caveat is that this only works in plain C. If you try to use this trick in C++ you get:

error: ‘__flash’ does not name a type

This is an implementation of the “named address spaces” extension to the standard C. Since nothing like this is standardized in C++, the authors of gcc assumed it would not be useful to users of C++. :-( You can mix C and C++ sources in Arduino, but you can't call class methods from C.