View previous topic :: View next topic |
Author |
Message |
Guest
|
Figuring out what this code from Loader.c is doing |
Posted: Tue Jan 04, 2005 2:15 pm |
|
|
I am using an 18f8720.
I wanted to modify my bootloader (I know, there are LOTS of them out there) and I was looking at the loader.c file that comes with PICC.
I am having a problem understanding this snippet:
Code: |
if (line_type == 0) {
// Loops through all of the data and stores it in data
// The last 2 bytes are the check sum, hence buffidx-3
for (i = 9,dataidx=0; i < buffidx-3; i += 2)
data[dataidx++]=atoi_b16(&buffer[i]);
#if getenv("FLASH_ERASE_SIZE")>2
#if defined(__PCM__)
if ((addr!=next_addr)&&(addr&(getenv("FLASH_ERASE_SIZE")-1)!=0))
#else
if ((addr!=next_addr)&&(addr&(getenv("FLASH_ERASE_SIZE")/2-1)!=0))
#endif
erase_program_eeprom(addr);
next_addr = addr + 1;
#endif
write_program_memory(addr, data, count);
}
else if (line_type == 4)
h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer 11]));
|
The problem I run into is with:
Code: | if ((addr!=next_addr)&&(addr&(getenv("FLASH_ERASE_SIZE")/2-1)!=0))
|
First note that next_addr is never intialized, but let's assume the compiler always intitializes to 0 unless otherwise told.
The variable addr will probably never start at zero, and when we go through the code (assuming FLASH_ERASE_SIZE is always >2) next_addr is always set to addr+1 which means that addr will probably NEVER equal next_addr and so I can't see why (addr!=next_addr) is part of the if statement.
Let's assume that getenv("FLASH_ERASE_SIZE")/2-1) is 0x1F. This is bits 0 to 5. According to the PIC data sheet, flash erase will only operate on bits 6 to 21, bits 0 to 5 are ignored so if I call erase_program_eeprom with any address of ABC0 to ABDF, the block from ABC0 to ABDF will be erased. Obviously if I erase the block beginning at ABC0 the write 4 bytes of data I DON'T want to call erase again with ABC4 since it will simply erase the whole block beginning at ABC0 again (including the 4 bytes I just put in!)
So you would think that I would want to call erase_program_eeprom only when the address anded with 1f EQUALS zero ( (addr & 0x1f)==0) . The program sample does this when it does NOT equal zero.
Maybe I missed something. I imagine this code works, I never tried it myself but it seems other people have.
Can anyone expalin what I am seeing (or missing) here?
Thanks,
-Pete |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jan 05, 2005 4:47 am |
|
|
It looks like a bug to me.
Which compiler version do you have?
Between versions 3.187 and 3.190 the line with 'next_addr = addr +1' was added, so it seems like some last minutes changes were applied to this part of the code.
From the release notes: Quote: | 3.202 Some reported problems with the Bootloader examples are fixed |
|
|
|
pfournier
Joined: 30 Sep 2003 Posts: 89
|
|
Posted: Wed Jan 05, 2005 7:19 am |
|
|
I'm was using 3.214, I just upgraded to 3.215. _________________ -Pete |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jan 05, 2005 8:38 am |
|
|
I cracked it:
In an Intel-hex file it is allowed to have multiple data blocks. It is possible for these data blocks to have 'holes' in between.
The function write_program_memory will perform the erase automatically when the start address is a multiple of FLASH_ERASE_SIZE. The if-statement handles the special situations where there is a 'hole' in the hex-file with the new data block not starting at the FLASH_ERASE_SIZE multiple. |
|
|
pfournier
Joined: 30 Sep 2003 Posts: 89
|
Re: Figuring out what this code from Loader.c is doing |
Posted: Wed Jan 05, 2005 8:47 am |
|
|
Anonymous wrote: |
The problem I run into is with:
Code: | if ((addr!=next_addr)&&(addr&(getenv("FLASH_ERASE_SIZE")/2-1)!=0))
|
Let's assume that getenv("FLASH_ERASE_SIZE")/2-1) is 0x1F. This is bits 0 to 5. According to the PIC data sheet, flash erase will only operate on bits 6 to 21, bits 0 to 5 are ignored so if I call erase_program_eeprom with any address of ABC0 to ABDF, the block from ABC0 to ABDF will be erased. Obviously if I erase the block beginning at ABC0 the write 4 bytes of data I DON'T want to call erase again with ABC4 since it will simply erase the whole block beginning at ABC0 again (including the 4 bytes I just put in!)
So you would think that I would want to call erase_program_eeprom only when the address anded with 1f EQUALS zero ( (addr & 0x1f)==0) . The program sample does this when it does NOT equal zero.
|
Here I am answering part of my own post....
First of all 0x1F is NOT bits 0 to 5. That would be 0x3F. I don't know why the FLASH_ERASE_SIZE is divided by two before anding with the addr BUT I did discover what is happening in general. ERASE_PROGRAM_EPROM is needed ONLY if the address given to WRITE_PROGRAM_MEMORY is NOT on a block. WRITE_PROGRAM_MEMORY will automatically erase a block if it starts on a block, so you don't have to do it manually.
Now, why divide FLASH_ERASE_SIZE by two (which seems wrong)? And what purpose does next_addr serve?
-Pete _________________ -Pete |
|
|
pfournier
Joined: 30 Sep 2003 Posts: 89
|
|
Posted: Wed Jan 05, 2005 8:54 am |
|
|
ckielstra
We must have been replying at the same time! I didn't see your post until I submitted my own.
Example code needs more comments! _________________ -Pete |
|
|
|