# Pointer to array gets highest bit toggled by … compiler? (dsPIC33EP & XC16)

Brief:

• Pointer to a const-int-array, nested in a struct
• Using ptr to this struct (type) in various places
• ptr-deref causes address-error, because value was changed from i.e. 0x00AE to 0x80AE -> highest bit was toggled.

Detailed:

Declarations etc:

typedef struct {
const uint8_t *rawDataPtr;
uint16_t width;      ///<in Bits!
uint16_t height;     ///<in Bytes!
} image_t;

const uint8_t image_data_timer_53x56[53] = {
0x00, 0x00, 0x02, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0xfc, 0x00, 0x00,
0x00, 0x03, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x0f, 0xff, 0xff, 0xff, 0xc0, 0x00,
0x00, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x00,
0x00, 0x7f, 0xff, 0xff, 0xff, 0xf0, 0x00,
0x00, 0x7f, 0xff, 0xff}

image_t image_timer3 = {image_data_timer_53x56, 53, 1};


Edit: These definitions (above) are outside of any function-body.

void LCD_draw_image(uint16_t x, uint16_t y, image_t *img, uint16_t fg_color, uint16_t bg_color);


"image_timer_3" is global and extern.

Call of function "LCD_draw_image":

LCD_draw_image(X_WIDTH_FRAME, Y_POS_ICON, &image_timer3, COL_BLACK, COL_WHITE);


...using "img" in the subroutine in various ways. Doesn't actually matter how, because the pointer is already corrupted. See debugger output: (Edit: Breakpoint BEFORE calling the subroutine mentioned => deref inside of it is not crucial to this question)

Now, I tried size-changing of the initial int-array and it does have an effect since it did work for a while. But now the error reoccurred and I assume it is a setting of the compiler but I cannot figure out what! Each time I use the pointer I get ADDRESS ERROR (traps code 2), of course, since it does not exist.

WHAT HAPPENS TO THIS POINTER?

dsPIC33EP64GS804, Mplab 5.4, XC16, ICD3

• image_timer3_rawDataPtr's value is out of the boundary of the datatype unsigned char it seems. Is it ok? – CNA Mar 15 at 9:04
• Hm... don't quite see it. "rawDataPtr" ist a pointer to uint8, the dsPIC33 is a 16-bit system. That's fine, isn't it? Or did I get this wrong? – Raphael B. Mar 15 at 9:31
• When troubleshooting compiler bugs, I would look at the assembly code the compiler is generating. – user253751 Mar 15 at 9:55
• @CNA what you're writing doesn't make sense. The OP has declared rawDataPtr as a pointer to a uint8_t, not as a uint8_t. It'll be allocated with whatever amount of space is required to hold a pointer. The fact that it points to a uint8_t is irrelevant. – brhans Mar 15 at 11:31
• @RaphaelB. I suspect that your problem has something to do with the way the PIC differentiates between pointers to RAM and pointers to Flash - as far as I remember the MSbit being set indicates that the address is in Flash (as you would expect for a pointer to a const). How are you dereferencing the pointer in your LCD_draw_image function? are you using an intermediate variable of a different type somewhere? – brhans Mar 15 at 11:39

Ok, I'll answer myself, but credits to @BRHANS, who gave the correct hint!

• Default setting of XC16 memory model: "CONST IN CODE" = variables declared as CONST will be placed in flash rom. In this case it is this variable:
  const uint8_t image_data_timer_53x56[53]

• The PSV-feature of the dsPIC allows using those const-rom-variables like any other variable in RAM. For more info on PSV see section "Memory Organization" in the DS.
• BUT...common "RAM"-variables will be found in the lower half of data memory space while the upper half is reserved for PSV-variables (mapped).
• So, when using a POINTER to such a variable it makes a big difference. The compiler needs to know, that the variable is PSV-managed to handle it correctly.
• This is done by the "psv" type qualifier:
  const uint8_t *rawDataPtr

 needs to be:

  __psv__ const uint8_t *rawDataPtr

• Here we go.. it works!