|
|
View previous topic :: View next topic |
Author |
Message |
tolliug
Joined: 09 Aug 2018 Posts: 15
|
write_program_memory PIC18F46k80 Bootloader |
Posted: Fri Dec 07, 2018 5:31 am |
|
|
Hello,
I am working on a CAN bus bootloader for a PIC18F46K80. HEX file is received through CAN bus (without line preamble and Checksum) by packets of 6 bytes at most and stored in a temp_buffer (i.e an int8 array).
I am trying to use write_program_memory like that:
Code: |
write_program_memory(0x500+received_size,temp_buff,length-2);
|
0x500 is the relocated reset vector and received_size is a counter of received bytes.
This does not work at all (if a check program memory data are not written) and do not know how to go further. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Fri Dec 07, 2018 8:21 am |
|
|
You need to rethink what you are doing.
Writes to the page boundary (every 64 bytes), trigger a block erase. This chip
does not support 'byte write' (most do). Writes can only be a 64byte block. To
write a byte in the middle of a block, requires one to read the entire block into
a 64byte buffer, change the single byte, and write all 64 bytes back. Uses a write life every time....
You code needs to be writing whole blocks otherwise you will be 'drinking' write
lives. The 'write life' of this chip is only 1K cycles.
When writing, the chip completely stops running, so your source code will need
to send a 64byte block, then pause for long enough for the write, before
proceeding.
Also since your size does not align to the write boundary every time, erases
won't occur... |
|
|
tolliug
Joined: 09 Aug 2018 Posts: 15
|
|
Posted: Tue Dec 11, 2018 5:11 am |
|
|
From datasheet of pic18F46k80 (section 7,0 page 125), erase block size is 64 bytes and write block size is also 64 bytes. From CCS compiler documentation, page 90:
Quote: | For chips where getenv("FLASH_ERASE_SIZE") = getenv("FLASH_WRITE_SIZE")
WRITE_PROGRAM_EEPROM - Writes 2 bytes, no erase is needed. WRITE_PROGRAM_MEMORY - Writes any number of bytes, bytes outside the range of the
write block are not changed. No erase is needed.
ERASE_PROGRAM_EEPROM - Not available. |
This sounds to me that I just need to WRITE_PROGRAM_MEMORY. However I do not know how to deal with this case:
Code: |
:0E0280006E513B0801E26E6B0101E9D70300ED
:0406000000EF00F017
:08060800116ED8CF12F0E0CF13
:1006100013F00001E9CF19F0EACF14F0E1CF15F0A3
:10062000E2CF16F0D9CF17F0DACF18F0F3CF1FF0E2
:10063000F4CF20F0FACF21F0F5CF22F0F6CF23F05F
:10064000F7CF24F000C01BF001C01CF002C01DF069
:1006500003C01EF0F2AA30EF03F0F2B4F9EF21F07C
:100660009DA036EF03F09EB00DEF22F076A23CEF96
:1006700003F077B27FEF20F076A842EF03F077B86F
:1006800084EF20F01BC000F01CC001F01DC002F080
|
Application code start at 0x600 (24th block of 64 bytes) right?
Next block therefore will concern 0x640 am I still right? if yes should I build a 64 bytes array and then fill the array with all data that exists between 0x600 and 0x640? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Dec 11, 2018 10:14 am |
|
|
The key problem is using 6 bytes.
The write function, will erase a block, when you write to the first address in
the block. With 6 bytes, you are only going to hit the erase boundary, every
third block, so there will not be an erase for the intermediate two blocks.
Then as explained you have the issue of write life. If you write an entire
block of 64 bytes, this is a single write operation. If you write little numbers
of bytes, you use up a write life every time you do this.
This is why the example bootloader, uses a 64byte buffer, assembles all
the data to fit in this, then send an XOFF to stop the comms, and writes
this.
CAN doesn't have an XOFF, so you will have to have a pause in communication
instead, but you need to be doing the writes in 64byte blocks. |
|
|
tolliug
Joined: 09 Aug 2018 Posts: 15
|
|
Posted: Tue Dec 11, 2018 10:30 am |
|
|
I understand that and now create a 64 bytes array that I fill in with CAN data. however I still miss something because ROM is not update (my write method is wrong... and need to first understand why....) |
|
|
tolliug
Joined: 09 Aug 2018 Posts: 15
|
|
Posted: Tue Dec 11, 2018 11:09 am |
|
|
Code: |
//memory program method
// unoptimized should use pointer instead of vreating new vars
void write_prog(int32 addr, int32 cpt_block, int8 * global_buffer,int8 received_size)
{
//writes a bloc of received_size at addr address shiffted by already received numbers of bloc already written
write_program_memory(addr+64* cpt_block,global_buffer,received_size);
//increment block counts
cpt_block++;
//data have been written, reset received size
received_size=0;
}
|
Here's the code I am using, addr is 0x700 (my bootloader has grown up) cpt block is 0 and received size was set to 64 to force it to an entire block size. However the ROM is not updated. Is there's a protection mechanism? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Dec 11, 2018 11:27 am |
|
|
Yes. Depends on your fuses. You need to check what fuses are actually being set, when the chip is programmed (look at the listing file - fuses are at the end).
CPB would protect the bootblock area. Depending on the size BBSIZ1K or BBSIZ2K, this could affect this area.
PROTECT would prevent the whole of the ROM from being written.
WRT would also protect it from being written.
As a comment, you do realise that setting 'received_size' to zero in your
function does nothing?.
This variable here is a _local copy_ if the value sent. Changing it here will
not affect the value outside. If you want to change the value outside, you
need to look at 'pass by reference', or sending a pointer, which can then allow
the function to change the value being passed.
The same applies to cpt_block. |
|
|
tolliug
Joined: 09 Aug 2018 Posts: 15
|
|
Posted: Wed Dec 12, 2018 2:25 am |
|
|
Here's the fuses:
Code: | Configuration Fuses:
Word 1: 5215 VREGSLEEP INTRC_HP SOSC_DIG NOXINST HSH PLLEN FCMEN NOIESO
Word 2: 3469 NOPUT NOBROWNOUT BORV27 ZPBORM NOWDT WDT8192
Word 3: 8900 CANB MSSPMSK7 MCLR
Word 4: 0010 NOSTVREN BBSIZ2K DEBUG
Word 5: C00F NOPROTECT NOCPB NOCPD
Word 6: E00F NOWRT NOWRTC NOWRTB NOWRTD
Word 7: 400F NOEBTR NOEBTRB
|
For the last comment, yes I do realise that this is just a test case. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Wed Dec 12, 2018 3:15 am |
|
|
How are yow testing whether a write has occurred?.
In MPLAB for example, the 'program memory' window does not allow live
updates. Also if you debug the unlock sequence, it is invalidated by the
debugger. You have to run the unlock at full speed, and then read back the
program memory, to see that a write has occurred.
I just did a test program with this chip:
Code: |
void main()
{
int8 buffer[64] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
49,50,51,52,53,54,55,56,57,58,59,60,60,62,63,64 };
while(TRUE)
{
write_program_memory(0x2000,buffer,64);
delay_ms(20000);
}
}
|
Ran with a breakpoint in the delay, then read back the program memory
and it merrily shows:
Code: |
2000 0201 0403 0605 0807 0A09 0C0B 0E0D 100F
|
in the program memory. |
|
|
tolliug
Joined: 09 Aug 2018 Posts: 15
|
|
Posted: Wed Dec 12, 2018 3:44 am |
|
|
I am testing the write behavior using ccsinfo debugging mode and an ICD-U64 programmer, maybe you are right this might be not possible while debugging...
I will try your test code. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Wed Dec 12, 2018 3:57 am |
|
|
The key point is that the actual write must be run at full speed.
When you debug, if you single step, the 'debug executive' takes over after
each instruction is executed. The unlock sequence needed to make a write
actually happen, _requires_ that the sequence is uninterrupted. The
same is true for interrupts (must be disabled during the write). |
|
|
tolliug
Joined: 09 Aug 2018 Posts: 15
|
|
Posted: Thu Dec 13, 2018 2:30 am |
|
|
Hello Ttelmah, There's definitely something wrong with the way I try to update program memory.
I am using CCSInfo IDE and ICD-U64. To check if program memory has been updated I am running the boot loader in normal mode. It runs your sample code, then I attach the debugger and check the ROM windows.
This shows me address up to 0x1802... nothing at 0x2000. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Dec 13, 2018 3:00 am |
|
|
The CCS IDE defaults to only showing ROM memory that it knows it has
loaded. The CCSLoad program does the same. I've complained about this
to CCS, but so far no change....
This is one reason I end up having to use other debug tools (though these
then have their own issues for other things...).
Worst comes to the worst, just read the memory out with
read_program_memory, and display the RAM buffer from this to see what
is there. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|