memcpy_P and uint8_t array

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to store 8-byte uint8_t array in program. This is how I do it:

 

const uint8_t PROGMEM playIcon[] PROGMEM = {

    0b10000,
    0b11000,
    0b11100,
    0b11110,
    0b11100,
    0b11000,
    0b10000,
    0b00000

};

const uint8_t PROGMEM recordIcon[] PROGMEM = {

    0b01110,
    0b10001,
    0b10101,
    0b11011,
    0b10101,
    0b10001,
    0b01110,
    0b00000

};

const uint8_t PROGMEM stopIcon[] PROGMEM = {

    0b01110,
    0b10001,
    0b11111,
    0b11111,
    0b11111,
    0b10001,
    0b01110,
    0b00000

};

Then, for easier access, I want to put all those elements inside array, like this:

const uint8_t* const iconArray[] PROGMEM = {

    playIcon,
    recordIcon,
    stopIcon

};

Now, how do I copy contents of wanted parameter inside iconArray? I tried this:

 

uint8_t buffer[8];
memcpy_P(buffer, &iconArray[0], sizeof(iconArray[0]));

But that's not really working, even tho it compiles fine. The results are not those bytes stored in playIcon array, instead I get this (decimal):

 

231
2
45
45
45
45
45
45

What am I doing wrong?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Shantea wrote:
What am I doing wrong?

You need a double dereference. Both the icons themselves AND the pointers to them are in PROGMEM. The memcpy_P() will handle doing the LPM on the bytes of the icons themselves but not the pointer from the table which also needs an LPM access. Try:

memcpy_P(buffer, pgm_read_word(&iconArray[0]), sizeof(playIcon));

If you are using a compiler beyond version 4.6 you probably want to be exploring the new __flash at this point. You will still need the memcpy_P() but you won't need the pgm_read_word() dereference because the compiler will already know that iconArray[] is in __flash and will therefore use LPM anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Shantea wrote:

What am I doing wrong?

 

You need a double dereference. Both the icons themselves AND the pointers to them are in PROGMEM. The memcpy_P() will handle doing the LPM on the bytes of the icons themselves but not the pointer from the table which also needs an LPM access. Try:

memcpy_P(buffer, pgm_read_word(&iconArray[0]), sizeof(playIcon));

Great, thanks!

 

clawson wrote:
If you are using a compiler beyond version 4.6 you probably want to be exploring the new __flash at this point. You will still need the memcpy_P() but you won't need the pgm_read_word() dereference because the compiler will already know that iconArray[] is in __flash and will therefore use LPM anyway.

 

Didn't know about that. Do I need special include for that?

Last Edited: Wed. Mar 16, 2016 - 12:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Shantea wrote:
Do I need special include for that?

Nope this (__flash) support is built into the compiler itself - not part of the library. The C compiler actually "knows" __flash a bit like it knows "volatile" or "register" etc.

 

However you would still (almost always) continue to include <avr/pgmspace.h> anyway as you will still use things like memcpy_P(), PSTR() and all that stuff. The things you won't use any more are "PROGMEM" or any form of pgm_read_XXX() functions.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Shantea wrote:

Do I need special include for that?

 

Nope this (__flash) support is built into the compiler itself - not part of the library. The C compiler actually "knows" __flash a bit like it knows "volatile" or "register" etc.

 

However you would still (almost always) continue to include <avr/pgmspace.h> anyway as you will still use things like memcpy_P(), PSTR() and all that stuff. The things you won't use any more are "PROGMEM" or any form of pgm_read_XXX() functions.

 

Guess bold part was the key I didn't get it to compile. Also this: https://www.avrfreaks.net/forum/a...

 

I'm using C++.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Shantea wrote:

I'm using C++.

 

Oops. The C++ compiler doesn't know about __flash. Or was that just memex the C++ compiler doesn't know?

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Torby wrote:
The C++ compiler doesn't know about __flash. Or was that just memex the C++ compiler doesn't know?
No, it's all of it. The C++ development team won't let "non standard" things like "__flash" into their shiny compiler.