Reading Flash Memory from Sketch

Dear Community,
I am quite new in this world, so please be kind :-).

Using Arduino MEGA2560.

I got a task to do arduino sketch where I will check the CRC of the loaded sketch.
So I would like to know, if there is a way how to directly read Flash memory - plase where the sketc is loaded and do CRC from this data.

The result shall be that If I add some line to sketck and load it to the board, the value shall change, if the sketch will be without chenge the number shall stay same.

I tryied to read so many threads but without luck.

I tryied

for (int i = 0; i < 64; i++){
  byte b = pgm_read_byte(i);
  Serial.print(b,HEX);
 }

But this not change if sketch is changed - maybe wrong address I am looking at...

Thanks in advance!

Pavel

the first many bytes may be interrupt vectors as well as other startup code that doesn't change depending on the sketch

at least one listing i have suggests that main starts at address 0x358 (not sure why i don't see setup and loop)

00000000 T __vectors
00000068 T __trampolines_end
00000068 T __trampolines_start
000000c2 T __ctors_start
000000c4 T __ctors_end
000000c4 T __dtors_end
000000c4 T __dtors_start
000000d0 T __do_clear_bss
000000e0 T __do_global_ctors
000000fe T __bad_interrupt
000002c4 T __vector_16
00000358 T main
00000830 T __tablejump2__
0000083c T _exit
00000840 T _etext

Your simple test for loop probably gives the same result because that particular part of FLASH holds the interrupt vector table (I think!). Unless you use interrupts, it is unlikely to change from one sketch to the next.

The problem you may have is that you would need to determine if the compiled, assembled and linked binary file that gets uploaded to your Arduino occupies contiguous memory locations from $0000 upwards. If your binary file used addresses $0000-$0032 for the vector table but then placed the code starting at address $0100, you would not know this and a simple for loop would included addresses $0033-$00FF in the calculation - which could be any old garbage.

You also would not know the size of the binary file that has been programmed into flash so you wouldn't know where your current sketch ended in memory.

Here is an example I made a while ago. It dumps SRAM, EEPROM and FLASH and gives a reasonably familiar output (if you have worked with hexdump before):

000120  0c bf 12 e0 a0 e0 b2 e0 ea e0 ff e0 00 e0 0b bf  ................
000130  02 c0 07 90 0d 92 a0 34 b1 07 d9 f7 22 e0 a0 e4  .......4...."...
000140  b2 e0 01 c0 1d 92 a6 3e b2 07 e1 f7 10 e0 c9 e8  .......>........

Dear Guys, gcjr, markd833, jfjlaros,

thank to all of you for very good points and summary, I did not expect so fast reaction.
The Dump from jfjlaros works wery good, I just need to somehow do CRC from that stream.
Once I will get there I will try to only do CRC of the flash where is the program.
Do you know how to say to arduino software that before the sketch is loaded all memory for sketches shall be deleted/rewrited?
This will help very much so I do not neet to take care about previous sketches loaded in the procesor.
Thanks a lot again!

Pavel

The flash memory is erased as part of the programming process.

Is it all erased or is only the memory required by the new sketch overwritten ?

This was exactly I was wondering. On some forum thread was writen that only some part is overwriten and the part what is not needed is left untached, so if previous sketch was bigger it shall mess up the process of CRC.

wouldn't you only compute a checksum over the section of memory being written? you can't assume values for unwritten space

My mistake. I just checked with a couple of different sketches and it appears that the whole of flash isn't erased when a new sketch is uploaded. It looks like only enough pages of flash memory are erased to take the size of the new sketch.

The remaining area(s) of flash contain the remnants of previous sketches.

The OP would likely need to add a step to the build process to calculate the CRC as well as determine the bounds of the flash memory to check the CRC against so that those values could be stored on the chip. That would probably require knowledge of where the linker was placing the various sections and whether there were "holes" in the memory space where previous code remnants would lurk!

You can have the IDE save the output file that gets uploaded to the arduino. That will be in Intel hex format, but for the atmega2560 the flash memory is large enough that it is divided into several pages, making it slightly more complex to calculate the physical addresses the code is stored at.

Do you have any idea how to get some informations where the code is writen? Someone mentioned some linker... is this some way how to deal with this?
I would imagine some code, what is goinf thru memory and a "linker" will say - yes this is a part of a code, or no this not a part of a code - ignore it.
Is here any way?
Or is there some way how to erase the flash complettely - some tool what will leave only bootloader and the res of the memory will be deleted, so the sketch will be always on the same place?

Also I was now going thru some tests and found that If I make some changes in the code the CRC of Flash doesnt change, but CRC of Memory change. How I can know what change is writen to Flash and what part to ProgMemory?
This is a bit confusing :wink:

here the link to simulator:

post #2?

Thanks, this I found, but as markd833 mentioned, the code can be split to more places. So How I can find out where actual code is? I only found that If I dump flash memory the end code is always finished with severals FF bytes. But is all between 0358 and FF part the code?

Also what I found that some parts of sketch are not in flas but in memory directly and there it is even more tricky to find out what is what :wink: What I did not I am doing CRC of FLASH from 00000 to the size of the sketch what I got from MemoryFree.h and complette Progmem. This shall be always the same even with multiple downloads, if processed on the same part of the code(in Setup).

I am just not really sure if this is a good way how to do it :smiley: probably not the clearest one.

Edit: I just go from address 0000 because I also would like to include all settings from processor, so it doesnt hurt to include.

isn't the code from main to exit. i believe the arduino sketch code is contiguous. variables are in RAM

you should also look at the .HEX file that contains the compiled/reformatted output. the .

Thanks, I just can not find, if the table you poested is also fit to Mega2560 board. For me it seems too little I see there only 1254 bytes for sketch, what dosnt seems to be right.

did you look at your .HEX output?

the output from the code below


0000 0c9435000c945d00 0c945d000c945d00 0c945d000c945d00 0c945d000c945d00
0020 0c945d000c945d00 0c945d000c945d00 0c945d000c945d00 0c945d000c945d00
0040 0c946c010c945d00 0c94dc010c94b601 0c945d000c945d00 0c945d000c945d00
0060 0c945d000c945d00 f70211241fbecfef d8e0debfcdbf11e0 a0e0b1e0e8e0fce0
0080 02c005900d92a232 b107d9f722e0a2e2 b1e001c01d92a831 b207e1f710e0c5e3
00a0 d0e004c02197fe01 0e942403c433d107 c9f70e940e020c94 02060c940000af92
00c0 bf92cf92df92ef92 ff920f931f93cf93 df936c017b018b01 040f151feb015e01
00e0 ae18bf08c017d107 59f06991d601ed91 fc910190f081e02d c6010995892b79f7
0100 c501df91cf911f91 0f91ff90ef90df90 cf90bf90af900895 fc01538d448d252f
0120 30e0842f90e0821b 930b541710f0cf96 089501970895fc01 918d828d981761f0
0140 a28dae0fbf2fb11d 5d968c91928d9f5f 9f73928f90e00895 8fef9fef0895fc01
0160 918d828d981731f0 828de80ff11d858d 90e008958fef9fef 0895fc01918d228d
0180 892f90e0805c9f4f 821b91098f739927 089582e791e00e94 bd0021e0892b09f4
01a0 20e0822f089580e0 90e0892b29f00e94 c90081110c940000 0895fc01a48da80f
01c0 b92fb11da35abf4f 2c91848d90e00196 8f739927848fa689 b7892c93a089b189
01e0 8c91837080648c93 938d848d981306c0 0288f389e02d8081 8f7d80830895ef92
char s [80];

void
dump (
    int N )
{
    for (int i = 0; i < N; i++) {
        if (! (i % 32))  {
            sprintf (s, "\n%04x ", i);
            Serial.print (s);
        }
        else if (! (i % 8))  {
            Serial.print (" ");
        }

        sprintf (s, "%02x", pgm_read_byte(i));
        Serial.print (s);
    }
        Serial.println ();
}

void
setup (void)
{
    Serial.begin (9600);
    dump (0xC30);
}

void
loop (void)
{
}

This I have like that:

:1000000080C100000C94A9200C947E200C945320F5
:100010000C9428200C94FD1F0C94D21F0C94A71F45
:100020000C947C1F9FC100009DC100009BC100007B
:1000300099C1000097C1000095C1000093C1000064
:1000400091C100000C94D4208DC100008BC1000030
:1000500089C1000087C1000085C100000C94321FD7
.
.
:107A8000726F6D20454550524F4D203A2000706175
:107A90006765302049442039202D20004C6F6164F7
:107AA0006564204B4F45462066726F6D20454550FA
:107AB000524F4D203A2000496E697469616C697AB1
:047AC00065642000D9
:00000001FF

It this means that my code start from 10000 HEX and goes all tha way to 107AB ?

no, the first byte is the # of bytes in the record

.hex file format