accessing data from structure in flash









up vote
2
down vote

favorite












I am using an Atmel AVR and am trying to access data from a structure which is stored in flash (program) memory.



The structure is:



typedef struct 
uint8_t width;
uint8_t height; // row number 0 to 5
uint8_t images; // how many frames does this bitmap have
uint8_t data; // the actual pixel data
bitmap_t;


the data is:



 __flash static const bitmap_t bmp_stereo2 = 14,1,1,126,129,60,66,24,36,60,60,36,24,66,60,129,126;


I'm trying to access the data with (partial code shown)...



void lcd_bitmap2(const bitmap_t *bit, uint8_t id, uint8_t posx, uint8_t posy) {
uint8_t x;
uint8_t y;

const uint8_t bw = pgm_read_byte(&bit->width); // this works -- I can print out to serial
const uint8_t bh = pgm_read_byte(&bit->height); //this also works -- I can print out to serial
// this doesn't work
const uint8_t *data = pgm_read_word(&bit->data); // I get: - initialization makes pointer from integer without a cast [enabled by default]

const uint8_t *data = (uint8_t *)pgm_read_word(&bit->data); // this also doen't work (no warning, but wrong data read out)

//rest of function...


So I can access the width, height and image variable, but not the data part of the structure.
It all works if I don't store in flash - It's my retrieval and only has a problem with the data array part of the structure (width, height and image are read ok)










share|improve this question



























    up vote
    2
    down vote

    favorite












    I am using an Atmel AVR and am trying to access data from a structure which is stored in flash (program) memory.



    The structure is:



    typedef struct 
    uint8_t width;
    uint8_t height; // row number 0 to 5
    uint8_t images; // how many frames does this bitmap have
    uint8_t data; // the actual pixel data
    bitmap_t;


    the data is:



     __flash static const bitmap_t bmp_stereo2 = 14,1,1,126,129,60,66,24,36,60,60,36,24,66,60,129,126;


    I'm trying to access the data with (partial code shown)...



    void lcd_bitmap2(const bitmap_t *bit, uint8_t id, uint8_t posx, uint8_t posy) {
    uint8_t x;
    uint8_t y;

    const uint8_t bw = pgm_read_byte(&bit->width); // this works -- I can print out to serial
    const uint8_t bh = pgm_read_byte(&bit->height); //this also works -- I can print out to serial
    // this doesn't work
    const uint8_t *data = pgm_read_word(&bit->data); // I get: - initialization makes pointer from integer without a cast [enabled by default]

    const uint8_t *data = (uint8_t *)pgm_read_word(&bit->data); // this also doen't work (no warning, but wrong data read out)

    //rest of function...


    So I can access the width, height and image variable, but not the data part of the structure.
    It all works if I don't store in flash - It's my retrieval and only has a problem with the data array part of the structure (width, height and image are read ok)










    share|improve this question

























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I am using an Atmel AVR and am trying to access data from a structure which is stored in flash (program) memory.



      The structure is:



      typedef struct 
      uint8_t width;
      uint8_t height; // row number 0 to 5
      uint8_t images; // how many frames does this bitmap have
      uint8_t data; // the actual pixel data
      bitmap_t;


      the data is:



       __flash static const bitmap_t bmp_stereo2 = 14,1,1,126,129,60,66,24,36,60,60,36,24,66,60,129,126;


      I'm trying to access the data with (partial code shown)...



      void lcd_bitmap2(const bitmap_t *bit, uint8_t id, uint8_t posx, uint8_t posy) {
      uint8_t x;
      uint8_t y;

      const uint8_t bw = pgm_read_byte(&bit->width); // this works -- I can print out to serial
      const uint8_t bh = pgm_read_byte(&bit->height); //this also works -- I can print out to serial
      // this doesn't work
      const uint8_t *data = pgm_read_word(&bit->data); // I get: - initialization makes pointer from integer without a cast [enabled by default]

      const uint8_t *data = (uint8_t *)pgm_read_word(&bit->data); // this also doen't work (no warning, but wrong data read out)

      //rest of function...


      So I can access the width, height and image variable, but not the data part of the structure.
      It all works if I don't store in flash - It's my retrieval and only has a problem with the data array part of the structure (width, height and image are read ok)










      share|improve this question















      I am using an Atmel AVR and am trying to access data from a structure which is stored in flash (program) memory.



      The structure is:



      typedef struct 
      uint8_t width;
      uint8_t height; // row number 0 to 5
      uint8_t images; // how many frames does this bitmap have
      uint8_t data; // the actual pixel data
      bitmap_t;


      the data is:



       __flash static const bitmap_t bmp_stereo2 = 14,1,1,126,129,60,66,24,36,60,60,36,24,66,60,129,126;


      I'm trying to access the data with (partial code shown)...



      void lcd_bitmap2(const bitmap_t *bit, uint8_t id, uint8_t posx, uint8_t posy) {
      uint8_t x;
      uint8_t y;

      const uint8_t bw = pgm_read_byte(&bit->width); // this works -- I can print out to serial
      const uint8_t bh = pgm_read_byte(&bit->height); //this also works -- I can print out to serial
      // this doesn't work
      const uint8_t *data = pgm_read_word(&bit->data); // I get: - initialization makes pointer from integer without a cast [enabled by default]

      const uint8_t *data = (uint8_t *)pgm_read_word(&bit->data); // this also doen't work (no warning, but wrong data read out)

      //rest of function...


      So I can access the width, height and image variable, but not the data part of the structure.
      It all works if I don't store in flash - It's my retrieval and only has a problem with the data array part of the structure (width, height and image are read ok)







      c structure avr avr-gcc flash-memory






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 10 at 17:35









      ReAl

      542215




      542215










      asked Nov 10 at 15:20









      Russell

      111




      111






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          1
          down vote













          TL;DR: you cannot safely do that in standard C.



          Given this definition ...




          typedef struct 
          uint8_t width;
          uint8_t height; // row number 0 to 5
          uint8_t images; // how many frames does this bitmap have
          uint8_t data; // the actual pixel data
          bitmap_t;



          ... bitmap_t.data is a "flexible array member":




          As a special case, the last element of a structure with more than one
          named member may have an incomplete array type; this is called a
          flexible array member. In most situations, the flexible array member
          is ignored
          . In particular, the size of the structure is as if the
          flexible array member were omitted except that it may have more
          trailing padding than the omission would imply. However, when a . (or
          ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member,
          it behaves as if that member were replaced with the longest array
          (with the same element type) that would not make the structure larger
          than the object being accessed [...].




          [C2011 6.7.2.1/18; emphasis added]



          Examples in the standard clarify that it is invalid to provide an initializer for a flexible array member, as your code attempts to do. Moreover, there is no reason to expect that any space at all will be allocated for the contents of a flexible array member of an object with static or automatic storage duration, such as yours. Flexible array members are useful only in conjunction with dynamically allocated objects, unless in an implementation that makes promises in this area beyond those required by the standard.



          Accessing the flexible array member of your statically allocated object therefore produces undefined behavior. This is not directly related to the actual location of the storage, though it is possible that the UB manifests differently when it is in flash. (After all, the behavior is undefined.) To use objects of type bitmap_t in the way you are trying to do, you will need to modify that type so that its data member has a complete type (i.e. fixed dimension(s)).






          share|improve this answer




















          • Thank so much - that sorted it. Not sure why data needs the __flash in front -(__flash const uint8_t *data = bit->data;) but the others don't - is that the array handling difference? many thanks and all others who replied
            – Russell
            Nov 10 at 18:49










          • @Russell if some variable placed in __flash memory space, a pointer to this variable must be qualified as __flash. So, __flash const uint8_t *ptr; is a pointer in data space (perhaps in CPU register) that points to __flash const uint8_t variable, i.e. the variable placed in flash. Compare with uint8_t * __flash const ptrf; — constant pointer itself placed in __flash space and it points to variable in data space (RAM).
            – ReAl
            Nov 10 at 19:13

















          up vote
          1
          down vote













          (independently of John Bollinger answer)



          You incorrectly use pgm_read_word to ->data member of bitmap_t here and the code would not work even if the structure will be defined with, say, data[14].



          Let XXX is an byte-size object in flash memory.
          You can read it with pgm_read_byte(& XXX)
          So that, one can read pixel at position pixel_number (data[pixel_number] object) this way:



          // just address of first byte in data
          const uint8_t *data = bit->data;

          uint8_t pixel = pgm_read_byte(&data[pixel_number]);


          The same result gets from direct structure access



          uint8_t pixel = pgm_read_byte(&bit->data[pixel_number]);


          At last, modern avr-gcc compilers (those with the keyword __flash) can do this automatically.
          Just declare all pointers with __flash modifier (<avr/pgmspace.h> can be omitted):



          void lcd_bitmap2(__flash const bitmap_t *bit, uint8_t id,
          uint8_t posx, uint8_t posy)
          {
          uint8_t x;
          uint8_t y;

          const uint8_t bw = bit->width;
          const uint8_t bh = bit->height;
          __flash const uint8_t *data = bit->data;

          uint8_t pixel_number; // make calculations with id, bw, bh and positions

          uint8_t pixel = data[pixel_number];

          // or ditectly pixel = bit->data[pixel_number];


          p.s. From my experience, avr-gcc process incomplete array initialization (also in flash) and access in the way you expected.






          share|improve this answer






















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53240360%2faccessing-data-from-structure-in-flash%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote













            TL;DR: you cannot safely do that in standard C.



            Given this definition ...




            typedef struct 
            uint8_t width;
            uint8_t height; // row number 0 to 5
            uint8_t images; // how many frames does this bitmap have
            uint8_t data; // the actual pixel data
            bitmap_t;



            ... bitmap_t.data is a "flexible array member":




            As a special case, the last element of a structure with more than one
            named member may have an incomplete array type; this is called a
            flexible array member. In most situations, the flexible array member
            is ignored
            . In particular, the size of the structure is as if the
            flexible array member were omitted except that it may have more
            trailing padding than the omission would imply. However, when a . (or
            ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member,
            it behaves as if that member were replaced with the longest array
            (with the same element type) that would not make the structure larger
            than the object being accessed [...].




            [C2011 6.7.2.1/18; emphasis added]



            Examples in the standard clarify that it is invalid to provide an initializer for a flexible array member, as your code attempts to do. Moreover, there is no reason to expect that any space at all will be allocated for the contents of a flexible array member of an object with static or automatic storage duration, such as yours. Flexible array members are useful only in conjunction with dynamically allocated objects, unless in an implementation that makes promises in this area beyond those required by the standard.



            Accessing the flexible array member of your statically allocated object therefore produces undefined behavior. This is not directly related to the actual location of the storage, though it is possible that the UB manifests differently when it is in flash. (After all, the behavior is undefined.) To use objects of type bitmap_t in the way you are trying to do, you will need to modify that type so that its data member has a complete type (i.e. fixed dimension(s)).






            share|improve this answer




















            • Thank so much - that sorted it. Not sure why data needs the __flash in front -(__flash const uint8_t *data = bit->data;) but the others don't - is that the array handling difference? many thanks and all others who replied
              – Russell
              Nov 10 at 18:49










            • @Russell if some variable placed in __flash memory space, a pointer to this variable must be qualified as __flash. So, __flash const uint8_t *ptr; is a pointer in data space (perhaps in CPU register) that points to __flash const uint8_t variable, i.e. the variable placed in flash. Compare with uint8_t * __flash const ptrf; — constant pointer itself placed in __flash space and it points to variable in data space (RAM).
              – ReAl
              Nov 10 at 19:13














            up vote
            1
            down vote













            TL;DR: you cannot safely do that in standard C.



            Given this definition ...




            typedef struct 
            uint8_t width;
            uint8_t height; // row number 0 to 5
            uint8_t images; // how many frames does this bitmap have
            uint8_t data; // the actual pixel data
            bitmap_t;



            ... bitmap_t.data is a "flexible array member":




            As a special case, the last element of a structure with more than one
            named member may have an incomplete array type; this is called a
            flexible array member. In most situations, the flexible array member
            is ignored
            . In particular, the size of the structure is as if the
            flexible array member were omitted except that it may have more
            trailing padding than the omission would imply. However, when a . (or
            ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member,
            it behaves as if that member were replaced with the longest array
            (with the same element type) that would not make the structure larger
            than the object being accessed [...].




            [C2011 6.7.2.1/18; emphasis added]



            Examples in the standard clarify that it is invalid to provide an initializer for a flexible array member, as your code attempts to do. Moreover, there is no reason to expect that any space at all will be allocated for the contents of a flexible array member of an object with static or automatic storage duration, such as yours. Flexible array members are useful only in conjunction with dynamically allocated objects, unless in an implementation that makes promises in this area beyond those required by the standard.



            Accessing the flexible array member of your statically allocated object therefore produces undefined behavior. This is not directly related to the actual location of the storage, though it is possible that the UB manifests differently when it is in flash. (After all, the behavior is undefined.) To use objects of type bitmap_t in the way you are trying to do, you will need to modify that type so that its data member has a complete type (i.e. fixed dimension(s)).






            share|improve this answer




















            • Thank so much - that sorted it. Not sure why data needs the __flash in front -(__flash const uint8_t *data = bit->data;) but the others don't - is that the array handling difference? many thanks and all others who replied
              – Russell
              Nov 10 at 18:49










            • @Russell if some variable placed in __flash memory space, a pointer to this variable must be qualified as __flash. So, __flash const uint8_t *ptr; is a pointer in data space (perhaps in CPU register) that points to __flash const uint8_t variable, i.e. the variable placed in flash. Compare with uint8_t * __flash const ptrf; — constant pointer itself placed in __flash space and it points to variable in data space (RAM).
              – ReAl
              Nov 10 at 19:13












            up vote
            1
            down vote










            up vote
            1
            down vote









            TL;DR: you cannot safely do that in standard C.



            Given this definition ...




            typedef struct 
            uint8_t width;
            uint8_t height; // row number 0 to 5
            uint8_t images; // how many frames does this bitmap have
            uint8_t data; // the actual pixel data
            bitmap_t;



            ... bitmap_t.data is a "flexible array member":




            As a special case, the last element of a structure with more than one
            named member may have an incomplete array type; this is called a
            flexible array member. In most situations, the flexible array member
            is ignored
            . In particular, the size of the structure is as if the
            flexible array member were omitted except that it may have more
            trailing padding than the omission would imply. However, when a . (or
            ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member,
            it behaves as if that member were replaced with the longest array
            (with the same element type) that would not make the structure larger
            than the object being accessed [...].




            [C2011 6.7.2.1/18; emphasis added]



            Examples in the standard clarify that it is invalid to provide an initializer for a flexible array member, as your code attempts to do. Moreover, there is no reason to expect that any space at all will be allocated for the contents of a flexible array member of an object with static or automatic storage duration, such as yours. Flexible array members are useful only in conjunction with dynamically allocated objects, unless in an implementation that makes promises in this area beyond those required by the standard.



            Accessing the flexible array member of your statically allocated object therefore produces undefined behavior. This is not directly related to the actual location of the storage, though it is possible that the UB manifests differently when it is in flash. (After all, the behavior is undefined.) To use objects of type bitmap_t in the way you are trying to do, you will need to modify that type so that its data member has a complete type (i.e. fixed dimension(s)).






            share|improve this answer












            TL;DR: you cannot safely do that in standard C.



            Given this definition ...




            typedef struct 
            uint8_t width;
            uint8_t height; // row number 0 to 5
            uint8_t images; // how many frames does this bitmap have
            uint8_t data; // the actual pixel data
            bitmap_t;



            ... bitmap_t.data is a "flexible array member":




            As a special case, the last element of a structure with more than one
            named member may have an incomplete array type; this is called a
            flexible array member. In most situations, the flexible array member
            is ignored
            . In particular, the size of the structure is as if the
            flexible array member were omitted except that it may have more
            trailing padding than the omission would imply. However, when a . (or
            ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member,
            it behaves as if that member were replaced with the longest array
            (with the same element type) that would not make the structure larger
            than the object being accessed [...].




            [C2011 6.7.2.1/18; emphasis added]



            Examples in the standard clarify that it is invalid to provide an initializer for a flexible array member, as your code attempts to do. Moreover, there is no reason to expect that any space at all will be allocated for the contents of a flexible array member of an object with static or automatic storage duration, such as yours. Flexible array members are useful only in conjunction with dynamically allocated objects, unless in an implementation that makes promises in this area beyond those required by the standard.



            Accessing the flexible array member of your statically allocated object therefore produces undefined behavior. This is not directly related to the actual location of the storage, though it is possible that the UB manifests differently when it is in flash. (After all, the behavior is undefined.) To use objects of type bitmap_t in the way you are trying to do, you will need to modify that type so that its data member has a complete type (i.e. fixed dimension(s)).







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 10 at 15:54









            John Bollinger

            76.3k63771




            76.3k63771











            • Thank so much - that sorted it. Not sure why data needs the __flash in front -(__flash const uint8_t *data = bit->data;) but the others don't - is that the array handling difference? many thanks and all others who replied
              – Russell
              Nov 10 at 18:49










            • @Russell if some variable placed in __flash memory space, a pointer to this variable must be qualified as __flash. So, __flash const uint8_t *ptr; is a pointer in data space (perhaps in CPU register) that points to __flash const uint8_t variable, i.e. the variable placed in flash. Compare with uint8_t * __flash const ptrf; — constant pointer itself placed in __flash space and it points to variable in data space (RAM).
              – ReAl
              Nov 10 at 19:13
















            • Thank so much - that sorted it. Not sure why data needs the __flash in front -(__flash const uint8_t *data = bit->data;) but the others don't - is that the array handling difference? many thanks and all others who replied
              – Russell
              Nov 10 at 18:49










            • @Russell if some variable placed in __flash memory space, a pointer to this variable must be qualified as __flash. So, __flash const uint8_t *ptr; is a pointer in data space (perhaps in CPU register) that points to __flash const uint8_t variable, i.e. the variable placed in flash. Compare with uint8_t * __flash const ptrf; — constant pointer itself placed in __flash space and it points to variable in data space (RAM).
              – ReAl
              Nov 10 at 19:13















            Thank so much - that sorted it. Not sure why data needs the __flash in front -(__flash const uint8_t *data = bit->data;) but the others don't - is that the array handling difference? many thanks and all others who replied
            – Russell
            Nov 10 at 18:49




            Thank so much - that sorted it. Not sure why data needs the __flash in front -(__flash const uint8_t *data = bit->data;) but the others don't - is that the array handling difference? many thanks and all others who replied
            – Russell
            Nov 10 at 18:49












            @Russell if some variable placed in __flash memory space, a pointer to this variable must be qualified as __flash. So, __flash const uint8_t *ptr; is a pointer in data space (perhaps in CPU register) that points to __flash const uint8_t variable, i.e. the variable placed in flash. Compare with uint8_t * __flash const ptrf; — constant pointer itself placed in __flash space and it points to variable in data space (RAM).
            – ReAl
            Nov 10 at 19:13




            @Russell if some variable placed in __flash memory space, a pointer to this variable must be qualified as __flash. So, __flash const uint8_t *ptr; is a pointer in data space (perhaps in CPU register) that points to __flash const uint8_t variable, i.e. the variable placed in flash. Compare with uint8_t * __flash const ptrf; — constant pointer itself placed in __flash space and it points to variable in data space (RAM).
            – ReAl
            Nov 10 at 19:13












            up vote
            1
            down vote













            (independently of John Bollinger answer)



            You incorrectly use pgm_read_word to ->data member of bitmap_t here and the code would not work even if the structure will be defined with, say, data[14].



            Let XXX is an byte-size object in flash memory.
            You can read it with pgm_read_byte(& XXX)
            So that, one can read pixel at position pixel_number (data[pixel_number] object) this way:



            // just address of first byte in data
            const uint8_t *data = bit->data;

            uint8_t pixel = pgm_read_byte(&data[pixel_number]);


            The same result gets from direct structure access



            uint8_t pixel = pgm_read_byte(&bit->data[pixel_number]);


            At last, modern avr-gcc compilers (those with the keyword __flash) can do this automatically.
            Just declare all pointers with __flash modifier (<avr/pgmspace.h> can be omitted):



            void lcd_bitmap2(__flash const bitmap_t *bit, uint8_t id,
            uint8_t posx, uint8_t posy)
            {
            uint8_t x;
            uint8_t y;

            const uint8_t bw = bit->width;
            const uint8_t bh = bit->height;
            __flash const uint8_t *data = bit->data;

            uint8_t pixel_number; // make calculations with id, bw, bh and positions

            uint8_t pixel = data[pixel_number];

            // or ditectly pixel = bit->data[pixel_number];


            p.s. From my experience, avr-gcc process incomplete array initialization (also in flash) and access in the way you expected.






            share|improve this answer


























              up vote
              1
              down vote













              (independently of John Bollinger answer)



              You incorrectly use pgm_read_word to ->data member of bitmap_t here and the code would not work even if the structure will be defined with, say, data[14].



              Let XXX is an byte-size object in flash memory.
              You can read it with pgm_read_byte(& XXX)
              So that, one can read pixel at position pixel_number (data[pixel_number] object) this way:



              // just address of first byte in data
              const uint8_t *data = bit->data;

              uint8_t pixel = pgm_read_byte(&data[pixel_number]);


              The same result gets from direct structure access



              uint8_t pixel = pgm_read_byte(&bit->data[pixel_number]);


              At last, modern avr-gcc compilers (those with the keyword __flash) can do this automatically.
              Just declare all pointers with __flash modifier (<avr/pgmspace.h> can be omitted):



              void lcd_bitmap2(__flash const bitmap_t *bit, uint8_t id,
              uint8_t posx, uint8_t posy)
              {
              uint8_t x;
              uint8_t y;

              const uint8_t bw = bit->width;
              const uint8_t bh = bit->height;
              __flash const uint8_t *data = bit->data;

              uint8_t pixel_number; // make calculations with id, bw, bh and positions

              uint8_t pixel = data[pixel_number];

              // or ditectly pixel = bit->data[pixel_number];


              p.s. From my experience, avr-gcc process incomplete array initialization (also in flash) and access in the way you expected.






              share|improve this answer
























                up vote
                1
                down vote










                up vote
                1
                down vote









                (independently of John Bollinger answer)



                You incorrectly use pgm_read_word to ->data member of bitmap_t here and the code would not work even if the structure will be defined with, say, data[14].



                Let XXX is an byte-size object in flash memory.
                You can read it with pgm_read_byte(& XXX)
                So that, one can read pixel at position pixel_number (data[pixel_number] object) this way:



                // just address of first byte in data
                const uint8_t *data = bit->data;

                uint8_t pixel = pgm_read_byte(&data[pixel_number]);


                The same result gets from direct structure access



                uint8_t pixel = pgm_read_byte(&bit->data[pixel_number]);


                At last, modern avr-gcc compilers (those with the keyword __flash) can do this automatically.
                Just declare all pointers with __flash modifier (<avr/pgmspace.h> can be omitted):



                void lcd_bitmap2(__flash const bitmap_t *bit, uint8_t id,
                uint8_t posx, uint8_t posy)
                {
                uint8_t x;
                uint8_t y;

                const uint8_t bw = bit->width;
                const uint8_t bh = bit->height;
                __flash const uint8_t *data = bit->data;

                uint8_t pixel_number; // make calculations with id, bw, bh and positions

                uint8_t pixel = data[pixel_number];

                // or ditectly pixel = bit->data[pixel_number];


                p.s. From my experience, avr-gcc process incomplete array initialization (also in flash) and access in the way you expected.






                share|improve this answer














                (independently of John Bollinger answer)



                You incorrectly use pgm_read_word to ->data member of bitmap_t here and the code would not work even if the structure will be defined with, say, data[14].



                Let XXX is an byte-size object in flash memory.
                You can read it with pgm_read_byte(& XXX)
                So that, one can read pixel at position pixel_number (data[pixel_number] object) this way:



                // just address of first byte in data
                const uint8_t *data = bit->data;

                uint8_t pixel = pgm_read_byte(&data[pixel_number]);


                The same result gets from direct structure access



                uint8_t pixel = pgm_read_byte(&bit->data[pixel_number]);


                At last, modern avr-gcc compilers (those with the keyword __flash) can do this automatically.
                Just declare all pointers with __flash modifier (<avr/pgmspace.h> can be omitted):



                void lcd_bitmap2(__flash const bitmap_t *bit, uint8_t id,
                uint8_t posx, uint8_t posy)
                {
                uint8_t x;
                uint8_t y;

                const uint8_t bw = bit->width;
                const uint8_t bh = bit->height;
                __flash const uint8_t *data = bit->data;

                uint8_t pixel_number; // make calculations with id, bw, bh and positions

                uint8_t pixel = data[pixel_number];

                // or ditectly pixel = bit->data[pixel_number];


                p.s. From my experience, avr-gcc process incomplete array initialization (also in flash) and access in the way you expected.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 10 at 16:45

























                answered Nov 10 at 16:27









                ReAl

                542215




                542215



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53240360%2faccessing-data-from-structure-in-flash%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    Barbados

                    How to read a connectionString WITH PROVIDER in .NET Core?

                    Node.js Script on GitHub Pages or Amazon S3