Is there a way to use pgm_read_byte_near(n) or pgm_read_byte_far(n) when n, in this particular case, is a physical address of type 0x00AFFFF (ie as a pointer to a variable, but without defining any variables? Namely, pgm_read_byte_near(0x00AFFFF).
I'm loading an array of data into the flash memory with avrdude and then I want from a program on my Arduino UNO, to have access to read any byte of that array in the flash (it must be assumed that I know in which position each byte is and what it represents).
I am not sure if this answers your question, but the following snippet will print the content of the first two kilobytes of FLASH if I am not mistaken.
void setup() {
Serial.begin(9600);
char const str[] = "hello there ";
Serial.println(str); // Actually use the variable or the compiler will optimise it out.
for (size_t i = 0; i < 2048; i++) {
Serial.print((char)pgm_read_byte(i));
}
}
Here is an example to play with.
You can see it displays the string at the end of the dump.
AVR are Harvard Architecture CPUs which means that SRAM and flash are separate address spaces. "Normal" memory reads are to RAM/IO and use LDS/STS/LD/St opcodes. To access the flash you need to use the LPM opcode.
-- Clawson: reading flash memory: AVRfreaks
Thanks guys for your notes. I have tested the suggestion of [jfjlaros] modifying it a bit. I put the code below. This small program prints in the terminal the Flash memory addresses 0 to 2000 and the byte contained in each one of them (hex format),
The code:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
char const str[] = "Reading Flash Memory";
Serial.println(str); // Actually use the variable.
for (word i = 0; i < 2000; i++) {
Serial.print(i, HEX);
Serial.print("\t");
Serial.println(pgm_read_byte(i), HEX);
delay(10);
}
}
void loop() {
}
The compiled program occupies 1970 bytes (including the .. bytes that the Arduino IDE always adds to the beginning). Therefore the program lists its own hex code and beyond until address 2000 (dec) the content of the Flash Ram is FF (hex) that is, there is no content.
Out of curiosity I have tried, but not succeeded, to list the content of the Bootlader, which in my Arduino Uno is located between the addresses of the Flash memory 0x7E00 and 0x7FFF (accessing with the pgm_read_byte() function always gives FF hex). But don't worry, the same thing happens if you read the flash memory with Atmel Studio 6.x, which also gives FF hex.
So for the purpose of loading data tables in the Flash Ram, its length must be taken into account and the addresses of the first and last data to be loaded must be calculated, so that it does not crush the bytes of the program that has to process that data. -below-, nor the bootlader -above-.
Yes, westfw, you are right. Actually when I asked the question I put an address 0x000AFFFF as an example type, but that value exceeds the addressable flash memory in an Atmega328P MPU of an Arduino Uno (32kb - 0x0000 to 0x7FFF). This range requires a 16-bit address. . Atmega128 (128kb) and Atmega2560 (256kb) exceed 64kb and require a 32-bit address.
Both pgm_read_byte() and pgm_read_byte_near() require a 16-bit argument (the address). Therefore we will have to define that argument as a short. It seems that both functions are equivalent and that surprises me.
However, pgm_read_byte_far() requires a 32-bit argument (the address). Therefore we will have to define that argument as a long.