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 problem

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



Joined: 22 Jun 2009
Posts: 5

View user's profile Send private message

Bootloader problem
PostPosted: Tue May 09, 2017 4:55 am     Reply with quote

Hello,

I use the pic 18f46k22 and the Compiler Revision 5.070.

I'm working on a bootloader application. The bootloader should have the loader routines and also routines for testing the pcb after assembling the board.

I have the following code:
- Bootloader:
Code:

#case
 
#include <18F46K22.h>

#FUSES NOWDT
#FUSES PUT                                                                    // Power Up Timer
#FUSES BORV29                                                                 // Brownout reset at 2.85V
#FUSES BROWNOUT                                                               // BrownOut-Reset aktiv
#FUSES NOPBADEN                                                               // PORTB pins Digital I/O nach RESET
#FUSES NOLVP                                                                  // no low voltage programing, B5 as I/O
#FUSES NOXINST                                                                // Extended set extension und Indexed Addressing mode ausgeschaltet
//#FUSES PROTECT                                                                // Code protected
//#FUSES CPB                                                                    // Boot Block read protected
//#FUSES WRTC                                                                   // Configuration registers write protected
//#FUSES WRTB                                                                   // Boot block write protected
//#FUSES EBTR                                                                   // memory read protected
//#FUSES EBTRB                                                                  // Boot block read protected


#define _bootloader

#include "bootloader.h"         
#include "bootloader_defs.h"
#include <string.h>
#include <math.h>
#include "my_eeprom.c"

#use delay(clock=32MHz, crystal=8MHz)                                         // 8 MHz-Crystal, PLL on -> 32 MHz
#use FAST_IO (ALL)

#use rs232(baud=57600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PCPORT,errors,brgh1ok)  // serial port -> 57600 Bd, 8 bit, No Parity
                                                                                            // -> RxD = PC6,  TxD = PC7


// -----  Global vars  ------------------------------------------------------------------------------------------------------------------------
char HWRevision[6] = "1.01b";

int             BLbuffidx;
char            BLbuffer[BUFFER_LEN_LOD] = {0};

unsigned int16  BLTimeOut = 0;                                       
unsigned int8   BLStartBootLoader = 0;
char            BLRXBuffer[20] = {0};
char            BLTXBuffer[20] = {0};
unsigned int8   BLError = 1;
unsigned int8   BLStartTest = 0;
unsigned int32  BLRXTimeOut = 0;
unsigned int8   BLReceivedBytes = 0;
unsigned int8   BLReceived = 0;
unsigned int8   BLNumberOfReceivedBytes = 0;
unsigned int8   BLReceiveState = 0;
char            BLReceivedByte = 0;
unsigned int8   BLRcvState = 0;


// --------------------------------------------------------------------------------------------------------------------------------------------------
//          Functions
// --------------------------------------------------------------------------------------------------------------------------------------------------

unsigned int16 ReadADC (unsigned int8 channel)                               // need for check the pcb
{
  unsigned int8   i = 0;   
  unsigned int16  retval = 0;

  ADCON0 &= 0x03;                       
  ADCON0 |= (channel << 2);             
  delay_us (200);                       
  for (i = 0; i < 10; i++)               
  {                                     
    ADCON0 |= 0x02;                     
    while (ADCON0 & 0x02);                       
    retval += (AD_RES_H * 0x100) + AD_RES_L;     
    delay_ms (2);                               
  }
  return (retval / 10);             
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
unsigned int8 CharToBIN (unsigned int8 *value)                                // ASCII to Bin
{
  unsigned int8 i;       
  unsigned int8 retval;
  unsigned int8 chr;
 
  for (i=0; i<2; i++)     
  {
    chr = toupper(*value);
    if (chr >= 'A')       
    {                     
      chr -= 'A';
      chr += 10;
    }
    else                   
      chr -= '0';           
    retval <<= 4;           
    retval |= chr;                                                 
    value++;               
  }
  return retval;     
}
// --------------------------------------------------------------------------------------------------------------------------------------------------

void CheckBoard(void)                                                         // Leiterplatten-Prüfroutine !
{


        // do some stuff to check the pcb.
        // only needed to test the board after assembling
        // should be overwritten with the device firmware


}
// --------------------------------------------------------------------------------------------------------------------------------------------------
unsigned int8 atoi_bl (unsigned int8 *value)                                  // ascii to bin for the bootloader
{   
  unsigned int8 i;     
  unsigned int8 retVal = 0;
  unsigned int8 chr;
 
  for (i = 0; i < 2; i++)         
  {
    chr = toupper(*value);   
    if (chr >= 'A')         
    {                       
      chr -= 'A';
      chr += 10;
    }
    else                         
      chr -= '0';               
    retVal <<= 4;               
    retVal |= chr;                                                 
    value++;                     
  }
  return retVal;
}
// --------------------------------------------------------------------------------------------------------------------------------------------------

// loader routine according the driver delivered with the compiler with some small modifications

void real_load_program (void) 
{
  int1  do_ACKLOD, done=FALSE;           
  unsigned int8  checksum, line_type;
  unsigned int16 l_addr;
  unsigned int16 h_addr = 0;
  signed int32 addr;
  #if getenv("FLASH_ERASE_SIZE") != getenv("FLASH_WRITE_SIZE")
   int32 next_addr;
  #endif
  unsigned int8  dataidx;
  unsigned int8  i;
  unsigned int8  count;
  unsigned int8  data[BUFFER_LEN_LOD / 2];
  unsigned int8  BLReceived = 0;
   
  BLRcvState = 0;   
  while (!done)     
  {
    BLbuffidx = 0;                                           
    BLReceived = 0;
    do                                                                        // polling serial port
    {
      if (kbhit(PCPORT))   
      {
        BLReceivedByte = getc(PCPORT);
        switch (BLRcvState)           
        {
          case 0:   if (BLReceivedByte == ':')     
                    {                                               
                      BLbuffer[0] = BLReceivedByte;
                      BLbuffidx = 1;               
                      BLRcvState = 1;             
                    }
                    break;
          case 1:   BLbuffer[BLbuffidx++] = BLReceivedByte;   
                    if (BLReceivedByte == 0x0a)               
                    {
                      BLReceived = 1;       
                      BLRcvState = 0;       
                    }
                    break;
        }
      }
    }
    while ((!BLReceived) && (BLbuffidx <= BUFFER_LEN_LOD));
    putchar (XOFF,PCPORT);                                 
    do_ACKLOD = TRUE;                                       
    if (BLbuffer[0] == ':')                                 
    {
      count = atoi_bl (&BLbuffer[1]); 
      l_addr = ((unsigned int16)(atoi_bl (&BLbuffer[3])) << 8) + atoi_bl (&BLbuffer[5]);
      line_type = atoi_bl (&BLbuffer[7]);
      addr = ((unsigned int32)(h_addr) << 16) + l_addr;   

      checksum = 0;                               
      for (i = 1; i < (BLbuffidx - 3); i+=2)
        checksum += atoi_bl (&BLbuffer[i]);
      checksum = 0xFF - checksum + 1;
      if (checksum != atoi_bl (&BLbuffer[BLbuffidx-3]))     
        do_ACKLOD = FALSE;                                   
      else                                                   
      {
        if (line_type == 1)         
          done = TRUE;             
        else                       
        {
          if (((addr < LOADER_ADDR) || (addr > LOADER_END)) && (addr < getenv("PROGRAM_MEMORY")))
          {
            for (i = 9; i <( BLbuffidx - 3); i += 2)                   
              data[dataidx++] = atoi_bl (&BLbuffer[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 ((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"), rBuffer[0].buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
                    erase_program_eeprom(addr);
                    write_program_memory(getenv("PROGRAM_MEMORY"), rBuffer[0].buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
                  }
                  else
                #endif
                    erase_program_eeprom(addr);
              }
              next_addr = addr + count;
            #endif
            #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"), rBuffer[0].buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
                write_program_memory(addr, data, count);
                write_program_memory(getenv("PROGRAM_MEMORY"), rBuffer[0].buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
              }
              else
            #endif
                write_program_memory(addr, data, count);
          }
        }
      }
    }
    if (do_ACKLOD)                                         
      putc (ACKLOD, PCPORT);
    putc(XON, PCPORT);     
  }
  putc (ACKLOD, PCPORT);                             
  putc(XON, PCPORT);                                 
  reset_cpu();                                       
}
// --------------------------------------------------------------------------------------------------------------------------------------------------

void load_program(void)
{
  real_load_program();     
}
// --------------------------------------------------------------------------------------------------------------------------------------------------

#org LOADER_END+2, LOADER_END+4

void application (void)       
{
  reset_cpu();                                                                // periodical start of the mcu if no application uploaded
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
//          Hauptprogramm
// --------------------------------------------------------------------------------------------------------------------------------------------------
void main(void)                                             
{
  unsigned int8 i = 0;                     
  unsigned int8 chksum = 0;
  char          outval[3] = "";
  unsigned int8 bytestosend = 0;
 
  setup_adc_ports (sAN0 | sAN1 | sAN2 | sAN3 | sAN4);                         // setup the adc for using durring check pcb
  setup_adc (ADC_CLOCK_INTERNAL | ADC_TAD_MUL_20);

  PORTA    = 0x00;                                                            // Init all portpins
  LATA     = 0x00;
  TRISA    = 0xff; 
 
  PORTB    = 0x20;   
  LATB     = 0x20;
  TRISB    = 0x00;
 
  PORTC    = 0x00;     
  LATC     = 0x00;
  TRISC    = 0x9f;

  PORTD    = 0x00;     
  LATD     = 0x00;
  TRISD    = 0x80;

  PORTE    = 0x00;   
  LATE     = 0x00;
  TRISE    = 0x01;

  ANSELA   = 0x2f;
  ANSELB   = 0x00;
  ANSELC   = 0x00;
  ANSELD   = 0x00;
  ANSELE   = 0x00;
   
  VREFCON0 = 0xb0;     
  ADCON1 = 0x08;       
  ADCON2 |= 0x80;     
 
  port_b_pullups (0x00); 
  disable_interrupts (GLOBAL);
 

  BUZZER = 1;                                                               // short beep to indicate the start of the mcu
  delay_ms (50);
  BUZZER = 0;
  BLTimeOut = 0;                                                            // Init vars
  BLReceived = 0;
  BLReceivedByte = 0;
  BLRXTimeOut = 0;
  BLReceiveState = 0;
  BLStartBootLoader = 0;

  while ((++BLTimeOut < 25) && (!BLStartBootLoader ))                       // loop till timeout or start bootloader
  {
    for (i = 0; i < 20; i++)                                                // clear buffer
    {
      BLRXBuffer[i] = 0;
      BLTXBuffer[i] = 0;
    }
    BLRXTimeOut = 0;                                     
    bytestosend = 0;
    while ((!BLReceived) && (++BLRXTimeOut < 10000))                        // poll serial port till data received or timeout
    {
      if (kbhit(PCPORT))                         
      {
        BLReceivedByte = getc(PCPORT);     
        switch (BLReceiveState)             
        {
          case 0:   if (BLReceivedByte == 0x02)     
                    {                                           
                      BLRXBuffer[0] = BLReceivedByte;           
                      BLReceivedBytes = 1;                   
                      BLRXTimeOut = 0;                       
                      BLReceiveState = 1;                     
                    }
                    break;
          case 1:   BLRXBuffer[BLReceivedBytes++] = BLReceivedByte;
                    BLRXTimeOut = 0;                               
                    if (BLReceivedByte == 0x03)                     
                    {
                      BLReceived = 1;       
                      BLNumberOfReceivedBytes = BLReceivedBytes - 1; 
                      BLReceivedBytes = 0;                           
                      BLReceiveState = 0;                             
                    }
                    break;
        }
      }
      delay_us (10);
    }
    if (BLReceived)                                                         // data received?
    {
      BLReceived = 0;
      switch (BLRXBuffer[1])                                                // evaluate data
      {
        case 'G':   switch (BLRXBuffer[2])                                  // (G)et
                    {
                      case 'I':   BLTXBuffer[0] = 0x02;                     // (I)d
                                  BLTXBuffer[1] = 'G';             
                                  BLTXBuffer[2] = 'B';
                                  BLTXBuffer[3] = 'o';
                                  BLTXBuffer[4] = 'o';
                                  BLTXBuffer[5] = 't';
                                  BLTXBuffer[6] = ' ';
                                  BLTXBuffer[7] = 'M';
                                  BLTXBuffer[8] = 'C';
                                  BLTXBuffer[9] = HWRevision[0]; 
                                  BLTXBuffer[10] = HWRevision[1];
                                  BLTXBuffer[11] = HWRevision[2];
                                  BLTXBuffer[12] = HWRevision[3];
                                  BLTXBuffer[13] = HWRevision[4];
                                  bytestosend = 14;
                                  break;
                    }
                    break;
        case 'S':   switch (BLRXBuffer[2])                                  // Start ->
                    {
                      case 'F':   BLStartBootLoader = 1;                    // -> firmware update
                                  BLTXBuffer[1] = 'O';
                                  BLTXBuffer[2] = 'K';
                                  bytestosend = 3;
                                  break;
                      case 'T':   if (read_eeprom_int16 (0x00) == 0xffff)   // no data stored -> new pcb with routine for board check
                                  {                                                                       
                                    BLStartTest = 1;
                                    BLTXBuffer[1] = 'T';                    // prepare answer to pc
                                    BLTXBuffer[2] = 'e';
                                    BLTXBuffer[3] = 's';
                                    BLTXBuffer[4] = 't';
                                    bytestosend = 5;
                                  }
                                  else                                      // pcb with firmware -> no test routine
                                  {                                         //
                                    BLTXBuffer[1] = 'N';
                                    BLTXBuffer[2] = 'o';
                                    BLTXBuffer[3] = 'T';
                                    BLTXBuffer[4] = 'e';
                                    BLTXBuffer[5] = 's';
                                    BLTXBuffer[6] = 't';
                                    bytestosend = 7;
                                  }
                                  break;
                    }
                    break;
      }
      if (bytestosend)                                                      // data to pc?
      {
        BLTXBuffer[0] = 0x02;                                               // STX
        chksum = 0;                                                         // checksum
        for (i = 1; i < bytestosend; i++)             
          chksum ^= BLTXBuffer[i];
        sprintf(outval,"%2u", chksum);
        BLTXBuffer[bytestosend++] = outval[0];                              // checksum into txbuffer
          BLTXBuffer[bytestosend++] = outval[1];
          BLTXBuffer[bytestosend++] = 0x03;                                 // ETX
          BLTXBuffer[bytestosend++] = 0x0a;                                 // LF
          BLTXBuffer[bytestosend++] = 0x0d;                                 // CR
          delay_ms (10);
          for(i = 0; i < bytestosend; i++)                                  // send answer
            putc(BLTXBuffer[i], PCPORT);
          bytestosend = 0;
        }
      }
    }
    if (BLStartBootLoader) 
    {
      BUZZER = 1;                                                           // -> only for development -> short beep
      delay_ms (100);
      BUZZER = 0;
      load_program ();                                                      // prog flash
    }
    if (BLStartTest)                                       
        CheckBoard ();                                                      // check pcb
    BLStartBootLoader = 0;                                                  // clear flags
    BLStartTest = 0;
  }
  application ();                                                           // run application
}
// --------------------------------------------------------------------------------------------------------------------------------------------------

#int_global
void isr(void)                                                              // map interrupt vectors
{
  jump_to_isr(LOADER_END + 5 * (getenv("BITS_PER_INSTRUCTION") / 8));
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------------------------------------


- Bootloader defines:
Code:


// -----  serial commands  ------------------------------------------------------------------------------------------------------------------------

#define ACKLOD 0x06                                                           // Zeichen "ACK"
#define XON    0x11                                                           // Zeichen "XON"
#define XOFF   0x13                                                           // Zeichen "XOFF"


// -----  port defines  ---------------------------------------------------------------------------------------------------------------

#byte PORTA = 0xf80
#byte PORTB = 0xf81
#byte PORTC = 0xf82
#byte PORTD = 0xf83
#byte PORTE = 0xf84

#byte TRISA = 0xf92
#byte TRISB = 0xf93
#byte TRISC = 0xf94
#byte TRISD = 0xf95
#byte TRISE = 0xf96

#byte LATA = 0xf89
#byte LATB = 0xf8a
#byte LATC = 0xf8b
#byte LATD = 0xf8c
#byte LATE = 0xf8d

// -----  ad converter defines  ---------------------------------------------------------------------------------------------------------

#byte ADCON0   = 0xfc2
#byte ADCON1   = 0xfc1
#byte ADCON2   = 0xfc0
#byte AD_RES_H = 0xfc4
#byte AD_RES_L = 0xfc3
#byte ANSELA   = 0xf38
#byte ANSELB   = 0xf39
#byte ANSELC   = 0xf3a
#byte ANSELD   = 0xf3b
#byte ANSELE   = 0xf3c
#byte VREFCON0 = 0xf42
#byte VREFCON1 = 0xf41
#byte VREFCON2 = 0xf40

// -----  interrupt control register  ---------------------------------------------------------------------------------------------------

#byte INTCON  = 0x0ff2
#byte INTCON2 = 0x0ff1                                                   
#byte INTCON3 = 0x0ff0                                                   
#byte PIR1    = 0x0f9e
#byte PIR2    = 0x0fa1                                       
#byte PIR3    = 0x0fa4
#byte PIR4    = 0x0f7b
#byte PIR5    = 0x0f7e

#byte PIE1    = 0x0f9d
#byte PIE2    = 0x0fa0                                       
#byte PIE3    = 0x0fa3
#byte PIE4    = 0x0f7a
#byte PIE5    = 0x0f7d

#byte IPR1    = 0x0f9f
#byte IPR2    = 0x0fa2       
#byte IPR3    = 0x0fa5
#byte IPR4    = 0x0f7c
#byte IPR5    = 0x0f7f

#byte RCON    = 0x0fd0

// -----  timer register  ---------------------------------------------------------------------------------------------------------------------------

#byte T0CON   = 0x0fd5
#byte TMR0H   = 0x0fd7
#byte TMR0L   = 0x0fd6

#byte T1CON   = 0x0fcd
#byte TMR1H   = 0x0fcf
#byte TMR1L   = 0x0fce
#byte T1GCON  = 0x0fcc
 
#byte T2CON   = 0x0fba
#byte TMR2_PR = 0x0fbb
#byte TMR2    = 0x0fbc

#byte T3CON   = 0x0fb1
#byte TMR3H   = 0x0fb3
#byte TMR3L   = 0x0fb2
#byte T3GCON  = 0x0fb4
 
#byte T4CON   = 0x0f51
#byte TMR4_PR = 0x0f52
#byte TMR4    = 0x0f53
 
#byte T5CON   = 0x0f4e
#byte TMR5H   = 0x0f50
#byte TMR5L   = 0x0f4f
#byte T5GCON  = 0x0f4d
 
#byte T6CON   = 0x0f4a
#byte TMR6_PR = 0x0f4b
#byte TMR6    = 0x0f4c

// -----  uart register  ----------------------------------------------------------------------------------------------------------------------------

#byte RCREG1   = 0x0fae                                                       // UART 1
#byte TXSTA1   = 0x0fac
#byte RCSTA1   = 0x0fab
#byte BAUDCON1 = 0x0fb8
#byte SPBRGH1  = 0x0fb0
#byte SPBRG1   = 0x0faf

#byte RCREG2   = 0x0f74                                                       // UART 2
#byte TXSTA2   = 0x0f72
#byte RCSTA2   = 0x0f71
#byte BAUDCON2 = 0x0f70
#byte SPBRGH2  = 0x0f76
#byte SPBRG2   = 0x0f75

// ----- portpin assign  -----------------------------------------------------------------------------------------------

#bit REMOTE_IN        = LATB.0
#bit REMOTE_OUT       = LATD.6

#bit LED_GREEN_RIGHT  = LATB.1
#bit LED_GREEN_LEFT   = LATB.2
#bit MOTOR_RIGHT_C    = LATB.3
#bit MOTOR_RIGHT_D    = LATB.4
#bit SWITCH_ACCU      = LATB.5
#bit LED_RED_LEFT     = LATB.6
#bit LED_RED_RIGHT    = LATB.7

#bit POS_1            = PORTC.2
#bit POS_2            = PORTC.1
#bit POS_3            = PORTC.0
#bit POS_4            = PORTD.7

#bit BUTTON_RIGHT     = PORTC.3
#bit BUTTON_LEFT      = PORTC.4
#bit BUZZER           = LATC.5

#bit MOTOR_LEFT_A     = LATD.0
#bit MOTOR_LEFT_B     = LATD.1
#bit MOTOR_LEFT_C     = LATD.2
#bit MOTOR_LEFT_D     = LATD.3
#bit MOTOR_RIGHT_A    = LATD.4
#bit MOTOR_RIGHT_B    = LATD.5

#bit KEYSWITCH_CLOSE  = PORTE.0
#bit KEYSWITCH_OPEN   = PORTA.4
#bit SEL_POS_LEFT     = LATE.1
#bit SEL_POS_RIGHT    = LATE.2

#bit DEBUG            = LATD.6



#define MOTORCURRENT_LEFT     0                                               // ad channels
#define MOTORCURRENT_RIGHT    1
#define PS_VOLTAGE            2
#define TEMPERATURE           3
#define ALARM                 4


// --------------------------------------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------------------------------------


- Bootloader settings
Code:



#define FLASH_SIZE getenv("FLASH_ERASE_SIZE")
#define LOADER_END    0x4FF
#define LOADER_SIZE   0x3ff
#define LOADER_ADDR (LOADER_END-LOADER_SIZE)                       

#ifndef _bootloader
  #build(reset=LOADER_END+1, interrupt=LOADER_END+9)
  #org 0, LOADER_END {}                             
#endif

#define BUFFER_LEN_LOD 64


- Routines for EEPROM read and write:
Code:


#if (getenv ("DATA_EEPROM") > 256)                                            // Größe EEPROM holen und Adresstyp automatisch setzen
  typedef unsigned int16 addr_size;
#else
  typedef unsigned int8 addr_size;
#endif

// --------------------------------------------------------------------------------------------------------------------------------------------------
//          Prototypes
// --------------------------------------------------------------------------------------------------------------------------------------------------

unsigned int16  read_eeprom_int16 (addr_size address);
void            write_eeprom_int16 (addr_size address, unsigned int16 data);

// --------------------------------------------------------------------------------------------------------------------------------------------------

void write_eeprom_int16 (addr_size address, unsigned int16 data)              // write 16bit value to eeprom
{
  signed int8 i = 0;

  for(i = 1; i >= 0; i--)   
  {
    write_eeprom ((address + i), (data & 0xff)); 
    data >>= 8;                                   
  }
}
// --------------------------------------------------------------------------------------------------------------------------------------------------

unsigned int16 read_eeprom_int16 (addr_size address)                          // read 16bit value from eeprom
{
  unsigned int8 i = 0;
  unsigned int16 data = 0;

  for (i=0; i<2; i++) 
  {
   data <<= 8;                         
   data += read_eeprom (address++);   
  }
  return data;         
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------------------------------------


The bootloader should read a command from the serial port.
If the command "Test" is received, the board check routine should start if there is no value at the first two positions in the eeprom. Otherwise the loader should send an answer, that no test routine is present.
If the command "Flash" is received, the loader should write the application to the flash. This should overwrite the routines for the board check. The routines for the board check are too big for storing in the bootloader area.

If the pcb is programed with the bootloader only, everything works fine. I can run the test routine and also start the upload of an firmware. But after I upload a firmware, the application did not start and also the bootloader did not start anymore. In the application software i included also the bootloader settings (_bootloader is not defined).

I'm sure i missed a setting for the bootloader in my application. Can you please help me ?


nhol
nhol



Joined: 22 Jun 2009
Posts: 5

View user's profile Send private message

PostPosted: Wed May 10, 2017 9:24 am     Reply with quote

Hello,

i found the problem. The Problem was the sprintf to convert the checksum to a string.

Snip from main of the bootloader:
Code:

      if (bytestosend)                                                      // data to pc?
      {
        BLTXBuffer[0] = 0x02;                                               // STX
        chksum = 0;                                                         // checksum
        for (i = 1; i < bytestosend; i++)             
          chksum ^= BLTXBuffer[i];
        sprintf(outval,"%2u", chksum);              // ---------->  did not work if application program is loaded
        BLTXBuffer[bytestosend++] = outval[0];                              // checksum into txbuffer
          BLTXBuffer[bytestosend++] = outval[1];
          BLTXBuffer[bytestosend++] = 0x03;                                 // ETX
          BLTXBuffer[bytestosend++] = 0x0a;                                 // LF
          BLTXBuffer[bytestosend++] = 0x0d;                                 // CR
          delay_ms (10);
          for(i = 0; i < bytestosend; i++)                                  // send answer
            putc(BLTXBuffer[i], PCPORT);
          bytestosend = 0;
        }
      }


nhol
jeremiah



Joined: 20 Jul 2010
Posts: 1355

View user's profile Send private message

PostPosted: Wed May 10, 2017 10:53 am     Reply with quote

You should check to see if the sprintf code is located inside the application address space. I didn't see any #orgs to prevent the bootloader from overwriting the application space. There was one for the application not to override the bootloader and one to place the dummy application main, but nothing to prevent an overly large bootloader from spilling out into the application space.
nhol



Joined: 22 Jun 2009
Posts: 5

View user's profile Send private message

PostPosted: Thu Jun 08, 2017 8:21 am     Reply with quote

Hello,

i've reworked may bootloader and put some #org into the code.
Code:


#case                                                         
 
#include <18F46K22.h>

#FUSES NOWDT
#FUSES PUT
#FUSES BORV29   
#FUSES BROWNOUT 
#FUSES NOPBADEN   
#FUSES NOLVP       
#FUSES NOXINST     
#FUSES PROTECT     
//#FUSES CPB       
//#FUSES WRTC     
#FUSES WRTB       
//#FUSES EBTR     
//#FUSES EBTRB     

#define _bootloader

#include "Motorcontroller_bootloader.h"
#include "Motorcontroller_bootloader_defs.h"
#include <string.h>
#include <math.h>
#include "my_eeprom.c"

#use delay(clock=32MHz, crystal=8MHz) 
#use FAST_IO (ALL)

#use rs232(baud=57600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PORT1,errors,brgh1ok) 

#ZERO_RAM
// -----  global vars ------------------------------------------------------------------------------------------------------------------------
char HWRevision[6] = "1.01b";

int             BLbuffidx;
char            BLbuffer[BUFFER_LEN_LOD] = {0};

unsigned int8   BLStartBootLoader = 0;
char            BLRXBuffer[30] = {0};
char            BLTXBuffer[30] = {0};
unsigned int8   BLStartTest = 0;

// --------------------------------------------------------------------------------------------------------------------------------------------------
//          functions
// --------------------------------------------------------------------------------------------------------------------------------------------------
#org APPLICATION_START, APPLICATION_START+0x100   
void application (void)                           
{
  reset_cpu();                                   
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
unsigned int16 ReadADC (unsigned int8 channel)
{
  unsigned int8   i = 0;                     
  unsigned int16  retval = 0;

  ADCON0 &= 0x03;                             
  ADCON0 |= (channel << 2);                   
  delay_us (200);                             
  for (i = 0; i < 10; i++)                   
  {                                           
    ADCON0 |= 0x02;                           
    while (ADCON0 & 0x02);                   
    retval += (AD_RES_H * 0x100) + AD_RES_L; 
    delay_ms (2);                             
  }
  return (retval / 10);                       
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
unsigned int8 CharToBIN (unsigned int8 *value)
{
  unsigned int8 i;                           
  unsigned int8 retval;
  unsigned int8 chr;
 
  for (i=0; i<2; i++)                         
  {
    chr = toupper(*value);                   
    if (chr >= 'A')                           
    {                         
      chr -= 'A';
      chr += 10;
    }
    else                     
      chr -= '0';             
    retval <<= 4;             
    retval |= chr;                                                 
    value++;                 
  }
  return retval;             
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
void CheckBoard(void) 
{
    // do some stuff to check the board after assembling

}
// --------------------------------------------------------------------------------------------------------------------------------------------------
#ORG LOADER_ADDR+10, LOADER_END auto=0 default         
unsigned int8 atoi_bl (unsigned int8 *value)   
{   
  unsigned int8 i;                             
  unsigned int8 retVal = 0;
  unsigned int8 chr;
 
  for (i = 0; i < 2; i++)                     
  {
    chr = toupper(*value);                     
    if (chr >= 'A')                           
    {                                         
      chr -= 'A';
      chr += 10;
    }
    else                                       
      chr -= '0';                             
    retVal <<= 4;                             
    retVal |= chr;                                                 
    value++;                                   
  }
  return retVal;                               
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
void real_load_program (void) 
{
  int1  do_ACKLOD, done=FALSE;
  unsigned int8  checksum, line_type;
  unsigned int16 l_addr;
  unsigned int16 h_addr = 0;
  unsigned int32 addr;
  #if getenv("FLASH_ERASE_SIZE") != getenv("FLASH_WRITE_SIZE")
   unsigned int32 next_addr;
  #endif
  unsigned int8  dataidx;
  unsigned int8  i;
  unsigned int8  count;
  unsigned int8  data[32];
  unsigned int8  BLReceived = 0;
  unsigned int8  rcvstate = 0;
  char rcvchar = 0;;
   
  rcvstate = 0;               
  while (!done)               
  {
    BLbuffidx = 0;             
    BLReceived = 0;
    do                         
    {
      if (kbhit(PORT1))       
      {
        rcvchar = getc(PORT1);
        switch (rcvstate)     
        {
          case 0:   if (rcvchar == ':')     
                    {                                               
                      BLbuffer[0] = rcvchar;
                      BLbuffidx = 1;       
                      rcvstate = 1;         
                    }
                    break;
          case 1:   BLbuffer[BLbuffidx++] = rcvchar;   
                    if (rcvchar == 0x0a)               
                    {
                      BLReceived = 1;                 
                      rcvstate = 0;                   
                    }
                    break;
        }
      }
    }
    while ((!BLReceived) && (BLbuffidx <= BUFFER_LEN_LOD));
    putchar (XOFF,PORT1);                                   
    do_ACKLOD = TRUE;                                       
    if (BLbuffer[0] == ':')
    {
      count = atoi_bl (&BLbuffer[1]);
      l_addr = ((unsigned int16)(atoi_bl (&BLbuffer[3])) << 8) + atoi_bl (&BLbuffer[5]);
      line_type = atoi_bl (&BLbuffer[7]);
      addr = ((unsigned int32)(h_addr) << 16) + l_addr;
      checksum = 0;                                     
      for (i=1; i<(BLbuffidx-3); i+=2)
        checksum += atoi_bl (&BLbuffer[i]);
      checksum = 0xFF - checksum + 1;
      if (checksum != atoi_bl (&BLbuffer[BLbuffidx-3]))
        do_ACKLOD = FALSE;                             
      else                                             
      {     
        switch (line_type)
        {
          case 0:   if (((addr < LOADER_ADDR) || (addr > LOADER_END)) && (addr < getenv("PROGRAM_MEMORY")))
                    {
                      dataidx = 0;   
                      for (i=9; i<(BLbuffidx-3); i+=2) 
                        data[dataidx++] = atoi_bl (&BLbuffer[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);
                    }
                    break;
          case 1:   done = TRUE;
                    break;
          case 4:   h_addr = ((unsigned int16)(atoi_bl (&BLbuffer[9]) << 8)) + atoi_bl (&BLbuffer[11]);
                    break;
        }
      }
    }
    if (do_ACKLOD)                                             
      putc (ACKLOD, PORT1);
    putc(XON, PORT1);                                         
  }
  putc (ACKLOD, PORT1);                                       
  putc(XON, PORT1);                                           
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
#org default
#org LOADER_ADDR, LOADER_ADDR+9
void load_program(void)
{
  real_load_program(); 
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
#int_global
void isr(void)   
{
  jump_to_isr(LOADER_END + 5 * (getenv("BITS_PER_INSTRUCTION") / 8));
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
//         main
// --------------------------------------------------------------------------------------------------------------------------------------------------
#org 0x0040, 0x044f   
void main(void)       
{
  unsigned int8   i = 0;
  unsigned int8   chksum = 0;
  unsigned int8   bytestosend = 0;
  unsigned int8   rxstate = 0;
  unsigned int16  rxtimeout = 0;
  unsigned int8   rcvchar = 0;
  int1            received = FALSE;
  unsigned int8   bytecounter = 0;
  unsigned int8   bootloaderruntime = 0;
  unsigned int8   nibble = 0;
 
  setup_adc_ports (sAN0 | sAN1 | sAN2 | sAN3 | sAN4);   
  setup_adc (ADC_CLOCK_INTERNAL | ADC_TAD_MUL_20);

  PORTA    = 0x00;                                     
  LATA     = 0x00;
  TRISA    = 0xff;                                     
 
  PORTB    = 0x20;                                     
  LATB     = 0x20;
  TRISB    = 0x00;                                     
 
  PORTC    = 0x00;                                     
  LATC     = 0x00;
  TRISC    = 0x9f;                                     

  PORTD    = 0x00;                                     
  LATD     = 0x00;
  TRISD    = 0x80;                                     

  PORTE    = 0x00;                                     
  LATE     = 0x00;
  TRISE    = 0x01;                                     

  ANSELA   = 0x2f;                                     
  ANSELB   = 0x00;                                     
  ANSELC   = 0x00;                                     
  ANSELD   = 0x00;                                     
  ANSELE   = 0x00;                                     
   
  VREFCON0 = 0xb0;                                     
  ADCON1 = 0x08;                                       
  ADCON2 |= 0x80;                                       
 
  port_b_pullups (0x00);                               
  disable_interrupts (GLOBAL);                         
  disable_interrupts (INT_TIMER0);
  disable_interrupts (INT_RDA);
  clear_interrupt (INT_TIMER0);                         
  clear_interrupt (INT_RDA);
 
//  while (TRUE)                                                                // delete comment for DEBUG
  {
    BUZZER = 1; 
    delay_ms (30);
    BUZZER = 0;
    received = FALSE;   
    rcvchar = 0;
    rxtimeout = 0;
    rxstate = 0;
    BLStartBootLoader = 0;
    bytecounter = 0;
    bootloaderruntime = 0;
   
    while ((++bootloaderruntime < 40) && (!BLStartBootLoader)) 
    {
      for (i = 0; i < 30; i++)                                 
      {
        BLRXBuffer[i] = 0;
        BLTXBuffer[i] = 0;
      }
      rxtimeout = 0;                                           
      bytestosend = 0;
      rxtimeout = 0;
      received = 0;
      while ((!received) && (++rxtimeout < 10000))             
      {
        if (kbhit(PORT1))                                       
        {
          rcvchar = getc(PORT1);                               
          switch (rxstate)                                     
          {
            case 0:   if (rcvchar == 0x02)                     
                      {                                         
                        BLRXBuffer[0] = rcvchar;               
                        bytecounter = 1;                       
                        rxtimeout = 0;                         
                        rxstate = 1;                           
                      }
                      break;
            case 1:   BLRXBuffer[bytecounter++] = rcvchar;     
                      rxtimeout = 0;                           
                      if (rcvchar == 0x03)                     
                      {
                        rcvchar = 0;
                        received = TRUE;                       
                        bytecounter = 0;                       
                        rxstate = 0;                           
                      }
                      if (bytecounter > 10)                     
                      {
                        rcvchar = 0;
                        bytecounter = 0;                       
                        rxstate = 0;                           
                        rxtimeout = 10000;
                      }                     
                      break;
          }
        }
        delay_us (10);                                         
      if (received)     
      {
        received = FALSE;   
        switch (BLRXBuffer[1])
        {
          case 'G':   switch (BLRXBuffer[2])
                      {
                        case 'I':   BLTXBuffer[0] = 0x02;   
                                    BLTXBuffer[1] = 'G';   
                                    BLTXBuffer[2] = 'B';
                                    BLTXBuffer[3] = 'o';
                                    BLTXBuffer[4] = 'o';
                                    BLTXBuffer[5] = 't';
                                    BLTXBuffer[6] = ' ';
                                    BLTXBuffer[7] = 'M';   
                                    BLTXBuffer[8] = 'C';
                                    BLTXBuffer[9] = HWRevision[0];
                                    BLTXBuffer[10] = HWRevision[1];
                                    BLTXBuffer[11] = HWRevision[2];
                                    BLTXBuffer[12] = HWRevision[3];
                                    BLTXBuffer[13] = HWRevision[4];
                                    bytestosend = 14;
                                    break;
                      }
                      break;
          case 'S':   switch (BLRXBuffer[2])                           
                      {
                        case 'F':   BLStartBootLoader = 1;             
                                    BLTXBuffer[1] = 'O';
                                    BLTXBuffer[2] = 'K';
                                    bytestosend = 3;
                                    break;
                        case 'T':   if (read_eeprom_int16 (0x00) == 0xffff)
                                    {                                                                       
                                      BLStartTest = 1;                     
                                      BLTXBuffer[1] = 'T';
                                      BLTXBuffer[2] = 'e';
                                      BLTXBuffer[3] = 's';
                                      BLTXBuffer[4] = 't';
                                      bytestosend = 5;
                                    }
                                    else                                   
                                    {                                       
                                      BLTXBuffer[1] = 'N';
                                      BLTXBuffer[2] = 'o';
                                      BLTXBuffer[3] = 'T';
                                      BLTXBuffer[4] = 'e';
                                      BLTXBuffer[5] = 's';
                                      BLTXBuffer[6] = 't';
                                      bytestosend = 7;
                                    }
                                    break;
                      }
                      break;
        }
        if (bytestosend)                                                   
        {
          BLTXBuffer[0] = 0x02;                                             
          chksum = 0;
          for (i = 1; i < bytestosend; i++)                                 
            chksum ^= BLTXBuffer[i];
          nibble = chksum / 0x10;                                           
          if (nibble > 9)
            BLTXBuffer[bytestosend++] = 'a' + (nibble - 10);               
          else
            BLTXBuffer[bytestosend++] = '0' + nibble;
          nibble = chksum % 0x10;                                           
          if (nibble > 9)
            BLTXBuffer[bytestosend++] = 'a' + (nibble - 10);               
          else
            BLTXBuffer[bytestosend++] = '0' + nibble;
          BLTXBuffer[bytestosend++] = 0x03;                                 
          BLTXBuffer[bytestosend++] = 0x0a;                                 
          BLTXBuffer[bytestosend++] = 0x0d;                                 
          delay_ms (10);
          for(i = 0; i < bytestosend; i++)                                 
            putc(BLTXBuffer[i], PORT1);
          bytestosend = 0;
        }
      }
    }
    if (BLStartBootLoader)                                                 
      load_program ();                                                     
    if (BLStartTest)                                                       
      CheckBoard ();                                                       
    BLStartBootLoader = 0;                                                 
    BLStartTest = 0;
  }
  application ();                                                           
}
// --------------------------------------------------------------------------------------------------------------------------------------------------
//          END
// --------------------------------------------------------------------------------------------------------------------------------------------------


Everything works fine. I can check my board and i can upload a firmware. If i programmed a firmware with about 50 % of ROM and about 77 % of RAM, my application works as expected. But if i programmed a firmware with about 69% of ROM and about 81 % of RAM, my application sporadical restart (checked by an counter that increments an eeprom cell after each start of the application).

If i programmed the bigger application without the bootloader (and also removed the #build before compiling), my application works fine.

Can you please give me some suggestions, what i should check to get my big application to work with the bootloader?


nhol
Ttelmah



Joined: 11 Mar 2010
Posts: 19545

View user's profile Send private message

PostPosted: Thu Jun 08, 2017 9:03 am     Reply with quote

I'd start the other way.

Get rid of your #org's.

Then build your bootloader.
Look at the resulting assembler.

Where is the end of the bootloader?. Remember LOADER_END needs to be one byte under the next page erase boundary above this.
Then where is the booloader const data being stored?.

Then try something else. Expand your code size without adding anything. Just create a large const array to use up some space. Don't do anything else. Does it still work?. Try the same with the RAM. Does it still work. I'd be slightly suspicious that something else is going wrong. Possibly a stack overflow in the extra code, or an array overflow etc.. So you need to make some demo code that is simple, and uses the space, to see if this really is the problem.
nhol



Joined: 22 Jun 2009
Posts: 5

View user's profile Send private message

PostPosted: Fri Jun 09, 2017 12:29 am     Reply with quote

Thanks Ttelmah

LOADER_END is defines with 0x07ff. This is the last address of the bootblock. The loader size is 0x0408. So this shouldn't be the problem.

The routines for the pcb test are located at the application space. They will be overwritten by the final application.

Now i store some countervalues and flags at the end of my eeprom. The flags are the restart causes. I hope, that with the flags i can find out the reason for the sporadic restarts.

nhol
Ttelmah



Joined: 11 Mar 2010
Posts: 19545

View user's profile Send private message

PostPosted: Fri Jun 09, 2017 1:37 am     Reply with quote

There are conflicts in what you are posting/saying.

If we look at your posted original bootloader 'main', the posted code has one more closing '}' than opening '{', so cannot compile.

There is a similar problem in your newer code, with a remarked out 'while', but the opening bracket still there, so it can't compile as posted....

Then you have as a posted code section:
Code:


#define FLASH_SIZE getenv("FLASH_ERASE_SIZE")
#define LOADER_END    0x4FF
#define LOADER_SIZE   0x3ff
#define LOADER_ADDR (LOADER_END-LOADER_SIZE)                       

#ifndef _bootloader
  #build(reset=LOADER_END+1, interrupt=LOADER_END+9)
  #org 0, LOADER_END {}                             
#endif

#define BUFFER_LEN_LOD 64

This differs from what you are saying about the declared loader size.

There is also a problem with this declaration. If you look at how the values are calculated in the bootloader.h, LOADER_SIZE is declared after other calculation, to be equal to LOADER_END. This way for a loader at the start of memory, LOADER_ADDR will always be zero. With your figures above, you have 100 locations at the start of memory, not protected from writes.....

You then say 'The loader size is 0x0408'. It isn't.
Fixing the bracket, the loader sizing errors, and compiling the code as posted, gives a size of 0x782.

You need to clean up and stop doing random fiddling.
It's important to understand how loader.h is used. All you need to do, to compile for a bootloader that is this size, is:
Code:

#define LOADER_END 0x7FF
#define _bootloader
#include "bootloader.h"


The bootloader file then automatically handles the #ORG's etc., for you.

As a general comment, sort out your include order. Generally the clock declaration must be in front of anything that may use the clock. I don't think there is any problem in this case, but it is bad practice to be putting it after other code includes.
nhol



Joined: 22 Jun 2009
Posts: 5

View user's profile Send private message

PostPosted: Fri Jun 09, 2017 5:00 am     Reply with quote

Thanks Ttelmah,

You are right. In my newest code, there is missing a closing bracket after the 10 us delay and before if (received). Sorry, for this (copy/paste error).
About the loader size, i forgot to show my new settings for the bootloader. I've changed the loader_end to 0x07ff.

All other points will be checked and will reorder my code. Thanks for your help.

nhol
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