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

Record bootloader with Hyperterminal.
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Ttelmah



Joined: 11 Mar 2010
Posts: 19587

View user's profile Send private message

PostPosted: Sun Nov 22, 2015 3:24 pm     Reply with quote

But, if you are loading this data via a system like a cell phone, then this is the main CRC you should check to verify that the whole communication has worked.
Problem is that the 'per line' CRC, does not guarantee that you have received the whole file. You could lose an entire line, and these would still be OK, but now the program would have a 'hole' in it.....
lucasromeiro



Joined: 27 Mar 2010
Posts: 167

View user's profile Send private message

PostPosted: Sun Nov 22, 2015 6:28 pm     Reply with quote

PCM programmer wrote:
It's a hex file comment. It should be ignored by the bootloader in the PIC.
The file 'loader.c' says this:
Quote:
// Only process data blocks that start with ':'
if (rBuffer[0].buffer[0] == ':')
{

Since that line starts with ';', the code will ignore it.


You're right!
I thought that was what was missing, but it is not.

I put some PRINTS to see where the error was.

I tested the bootloader transferring the program from the PC and then reading external EEPROM memory.
this was the result!

Code:

   while (!done)  // Loop until the entire program is downloaded
   {
      buffidx = 0;  // Read into the buffer until 0x0D ('\r') is received or the buffer is full
      flag_primeiro=1;
     
      for (J = 0; J < 64; J++) {
         buffer[J] = NULL;
      }
/*     
      do {
         //buffer[buffidx] = getc();
         
         aux_eeprom = read_ext_eeprom(contador);
         if(((aux_eeprom == ':') || (aux_eeprom == ';') ) && (flag_primeiro == 0)){buffer[buffidx] = 13;BREAK;}//0x0D
         if(aux_eeprom == 'O'){
            if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
         }
         buffer[buffidx] = aux_eeprom;
         contador = contador + 1;
         flag_primeiro=0;
      } while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
*/
      do {
         buffer[buffidx] = getc();
      } while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
      putchar (XOFF);  // Suspend sender

      do_ACKLOD = TRUE;

      // Only process data blocks that start with ':'
      if (buffer[0] == ':')
      {
printf("\r\n%s",buffer);
         count = atoi_b16 (&buffer[1]);  // Get the number of bytes from the buffer
printf("\r\n2- %d",buffer[1]);
printf("\r\n3- %d",count);
         // Get the lower 16 bits of address
         l_addr = make16(atoi_b16(&buffer[3]),atoi_b16(&buffer[5]));
printf("\r\n4- %ld",l_addr);
         line_type = atoi_b16 (&buffer[7]);
printf("\r\n5- %d",line_type);
         addr = make32(h_addr,l_addr);
printf("\r\n6- %ld",addr);
         #if defined(__PCM__)  // PIC16 uses word addresses
            addr /= 2;
         #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;
printf("\r\nCS:%d",checksum);
         if (checksum != atoi_b16 (&buffer[buffidx-3]))
            do_ACKLOD = FALSE;
         else
         {



result from PC:
:0406400037EF03F09D
2- 48
3- 4
4- 1600
5- 0
6- 1600
CS:-99
:08064800EA6A050EE96EEF50AD
2- 48
3- 8
4- 1608
5- 0
6- 1608
CS:-83
:100650000DE0060E016E006A002EFED7012EFBD7BC
2- 49
3- 16
4- 1616
5- 0
6- 1616
CS:-68
:100660007B0E006E002EFED7EF2EF3D71200F86A35
2- 49
3- 16
4- 1632
5- 0
6- 1632
CS:53
:10067000D09EB8862A0EAF6E000EB06EA60EAC6E7F
2- 49
3- 16
4- 1648
5- 0
6- 1648
CS:127
:10068000900EAB6EC150C00B0F09C16E840ED56EBB
2- 49
3- 16
4- 1664
5- 0
6- 1664
CS:-69
:10069000F29AF298F096F0989D9AF29CF29EF2BE31
2- 49
3- 16
4- 1680
5- 0
6- 1680
CS:49
:1006A000FDD794928B92939A8A8A640E056ECCDF62
2- 49
3- 16
4- 1696
5- 0
6- 1696
CS:98
:0E06B000939A8A9A640E056EC7DFF5D7030091
2- 48
3- 14
4- 1712
5- 0
6- 1712
CS:-111
:020000040030CA
2- 48
3- 2
4- 0
5- 4
6- 0
CS:-54
:0E00000000C2180E0084810000C03FE03F40A7
2- 48
3- 14
4- 0
5- 0
6- 3145728
CS:-89
:00000001FF
2- 48
3- 0
4- 0
5- 1
6- 3145728
CS:-1

-----------------------------------------


result from EEPROM:
:0406400037EF03F09D
2- 48
3- 4
4- 1600
5- 0
6- 1600
CS:-99
:08064800EA6A050EE96EEF50AD
2- 48
3- 8
4- 1608
5- 0
6- 1608
CS:-83
:100650000DE0060E016E006A002EFED7012EFBD7BC
2- 49
3- 16
4- 1616
5- 0
6- 1616
CS:-68
:100660007B0E006E002EFED7EF2EF3D71200F86A35
2- 49
3- 16
4- 1632
5- 0
6- 1632
CS:53
:10067000D09EB8862A0EAF6E000EB06EA60EAC6E7F
2- 49
3- 16
4- 1648
5- 0
6- 1648
CS:127
:10068000900EAB6EC150C00B0F09C16E840ED56EBB
2- 49
3- 16
4- 1664
5- 0
6- 1664
CS:-69
:10069000F29AF298F096F0989D9AF29CF29EF2BE31
2- 49
3- 16
4- 1680
5- 0
6- 1680
CS:49
:1006A000FDD794928B92939A8A8A640E056ECCDF62
2- 49
3- 16
4- 1696
5- 0
6- 1696
CS:98
:0E06B000939A8A9A640E056EC7DFF5D7030091
2- 48
3- 14
4- 1712
5- 0
6- 1712
CS:-111
:020000040030CA
2- 48
3- 2
4- 0
5- 4
6- 0
CS:-54
:0E00000000C2180E0084810000C03FE03F40A7
2- 48
3- 14
4- 0
5- 0
6- 0
CS:-89
:00000001FF
2- 48
3- 0
4- 0
5- 1
6- 0
CS:-1



I not understand why this happened!
Ttelmah



Joined: 11 Mar 2010
Posts: 19587

View user's profile Send private message

PostPosted: Mon Nov 23, 2015 1:40 am     Reply with quote

That is correct.......
However not with the code you show.

Look at the line before. Line type = 04. This says load the payload into the h_addr field (extended linear address). So 0x0030 gets put into h_addr. The code you show does not do this.

The next line it to be programmed at address 0x300000. Fuses probably.

Now, this raises a point.

Your bootloader _should not program the fuses_. If it does, you risk stopping it from running. Code that is to be loaded with the bootloader, _must_ run with the same fuses as the bootloader itself. Otherwise, once programmed, the bootloader will stop working.....

Ideally two things are done:

1) Write the bootloader to automatically reject writes to addresses outside the program memory.
2) Program code to be bootloaded, with "#FUSES NONE". This tells the compiler to not add fuses to the output file.

Preferably use _both_ approaches. This way if you (or another programmer), later 'forgets' to turn off the fuses, disaster is avoided, but also the extra space needed to send the fuses is also saved.

You need to handle the extended addressing, otherwise you can't program chips with >65K memory.

The CCS bootloader uses approach '1'. If you look, it only _writes_ to the memory if the decoded address < getenv("PROGRAM_MEMORY").
lucasromeiro



Joined: 27 Mar 2010
Posts: 167

View user's profile Send private message

PostPosted: Mon Nov 23, 2015 5:10 am     Reply with quote

Ttelmah wrote:
That is correct.......
However not with the code you show.

Look at the line before. Line type = 04. This says load the payload into the h_addr field (extended linear address). So 0x0030 gets put into h_addr. The code you show does not do this.

The next line it to be programmed at address 0x300000. Fuses probably.


I do not quite understand what you're saying.
but I do not I put the rest of the code, because it is the same as the original file.
I do not understand how the same "buffer" can have two different results ...
I still do not understand!

Ttelmah wrote:

Now, this raises a point.

Your bootloader _should not program the fuses_. If it does, you risk stopping it from running. Code that is to be loaded with the bootloader, _must_ run with the same fuses as the bootloader itself. Otherwise, once programmed, the bootloader will stop working.....

Ideally two things are done:

1) Write the bootloader to automatically reject writes to addresses outside the program memory.
2) Program code to be bootloaded, with "#FUSES NONE". This tells the compiler to not add fuses to the output file.

Preferably use _both_ approaches. This way if you (or another programmer), later 'forgets' to turn off the fuses, disaster is avoided, but also the extra space needed to send the fuses is also saved.

You need to handle the extended addressing, otherwise you can't program chips with >65K memory.

The CCS bootloader uses approach '1'. If you look, it only _writes_ to the memory if the decoded address < getenv("PROGRAM_MEMORY").


I did not understand anything he said here!
It was very confusing.
could be clearer?


I'm using the same fuses for the program and for the bootloader. I can not do that?

and the rest I do not understand anything! The standard bootloader does not do everything right? because you have to change something?



look at the code changes that I am making (loader.c):

Code:

///////////////////////////////////////////////////////////////////////////
////                         loader.c                                  ////
////                                                                   ////
//// This driver will take an Intel 8-bit Hex file over RS232 channels ////
//// and modify the flash program memory with the new code.  A proxy   ////
//// function is required to sit between the real loading function     ////
//// and the main code because the #org preprocessor command could     ////
//// possibly change the order of functions within a defined block.    ////
////                                                                   ////
//// After each good line, the loader sends an ACKLOD character.  The  ////
//// driver uses XON/XOFF flow control.  Also, any buffer on the PC    ////
//// UART must be turned off, or to its lowest setting, otherwise it   ////
//// will miss data.                                                   ////
////                                                                   ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2013 Custom Computer Services           ////
//// This source code may only be used by licensed users of the CCS C  ////
//// compiler.  This source code may only be distributed to other      ////
//// licensed users of the CCS C compiler.  No other use, reproduction ////
//// or distribution is permitted without written permission.          ////
//// Derivative programs created using this software in object code    ////
//// form are not restricted in any way.                               ////
///////////////////////////////////////////////////////////////////////////

#ifndef LOADER_END
 #define LOADER_END      getenv("PROGRAM_MEMORY")-1

 #if defined(__PCM__)
  #define LOADER_SIZE   0x27F
 #elif defined(__PCH__)
  #if (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")) == 0
   #define LOADER_SIZE   0x3FF
  #else
   #define LOADER_SIZE   (getenv("PROGRAM_MEMORY") % (getenv("FLASH_ERASE_SIZE")) - 1)
  #endif
 #endif
#endif

#define LOADER_ADDR LOADER_END-LOADER_SIZE

#ifndef BOOTLOADER_AT_START
 #ORG LOADER_ADDR+4, LOADER_END auto=0 default
#endif

#define BUFFER_LEN_LOD 64

int  buffidx;
char buffer[BUFFER_LEN_LOD];

#define ACKLOD 0x06
#define XON    0x11
#define XOFF   0x13

unsigned int atoi_b16(char *s);

void real_load_program (void)
{
   int1  do_ACKLOD, done=FALSE;
   int8  checksum, line_type;
   int16 l_addr,h_addr=0;
   int32 addr;
   #if getenv("FLASH_ERASE_SIZE") != getenv("FLASH_WRITE_SIZE")
      int32 next_addr;
   #endif
   int8  dataidx, i, count;
   int8  data[32];
   char aux_eeprom;
   int1 flag_primeiro;
   int J;
   while (!done)  // Loop until the entire program is downloaded
   {
      buffidx = 0;  // Read into the buffer until 0x0D ('\r') is received or the buffer is full
      flag_primeiro=1;
     
      for (J = 0; J < 64; J++) {
         buffer[J] = NULL;
      }
/*     
      do {
         //buffer[buffidx] = getc();
         
         aux_eeprom = read_ext_eeprom(contador);
         if(((aux_eeprom == ':') || (aux_eeprom == ';') ) && (flag_primeiro == 0)){buffer[buffidx] = 13;BREAK;}//0x0D
         if(aux_eeprom == 'O'){
            if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
         }
         buffer[buffidx] = aux_eeprom;
         contador = contador + 1;
         flag_primeiro=0;
      } while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
*/
      do {
         buffer[buffidx] = getc();
      } while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );




      putchar (XOFF);  // Suspend sender

      do_ACKLOD = TRUE;

      // Only process data blocks that start with ':'
      if (buffer[0] == ':')
      {
printf("\r\n%s",buffer);
         count = atoi_b16 (&buffer[1]);  // Get the number of bytes from the buffer
printf("\r\n2- %d",buffer[1]);
printf("\r\n3- %d",count);
         // Get the lower 16 bits of address
         l_addr = make16(atoi_b16(&buffer[3]),atoi_b16(&buffer[5]));
printf("\r\n4- %ld",l_addr);
         line_type = atoi_b16 (&buffer[7]);
printf("\r\n5- %d",line_type);
         addr = make32(h_addr,l_addr);
printf("\r\n6- %ld",addr);
         #if defined(__PCM__)  // PIC16 uses word addresses
            addr /= 2;
         #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;
printf("\r\nCS:%d",checksum);
         if (checksum != atoi_b16 (&buffer[buffidx-3]))
            do_ACKLOD = FALSE;
         else
         {
            // If the line type is 1, then data is done being sent
            if (line_type == 1)
               done = TRUE;
            else if (line_type == 4)
               h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
            else if (line_type == 0)
            {
               if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < getenv("PROGRAM_MEMORY"))
               {
                  // 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 ((addr!=next_addr) && (addr > (next_addr + (getenv("FLASH_ERASE_SIZE") - (next_addr % getenv("FLASH_ERASE_SIZE"))))) && ((addr & (getenv("FLASH_ERASE_SIZE")-1)) != 0))
                     {
                        #if defined(__PCH__) && defined(BOOTLOADER_AT_START)
                           #if ((getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")) != 0)
                              if (addr > (getenv("PROGRAM_MEMORY") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE"))))
                              {
                                 read_program_memory(getenv("PROGRAM_MEMORY"), buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
                                 erase_program_eeprom(addr);
                                 write_program_memory(getenv("PROGRAM_MEMORY"), buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
                              }
                              else
                           #endif
                        #endif
                                 erase_program_eeprom(addr);
                     }
                     #if defined(__PCM__)
                        next_addr = addr + count/2;
                     #else
                        next_addr = addr + count;
                     #endif
                  #endif
                 
                  #if defined(__PCH__) && defined(BOOTLOADER_AT_START)
                     #if ((getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")) != 0)
                        if (addr == (getenv("PROGRAM_MEMORY") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE"))))
                        {
                           read_program_memory(getenv("PROGRAM_MEMORY"), buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
                           write_program_memory(addr, data, count);
                           write_program_memory(getenv("PROGRAM_MEMORY"), buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
                        }
                        else
                     #endif
                  #endif
                           write_program_memory(addr, data, count);
               }

            }
         }
      }

      if (do_ACKLOD)
         putchar (ACKLOD);

      putchar(XON);
   }

   putchar (ACKLOD);
   putchar(XON);

   reset_cpu();
}

unsigned int atoi_b16(char *s) {  // Convert two hex characters to a int8
   unsigned int result = 0;
   int i;

   for (i=0; i<2; i++,s++)  {
      if (*s >= 'A')
         result = 16*result + (*s) - 'A' + 10;
      else
         result = 16*result + (*s) - '0';
   }

   return(result);
}

#ifndef BOOTLOADER_AT_START
 #ORG default
 #ORG LOADER_ADDR, LOADER_ADDR+3
#endif
void load_program(void)
{
   real_load_program();
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19587

View user's profile Send private message

PostPosted: Mon Nov 23, 2015 8:06 am     Reply with quote

This:
Code:

            else if (line_type == 4)
               h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));


Is what was missing from your earlier code, that loads the h_addr value.
Hence the difference between the two addresses.

The existing bootloader does everything to be a bootloader, _but_ is not what you want to be using if you are loading the value into an EEPROM, from a cell phone.

The bootloader assumes you are talking directly to the device, and will be able to reprogram, if something goes wrong. If you are 'pre-building' the data into an EEPROM from packets sent by a cell phone, _you_ need to add extra checking to ensure that what is built is 'right' before the loader can be used. This is _essential_.

This means the cellphone code is going to have to verify _all_ the data. Either by interpreting the checksum and testing this matches the received data, or by you adding another checksum outside the data. This though implies that the loader code is going to have to interpret the data. As such it is pointless to have this duplicated in the bootloader.
You could simplify the bootloader massively by just having it work directly with already interpreted data.
lucasromeiro



Joined: 27 Mar 2010
Posts: 167

View user's profile Send private message

PostPosted: Mon Nov 23, 2015 1:25 pm     Reply with quote

Ttelmah wrote:
This:
Code:

            else if (line_type == 4)
               h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));


Is what was missing from your earlier code, that loads the h_addr value.
Hence the difference between the two addresses.

The existing bootloader does everything to be a bootloader, _but_ is not what you want to be using if you are loading the value into an EEPROM, from a cell phone.

The bootloader assumes you are talking directly to the device, and will be able to reprogram, if something goes wrong. If you are 'pre-building' the data into an EEPROM from packets sent by a cell phone, _you_ need to add extra checking to ensure that what is built is 'right' before the loader can be used. This is _essential_.

This means the cellphone code is going to have to verify _all_ the data. Either by interpreting the checksum and testing this matches the received data, or by you adding another checksum outside the data. This though implies that the loader code is going to have to interpret the data. As such it is pointless to have this duplicated in the bootloader.
You could simplify the bootloader massively by just having it work directly with already interpreted data.



I'll still ride the safe transfer protocol for mobile data packet.
Now my difficulty is to read the EEPROM data and record them!
I assume that the EEPROM data is correct, because before recording them I already checked!

as I simplify the bootloader to work directly with the interpreted data?
I need help in this part!

.hex file of the data already have CRC?

how work?

:0406400037EF03F09D
:08064800EA6A050EE96EEF50AD
:100650000DE0060E016E006A002EFED7012EFBD7BC
:100660007B0E006E002EFED7EF2EF3D71200F86A35
:10067000D09EB8862A0EAF6E000EB06EA60EAC6E7F
:10068000900EAB6EC150C00B0F09C16E840ED56EBB
:10069000F29AF298F096F0989D9AF29CF29EF2BE31
:1006A000FDD794928B92939A8A8A640E056ECCDF62
:0E06B000939A8A9A640E056EC7DFF5D7030091
:020000040030CA
:0E00000000C2180E0084810000C03FE03F40A7
:00000001FF
;PIC18LF2685
;CRC=2444 CREATED="21-nov-15 13:04"
Ttelmah



Joined: 11 Mar 2010
Posts: 19587

View user's profile Send private message

PostPosted: Mon Nov 23, 2015 3:56 pm     Reply with quote

The supplied bootloader, 'dis-interprets' the incoming hex, to generate the bytes to feed to memory.

What you want to do is:

1) Have an EEPROM whose size matches or exceeds the ROM or your PIC.
2) Have a program running in your main code, which reads and dis-interprets the hex (bootloader shows how), and writes the values to the EEPROM.
3) Once the EEPROM is complete _check the CRC matches the one in the arriving hex.
4) Only if it does then set a flag in the EEPROM - remember if the EEPROM memory matches the PIC, there will be an unused block at the bottom of memory, where the bootloader resides in the PIC. You can use this to put a nice little table saying 'lowest location to program', 'highest location to program', and with a 'good' flag to say the data is valid.
5) If it doesn't, indicate the transfer has failed. Either tell the main system to send again, or whatever else you require.

6) On boot; the loader need only read the 'good' flag to know there is a new program there. You can either use a switch, or could completely get rid of this and just have the loader automatically trigger if the flag is set.
7) All the loader then has to do, is copy the data from the EEPROM to the program memory, from the 'lowest location', to 'highest location'. Once this is done, clear the 'good' flag.

Voila. The booloader code will actually be smaller than the standard bootloader (the extra space is the program in the main code which reads and verifies the data).

The approach you currently have, is like a person insisting on reading a document 'letter by letter', instead of the (amazing) way we scan word/section by section.
lucasromeiro



Joined: 27 Mar 2010
Posts: 167

View user's profile Send private message

PostPosted: Wed Nov 25, 2015 8:53 am     Reply with quote

Ttelmah wrote:
The supplied bootloader, 'dis-interprets' the incoming hex, to generate the bytes to feed to memory.

What you want to do is:

1) Have an EEPROM whose size matches or exceeds the ROM or your PIC.
2) Have a program running in your main code, which reads and dis-interprets the hex (bootloader shows how), and writes the values to the EEPROM.
3) Once the EEPROM is complete _check the CRC matches the one in the arriving hex.
4) Only if it does then set a flag in the EEPROM - remember if the EEPROM memory matches the PIC, there will be an unused block at the bottom of memory, where the bootloader resides in the PIC. You can use this to put a nice little table saying 'lowest location to program', 'highest location to program', and with a 'good' flag to say the data is valid.
5) If it doesn't, indicate the transfer has failed. Either tell the main system to send again, or whatever else you require.

6) On boot; the loader need only read the 'good' flag to know there is a new program there. You can either use a switch, or could completely get rid of this and just have the loader automatically trigger if the flag is set.
7) All the loader then has to do, is copy the data from the EEPROM to the program memory, from the 'lowest location', to 'highest location'. Once this is done, clear the 'good' flag.

Voila. The booloader code will actually be smaller than the standard bootloader (the extra space is the program in the main code which reads and verifies the data).

The approach you currently have, is like a person insisting on reading a document 'letter by letter', instead of the (amazing) way we scan word/section by section.



I understand what you want me to do!
I'm unable to do that!
I could understand that I can withdraw checksum lines of the .hex file and save memory on my EEPROM.
and take also checking the checksum in the bootloader.
the number 2 when you talk I will read the code "dis-interprets" I tried to understand the bootloader for how to do this, I understood how to get the checksum, removing the last 2 bytes.
in short, I will have to do this here?
Code:

for (i = 9, dataidx = 0; i <buffidx-3; i + = 2)
                     date [dataidx ++] = atoi_b16 (& buffer [i]);

This code above is part of the bootloader showing the useful part of the package that will be engraved in memory, am I right?

I do not understand what you meant in number 4. the same thing at number 7.
the rest I get it and I will do as you are asking!

I do not have much experience with this, I have trouble understanding. and do something.

I tried to understand why this error happens, but not understood:
: 0E00000000C2180E0084810000C03FE03F40A7
2- 48
3- 14
4- 0
5- 0
6- 0
CS: -89
: 00000001FF
2- 48
3- 0
4- 0
5- 1
6- 0
CS: -1

if I can not resolve the error, I can make it work.

because I could not do as you asked, I have no knowledge to that and not found anyone explain to me in more detail.

Can you help me?


you talking, it seems easy, but do not know how to do this:

Voila. The bootloader code will be smaller than Actually the standard bootloader (the extra space is the program in the main code Which reads and Verifies the date).

The approach you currently have, is like a person insisting on reading the document 'letter by letter, "instead of the (amazing) way we scan word / section by section.
jeremiah



Joined: 20 Jul 2010
Posts: 1358

View user's profile Send private message

PostPosted: Wed Nov 25, 2015 10:36 am     Reply with quote

The fact that the value is 3145728 (or 0x00300000) before and 0 after, would tend to move me towards a casting or conversion error somewhere. After all, if you cast or convert 3145728 to a 16bit number, it becomes 0.
lucasromeiro



Joined: 27 Mar 2010
Posts: 167

View user's profile Send private message

PostPosted: Wed Nov 25, 2015 11:19 am     Reply with quote

jeremiah wrote:
The fact that the value is 3145728 (or 0x00300000) before and 0 after, would tend to move me towards a casting or conversion error somewhere. After all, if you cast or convert 3145728 to a 16bit number, it becomes 0.


except!
I do not understand why the recording through the pc is that!
Interestingly, the recording through the PC goes to the end and restart the PIC!
The recording through the EEPROM, not ends and does not restart the pic.
I do not understand!!

I need help!
jeremiah



Joined: 20 Jul 2010
Posts: 1358

View user's profile Send private message

PostPosted: Wed Nov 25, 2015 1:28 pm     Reply with quote

So it could be a combination of things. I don't know exactly what the data looks like in the EEPROM. Based on your code, there are some "OK"s in it.

You do have some potential bugs that could cause your behavior:

1. Possible buffer overrun (doubtful the issue but still a bug):
Your buffer is 64 bytes long but certain parts of your code allow you access buffer[64] which is outside the range of the array:

Code:

      do {
         buffer[buffidx] = getc();
      } while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );


Notice here that you allow the loop to go if buffidx is less than or equal to BUFFER_LEN_LOD. This is not good. It should be just less than so the highest element you access is buffer[63]. I doubt this is the cause to your issue due to the size of the lines, but it is a potential bug later on. You will be overwriting other variables in memory with this bug. It also applies to your EEPROM reading loop which has the same condition.

2. Inconsistent final buffidx values (likely the issue):
In your EEPROM reading loop you have the following code
Code:

do {
         //buffer[buffidx] = getc();
         
         aux_eeprom = read_ext_eeprom(contador);
         if(((aux_eeprom == ':') || (aux_eeprom == ';') ) && (flag_primeiro == 0)){buffer[buffidx] = 13;BREAK;}//0x0D
         if(aux_eeprom == 'O'){
            if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
         }
         buffer[buffidx] = aux_eeprom;
         contador = contador + 1;
         flag_primeiro=0;
      } while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );


notice in particular:
Code:

         if(aux_eeprom == 'O'){
            if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
         }

here, if you get an "OK", it abruptly ends leaving the variable buffidx pointing to the 0x0D location. So if you line was ":020000040030CAOK", buffidx would be 15, pointing to the newly added '\r' just after the A

Your later check
Code:

if (checksum != atoi_b16 (&buffer[buffidx-3]))
            do_ACKLOD = FALSE;
         else
         {
            // If the line type is 1, then data is done being sent
            if (line_type == 1)
               done = TRUE;
            else if (line_type == 4)
               h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));

compares the computed checksum to the two characters starting at buffidx - 3 (in the initial if statement). Since buffidx is 15, it will start at 15-3 or index 12. The character at index 12 in this example is '0', not 'C' as you would expect. This would cause the checksum validation to fail in most cases (some number combinations would still work, but not many). If that check fails you never do the part:
Code:

h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));

which means, h_addr remains 0. Furthermore, you would never write the data to program memory, because you would never get into the else following the checksum validation.
lucasromeiro



Joined: 27 Mar 2010
Posts: 167

View user's profile Send private message

PostPosted: Wed Nov 25, 2015 3:10 pm     Reply with quote

jeremiah wrote:
So it could be a combination of things. I don't know exactly what the data looks like in the EEPROM. Based on your code, there are some "OK"s in it.

You do have some potential bugs that could cause your behavior:

1. Possible buffer overrun (doubtful the issue but still a bug):
Your buffer is 64 bytes long but certain parts of your code allow you access buffer[64] which is outside the range of the array:

Code:

      do {
         buffer[buffidx] = getc();
      } while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );


Notice here that you allow the loop to go if buffidx is less than or equal to BUFFER_LEN_LOD. This is not good. It should be just less than so the highest element you access is buffer[63]. I doubt this is the cause to your issue due to the size of the lines, but it is a potential bug later on. You will be overwriting other variables in memory with this bug. It also applies to your EEPROM reading loop which has the same condition.

2. Inconsistent final buffidx values (likely the issue):
In your EEPROM reading loop you have the following code
Code:

do {
         //buffer[buffidx] = getc();
         
         aux_eeprom = read_ext_eeprom(contador);
         if(((aux_eeprom == ':') || (aux_eeprom == ';') ) && (flag_primeiro == 0)){buffer[buffidx] = 13;BREAK;}//0x0D
         if(aux_eeprom == 'O'){
            if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
         }
         buffer[buffidx] = aux_eeprom;
         contador = contador + 1;
         flag_primeiro=0;
      } while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );


notice in particular:
Code:

         if(aux_eeprom == 'O'){
            if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
         }

here, if you get an "OK", it abruptly ends leaving the variable buffidx pointing to the 0x0D location. So if you line was ":020000040030CAOK", buffidx would be 15, pointing to the newly added '\r' just after the A

Your later check
Code:

if (checksum != atoi_b16 (&buffer[buffidx-3]))
            do_ACKLOD = FALSE;
         else
         {
            // If the line type is 1, then data is done being sent
            if (line_type == 1)
               done = TRUE;
            else if (line_type == 4)
               h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));

compares the computed checksum to the two characters starting at buffidx - 3 (in the initial if statement). Since buffidx is 15, it will start at 15-3 or index 12. The character at index 12 in this example is '0', not 'C' as you would expect. This would cause the checksum validation to fail in most cases (some number combinations would still work, but not many). If that check fails you never do the part:
Code:

h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));

which means, h_addr remains 0. Furthermore, you would never write the data to program memory, because you would never get into the else following the checksum validation.


Hello, thanks for your help!
I'm modifying the existing code already developed by CCS !!
Look LOADER.C file that comes with the ccs!
I'm modifying this file for him to read the data starting from the external EEPROM!
I already managed to get it completed the buffer with data from the EEPROM, but it did not work! I explained it above.

As for your questions,
much of what you said, not I who did. I was ready and it works. It is the standard ccs!

you said you would be my buffer (: 020000040030CAOK)
but that never happens! OK simply serves to detect the end of the program! It is a marker. He does not come in the package!
Note that I stop before putting it in the package!
His other doubts about the checksum, buffer size, etc ... Everything was done by the CCS team. I tested and work.
Look in my previous posts.
I posted the LOG of a debug what I did to see the value of the variables comparing a recording using PC with a recording reading the EEPROM program.
Buffer works well, I never burst! I do not lose data!
The checksum, always works!
The problem is what I told you before.
When I record a given from the PC by serial, everything is good and pic restarts to run the new program!
But when I record the program read by the EEPROM, everything happens in a similar way, except what I put in red in the debug I posted. Then the pic not complete recording and does not restart. But I do not understand why this happens.

Look 2 debugs I did and posted above! one with serial debug via recording and one with recording via EEPROM.
You will understand better, you will see the buffer and the checksum working.


The Ttelmah tried talking to help me step by step what to do, but I did not understand some of what he said. = (
lucasromeiro



Joined: 27 Mar 2010
Posts: 167

View user's profile Send private message

PostPosted: Mon Nov 30, 2015 5:31 pm     Reply with quote

Ttelmah wrote:
x


Hello Friend,
can you help me?
I read your text.
I had some doubts, posted above.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 30, 2015 6:40 pm     Reply with quote

Your complaint is that field 6 (the address) is displayed as 0. Jeremiah
told you that the problem is probably due to 'buffidx' being wrong.

That's what I found. I compiled your posted code, and the problem is
that buffidx is wrong. Because buffidx is wrong, the following code
doesn't read the checksum bytes from the HEX file line.
Code:
 if (checksum != atoi_b16 (&buffer[buffidx-3]))
            do_ACKLOD = FALSE;

As a result, the if() statement is False, and the "Type 4" code is not
executed, and the extended linear address is not extracted from the
hex file line, and field 6 is wrong.

The calculated checksum is correct. You are always loudly telling us that.
But the problem is that the "CA" checksum bytes in the following line
are not being read correctly, because buffidx is the wrong value.
Code:
:020000040030CA


You need to fix this. Do not ask us to fix it. It's your code.

Put in some debugging lines (printf), and look at the value of buffidx
just before it reads the checksum ("CA"), and make sure that buffidx
is correct. If not, then look at the code and fix it. Do not re-post
your request every couple of days, hoping that we will solve it for you.

Here are some tips:
buffidx should be pointing at the last character in the string.
In the tests that I ran, I used the following string:
Code:
 :020000040030CA 0x0d 0x0a

The hex file line ends with 0d, 0a, which is a carriage return and linefeed.
buffidx should be pointing at the 0x0a. Then when it gets to this line,
Code:
 if (checksum != atoi_b16 (&buffer[buffidx-3]))
            do_ACKLOD = FALSE;

buffidx will have 3 subtracted from it, and it will then point to "CA".
"CA" is the checksum for the hex line. atoi_b16() will convert it from
ascii to an integer. It will be compared to 'checksum', and will be equal.
The if() statement will be True, and the next code here will be executed:
Quote:
// If the line type is 1, then data is done being sent
if (line_type == 1)
done = TRUE;
else if (line_type == 4)
{
h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
printf("Processed line type 4 \n\r"); // *** ADDED ***
}

Then h_addr will be set to 0x3000, which is the desired result.

Here are the results of your tests when buffidx is correct:
Code:

:020000040030CA
buffidx = 16

2- 0
3- byte count = 02
4- l_addr = 0000
5- line_type = 04
6- addr = 00000000
CS in hex: ca

Processed line type 4

:0E00000000C2180E0084810000C03FE03F40A7
buffidx = 40

2- 0
3- byte count = 0e
4- l_addr = 0000
5- line_type = 00
6- addr = 00300000
CS in hex: a7

Done
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
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