3

I'm doing a project using the Microchip C18 compiler. I have a struct called a block that points to other blocks (north east south west). These blocks will make me a map. I then have a pointer that I use to evaluate everything.

Just using RAM it looks like:

struct block{
        struct block *north;
        struct block *east;
        struct block *south;
        struct block *west;
};


struct block map[5] =
{ // just a simple line.
        { NULL, &map[1], NULL, NULL },
        { NULL, &map[2], NULL, &map[0]},
        { NULL, &map[3], NULL, &map[2]},
        { NULL, &map[4], NULL, &map[3]},
        { NULL, NULL, NULL, &map[4]}
};


struct block* position = &map[0];

This lets me do stuff like:

void goWest()
{
if(position -> west != NULL) position = position -> west;
}

Problem is that I've run out of RAM in my project and need to use ROM What I have so far is:

struct block{
        rom struct block *north;
        rom struct block *east;
        rom struct block *south;
        rom struct block *west;
};
rom struct block map[5] =
{ // just a simple line.
        { NULL, &map[1], NULL, NULL },
        { NULL, &map[2], NULL, &map[0]},
        { NULL, &map[3], NULL, &map[2]},
        { NULL, &map[4], NULL, &map[3]},
        { NULL, NULL, NULL, &map[4]}
};

I've done some debugging and can tell the above part works, but trying to make the position pointer is giving me grief. so I guess my question is:

How do I hold the ROM variable addresses in a pointer which I can edit the values of?

When i try:

struct block *position = &map[0];

I get "Warning [2066] type qualifier mismatch in assignment"

I realize that a ROM variable and RAM variable are two different things, but I have no idea what to do.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
Cal Pratt
  • 33
  • 1
  • 4

1 Answers1

4

What is the definition of the rom macro? I'm guessing that it expands to const (and possibly a compiler-specific __attribute__ or somesuch), because the compiler is complaining about a "type qualifier mismatch", which refers to a const or volatile mismatch.

What that means is that you're trying to implicitly cast a pointer to constant data into a pointer to non-constant data. This code should generate the same warning with your compiler:

const int x = 0;
int *y = &x;  // &x is "pointer to const" but y is "pointer to non-const"

To fix it, you need to declare that your position pointer is a pointer to constant data (which, depending on the definition of the rom macro, should be done with either rom or the const qualifier):

// Declare a non-constant pointer to constant data
const struct block *position = &map[0];

At each pointer level, you can have a const qualifier or lack thereof, and likewise for the base non-pointer object. So, a single-level pointer can have 4 different variants:

int *x;  // Non-constant pointer to non-constant data
int *const x;  // Constant pointer to non-constant data
const int *x;  // Non-constant pointer to constant data
int const *x;  // Same as above
const int *const x;  // Constant pointer to constant data
int const *const x;  // Same as above

Note that int const and const int are equivalent, but otherwise the placement of const does matter.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • The Microchip PIC uses a Harvard architecture -- ROM and RAM are in completely separate address spaces, so you can't mix pointers to the two. I believe they're using a custom type qualifier to separate the two. –  Nov 21 '12 at 00:03
  • @duskwuff: Ah ok, I wasn't aware of that. In that case, just replace `const` with `rom` in all of the above, and it should still apply, assuming that the compiler is reasonably behaved. So `rom struct block *position = &map[0];` should be the correct definition. – Adam Rosenfield Nov 21 '12 at 00:07
  • @Adam Rosenfield: Thanks, that solved it!! I was so sure I tried doing that and it had failed :/ guess I should sleep soon haha. – Cal Pratt Nov 21 '12 at 00:30