2

I got:

#include <inttypes.h>

typedef struct dbg_s dbg_t;
struct dbg_s{
    const uint8_t size;
    const uint8_t* item;
};

#define DBG_SIZE 2
const uint8_t const dbgItems[DBG_SIZE] PROGMEM = {1,2};
const dbg_t const dbgMenu = {DBG_SIZE, dbgItems};
const dbg_t* ptr_global = &dbgMenu;

void dbg_init(void){
    const dbg_t* ptr_local = &dbgMenu;
}

what results in the watch of:

Name        Value                   Type
ptr_global  0xc47b                  dbg_t*{prog}@0x0000
ptr_local   0x0241                  dbg_t*{data}@0x21f1 ([R28]+1)
dbgMenu     {dbg_t(data)@0x0241}    dbg_t{data}@0x0241

Notice the local pointer points to the correct location and the global points anywhere, although I intended to point both to the prog-location. Why is the local pointer correct and the global pointer fails?

8
  • Are you actually using ptr_global somewhere in your code? Commented Sep 11 at 11:14
  • This is just a minimal example. But of course my original code refers to the global pointer Commented Sep 11 at 11:16
  • Edit the question to provide a minimal reproducible example. Even after the missing #include <stdint.h> is supplied, const uint8_t const dbgItems[DBG_SIZE] PROGMEM = {1,2}; gets a compiler error due to incorrect grammar—after dbgItems[DBG_SIZE], the compiler expects ; or =, not PROGMEM. If there are missing macro definitions, from your own code or some other header, a minimal reproducible example should include them. Commented Sep 11 at 11:58
  • I guess it is more helpful to add the information about the target, than trying to build an universal minimal reproducible example. Sorry for missing out the information my code is arduino specific using the PROGMEM from ArduinoCore. I thought mentioning PROGMEM was sufficiertly indicating the use of related embedded environments (AVR-GCC). Commented Sep 11 at 12:18
  • Try breaking the debugger at the earliest point in your program that you can. Is ptr_global correct then? If so, I'm guessing there is a buffer overrun that corrupts the prt_global's value. Commented Sep 11 at 13:34

3 Answers 3

1

Your local pointer appeared to work because it was likely pointing to a RAM copy of the data that the compiler created temporarily! The global pointer failed because it was trying to directly point to PROGMEM with a regular data pointer type.

The key insight is that all pointers to PROGMEM data should themselves be declared with PROGMEM to ensure they use the correct memory space and pointer representation.

Sign up to request clarification or add additional context in comments.

Comments

0

The minimal example was not representing the issue I had.
- the first comment was right. Without using of ptr_global, the example is useless for debugging. When using ptr_global, the value will be set. The issue was identical, so I expected the example to be representative. Somehow it was, but this is hard to explain.
- Nevertheless I was confused about accessing pointers and values in "data"- and "prog"-memory. I mixed it up unintentionally. Now I use the functions of "avr/pgmspace.h" for access.

Comments

0

The problem with PROGMEM is that it doesn't allow for checks when a progmem pointer is assigned a non-progmem pointer, or vice versa. This is because PROGEM is just a variable attribute very much like the section attribute with enfoced const-ness.

A more solid approach is to use named-address space __flash which is supported since GCC 4.7.

Together with -Waddr-space-convert you get warnings when you violate address-space qualification in assignments.

One more benefit is that you can read from __flash with open coded C; no pgm_read_xxx stuff required!

With that, your code reads something like

#include <stdint.h>

typedef struct
{
    const uint8_t size;
    const __flash uint8_t *item;
} dbg_t;

#define DBG_SIZE 2

const __flash uint8_t const dbgItems[DBG_SIZE] = { 1, 2 };
const __flash dbg_t const dbgMenu = { DBG_SIZE, dbgItems };
const __flash dbg_t *ptr_global = & dbgMenu;

void dbg_init (void)
{
    const __flash dbg_t *ptr_local = & dbgMenu;
}

provided dbgMenu is located in flash. If not, remove the __flash qualifier from dbgMenu and ptr_global's and ptr_local's pointer target.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.