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

Bootloader questions

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



Joined: 20 Oct 2009
Posts: 18

View user's profile Send private message

Bootloader questions
PostPosted: Thu Oct 18, 2012 10:38 am     Reply with quote

Hi all,

I'm currently building a wireless boot-loader for PIC24F. I have some questions about how I could generate an object file from my project code.

The problem is the following, the Hex File and the addresses in each line are not sequential, this makes the standard bootloader quite complicated because Flash Memory is only programmable in sectors of 64 instructions. Therefore when I am reading through the hex file, there will be breaks between sectors in program memory which are programmable. This will lead to very slow programming.

Is it possible for the compiler to generate a file which simply give a list of the instruction at each memory location. This would allow for much faster programming of the device.

Any ideas thoughts?

Eoin
jeremiah



Joined: 20 Jul 2010
Posts: 1346

View user's profile Send private message

PostPosted: Thu Oct 18, 2012 1:44 pm     Reply with quote

Well the nice thing is you can write 0xFFFF in words that are not currently being written to until those data values are read from the file, so while, yes slower, you don't have to re-erase the block which is nice.

In general I have found most files to be in order, but you are right, I have seen some that are not in order.

The tricky thing with CCS and non sequential hex files is that the write_program_memory() function will erase the block automatically if the address supplied is on a page boundary. This can get you if you have already erased a block but written to other parts of it prior to calling it for a page boundary address. I ended up having to write my own copy of write_program_memory() that didn't call the erase and managed the erases manually.

In terms of if you can generate a file with specific order of instructions...I don't think it is possible, but maybe a more experienced person here can comment. I've tried using #ROM statements to force stuff, but in the end, the hex file was still out of order, so not sure on that.
Eoin87



Joined: 20 Oct 2009
Posts: 18

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 4:41 am     Reply with quote

Exactly my thoughts Smile

Thanks for clarifying that, I managed to read the program memory and save to a file on my PC.This way I should be able to write sequentially in full blocks and save time.

Thanks!
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 4:43 am     Reply with quote

Yes, I'd say to a question like this, read it into MPLAB, and write it out from this. It'll then be sequential.

Best Wishes
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 5:12 am     Reply with quote

Ttelmah wrote:
Yes, I'd say to a question like this, read it into MPLAB, and write it out from this. It'll then be sequential.


Until Microchip updates MPLAB in some way that just happens to make it non-sequential. There is no *guarantee* that any file will be sequential: that is built in to the specification. Best therefore to allow for it... somehow.

Another way therefore would be to write a PC app loader that reads the hex into a shadow, and then downloads it sequentially.

RF Developer
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Oct 19, 2012 6:20 am     Reply with quote

I just want to make sure I understand the comments in this thread correctly. I interpreted Eoin's original post to mean the hex file was disjointed but contiguous (i.e. each record is located in memory above the previous record).

However Jeremiah is saying he has seen examples where the records are not contiguous (i.e. a record may be destined for a memory location lower in program memory than the current record). Personally I have not seen this from CCS hex file or Microchip hex files. Also, knowing how some commercial programmers work, they would fail as a result.

Question for Eoin - is the problem you are experiencing because the record is disjointed but contiguous?
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 6:31 am     Reply with quote

RF_Developer wrote:
Ttelmah wrote:
Yes, I'd say to a question like this, read it into MPLAB, and write it out from this. It'll then be sequential.


Until Microchip updates MPLAB in some way that just happens to make it non-sequential. There is no *guarantee* that any file will be sequential: that is built in to the specification. Best therefore to allow for it... somehow.

Another way therefore would be to write a PC app loader that reads the hex into a shadow, and then downloads it sequentially.

RF Developer

Yes, however it is very unlikely that a program simply outputting hex from a memory block, would do it in a non sequential way, since this would require extra code, and gain nothing. Just like reading a page, if you have to read the whole thing, the simplest way is to go through it from top to bottom...
It is very different from how the compiler will generate code, since here it is working on logical 'sections' (functions), and having to fit them into available gaps.
Better by far to make the target code support this, but I think the odds are that load and output will give sequential output for any conceivable time.

Best Wishes
jeremiah



Joined: 20 Jul 2010
Posts: 1346

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 3:01 pm     Reply with quote

Yeah, when he said not sequential, I was thinking "out of sequence" rather than "missing chunk". I think I misunderstood what he meant. My apologies.

asmallri wrote:

However Jeremiah is saying he has seen examples where the records are not contiguous (i.e. a record may be destined for a memory location lower in program memory than the current record). Personally I have not seen this from CCS hex file or Microchip hex files. Also, knowing how some commercial programmers work, they would fail as a result.


If you want, I can pm you one of the hex files (assuming it fits in the PM limit). What did it was my IVT remap. Even though the #ROM calls were at the beginning of the code, they placed the actual hex file data at the end. I found it quite weird.

If I get time, I'll try to generate a small example, if you don't think it will derail this thread too much.

EDIT: Did this for PCWHD 4.135:
Code:

#case
#include <24FJ256GA106.h>

#DEVICE *=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOWINDIS                 //Watch Dog Timer in Window mode
#FUSES NOJTAG                   //JTAG disabled
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOIOL1WAY                //Allows multiple reconfigurations of peripheral pins
#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES PR                       //Primary Oscillator

//Set application space at two pages away

#define PM_END       (getenv("PROGRAM_MEMORY")-1)      //in words
#define PM_PAGE_SIZE (getenv("FLASH_ERASE_SIZE")/2)    //in words
#define PM_ROW_SIZE  (getenv("FLASH_WRITE_SIZE")/2)    //in words
#define PM_NUM_PAGES (PM_END/PM_PAGE_SIZE)
#define PM_FUSE_PAGE (PM_NUM_PAGES*PM_PAGE_SIZE)


//Just for convenience
#DEFINE BL_IVT_START  0x0004
#DEFINE APP_RESET_LOC (PM_PAGE_SIZE*1)
#DEFINE APP_IVT_START (APP_RESET_LOC+4)

//App IVT entries are spaced twice as far apart as Bootloader IVT entries
//due to using GOTO commands (4 WORDs) instead of just addresses (2 WORDs)
#define REMAP_IVT_ENTRY(entry) \
   #ROM entry = {0x00FFFFFF & ((entry-BL_IVT_START)*2+APP_IVT_START)}

//Remap the IVT using the APP IVT location to keep the compiler from
//not wanting to let you remap the IVT here.  This doesn't generate any code,
//but lets the #ROM and #ORG statements work
#BUILD (interrupt=APP_IVT_START)  //must do this to remap IVT table

//IVT Mapping to application code space
//To mass generate these, use a compiler with output with the following
//code:
//for(int i = 0x0004; i < 0x0100; i+=2){
//   printf("REMAP_IVT_ENTRY(0x%04x)\r\n",i);
//}
REMAP_IVT_ENTRY(0x0004)
REMAP_IVT_ENTRY(0x0006)
REMAP_IVT_ENTRY(0x0008)
REMAP_IVT_ENTRY(0x000a)
REMAP_IVT_ENTRY(0x000c)
REMAP_IVT_ENTRY(0x000e)
REMAP_IVT_ENTRY(0x0010)
REMAP_IVT_ENTRY(0x0012)
REMAP_IVT_ENTRY(0x0014)
REMAP_IVT_ENTRY(0x0016)
REMAP_IVT_ENTRY(0x0018)
REMAP_IVT_ENTRY(0x001a)
REMAP_IVT_ENTRY(0x001c)
REMAP_IVT_ENTRY(0x001e)

#ORG 0x0020,0x01FF{} 

////////////////////////////////////////////////////////////////////////////////
//BOOTLOADER Utility Code
////////////////////////////////////////////////////////////////////////////////
#ORG (PM_FUSE_PAGE-PM_PAGE_SIZE),(PM_FUSE_PAGE-1) default

#use delay(clock=22118400)

void main()
{
   unsigned int8 read_data[32];

   //read_program_memory(APP_RESET_LOC,read_data,4);
   read_program_memory(APP_RESET_LOC,read_data,4);

   delay_ms(3000);   
                                         
   #asm
      GOTO APP_RESET_LOC;
   #endasm
}
#ORG default


This was the resultant hex:
Code:

:080000003EA404000200000010
:020000040005F5
:10480000910188000300E000130032000000AF00B7
:10481000060037003059BA008301E9000E0032006B
:104820001059BA008301E9000B0032000000E900D2
:1048300030D9BA008301E900070032000059EB00CB
:104840008301E9000000E8000000E0004220AF0022
:104850003220EC00EBFF3700000006000000E00013
:104860004220AF00040037002E2B0900000000009A
:104870000000E900FCFF3A000000060081E0A8000B
:104880002CA3EF000F782400F07F240020A0B700B5
:10489000000000000F782400F07F240020A0B70063
:1048A00000000000004020000100200022802000C5
:1048B0004300200000A402000200000080BB200092
:1048C0002EA402000200000000040400000000000A
:0448D0000040FE00A6
:020000040000FA
:1000080004040000080400000C04000010040000B0
:1000180014040000180400001C0400002004000060
:1000280024040000280400002C0400003004000010
:0800380034040000380400004C
:020000040005F5
:1057F000000000FFFFFF00FFAA8200FF1F3F00FF25
:00000001FF
;PIC24FJ256GA106
;CRC=E217  CREATED="19-Oct-12 17:44"


Notice how it toggles the upper address word throughout the hex
Eoin87



Joined: 20 Oct 2009
Posts: 18

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 5:45 pm     Reply with quote

Often when I looked at my hex files I saw sudden jumps in the addresses.
From the above posted example, one can even see the initial goto being written to location 0x0000 and the main body of the code being written to 0X4800.

heres another example from one of my .hex files
Code:

:104FF00056250200000000007053880081E0A900DF
:10500000040820001402880081E0A8006E2AEF0046
:1050100000002500A820B7009560A800FFFF37001A
:04502000FFFF370057
:10A00000362BEF00CCA2A90041E2A900F4132000F6
:10A010001412880041E2A800481280003400200099

Here there is a jump from 0x5020(phy addr /2) to 0XA000.

I want to write full blocks everytime to the flash memory and not have to run back and forward. This involves also reading before writing and modifying the positions which should be modified.
My aim is to have a file which looks like the following:

Code:

Address  Opcode

   0000   04275C
   0002   000000
   0004   FFFFFF
   0006   FFFFFF
   0008   0004C0
   000A   FFFFFF
   000C   FFFFFF
   000E   FFFFFF
   0010   FFFFFF
   0012   FFFFFF
   0014   00237E


I achieved this file by viewing program memory and exporting the resultant table. This should allow for very fast programming because I can program the flash memory rows, in full 64 instruction blocks, of course after first erasing the correct number of blocks for the new program
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Oct 19, 2012 6:56 pm     Reply with quote

Eoin87 wrote:
Often when I looked at my hex files I saw sudden jumps in the addresses.
From the above posted example, one can even see the initial goto being written to location 0x0000 and the main body of the code being written to 0X4800.

heres another example from one of my .hex files
Code:

:104FF00056250200000000007053880081E0A900DF
:10500000040820001402880081E0A8006E2AEF0046
:1050100000002500A820B7009560A800FFFF37001A
:04502000FFFF370057
:10A00000362BEF00CCA2A90041E2A900F4132000F6
:10A010001412880041E2A800481280003400200099

Here there is a jump from 0x5020(phy addr /2) to 0XA000.

I want to write full blocks everytime to the flash memory and not have to run back and forward. This involves also reading before writing and modifying the positions which should be modified.
My aim is to have a file which looks like the following:

Code:

Address  Opcode

   0000   04275C
   0002   000000
   0004   FFFFFF
   0006   FFFFFF
   0008   0004C0
   000A   FFFFFF
   000C   FFFFFF
   000E   FFFFFF
   0010   FFFFFF
   0012   FFFFFF
   0014   00237E


I achieved this file by viewing program memory and exporting the resultant table. This should allow for very fast programming because I can program the flash memory rows, in full 64 instruction blocks, of course after first erasing the correct number of blocks for the new program


In your example the blocks are disjointed but contiguous. This is not as efficient for a bootloader as non contiguous code but it is not really going to impact the bootload time significantly.

Jeremiah's example listing has more significance because it will result in writing multiple times to the same page in program memory. Some basic bootloaders (low program memory footprint) will have a problem with this as they will perform a page erase whenever a type 4 record crosses a page boundary. The result is that records from an earlier section of the hex file that has already been programmed earlier in the sequence will be lost during the page erase. It is also BAD for PICs with low program memory flash endurance, significantly shortening the programming life of these PICs.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
jeremiah



Joined: 20 Jul 2010
Posts: 1346

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 10:26 pm     Reply with quote

Eoin87,

One thing you can do to combat the "missing chunks" issue is to have a page sized buffer in your bootloader, initialized to 0xFF in all bytes. Then just fill in data as you get it from the downloader and do a single write.

The gotcha for this method is the issue I was highlighting (and mistakenly thought you meant) where memory jumps around, preventing you from saving data to a page sized buffer completely before data from the next page is introduced. In that scenario, you would just have to write what you have, and eat the "extra" time spent on any later chunks for that page. Remember, you can write 0xFF to any program memory spot as many times as you want as it doesn't change the current value of the spot, so overlap from 0xFF won't hurt you.

Asmallri,
One thing I have been experimenting with to combat this is to rewrite the write_program_memory() method to not erase if the address is a multiple of the page size. Then what I do is when the bootloader starts, it just bulk erases all pages in the user application space before it even determines which pages will be written to.

Now this method means I will be erasing pages that I may not be using, but all pages will have roughly the same lifetime at least. I still may have to deal with not having all of a page's data at once, but I won't have to erase the pages over and over due to data being out of order.
Eoin87



Joined: 20 Oct 2009
Posts: 18

View user's profile Send private message

PostPosted: Wed Oct 31, 2012 9:43 am     Reply with quote

Getting back to this, reading the program memory and saving to a file works like a charm Smile Very efficient programming.
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