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

Memory stomping in the bootloader

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



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

Memory stomping in the bootloader
PostPosted: Thu Sep 01, 2011 12:07 pm     Reply with quote

Hi Everyone -

I have been fighting the good fight in regards to the bootloader on 16F1947. In general, I am able to get it to work for very small applications.

Using the 4.124 CCS Compiler, MPLAB 8.73 as the host for the compiler.

I seem to be stomping on memory in the bootloader as I increase the size of the application program that the bootloader is loading.

I have mapped out my allocations as follows:


    0000-0002 - loader - Initial Jump (goto 030) with MOVLP set to 00
    0004-0008 - loader - #int_global
    0009-001E - loader - Location for delay_ms command
    0030-0069 - loader - Bootloader Main
    0080-0081 - loader - Load_Program (which calls the real load program)
    0094-0099 - loader - #use rs232 declaration for UART
    009A-00CE -loader - AtoI function
    00E1-026A -loader - Real load program part I
    02B6-0315 - loader - Real load program part II
    0400-0401 - loader - Application loop (never ending call to itself)
    0400-0402 - Application - initial jump w/MOVLP set to 08 & goto set to 000
    05A0-05D2 -Application - AtoI function (used in the application)
    055E-06D6 - Application -main


In attempting to find the general location of the stomping, I created a series of "beacons" in the code to see at what point the stomping may be occuring. They are nothing more than putc commands for me to see as the data is being processed. I have systematically placed then in the code, which I will explain momentarily.

I am using RealTerm with a delay of 5ms/char and 300ms/line. The 300ms is to allow the write back to the terminal window after the line of hex code is received. Since I am running half duplex, I added some delay to the putchar commands when switching from RX to TX and back. I can speed things up later when I have this memory thing beat and can remove the beacons.

A basic output of the beacons looks like:

1aIIII1bIIIIIIIIIIIIIIIIIIII2aIIIIIIIIIIIIIIIII2b

1a - Located immediately after the while loop that obtains the line data
I - Indicates that the AtoI function is being implimented
1b - Located after all of the commands to extract memory addr data
2a - Located after the accumulation of checksum values prior to checksum compare
2b - Just after a write to memory is performed

What I wanted to see is if or when any of the beacons failed to "light" when the bootloader was writing to memory.

In this process, I found 2 notes of potential interest:

The last lines of the hex code are as follows:

:020000040001F9
:04000E00E219FF0FE5
:00000001FF

HOWEVER, the second to last line NEVER gets written, even when the loader works. Note the beacons:

:020000040001F9
1aIIII1bIIIIII2aIII3a


:04000E00E219FF0FE5
1aIIII1b

The program sees it and establishes a memory address for it; however, it is never written.

I believe that the following line in the bootloader is preventing it from doing so:
//"else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x2000){"

:00000001FF
1aIIII1b2c
!!!

The other beacons:

2c - EOF record detected
3a - Line Type 4 declared (and I'm not sure if this has any bearing on PCM)
!!! - Occurs at the very end of the load function prior to the jump back to the main.

After establishing the beacons, I started to grow the application. It did not take that long t break it.

For application program lengths between 400 to 6A7, everything seems fine. Once I added another print statement and brought the range to 6D6, the failures started to occur.

Below is the signature of the beacons for the failure. It stopped dead and does not proceed at this point. I believe this to be the 3rd to last line of the hex file since the prior line matches the signature for a 00 record type of 1aIIII1bIIIIIIIIIIIIIIIIIIII2aIIIIIIIIIIIIIIIII2b:


1aIIII1bIIIIIIII2aIIIII

By the way, this does NOT match the healthy signature:
1aIIII1bIIIIII2aIII3a

One other note. I did try it on Tera Term and got the exact same result.

Anyways, I hope that these are a few clues for you. Any leads would be greatly appreciate. More than happy to post what you need.

I will post the codes momentarily.....
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

code with beacons
PostPosted: Thu Sep 01, 2011 12:17 pm     Reply with quote

I only made changes as needed to loader.c:

Code:

#ifndef LOADER_END

#define LOADER_END      getenv("PROGRAM_MEMORY")-1

#if defined(__PCM__)
   #define LOADER_SIZE   0x17F
#elif defined(__PCH__)
   #define LOADER_SIZE   0x3FF
#endif

#endif


#define LOADER_ADDR LOADER_END-LOADER_SIZE
#define BUFFER_LEN_LOD 64

int  buffidx;
char buffer[BUFFER_LEN_LOD];

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

#SEPARATE
unsigned int atoi_b16(char *s);

//#ORG LOADER_ADDR+10, LOADER_END auto=0 default
#ORG LOADER_ADDR+20, LOADER_END auto=0 default

#use rs232(UART2, baud=9600, xmit=PIN_G1, rcv=PIN_G2)

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")>2
      int32 next_addr;
   #endif
   int8  dataidx, i, count;
   int8  data[32];
   
   //lights to indicate bootload operation
   
   output_low(PIN_D1); 
   output_low(PIN_D3);
   output_low(PIN_D5);
   output_low(PIN_D7);
   
   // must enable transceiver for UART2/source side
   
   output_high(PIN_E5);  // OUT-ON enabled
   output_high(PIN_E6);  // RS-485
   

   while (!done)  // Loop until the entire program is downloaded
   {
   output_low(PIN_E7);   // TX Off
   output_high(PIN_E4);  // RX On
   
   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) );

      output_low(PIN_E4);  // RX Off    
      output_high(PIN_E7); // TX On

      putchar (XOFF);  // Suspend sender
     delay_ms(5);
     putchar ('1');
     delay_ms(5);
      putchar ('a');
     delay_ms(5);
      output_high(PIN_E7); // TX Off
    
      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

     output_high(PIN_E7); // TX On
     putchar ('1');
     delay_ms(5);    
      putchar ('b');
     delay_ms(5);
      output_low(PIN_E7); // TX Off
    
      
         // If the line type is 1, then data is done being sent
         if (line_type == 1) {
            done = TRUE;
           output_high(PIN_E7); // TX On
           putchar ('2');
           delay_ms(5);    
            putchar ('c');
           delay_ms(5);
         output_low(PIN_E7); // TX Off
         #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;

        output_high(PIN_E7); // TX On
        putchar ('2');
        delay_ms(5);    
         putchar ('a');
        delay_ms(5);
         output_low(PIN_E7); // TX Off
         
            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 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);
        output_high(PIN_E7); // TX On
        putchar ('2');
        delay_ms(5);    
         putchar ('b');
        delay_ms(5);
         output_low(PIN_E7); // TX Off
 }
               else if (line_type == 4)
             {
                  h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
                 output_high(PIN_E7); // TX On
                 putchar ('3');
                 delay_ms(5);    
                  putchar ('a');
                 delay_ms(5);
                  output_low(PIN_E7); // TX Off             
             }
            }
         }
      }


The changes made:


    Putc characters for beacons.
    ms_delay added for transceivers
    PIN_E7 and PIN_E4 for TX and Rx enablement
    PIN_Dx for LEDs
    #device name change


My bootloader.h code was given another name to prevent the compiler from using the one in the PICC directory:

Code:

  #define LOADER_END   (0x3FF)  //extend out the end addr
  #define LOADER_SIZE  (0x37F)  //but keep the size slightly smaller

#ifndef _bootloader

#build(reset=LOADER_END+1, interrupt=LOADER_END+5)

#org 0, LOADER_END {}

#endif


My loader main is as follows:

Code:

#include <ROS16F1947.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=16000000)
#use rs232(UART2, baud=9600, xmit=PIN_G1, rcv=PIN_G2, stream=sourceside)

#define _bootloader

#include <ROSbootloader.h>
#include <ROSloader.c>

#org LOADER_END+1,LOADER_END+20

void application(void) {
  while(TRUE);
}

//#org 0x20,0x3F
#org 0x30, 0x7A
void main(void) {
   setup_oscillator(OSC_16MHZ);
   if(!input(PIN_C5))
   {
    load_program();
   }
   delay_ms(1000);  // Ensure that there is no cross communication
                    // since RealTerm is still data dumping
   application();
}

#ORG default

#int_global
void isr(void) {
   jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Sep 01, 2011 1:21 pm     Reply with quote

The posted code is incomplete and can't be compiled.

I guess, the problem is, that you are leaving voids in the boot loader area, that is filled by the main application. These locations are however excluded from the bootload process.
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

That's an interestng idea
PostPosted: Thu Sep 01, 2011 2:13 pm     Reply with quote

FvM -

thank you for taking the time to look at the code. It may not be compiling due to the include statements. I have a file names with these prefixes in order to prevent the compiler from looking at the original code in the PICC directory. If the code is incomplete in any other way, please let me know and I will repost.

But, I did forget to add my targeted application code:

Code:

#include <ROS16F1947.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=16000000)
#use rs232( UART2, baud=9600, parity=N, xmit=PIN_G1, rcv=PIN_G2, bits=8, stream=sourceside)


#include <ROSbootloader.h>

   int i=0;
   char buffer[12];
   int16 l_addr1, l_addr2, l_addr3, l_addr4;
   int8  atoi1,atoi2, atoi3, atoi4, atoi5, atoi6;
   long l_addr5;
   int8 offset;
   int32 addr;
//Added a make16 command to see if it works

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);
}

void main(void) {

   
   //Activate the Transciever (OUT-ON)
    output_high(PIN_E5);
    // Establish protocol mode on Pin RE6:  RS-485 is high
    output_high(PIN_E6);
   //// Enable TX mode (DXEN)
    output_high(PIN_E7);
    //// Disable RX mode (RXEN)
   output_low(PIN_E4);

   setup_oscillator(OSC_16MHZ);
   
   fprintf(sourceside, "\r\nApplication program version 1.00 \r\n");

   buffer[0] = '0';
   buffer[1] = '1';
   buffer[2] = '2';
   buffer[3] = '3';
   buffer[4] = '4';
   buffer[5] = '5';
   buffer[6] = '6';
   buffer[7] = '7';
   buffer[8] = '8';
   buffer[9] = '9';
   buffer[10] = 'A';
   buffer[11] = 'B';
   
//   while(TRUE)
//   {
//     fprintf(sourceside,"%u ",++i);
    atoi1 = atoi_b16(&buffer[0]);
    atoi2 = atoi_b16(&buffer[2]);
    atoi3 = atoi_b16(&buffer[4]);
    atoi4 = atoi_b16(&buffer[6]);
    atoi5 = atoi_b16(&buffer[8]);
    atoi6 = atoi_b16(&buffer[10]);

   // fprintf(sourceside,"atoi1: 0x%4x  \r\n", atoi1);
   // fprintf(sourceside,"atoi2: 0x%4x  \r\n", atoi2);
   // fprintf(sourceside,"atoi3: 0x%4x  \r\n", atoi3);
   // fprintf(sourceside,"atoi4: 0x%4x  \r\n", atoi4);
   // fprintf(sourceside,"atoi5: 0x%4x  \r\n", atoi5);
   // fprintf(sourceside,"atoi6: 0x%4x  \r\n", atoi6);

   offset = 2;
   
    l_addr1 = make16(atoi_b16(&buffer[0]),atoi_b16(&buffer[2+offset]));
    l_addr2 = make16(atoi_b16(&buffer[4]),atoi_b16(&buffer[6+offset]));
    l_addr3 = make16(atoi_b16(&buffer[8]),atoi_b16(&buffer[10]));
    l_addr4 = make16(atoi_b16(&buffer[0]),atoi_b16(&buffer[2+1]));
    l_addr5 = make16(atoi_b16(&buffer[4]),atoi_b16(&buffer[6+1]));   
    fprintf(sourceside,"laddr1 with offset=2: 0x%4lx  \r\n", l_addr1);

    fprintf(sourceside,"laddr2 with offset=2: 0x%4lx  \r\n", l_addr2);
    fprintf(sourceside,"laddr3: 0x%4lx  \r\n", l_addr3);

    fprintf(sourceside,"laddr4 with offset=1: 0x%4lx  \r\n", l_addr4);

    fprintf(sourceside,"laddr5 with offset=1: 0x%4lx  \r\n", l_addr5);
/*   
   
   addr = make32(l_addr1,l_addr2);

   fprintf(sourceside,"make32 with addr 1 & 2: 0x%8lx  \r\n", addr);
   
    addr /= 2;  //PIC16 uses word addresses
   
   fprintf(sourceside,"make32 with addr 1 & 2 /2: 0x%8lx  \r\n", addr);
*/
}


I have some additional thoughts and questionson this, but let me construct an intelligent response. Back soon....
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

I don't think it is the application that pulls the trigger
PostPosted: Thu Sep 01, 2011 2:25 pm     Reply with quote

I do not believe that it is the application that causes the stompage since the bootloader.h has a very specific command that prevents this from happening:

Code:

#org 0, LOADER_END {}


As for the bootloader, there is some protection in the code to prevent the load command from being stomped upon:

Code:

else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x2000)


HOWEVER, it only protects the loader function, not the main() or the AtoI function, that happens before the code.

There is one piece of code that seem to take the brunt of the stomage is the end of the real_load_program, from the declaration of line_type == 4 to the end of the function.
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

The loader.c with ALL the code.
PostPosted: Thu Sep 01, 2011 2:27 pm     Reply with quote

Sorry about that FvM!

Code:


#ifndef LOADER_END

#define LOADER_END      getenv("PROGRAM_MEMORY")-1

#if defined(__PCM__)
   #define LOADER_SIZE   0x17F
#elif defined(__PCH__)
   #define LOADER_SIZE   0x3FF
#endif

#endif


#define LOADER_ADDR LOADER_END-LOADER_SIZE
#define BUFFER_LEN_LOD 64

int  buffidx;
char buffer[BUFFER_LEN_LOD];

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

#SEPARATE
unsigned int atoi_b16(char *s);

//#ORG LOADER_ADDR+10, LOADER_END auto=0 default
#ORG LOADER_ADDR+20, LOADER_END auto=0 default

#use rs232(UART2, baud=9600, xmit=PIN_G1, rcv=PIN_G2)

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")>2
      int32 next_addr;
   #endif
   int8  dataidx, i, count;
   int8  data[32];
   
   //lights to indicate bootload operation
   
   output_low(PIN_D1); 
   output_low(PIN_D3);
   output_low(PIN_D5);
   output_low(PIN_D7);
   
   // must enable transceiver for UART2/source side
   
   output_high(PIN_E5);  // OUT-ON enabled
   output_high(PIN_E6);  // RS-485
   

   while (!done)  // Loop until the entire program is downloaded
   {
   output_low(PIN_E7);   // TX Off
   output_high(PIN_E4);  // RX On
   
   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) );

      output_low(PIN_E4);  // RX Off    
      output_high(PIN_E7); // TX On

      putchar (XOFF);  // Suspend sender
     delay_ms(5);
     putchar ('1');
     delay_ms(5);
      putchar ('a');
     delay_ms(5);
      output_high(PIN_E7); // TX Off
    
      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

     output_high(PIN_E7); // TX On
     putchar ('1');
     delay_ms(5);    
      putchar ('b');
     delay_ms(5);
      output_low(PIN_E7); // TX Off
    
      
         // If the line type is 1, then data is done being sent
         if (line_type == 1) {
            done = TRUE;
           output_high(PIN_E7); // TX On
           putchar ('2');
           delay_ms(5);    
            putchar ('c');
           delay_ms(5);
         output_low(PIN_E7); // TX Off
         #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;

        output_high(PIN_E7); // TX On
        putchar ('2');
        delay_ms(5);    
         putchar ('a');
        delay_ms(5);
         output_low(PIN_E7); // TX Off
         
            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 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);
        output_high(PIN_E7); // TX On
        putchar ('2');
        delay_ms(5);    
         putchar ('b');
        delay_ms(5);
         output_low(PIN_E7); // TX Off
 }
               else if (line_type == 4)
             {
                  h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
                 output_high(PIN_E7); // TX On
                 putchar ('3');
                 delay_ms(5);    
                  putchar ('a');
                 delay_ms(5);
                  output_low(PIN_E7); // TX Off             
             }
            }
         }
      }
    
     output_high(PIN_E7);  // TX ON   
      if (do_ACKLOD)
       {
         putchar (ACKLOD);
       }
      
      putchar(XON);
     delay_ms(5);
     putchar(CR);
     delay_ms(5);
     //output_low(PIN_E7);  // TX OFF
     }

   output_high(PIN_E7);  // TX ON
   putchar (ACKLOD);
   delay_ms(5);
   putchar(XON);
   delay_ms(5);
   putchar('!');
   delay_ms(5);
   putchar('!');
   delay_ms(5);
   putchar('!');
   delay_ms(5);
   output_low(PIN_E7);  // TX OFF
   #ifndef _bootloader
   reset_cpu();
   #endif
}

unsigned int atoi_b16(char *s) {  // Convert two hex characters to a int8
   unsigned int result = 0;
   int i;
   output_high(PIN_E7); // TX On
   //putchar ('A');
   //delay_ms(5);    
   putchar ('I');
   delay_ms(5);
   output_low(PIN_E7); // TX Off
   for (i=0; i<2; i++,s++)  {
      if (*s >= 'A')
         result = 16*result + (*s) - 'A' + 10;
      else
         result = 16*result + (*s) - '0';
   }

   return(result);
}

#ORG default


//#ORG LOADER_ADDR, LOADER_ADDR+9
#ORG LOADER_ADDR, LOADER_ADDR+19

void load_program(void)
{
   real_load_program();
}
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

Bad unit?
PostPosted: Thu Sep 01, 2011 2:31 pm     Reply with quote

Though I have requested a 2nd unit and awaiting its arrival, is there a chance that I am dealing with a bad part? I know that the ICD will perform a checksum and I can verify the checksum (which I always do). Are they bulletproof?
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Sep 01, 2011 4:10 pm     Reply with quote

Quote:
HOWEVER, it only protects the loader function, not the main() or the AtoI function, that happens before the code.

Yes, I don't know why. I didn't yet work with the PIC16 bootloader code. In my PIC18 bootloader, the complete bootloader area and the fuses are protected. Apparently, CCS is writing confuse stuff in the low memory range. Simply block this in the bootloader and see what happens. I didn't check however, if the code starting at 0x400 is correct or if something is mssing.
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

Another twist to this story
PostPosted: Mon Sep 05, 2011 12:05 pm     Reply with quote

FvM -

I have been running different size pieces of code. What I am finding interesting is that the failure seems to occur at the end of the code, in particular, if the code is calling for 14 data words (0Eh) rather than the usual 16(10h) I am wondering if the size of the line is having something to do with it.

For example: The good code that works:

Code:

:100C30002300910004309200031004302000C20011
:040C4000A724212E96
:020000040001F9
:04000E00E219FF0FE5
:00000001FF


Example of the 2 code that do not work:

Code:

:100D9000C2005730C3003725623023009100043071
:0E0DA0009200031004302000C200E424D62E7E
:020000040001F9
:04000E00E219FF0FE5
:00000001FF


Code:

:1026F00003197C2B22007E2B2200B603852B2000A1
:0E270000F501FB01FC012200852B20000800E2
:020000040001F9
:04000E00E219FF0FE5
:00000001FF
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon Sep 05, 2011 2:40 pm     Reply with quote

You should change
Code:
else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x2000)

to
Code:
else if (addr > LOADER_END && addr < 0x4000)

as a first step.
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

An interesting find
PostPosted: Tue Sep 06, 2011 12:49 am     Reply with quote

FvM -

I will definitely give your recommendation a try. In the meantime, I have been experimenting by adding NOPs into the code. Each time I added a NOP into the application code to see if the bootloader responded correctly. No changes to the bootloader were made. Note that the lower data counts for a given line were fine. The higher data counts for a line caused the bootloader to hang.

I am curious to know if this correlates to the code change you recommended. I was under the impression that the 2000 was simply an upper address limit. If there is more to it, please explain.


Code:

#include <ROS16F1947.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=16000000)
#use rs232( UART2, baud=9600, parity=N, xmit=PIN_G1, rcv=PIN_G2, bits=8, stream=sourceside)


#include <ROSbootloader.h>

   int i=0;
   char buffer[12];
   int16 l_addr1, l_addr2, l_addr3, l_addr4;
   int8  atoi1,atoi2, atoi3, atoi4, atoi5, atoi6;
   long l_addr5;
   int8 offset;
   int32 addr;
//Added a make16 command to see if it works

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);
}

void main(void) {

   
   //Activate the Transciever (OUT-ON)
    output_high(PIN_E5);
    // Establish protocol mode on Pin RE6:  RS-485 is high
    output_high(PIN_E6);
   //// Enable TX mode (DXEN)
    output_high(PIN_E7);
    //// Disable RX mode (RXEN)
   output_low(PIN_E4);

   setup_oscillator(OSC_16MHZ);
   
   fprintf(sourceside, "\r\nApplication program version 1.00 \r\n");

   buffer[0] = '0';
   buffer[1] = '1';
   buffer[2] = '2';
   buffer[3] = '3';
   buffer[4] = '4';
   buffer[5] = '5';
   buffer[6] = '6';
   buffer[7] = '7';
   buffer[8] = '8';
   buffer[9] = '9';
   buffer[10] = 'A';
   buffer[11] = 'B';
   
//   while(TRUE)
//   {
//     fprintf(sourceside,"%u ",++i);
    atoi1 = atoi_b16(&buffer[0]);
    atoi2 = atoi_b16(&buffer[2]);
    atoi3 = atoi_b16(&buffer[4]);
    atoi4 = atoi_b16(&buffer[6]);
    atoi5 = atoi_b16(&buffer[8]);
    atoi6 = atoi_b16(&buffer[10]);

   // fprintf(sourceside,"atoi1: 0x%4x  \r\n", atoi1);
   // fprintf(sourceside,"atoi2: 0x%4x  \r\n", atoi2);
   // fprintf(sourceside,"atoi3: 0x%4x  \r\n", atoi3);
   // fprintf(sourceside,"atoi4: 0x%4x  \r\n", atoi4);
   // fprintf(sourceside,"atoi5: 0x%4x  \r\n", atoi5);
   // fprintf(sourceside,"atoi6: 0x%4x  \r\n", atoi6);

   offset = 2;
   
    l_addr1 = make16(atoi_b16(&buffer[0]),atoi_b16(&buffer[2+offset]));
    l_addr2 = make16(atoi_b16(&buffer[4]),atoi_b16(&buffer[6+offset]));
    l_addr3 = make16(atoi_b16(&buffer[8]),atoi_b16(&buffer[10]));
    l_addr4 = make16(atoi_b16(&buffer[0]),atoi_b16(&buffer[2+1]));
    l_addr5 = make16(atoi_b16(&buffer[4]),atoi_b16(&buffer[6+1]));   
    fprintf(sourceside,"laddr1 with offset=2: 0x%4lx  \r\n", l_addr1);

    fprintf(sourceside,"laddr2 with offset=2: 0x%4lx  \r\n", l_addr2);
    fprintf(sourceside,"laddr3: 0x%4lx  \r\n", l_addr3);

    fprintf(sourceside,"laddr4 with offset=1: 0x%4lx  \r\n", l_addr4);

    fprintf(sourceside,"laddr5 with offset=1: 0x%4lx  \r\n", l_addr5);
     #asm ASIS
     // Up to this point, the end hex is 0E, which did not work

   nop;   //00 - Worked :100DA0009200031004302000C200E4240000D72E7B
    nop;   //02 - Worked :020DB000D82E3B
    nop;   //04 - Worked :040DB0000000D92E38
    nop;   //06 - Worked :060DB00000000000DA2E35
    nop;   //08 - No Go  :080DB000000000000000DB2E32
    nop;   //0A - No Go  :0A0DB0000000000000000000DC2E2F
    nop;   //0C - No Go  :0C0DB00000000000000000000000DD2E2C
    nop;   //0E - No Go  :0E0DB000000000000000000000000000DE2E29
    nop;   //10 - Worked :100DB0000000000000000000000000000000DF2E26
     nop;   //12 - Worked :020DC000E02E23
     nop;   //14 - Worked :040DC0000000E12E20
     nop;   //16 - Worked :060DC00000000000E22E1D
     nop;   //18 - No Go  :080DC000000000000000E32E1A
     nop;   //1a - No Go  :0A0DC0000000000000000000E42E17
     nop;   //1c - No Go  :0C0DC00000000000000000000000E52E14
     nop;   //1e - No Go  :0E0DC000000000000000000000000000E62E11
     nop;   //20 - Worked :100DC0000000000000000000000000000000E72E0E
*/
     #endasm

//   }
}
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Sep 06, 2011 1:53 am     Reply with quote

The highest code address code 16F1947 is 0x3fff instead of 0x1fff. The respective change to the bootloader matters only for larger applications. The problem, as far as I saw, was that the compiler tried to write a few bytes in the 0..0x1f memory range, corrupting the bootloader image, although no regular code seems to be placed there. I didn't yet understand what it's intended for, so idea is to block it and check if something's missing for the application.

P.S.: The last lines of the hex files are intended to write the fuses. They are apparently misunderstood by the bootloader. But fuse reprogramming should be blocked by the bootloader anyway.

P.P.S.: I reviewed the bootloader code and think, the last lines should be decoded correctly and not allowed to be written to the device.
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