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 hex file corruption

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



Joined: 08 Aug 2012
Posts: 34

View user's profile Send private message

bootloader hex file corruption
PostPosted: Fri Mar 22, 2013 11:02 am     Reply with quote

Hi all:

Environment is as follows:
-PIC18F2680
-Using ccs compiler v 4.092
-Using RS-485 for writing to program memory.
-Using ccsbootloader utility on the website for program download.
- I am using the bootloader.h,loader.c and ex_bootloader.c file provided by ccs.


I looked into forums, but I could not find what I am seeing. When I write to the PIC through the RS-485 line I am seeing all "ff" being written for some lines. I can't figure out why. Shouldn't the checksum catch it?

I don't have the greatest debugging environment to write it out a console. So, I am having to live with that.

The way I discovered this is I used the "ccs ICD-U64" programmer to read the chip after it is written and then do a diff with the original hex file.

a) I played with delay after write_program_memory() function in loader.c
What I find is that a delay of 90-100ms helps me reduce the number of corruptions to 1 or 2 lines.

Code:


:10160000E111E21102E1006A0DD0D89001BE09D0CB
:10161000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA
:10162000F4D7019E0001000C09010251D8B4A5D0E5



Anyone seen this? Any ideas, thoughts?
I don't see this issue if I flash a small program.

Any help is appreciated..

Regards.
Ttelmah



Joined: 11 Mar 2010
Posts: 19553

View user's profile Send private message

PostPosted: Fri Mar 22, 2013 12:04 pm     Reply with quote

Do some tests with your RS485.

It is not writing FFFFFF. This is the erased value. It is rejecting the line.

The commonest problems with RS485, are poor termination (how essential this is, depends on the data rate involved), and lack of bias, when the bus is not driven. I'd suggest the loader is possibly receiving a low of garbage when the bus is not driven, and then having trouble identifying the start of the packet.

Best Wishes
wirelessage



Joined: 08 Aug 2012
Posts: 34

View user's profile Send private message

PostPosted: Fri Mar 22, 2013 12:37 pm     Reply with quote

Thanks Ttelmah!

Makes sense. Shall look into it.
wirelessage



Joined: 08 Aug 2012
Posts: 34

View user's profile Send private message

PostPosted: Sun Mar 24, 2013 3:25 pm     Reply with quote

Actually. It doesn't make sense what is going on Smile

The checksum for the data turns out to be "DA". So, it cannot be data corruption over the wire.

Also, the location isn't the same. It changes on every write.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon Mar 25, 2013 2:07 am     Reply with quote

Did you consider that CCS doesn't necessarily write full hex lines? To check for possible corruption of the binary image, you must compare the translated binary.
Ttelmah



Joined: 11 Mar 2010
Posts: 19553

View user's profile Send private message

PostPosted: Mon Mar 25, 2013 2:10 am     Reply with quote

Of course it can (be data corruption over the wire).
Think about it. The hex file you are showing with the FF line, is generated by the ICD, so has a legitimate checksum for the line (since this is what is in the chip).
You are not seeing/showing what has actually been received.

You need to re-write the bootloader to do some diagnostics, or (simpler) write a program to emulate the bootloader. Have the same code as the bootloader, but have it when it receives a packet, instead of programming the chip, echo it out on another serial port. Then on your PC attach a second serial, and have it receive this data. You will then (hopefully) see what is being received.

Best Wishes


Last edited by Ttelmah on Mon Mar 25, 2013 3:25 am; edited 1 time in total
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Mar 25, 2013 2:59 am     Reply with quote

Just a general note:
Apart from your communication problems there is a fundamental feature missing from the CCS bootloader that will cause future problems.
As you have discovered there is a checksum on every line in the hex file, but what should the bootloader do when an error is discovered? I didn't check the source code, but I expect the line is dropped and that's why you see all 0xFF's (unprogrammed data). Now, the missing feature is that there is no mechanism available for the bootloader to request a retransmit of the corrupted line.

CCS can't be blamed for this, they built a small bootloader that will receive data from a simple text sending program like Hyperterm. Bootloaders from several other projects lack the same feature.

For a more robust bootloader a two-way protocol is needed. This can be done in many ways and even allows adding advanced features like memory read and verify. Disadvantage is that the user will have to install a dedicated bootloader program on his PC.
One of my favorites it the Tiny PIC Bootloader. The low level protocol is solid and bootloader code is tiny (about 100 words). Disadvantages are that you perhaps have to tweak the assembly code a bit to get it working for your processor and my main problem is that the PC program source code is not available (but you could always ask the author ...)

The protocol is simple and you could write your own PC host program, or searching the internet I found several other projects offering a PC host program using the same protocol. Here a first hit, aLinux port, but as it is written in Python it can easily be used on Windows as well.
Based on the above Linux code there is a new (January 2013) variant written in C# and offering complete source code: http://sourceforge.net/projects/tinypicbootload/
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon Mar 25, 2013 4:48 am     Reply with quote

Quote:
Now, the missing feature is that there is no mechanism available for the bootloader to request a retransmit of the corrupted line.

It's not actually missing, but probably not used by the loader tool.

The bootloader doesn't acknowledge packets with wrong checksum, it's up to the loader tool to retransmit it until getting an acknowledge, or cancel the download.
wirelessage



Joined: 08 Aug 2012
Posts: 34

View user's profile Send private message

PostPosted: Wed Mar 27, 2013 9:08 am     Reply with quote

Here is what I have found so far:

- Like some of you have illustrated, there is an issue with loader.c code in terms of error handling. The code verifies the checksum ONLY AFTER SUCCESSFULLY PARSING the first 8 bytes. What if there is corruption in the first 8 bytes. The code I downloaded from ccs does not address that. Here is the modified code that seems to have helped me.

You have to set the do_ACKLOD flag to FALSE, and then set it to true ONLY after verifying the checksum (for line-type == 0).

I have run a couple of runs to see (through a serial sniffer) that now if there is a corruption the CCS client sees that there is no ACK, and so re-transmits (up to 3 times) which should be good if the baud rate is set right.
I shall run more tests and provide an update.. but initial tests look encouraging.

Code:

      do_ACKLOD = FALSE; //Set to TRUE in the original code.
      //This is needed for ccsbootloader client. It first sends a ";HELLO" packet.
      if( buffer[0] == ';')
      {
         do_ACKLOD = TRUE;
      }
     
// Only process data blocks that start with ':'
      if (buffer[0] == ':') {
         count = atoi_b16 (&buffer[1]);  // Get the number of bytes from the buffer
         // Get the lower 16 bits of address
         l_addr = make16(atoi_b16(&buffer[3]),atoi_b16(&buffer[5]));

         line_type = atoi_b16 (&buffer[7]);

         addr = make32(h_addr,l_addr);
           
         #if defined(__PCM__)  // PIC16 uses word addresses
            addr /= 2;
         #endif

         // If the line type is 1, then data is done being sent
         if (line_type == 1) {
            done = TRUE;
            do_ACKLOD = TRUE;
         #if defined(__PCM__)
         } else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x2000){
         #elif defined(__PCH__)
         } else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x300000){
         #endif
            checksum = 0;  // Sum the bytes to find the check sum value
            for (i=1; i<(buffidx-3); i+=2)
               checksum += atoi_b16 (&buffer[i]);
            checksum = 0xFF - checksum + 1;

            if (checksum != atoi_b16 (&buffer[buffidx-3]))
               do_ACKLOD = FALSE;
            else   {
               do_ACKLOD = TRUE;
               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") > getenv("FLASH_WRITE_SIZE")
                     #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);
                  delay_ms(1);

               }
               else if (line_type == 4)
                  h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
            }
         }
      }
     
      if (do_ACKLOD)
         fputc(ACKLOD,PC);
      delay_ms(3);
     
      fputc(XON,PC);
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