CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

write_program_memory PIC18F46k80 Bootloader

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
tolliug



Joined: 09 Aug 2018
Posts: 15

View user's profile Send private message

write_program_memory PIC18F46k80 Bootloader
PostPosted: Fri Dec 07, 2018 5:31 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Dec 07, 2018 8:21 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 11, 2018 5:11 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 11, 2018 10:14 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 11, 2018 10:30 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 11, 2018 11:09 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 11, 2018 11:27 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Dec 12, 2018 2:25 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Dec 12, 2018 3:15 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Dec 12, 2018 3:44 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Dec 12, 2018 3:57 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Dec 13, 2018 2:30 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Dec 13, 2018 3:00 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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