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 support@ccsinfo.com

Change configuration register from code
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
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Sun Nov 29, 2020 1:53 pm     Reply with quote

About eeprom write I have zero crossing signal so, in case it miss for more than 50 ms I stop eeprom write. I'll rise up VBOR to 2,5V. I'll try to understand if this change is possible by firmware so I can update devices with new release.
About test I have reprogrammed devices working from month without any problem. I also tested again with burst generator.

What do you think about bootloader ? Maybe something happens in case program counter jumps to bootloader routine ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Mon Nov 30, 2020 1:20 am     Reply with quote

This is down to how the bootloader is actually designed. The obvious
possibility is that some code 'overruns', and drops off the end, allowing
the top of memory loader to be reached. Does the bootloader contain the
ZCD detection code as well?. What would happen if you arrived at the
bootloader without the serial data arriving that it requires?. Could it do
some form of partial write?.
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Mon Nov 30, 2020 3:24 am     Reply with quote

Bootloader is based on example code of CCS. After received serial command firmware jump to routine waiting for serial string checking start bit and checksum. This is routine of boot.

Code:

void boot (void)
{
   uint1_t  do_ACKLOD, done=FALSE;
   uint8_t  checksum, line_type, dataidx, i, count, buffidx;
   uint16_t l_addr, h_addr=0;
   uint32_t addr;
   
   // Buffers
   uint8_t  data[32];
   uint8_t buffer[BUFFER_LEN_LOD];

   // Only required for parts where the flash erase and write sizes are different
   #if (getenv("FLASH_ERASE_SIZE") > getenv("FLASH_WRITE_SIZE"))
      uint32_t next_addr = 0;
   #endif

   disable_interrupts(global);

   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
      do
      {
         buffer[buffidx] = getc();

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

     putchar(XOFF);
      do_ACKLOD = TRUE;                                                          // Flag to indicate this is a sentence we should acknowledge

      // Only process data blocks that start with ':'
      if (buffer[0] == ':')
      {
         count = atoi_b16(&buffer[1]);                                           // Get the number of bytes from the buffer
         l_addr = make16(atoi_b16(&buffer[3]),atoi_b16(&buffer[5]));             // Get the lower 16 bits of address
         line_type = atoi_b16(&buffer[7]);                                       // Get the line type code from the string
         addr = make32(h_addr,l_addr);                                           // At the first time through h_addr is zero as we are assuming the high bytes of the addr are zero until we get a type 4 command

         if (line_type == 1)                                                     // If the line type is 1, then data is done being sent
         {
            done = TRUE;
//            do_ACKLOD = FALSE;   //tolto ?
         }
         else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x300000)  // Don't try to overwrite the loader
         {
            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
            {
               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 ((addr!=next_addr)&&(addr&(getenv("FLASH_ERASE_SIZE")/2-1)!=0))
                        erase_program_eeprom(addr);
                   
                     next_addr = addr + 1;
                  #endif

                  write_program_memory(addr, data, count);                             // Attempt a write to the program memory
//                 do_ACKLOD = FALSE; // tolto ?

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

      if (do_ACKLOD)                                                       // Only do this for sentences we have not already responded to
       putchar(ACKLOD);

       putchar(XON);
   }

   putchar(ACKLOD);
   putchar(XON);

   reset_cpu();                                                            // After writing a new program we always want to reset the CPU
}
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Nov 30, 2020 6:21 am     Reply with quote

Ok, I'm really confused now.....
earlier you posted that the oscillator stopped working,so the program can't run.
there's NO way the 'bootloader' code can STOP the clock, least none I know of.
the only software that I know that CAN stop the clock is the sleep() command according to a diagram in the datasheet.

Now there's a possiblity that the PIC is seeing 'EMI' as you have some sort of ZCD @ 50ms. I assume that's european line voltage ? A line voltage 'glitch' could randomly stop a PIC.

Again, use the internal osicallator for at least test. This eliminates any external clock hardware(xtal/caps/PCB) . I've got PIC with 1,000s of hours on them, using the internal osc, and none have ever 'stopped'.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Mon Nov 30, 2020 7:48 am     Reply with quote

Also the bootloader you show is different in two key ways.
First you have said that this is at the top of memory. This implies it is
possible for code 'walking' up the memory to reach it. Then it has no form
of testing when entered for the code actually wanting to do a bootload. You
should be adding a test for something (possibly a 'flag' byte set in the main
code, when you do want a bootload to occur, which if it is not set, results
in the bootloader calling a reset, instead of executing). Currently if you walk
into the bootloader you will be stuck.
Also there is a huge difference in terms of the protection that the actual
bootloader code needs to apply. The CCS code by default ensures that a
write cannot occur to a location where the bootloader is, or to the config
registers. This modified bootloader needs the same protections for it's
addresses.
There is another nastier difference. The CCS code is designed so that
'worst case', if a bootload fails, the bootloader itself is still left intact.
Since this bootloader is dependant on the main code calling it, this
protection is lost. A failed write will result in a chip that has to be
reprogrammed. Think again. Work out how to keep the bootloader like
the standard one so it launches at 'boot'.....
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Mon Nov 30, 2020 8:36 am     Reply with quote

I'm working on test with internal oscillator but issue is quite rare so it can take months or years. About bootloader I'll work around as you suggest. I can introduce a flag in order to check if call to bootloader is serial comunication or just a noise or program counter error. In this last case I can go out with reset.
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Nov 30, 2020 10:30 am     Reply with quote

The 'flag' for serial bootloading should be at least 3 unique characters long to prevent 'random' bootloading....
Also it'd be best to have 2 'partitions' for storing two programs, the 'current' one and the 'new' one. That way if the downloading fails, for ANY reason, the PIC can still use the 'current' version of the program. This scheme is similar to how some PC BIOS EEPROMs are unpgraded over the Internet. If this wasn't done the PC could become a 'brick'.
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Mon Nov 30, 2020 11:18 am     Reply with quote

yes, two partition is best solution but I haven't space. Bootload is used in production from customers so, in case something gone wrong with boot, they return back board. This isn't a a big problem.
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