arduino / Arduino

Arduino IDE 1.x
https://www.arduino.cc/en/software
Other
14.14k stars 7.01k forks source link

Result of adresspointer wrong w/ progmem #1645

Closed Hubbie0001 closed 10 years ago

Hubbie0001 commented 10 years ago

Hello team,

I found a bug with adresses with progmem values > 0x7FFF are wrong.

Please find the example below, its on an arduino Mega 2560, with Arduino 1.0.3

Thanks in advance for your help

Hubbie

Test Scetch:

// ----------------------------------------------- // Problem example with adresspointer w/ Progmem // -----------------------------------------------

include <avr/pgmspace.h>

byte Mem [32767] PROGMEM = {0x00};

int i; byte * addr; void setup() {

Serial.begin(9600); Serial.println("Problem-Report 01"); }

void loop() { for (i=0;i<10;i++){ addr = &Mem[32535+i]; Serial.print((unsigned long)addr); Serial.print(" / "); Serial.println((unsigned long)addr,HEX);

} delay(20000);
}

Output :

Problem-Report 01 32763 / 7FFB 32764 / 7FFC 32765 / 7FFD 32766 / 7FFE 32767 / 7FFF 4294934528 / FFFF8000 4294934529 / FFFF8001 4294934530 / FFFF8002 4294934531 / FFFF8003 4294934532 / FFFF8004

matthijskooijman commented 10 years ago

Apart from this being an interesting peculiarity, is this behaviour actually causing a problem for you? Normally, you'd pass the address of progmem variables to pgm_read_byte, or some function like memcpy_P (IIRC). Are you also having problems using the PROGMEM value as intended?

As for what you're seeing: it seems that for some reason your pointer variable is sign-extended. A pointer is normally 16 bits. You're casting it to unsigned long, which is 32 bits. When doing this with signed integers, the most significant bit (which is sorto of a sign bit in two-complement notation) is copied into each of the extra 16 bits, which is called sign-extending. This makes sure that negative values keep the same value, even if they are casted to a longer type. For unsigned values, each of the extra 16 bits are just set to zero, which is called zero-extending.

I would assume a pointer is an unsigned type, and you're casting to unsigned long, so there is really no reason for the compiler to do sign extension. However, if you would cast to unsigned int, which 16 bit like pointers, I think you wouldn't see the weirdness.

Having said all that, I'm not quite sure what happens when you would have a PROGMEM variable which is not in the first 64Kbyte of flash (e.g., not addressable with a 16-bit pointer). The existence of the pgm_read_byte_far function suggests that you could get a 32-bit pointer to such variables, but I'm not sure how that works.

Hubbie0001 commented 10 years ago

An adresspointer should be unsigned

barbudor commented 10 years ago

May be but array index arithmetics in C are signed and operate on int Array[-1] is valid You may try addr = &Mem[0] + i With i being unsigned Le 26 oct. 2013 23:55, "Hubbie0001" notifications@github.com a écrit :

An adresspointer should be unsigned

— Reply to this email directly or view it on GitHubhttps://github.com/arduino/Arduino/issues/1645#issuecomment-27156670 .

Hubbie0001 commented 10 years ago

Thank you for your Explanation. Now I see an adresspointer is signed and has 2 bytes only.