# Bootloader PIC18F2550 con CCS PIC C Compiler



## darez (May 27, 2012)

Hace algunos dias me encuentro trabajando en el botloader para este pic , he buscado información el la red y he encontrado que  el compilador CCS o mas conocido como pic C compiler ofrece un bootloader fabricado por ellos
acá hay una pagina de referencia 

http://curiosidadesford.blogspot.com/2011/04/bootloader-hidcdc-para-pic18f2550.html

lo que hago es buscar e archivo fuente  que según la pagina citada es Ex_usb_bootloader.c  y lo compilo en un proyecto para 2550 
la compilación es correcta si ningún error  




luego de ello procedí a grabar este archivo con el pk2 como normalmente lo haría mediante e puerto ICSP, efectivamente el archivo se carga y cuando lo conecto al pc se reconoce como un nuevo dispocitivo USB y procedo a instalar los drivers del USB TO UART que asi se denomina el bootloader de ccs

el driver esta ubicado en directorio de instalación del compilador (C:\Archivos de programa\PICC\Drivers\NT,2000,XP,VISTA,7) efectivamente queda instalado de manera correcta .

hasta el momento el bootloader esta bn '
luego procedo a crear un programa sencillo con el cual busco hacer parpadear un led cada 1s  
para ello inclui la librería (#INCLUDE "usb_bootloader.h")

y procedo a cargar el archivo con el CCSLOAD 




selecciono el puerto rs232 y le doy COM 4 que fue donde quedo instalado el driver de 
USB TO COM

pero no funciona sale este error ¡ 



espero que alguien tenga este bootloader y me diga que es lo que estoy haciendo mal ¡ porfavor


----------



## rachelies (May 27, 2012)

Yo le cargo el programa con el Siow que trae el propio paquete PICC


----------



## darez (May 27, 2012)

rachelies dijo:


> Yo le cargo el programa con el Siow que trae el propio paquete PICC


Podria explicarme (Siow) ' la vdd lo unico que veo en ccs es el ccsload


----------



## rachelies (May 28, 2012)

Al instalar el Ccs, a mi me crea una carpeta en archivos de programa llamada PICC, y además del compilador se instalan mas cosas. Pues dentro de esa carpeta hay un programa llamado Siow, serial input/output monitor. Cuando lo abres configuras la comunicación, el puerto que usas, la velocidad, etc...  y después en la pestaña Download, eliges el .hex que quieres pasarle al PIC y te lo transfiere.
En el ejemplo "ex_usb_bootloader" es donde dice hacerlo así, y es como llevo tiempo haciendo:

```
This program must be loaded into a target chip using a device    ////
////  programmer.  Afterwards this program may be used to load new     ////
////  versions of the application program.  There is a specific        ////
////  protocol used by the bootloader, SIOW.EXE uses this protocol     ////
////  if you use the 'Download Software' option.
```

Un saludo y espero que tengas suerte.


----------



## darez (May 28, 2012)

Viejo gracias por su respuesta ya estoy un poco  mas cerca de lograrlo ¡
la verdad creo que tengo problemas con el hadware 

porque conecto el dispocitivo y instala el driver pero luego me sale una advertencia diciendo que no me reconoce el dispositivo 
luego intento tocar la placa y lo reconoce en el com 2 , luego habro el siow  en file y download sofware  aparentemente ha cargado el archivo ..
el programa que cargo es este 


```
#INCLUDE <18f2550.h>
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
//#use delay(clock=4mhz)
#USE delay (clock=20mhz)
#INCLUDE "usb_bootloader.h"



VOID MAIN(VOID){
set_tris_b(0x00);
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_2);
WHILE(TRUE){
DELAY_MS(100);
OUTPUT_TOGGLE(PIN_b7);
}
}
```
no se si tenga algo mal en el código  ps no hace nada ¡

Podría ayudarme diciéndome su hay alguna conexión en especial  yo tengo un condensador de 10 uf a 50 v conectado al voltage usb y resistencias de 22hom a los pines de datos del pic


----------



## rachelies (May 28, 2012)

Un dato importante es que tienes que tener los mismos fuses en el bootloader que hayas cargado que en el programa que quieras cargar después


----------



## darez (May 28, 2012)

rachelies dijo:


> Un dato importante es que tienes que tener los mismos fuses en el bootloader que hayas cargado que en el programa que quieras cargar después





Mi viejo muchas gracias ¡ deverdad ya me funciono  espero pagarte el favor luego de alguna manera ¡
modifique el programa y coloque el pulsador en el pin A0 

```
///////////////////////////////////////////////////////////////////////////
////                    EX_USB_BOOTLOADER.C                            ////
////                                                                   ////
////  This program is an example stand alone USB bootloader.  It uses  ////
////  the communication device class (CDC) that creates a virtual COM  ////
////  port on your PC.  The bootloader contains it's own set of USB    ////
////  and bootloader code in low memory, the high memory will contain  ////
////  the application (and if you are developing a USB application,    ////
////  this will hold it's own USB code).                               ////
////                                                                   ////
////  This program must be loaded into a target chip using a device    ////
////  programmer.  Afterwards this program may be used to load new     ////
////  versions of the application program.  There is a specific        ////
////  protocol used by the bootloader, SIOW.EXE uses this protocol     ////
////  if you use the 'Download Software' option.                       ////
////                                                                   ////
////  Compiling this program gives you a HEX file of just the loader.  ////
////  To load the application you have two choices: a.) use the loader ////
////  to load the application, or b.) merge the application HEX and    ////
////  loader HEX into one production HEX.  The #import() CCS command   ////
////  will help you perfrom the latter.  Be aware that if you do the   ////
////  former the PIC will get it's configuration bit settings (fuses)  ////
////  from the loader and not the application (this bootloader does    ////
////  not change the configuration bits)                               ////
////                                                                   ////
////  To create an application that is compatible with this loader     ////
////  simply #include usb_bootlaoder.h into your application.  This    ////
////  loader does support interrupts in your application.              ////
////                                                                   ////
////  This bootloader is designed to detect pin A4 low on reset (this  ////
////  is the push-button on the CCS USB Development kit).  If A4 is    ////
////  low it starts the USB CDC stack and checks for bootload          ////
////  information over USB.  Otherwise the application program is      ////
////  started.                                                         ////
////                                                                   ////
////  This is a port of ex_bootloader.c, which is a serial bootloader. ////
////  Since CDC makes it easy to port legacy applications, the         ////
////  previous example makes the bulk of this code.                    ////
////                                                                   ////
////  This example will work with the PCH compiler.  The               ////
////  following conditional compilation lines are used to include a    ////
////  valid device for each compiler.  Change the device, clock and    ////
////  RS232 pins for your hardware if needed.                          ////
////                                                                   ////
//// This file is part of CCS's PIC USB driver code.  See USB.H        ////
//// for more documentation and a list of examples.                    ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
//// VERSION HISTORY                                                   ////
////                                                                   ////
//// March 5th, 2009:                                                  ////
////   Cleanup for Wizard.                                             ////
////   PIC24 Initial release.                                          ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2009 Custom Computer Services           ////
//// This source code may only be used by licensed users of the CCS    ////
//// C compiler.  This source code may only be distributed to other    ////
//// licensed users of the CCS C compiler.  No other use,              ////
//// reproduction or distribution is permitted without written         ////
//// permission.  Derivative programs created using this software      ////
//// in object code form are not restricted in any way.                ////
///////////////////////////////////////////////////////////////////////////

//set to 1 to use a PIC's internal USB Peripheral
//set to 0 to use a National USBN960x peripheral
#define __USB_PIC_PERIF__ 1

#if !defined(__PCH__)
 #error This bootloader written for PIC18
#endif

#if __USB_PIC_PERIF__

 #INCLUDE <18f2550.h>
#fuses HSPLL,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN
#USE delay (clock=20mhz)

  //configure a 20MHz crystal to operate at 48MHz, for 4550
/*  #include <18F4550.h>
  #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN

  //configure a 8MHz crystal to operate at 48MHz, for 67j50
  //#include <18F67J50.h>
  //#fuses H4_SW,NOXINST,NOWDT,NOSTVREN,NOFCMEN,NOIESO,NOPROTECT,NODEBUG,PLL2,NOCPUDIV
  
  #use delay(clock=48000000)*/
#else //use the National USBN960x peripheral
  #include <18F452.h>
  #fuses HS,NOWDT,NOPROTECT,NOLVP
  #use delay(clock=20000000)
#endif   //endif check to see which peripheral to use

/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here.  If you are
// not using connection sense, comment out this line.  Without connection
// sense you will not know if the device gets disconnected.
//       (connection sense should look like this:
//                             100k
//            VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
//                     |
//                     +----/\/\/\/\/\-----GND
//                             100k
//        (where VBUS is pin1 of the USB connector)
//
/////////////////////////////////////////////////////////////////////////////
///only ccs's 18F4550 development kit has this pin
#if __USB_PIC_PERIF__ && defined(__PCH__)
 #define USB_CON_SENSE_PIN PIN_B2
#endif

#define LOADER_ISR 0x28
#build(interrupt=LOADER_ISR)

/*
 Configure, then load the bootloader definitions
*/
#define _bootloader
#include <usb_bootloader.h>

// Includes all USB code and interrupts, as well as the CDC API
#include <usb_cdc.h>


/*
 Goto the interrupt vector of the application.
*/
#org 0x08,0x17
void high_isr(void) 
{
   if (bit_test(g_InBootloader,0))
   {
    #ASM
     goto LOADER_ISR
    #ENDASM
   }
   else
   {
    #ASM
     goto APPLICATION_ISR
    #ENDASM
   }
}

#org 0x18,0x27
void low_isr(void) 
{
   if (bit_test(g_InBootloader,0))
   {
    #ASM
     goto LOADER_ISR+0x10
    #ENDASM
   }
   else
   {
    #ASM
     goto APPLICATION_ISR+0x10
    #ENDASM
   }
}

#define ROM_BLOCK_INVALID -1

int32 rom_block_start = ROM_BLOCK_INVALID;

#define EEPROM_ERASE_SIZE  getenv("FLASH_ERASE_SIZE")
int8 rom_block[EEPROM_ERASE_SIZE];

// see rom_w() documentation.  performs the flushing
void rom_w_flush(void)
{
   if (rom_block_start != ROM_BLOCK_INVALID)
   {
      erase_program_eeprom(rom_block_start);     //erase entire block
   
      write_program_memory(rom_block_start, rom_block, sizeof(rom_block));    //write modified block
      
      rom_block_start = ROM_BLOCK_INVALID;
   }
}

// see rom_w() documentation.  performs the writing
void rom_w_block(int32 location, char *src, int16 size)
{
   int32 block_start;
   int16 i,num;

   block_start = location & (~((int32)EEPROM_ERASE_SIZE-1));
      
   i = location - block_start;

   while (size) 
   {
      if (block_start != rom_block_start)
      {
         rom_w_flush();
         
         rom_block_start = block_start;
         
         read_program_memory(block_start, rom_block, sizeof(rom_block));  //read entire block to ram buffer
      }
      

      if (size>(EEPROM_ERASE_SIZE-i)) {num=EEPROM_ERASE_SIZE-i;} else {num=size;}

      memcpy(&rom_block[i], src, num);    //modify ram buffer

      src += num;
      block_start += EEPROM_ERASE_SIZE;
      i = 0;
      size -= num;
   }
}

// Write to Flash ROM.
//
// location - flash program memory address
// src - pointer to data to write
// size - number of bytes to write to flash
//
// Here is the sequence of events:
//   1.) Goes to the beginning of the first erase block for this address
//   2.) Reads n records to ram, where n is the PIC's flash erase size
//   3.) Erases block in flash
//   4.) Modifies block in RAM
//   5.) Writes changed block back to FLASH.  Writes in chunks defined by PIC's flash write size
//   6.) Goes back to step1 if there is still more data to be written
void rom_w(int32 location, char *src, int16 size)
{
   rom_w_block(location, src, size);
   rom_w_flush();
}

#define BUFFER_LEN_LOD 64

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

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

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

   return(result);
}

void load_program(void)
{
   int1  do_ACKLOD, done=FALSE;
   int8  checksum, line_type;
   int16 l_addr,h_addr=0;
   int8 to;
   int32 addr;
   int8  dataidx, i, count;
   int8  data[32];
   int  buffidx;
   char buffer[BUFFER_LEN_LOD];
   
   while (!done)  // Loop until the entire program is downloaded
   {
      usb_task();
      
      if (!usb_cdc_kbhit())
         continue;
         
      buffidx = 0;  // Read into the buffer until 0x0D ('\r') is received or the buffer is full
      to = 250;   //250 milliseconds
      do 
      {
         if (!usb_cdc_kbhit())
         {
            delay_ms(1);
            to--;
            if (!to)
               break;
         }
         else
            to = 250;
         i = usb_cdc_getc();
         buffer[buffidx++] = i;
      } while ( (i != 0x0D) && (i != 0x0A) && (buffidx <= BUFFER_LEN_LOD) );
            
      if (!to)
         continue;

      usb_cdc_putc(XOFF);  // Suspend sender

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

         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 the line type is 1, then data is done being sent
            if (line_type == 1) 
               done = TRUE;
            else if (line_type == 4)
               h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
            else if ((line_type == 0) && (addr >= (int32)APPLICATION_START) && (addr < ((int32)APPLICATION_END)))
            {
                  // 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]);
                       
                  rom_w_block(addr, data, count);
            }
         }
      }

      if (do_ACKLOD)
         usb_cdc_putc (ACKLOD);

      usb_cdc_putc(XON);
   }

   rom_w_flush();

   usb_cdc_putc (ACKLOD);
   usb_cdc_putc(XON);
   delay_ms(2000);   //give time for packet to flush
   reset_cpu();
}

void main(void) 
{
  #if (defined(__USB_87J50__) && (getenv("FUSE_SET:H4_SW")))
   #byte OSCTUNE = 0xF9B
   #bit PLLEN=OSCTUNE.6
   PLLEN = TRUE;
   delay_ms(250);
  #endif

   //we use PIN_A4 as an event to determine if we should start the USB CDC
   //bootloader.  if it is not low (button is not pressed) then goto the 
   //application, else if is low (button is pressed) then do the bootloader.
   if(!input(PIN_a0))
   {
      g_InBootloader = TRUE;
      usb_cdc_init();
      usb_init();
      while(!usb_enumerated());
      load_program();
   }

   g_InBootloader = FALSE;
   
  #ASM
   goto APPLICATION_START
  #ENDASM
}
```


----------



## rachelies (May 29, 2012)

Me alegro que te haya funcionado. Estamos para ayudarnos los unos a los otros.
Un saludo y suerte.


----------



## xyboni (Sep 14, 2012)

viejo darez, disculpa la ignorancia donde cambio el pulsador



disculpa ya lo encontre


----------



## bondadoso (Sep 30, 2012)

hola,
estoy utilizando el usb bootloader de ccs y quiero usar rc4,rc5,rc6,rc7 que son los pines del rs-232 y usb, como io, hize un programa para parpadear todos los puertos pero estos cuatro pines no parpadean, alguien sabe porque?


----------



## mjug02 (Nov 15, 2012)

darez ..hola que tal estoy empezando a involucrarme al bootloader y vi tus aportaciones que me parecieron importantes para mi iniciación, con este código pudiste hacer la comunicación',  no se como buscar este código yo puse #include usb_bootloader.h y la lineas de codigo son diferente me pudieras ayudar a entender que pasa? en el CCS


----------



## darez (Nov 16, 2012)

mjug02 dijo:


> darez ..hola que tal estoy empezando a involucrarme al bootloader y vi tus aportaciones que me parecieron importantes para mi iniciación, con este código pudiste hacer la comunicación',  no se como buscar este código yo puse #include usb_bootloader.h y la lineas de codigo son diferente me pudieras ayudar a entender que pasa? en el CCS



hola mjug02

Colega este es un tema viejo , el bootloader que esta planteado tiene algunos bugs y errores 
pero de igual manera investigando en Internet y con un poco de experiencia obtenida en ccs he logrado implementar un botloadre 100% funcional 

mire el siguiente código esta diseñado para un pic 2550 con un cristal de 20 mhz 


```
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL2,CPUDIV1,VREGEN,PUT,NOMCLR
#use delay(clock=48000000)

#define  ON    output_high
#define  OFF   output_low

//#define  LedV  PIN_B0
//#define  LedR  PIN_B1

#define  BTLDR PIN_E3

#define LOADER_ISR 0x28
#build(interrupt=LOADER_ISR)

#define _bootloader
#include "usb/usb_bootloader.h"
#include "usb/usb_cdc.h"

#org 0x08,0x17
void high_isr(void) 
{
   if (bit_test(g_InBootloader,0))
   {
    #ASM
     goto LOADER_ISR
    #ENDASM
   }
   else
   {
    #ASM
     goto APPLICATION_ISR
    #ENDASM
   }
}

#org 0x18,0x27
void low_isr(void) 
{
   if (bit_test(g_InBootloader,0))
   {
    #ASM
     goto LOADER_ISR+0x10
    #ENDASM
   }
   else
   {
    #ASM
     goto APPLICATION_ISR+0x10
    #ENDASM
   }
}

#define ROM_BLOCK_INVALID -1

int32 rom_block_start = ROM_BLOCK_INVALID;

#define EEPROM_ERASE_SIZE  getenv("FLASH_ERASE_SIZE")
int8 rom_block[EEPROM_ERASE_SIZE];

void rom_w_flush(void)
{
   if (rom_block_start != ROM_BLOCK_INVALID)
   {
      erase_program_eeprom(rom_block_start);
   
      write_program_memory(rom_block_start, rom_block, sizeof(rom_block));
      
      rom_block_start = ROM_BLOCK_INVALID;
   }
}

void rom_w_block(int32 location, char *src, int16 size)
{
   int32 block_start;
   int16 i,num;

   block_start = location & (~((int32)EEPROM_ERASE_SIZE-1));
      
   i = location - block_start;

   while (size) 
   {
      if (block_start != rom_block_start)
      {
         rom_w_flush();
         
         rom_block_start = block_start;
         
         read_program_memory(block_start, rom_block, sizeof(rom_block));
      }   

      if (size>(EEPROM_ERASE_SIZE-i)) num=EEPROM_ERASE_SIZE-i;
      else num=size;

      memcpy(&rom_block[i], src, num);

      src += num;
      block_start += EEPROM_ERASE_SIZE;
      i = 0;
      size -= num;
   }
}

void rom_w(int32 location, char *src, int16 size)
{
   rom_w_block(location, src, size);
   rom_w_flush();
}

#define BUFFER_LEN_LOD 64

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

unsigned int8 atoi_b16(char *s) 
{  
   char c;
   unsigned int8 result = 0;
   int i;

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

   return(result);
}

void load_program(void)
{
   int1  do_ACKLOD, done=FALSE;
   int8  checksum, line_type;
   int16 l_addr,h_addr=0;
   int8 to;
   int32 addr;
   int8  dataidx, i, count;
   int8  data[32];
   int  buffidx;
   char buffer[BUFFER_LEN_LOD];
   
   while (!done)
   {
      usb_task();
      
      if (!usb_cdc_kbhit())
         continue;
         
      buffidx = 0;
      to = 250;
      do 
      {
         if (!usb_cdc_kbhit())
         {
            delay_ms(1);
            to--;
            if (!to)
               break;
         }
         else
            to = 250;
         i = usb_cdc_getc();
         buffer[buffidx++] = i;
      } while ( (i != 0x0D) && (i != 0x0A) && (buffidx <= BUFFER_LEN_LOD) );
            
      if (!to)
         continue;

      usb_cdc_putc(XOFF);

      do_ACKLOD = TRUE;

      if (buffer[0] == ':') 
      {
         count = atoi_b16 (&buffer[1]);

         l_addr = make16(atoi_b16(&buffer[3]),atoi_b16(&buffer[5]));

         line_type = atoi_b16 (&buffer[7]);

         addr = make32(h_addr,l_addr);

         checksum = 0;
         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 == 1) 
               done = TRUE;
            else if (line_type == 4)
               h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
            else if ((line_type == 0) && (addr >= (int32)APPLICATION_START) && (addr < ((int32)APPLICATION_END)))
            {
               for (i = 9,dataidx=0; i < buffidx-3; i += 2)
                  data[dataidx++]=atoi_b16(&buffer[i]);
                       
               rom_w_block(addr, data, count);
            }
         }
      }

      if (do_ACKLOD) usb_cdc_putc (ACKLOD);

      usb_cdc_putc(XON);
   }

   rom_w_flush();

   usb_cdc_putc (ACKLOD);
   usb_cdc_putc(XON);
   delay_ms(100);
   #zero_ram
   reset_cpu();
}

void main(void) 
{
   if(!input(BTLDR))
   {
      //ON(LEDR);ON(LEDV);
      g_InBootloader = TRUE;
      usb_cdc_init();
      usb_init();
      while(!usb_enumerated());
      load_program();
   }
   g_InBootloader = FALSE;
   
   #ASM
      goto APPLICATION_START
   #ENDASM
}
```

con este código creas el proyecto en ccs  generas el .hex el cual podrá grabar con el pk2 
si te fijas en la linea 6 del condigo encontraras la siguiente instrucción  "#define  BTLDR PIN_E3" en la cuaal pordra modificar el pulsador para acceder al modo Bootloader 
el pulsador debe estar con una resistencia normalmente a 5volt y cuando presiones debe enviar un cero 
puedes intentarlo hasta aca mas mas luego escribo mas info de esto y te paso links de información con respecto a este tema


----------



## crooin (Nov 17, 2012)

Hola Darez, te hago una consulta, vi que subiste el codigo de un bootloader pero hace referencia a archivos que no estan, y ademas decis que es para 18f2550 pero se incluye el .h del 18f4550. Te pido si podes subir el proyecto completo de tu bootloader que funciona, el hardware y con que programa se cargan las aplicaciones de usuario. 
En realidad tengo una aplicación ya armada con 18F4550 y me gustaría que se pudiera actualizar por usb, pero solo me queda el pin E0 desocupado lo otro lo uso todo. Por eso sería importante conocer el codigo del bootloader para modificarle el mdo de entrada al bootloader y sacarle todo tipo de led de indicación de modo y eso.
Espero que me des una mano, y desde ya gracias por los aportes...


----------



## mjug02 (Nov 17, 2012)

muchas graciass darez por tu aporte, pondre en prueba tu codigo!!


----------



## darez (Nov 18, 2012)

crooin dijo:


> Hola Darez, te hago una consulta, vi que subiste el codigo de un bootloader pero hace referencia a archivos que no estan, y ademas decis que es para 18f2550 pero se incluye el .h del 18f4550. Te pido si podes subir el proyecto completo de tu bootloader que funciona, el hardware y con que programa se cargan las aplicaciones de usuario.
> En realidad tengo una aplicación ya armada con 18F4550 y me gustaría que se pudiera actualizar por usb, pero solo me queda el pin E0 desocupado lo otro lo uso todo. Por eso sería importante conocer el codigo del bootloader para modificarle el mdo de entrada al bootloader y sacarle todo tipo de led de indicación de modo y eso.
> Espero que me des una mano, y desde ya gracias por los aportes...



Teoricamente los bits de configuracion son los mismos  esete codigo funciona tanto para 2550 y 4550 ¡ solo es cambiar el #include<"Pic"> 
claro esta para pics gama 18 con usb ¡
Mañana o mas adelante con buen tiempo subiré los archivos o el proyecto completo


----------



## crooin (Nov 22, 2012)

darez dijo:


> Teoricamente los bits de configuracion son los mismos  esete codigo funciona tanto para 2550 y 4550 ¡ solo es cambiar el #include<"Pic">
> claro esta para pics gama 18 con usb ¡
> Mañana o mas adelante con buen tiempo subiré los archivos o el proyecto completo



Hola Darez, ya se que para cambiar el pic solo cambio el define, mi problema para poder probar tu codigo es los archivos:
"usb/usb_bootloader.h"
"usb/usb_cdc.h"
Son los del CCS?
Saludos


----------



## rachelies (Dic 12, 2012)

Si, esos archivos son del CCS, y son necesarios, son los que definen todo para hacer funcionar el Bootloader.
Un saludo


----------



## deadsistem (Jul 18, 2014)

Hola a todos, desde hace varios dias he intentado usar un bootloader en mi pic18f2550 para cargar firmware sin necesidad de un programador...pero no he tenido exito, si compila bien el bootloader en CCS y lo cargo por ICSP al pic y hasta ahi todo bien, pero al conectar el cable usb a la PC, no lo reconoce... oprimo el boton de boot antes de conectarlo a la PC y si entra en modo boot porque prende el LED, pero la PC no hace nada..

les dejo el código del bootloader que me encontre aki en el foro, del amigo DAREZ de un tema muy viejo referente a lo mismo... este es el bootloader que estoy utilizando


```
#include "18F2550.h"
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV2,VREGEN,PUT,MCLR
#use delay(clock=48000000)

#define  ON    output_high
#define  OFF   output_low
#define  LEDR  PIN_C1
#define  BTLDR PIN_C2

#define LOADER_ISR 0x28
#build(interrupt=LOADER_ISR)

#define _bootloader
#include "usb_bootloader.h"
#include "usb_cdc.h"

#org 0x08,0x17
void high_isr(void) 
{
   if (bit_test(g_InBootloader,0))
   {
    #ASM
     goto LOADER_ISR
    #ENDASM
   }
   else
   {
    #ASM
     goto APPLICATION_ISR
    #ENDASM
   }
}

#org 0x18,0x27
void low_isr(void) 
{
   if (bit_test(g_InBootloader,0))
   {
    #ASM
     goto LOADER_ISR+0x10
    #ENDASM
   }
   else
   {
    #ASM
     goto APPLICATION_ISR+0x10
    #ENDASM
   }
}

#define ROM_BLOCK_INVALID -1

int32 rom_block_start = ROM_BLOCK_INVALID;

#define EEPROM_ERASE_SIZE  getenv("FLASH_ERASE_SIZE")
int8 rom_block[EEPROM_ERASE_SIZE];

void rom_w_flush(void)
{
   if (rom_block_start != ROM_BLOCK_INVALID)
   {
      erase_program_eeprom(rom_block_start);
   
      write_program_memory(rom_block_start, rom_block, sizeof(rom_block));
      
      rom_block_start = ROM_BLOCK_INVALID;
   }
}

void rom_w_block(int32 location, char *src, int16 size)
{
   int32 block_start;
   int16 i,num;

   block_start = location & (~((int32)EEPROM_ERASE_SIZE-1));
      
   i = location - block_start;

   while (size) 
   {
      if (block_start != rom_block_start)
      {
         rom_w_flush();
         
         rom_block_start = block_start;
         
         read_program_memory(block_start, rom_block, sizeof(rom_block));
      }   

      if (size>(EEPROM_ERASE_SIZE-i)) num=EEPROM_ERASE_SIZE-i;
      else num=size;

      memcpy(&rom_block[i], src, num);

      src += num;
      block_start += EEPROM_ERASE_SIZE;
      i = 0;
      size -= num;
   }
}

void rom_w(int32 location, char *src, int16 size)
{
   rom_w_block(location, src, size);
   rom_w_flush();
}

#define BUFFER_LEN_LOD 64

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

unsigned int8 atoi_b16(char *s) 
{  
   char c;
   unsigned int8 result = 0;
   int i;

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

   return(result);
}

void load_program(void)
{
   int1  do_ACKLOD, done=FALSE;
   int8  checksum, line_type;
   int16 l_addr,h_addr=0;
   int8 to;
   int32 addr;
   int8  dataidx, i, count;
   int8  data[32];
   int  buffidx;
   char buffer[BUFFER_LEN_LOD];
   
   while (!done)
   {
      usb_task();
      
      if (!usb_cdc_kbhit())
         continue;
         
      buffidx = 0;
      to = 250;
      do 
      {
         if (!usb_cdc_kbhit())
         {
            delay_ms(1);
            to--;
            if (!to)
               break;
         }
         else
            to = 250;
         i = usb_cdc_getc();
         buffer[buffidx++] = i;
      } while ( (i != 0x0D) && (i != 0x0A) && (buffidx <= BUFFER_LEN_LOD) );
            
      if (!to)
         continue;

      usb_cdc_putc(XOFF);

      do_ACKLOD = TRUE;

      if (buffer[0] == ':') 
      {
         count = atoi_b16 (&buffer[1]);

         l_addr = make16(atoi_b16(&buffer[3]),atoi_b16(&buffer[5]));

         line_type = atoi_b16 (&buffer[7]);

         addr = make32(h_addr,l_addr);

         checksum = 0;
         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 == 1) 
               done = TRUE;
            else if (line_type == 4)
               h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
            else if ((line_type == 0) && (addr >= (int32)APPLICATION_START) && (addr < ((int32)APPLICATION_END)))
            {
               for (i = 9,dataidx=0; i < buffidx-3; i += 2)
                  data[dataidx++]=atoi_b16(&buffer[i]);
                       
               rom_w_block(addr, data, count);
            }
         }
      }

      if (do_ACKLOD) usb_cdc_putc (ACKLOD);

      usb_cdc_putc(XON);
   }

   rom_w_flush();

   usb_cdc_putc (ACKLOD);
   usb_cdc_putc(XON);
   delay_ms(100);
   #zero_ram
   reset_cpu();
}

void main(void) 
{
   if(!input(BTLDR))
   {
      ON(LEDR);
      g_InBootloader = TRUE;
      usb_cdc_init();
      usb_init();
      while(!usb_enumerated());
      load_program();
   }
   g_InBootloader = FALSE;
   OFF(LEDR);
   #ASM
      goto APPLICATION_START
   #ENDASM
}
```

y el siguiente codigo es el USB_BOOTLOADER.H al que hace referencia, aunque tengo dudas en las direcciones de memoria... checando el datasheet del pic18f2550 empieza en la 0x0000 y termina en la 0x7FFF.. y en el bootloader tiene 0x1FFFF, hay alguna diferencia?


```
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
////                     USB_BOOTLOADER.H                              ////
////                                                                   ////
////  This include file must be included by any application loaded     ////
////  by the example USB bootloader (ex_usb_bootloader                 ////
////                                                                   ////
////  The directives in this file relocate the reset and interrupt     ////
////  vectors as well as reserving space for the bootloader.           ////
////                                                                   ////
////  For more documentation see ex_usb_bootloader.c                   ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
//// VERSION HISTORY                                                   ////
////                                                                   ////
//// March 5th, 2009:                                                  ////
////   Cleanup for Wizard.                                             ////
////   PIC24 Initial release.                                          ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2009 Custom Computer Services           ////
//// This source code may only be used by licensed users of the CCS    ////
//// C compiler.  This source code may only be distributed to other    ////
//// licensed users of the CCS C compiler.  No other use,              ////
//// reproduction or distribution is permitted without written         ////
//// permission.  Derivative programs created using this software      ////
//// in object code form are not restricted in any way.                ////
///////////////////////////////////////////////////////////////////////////

//how big is the bootloader?
//the bootloader will reside from address 0x0000 to this location.  the
//application will then sit at this location+1 to the end of program memory.
//#if defined(__DEBUG)
#define LOADER_SIZE        (0x1FFF)
//#else
//#define LOADER_SIZE        (0x17FF)
//#endif

//the loader and application need a common flag that determines if we are in
//the bootloader or application, that way the ISR knows where to go.  this
//is the location in ram that is reserved for this flag.
#define LOC_IN_LOADER_FLAG  0x25

//// --- end configuration --- ////////////////////////////////////////////

#reserve LOC_IN_LOADER_FLAG

int8 g_InBootloader;
#locate g_InBootloader=LOC_IN_LOADER_FLAG

#define LOADER_START       (0)
#define LOADER_END         (LOADER_SIZE)
#define APPLICATION_START  (LOADER_SIZE+1)
#if defined(__USB_87J50__)
 #define APPLICATION_END    (getenv("PROGRAM_MEMORY")-9) //configuration bits
#else
 #define APPLICATION_END    (getenv("PROGRAM_MEMORY")-1)
#endif 
#define APPLICATION_ISR    (APPLICATION_START+8)

#ifdef _bootloader
 /*
  Provide an empty application, so if you load this .HEX file into the pic
  without an application this will prevent the pic from executing unknown code.
 */
 #org APPLICATION_START,APPLICATION_START+0xF
 void BlankApplication(void) 
 {
   while(TRUE);
 }

 //we need to prevent the loader from using application space
 #if (APPLICATION_END > 0x10000)
   #org APPLICATION_START+0x10, 0xFFFF {}
   #if (APPLICATION_END > 0x20000)
      #org 0x10000, 0x1FFFF {}
      #org 0x20000, APPLICATION_END {}
   #else
      #org 0x10000, APPLICATION_END {}
   #endif
 #else
   #org APPLICATION_START+0x10, APPLICATION_END {}
 #endif

   #define  USB_CONFIG_PID       0x0034

   #define USB_STRINGS_OVERWRITTEN
   char USB_STRING_DESC_OFFSET[]={0,4,12};

   // Here is where the "CCS" Manufacturer string and "SERIAL DEMO" are stored.
   // Strings are saved as unicode.
   // These strings are mostly only displayed during the add hardware wizard.
   // Once the operating system drivers have been installed it will usually display
   // the name from the drivers .INF.
   char const USB_STRING_DESC[]={
      //string 0
            4, //length of string index
            0x03, //USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
            0x09,0x04,   //Microsoft Defined for US-English
      //string 1  - manufacturer
            8, //length of string index
            0x03, //USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
            'C',0,
            'C',0,
            'S',0,
      //string 2 - product
            30, //length of string index
            0x03, //USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
            'C',0,
            'D',0,
            'C',0,
            ' ',0,
            'B',0,
            'o',0,
            'o',0,
            't',0,
            'l',0,
            'o',0,
            'a',0,
            'd',0,
            'e',0,
            'r',0
   };
#endif   //_bootloader

#ifndef _bootloader
 //in the application, this moves the reset and isr vector out of the bootload
 //space.  it then reserves the loader space from being used by the application.
 #build(reset=APPLICATION_START, interrupt=APPLICATION_ISR)
 #org 0, LOADER_END {}
#endif
```

tambien les comento que mi diagrama únicamente tiene un cristal de 20Mhz, el pic, R1 del MCLR, Boton de reset, boton de Boot, y un led indicador, cable USB (rojo=5vcd,verde=D+,blanco=D-,negro=GND), un capacitor de 100nf del pin VBUS del pic a GND...

QUE PODRE ESTAR HACIENDO MAL? 
hay que modificar las direcciones de memoria?
porque la pc no lo detecta?
ya habia instalado anteriormente un driver y quedo en el COM13, pero solo funcionó una vez y desde entonces ya no aparece ni el puerto ni el dispositivo... 
 pero se supone que es HID entonces no necesito drivers?
aun asi, probe conectandolo a otra PC que no sabe de mi existencia y de igual manera, no pasa nada, no lo detecta aunque entre en modo bootloader desde el pic.

por favor, de antemano gracias por la atención y espero alguien pueda ayudarme. saludos


----------



## D@rkbytes (Jul 18, 2014)

deadsistem dijo:


> les comento que mi diagrama únicamente tiene *un  cristal de 20Mhz*, el pic, R1 del MCLR, botón de reset, botón de Boot, y  un led indicador, cable USB (rojo=5vcd,verde=D+,blanco=D-,negro=GND),  un capacitor de 100nf del pin VBUS del pic a GND.


 Si estás usando un cristal de 20MHz. para llevar el CPU a 48MHz, entonces tienes mal la palabra de configuración.

Usa esta:
*#fuses hspll, cpudiv1, pll5, nobrownout, nopbaden, nolvp
#use delay(clock = 48MHz)*

Suerte.


----------



## deadsistem (Jul 18, 2014)

D@rkbytes dijo:


> Si estás usando un cristal de 20MHz. para llevar el CPU a 48MHz, entonces tienes mal la palabra de configuración.
> 
> Usa esta:
> *#fuses hspll, cpudiv1, pll5, nobrownout, nopbaden, nolvp
> ...



gracias por tu pronta respuesta Darkbytes pero sigue sin funcionar.. si entra el modo bootloader pero la PC no detecta el dispositivo... otra pregunta: tiene que llevar USBDIV, no? debido a que el periferico es de 48MHz, de todos modos lo probe sin USBDIV y con USBDIV y sigue igual... no lo detecta ninguna PC... que podrá ser?


----------



## TRILO-BYTE (Jul 19, 2014)

puede que compile bien pero el CCS dependiendo la vercion genera errores en el USB
lo se por que me paso ami

lo que puedes hacer es buscar un .hex de un bootloader como el que da microchip que esta en microchip solutions 2013 

tiene 2 bootloaders uno para el 2550 y el efectivo del 4550
se lo cargas y funciona bastante bien


----------



## D@rkbytes (Jul 19, 2014)

deadsistem dijo:


> Gracias por tu pronta respuesta D@rkbytes pero sigue sin funcionar.
> Si entra el modo bootloader pero la PC no detecta el dispositivo.
> Otra pregunta: ¿Tiene que llevar USBDIV, no? Debido a  que el periferico es de 48MHz.


Lo que pasa es que existen fuses que el compilador establece por defecto aún sin escribirlos en el programa.
Pones y quitas por software los que no hagan falta, por lo tanto, no es necesario escribirlos todos.
Mirando el archivo hex te puedes dar cuenta sobre la correcta configuración.


deadsistem dijo:


> Sigue igual. No lo detecta ninguna PC. ¿Qué podrá ser?


Posiblemente tengas algo mal conectado, si usas protobord revisa falsos contactos.
Existen algunos que no hacen buen contacto y dan muchos dolores de cabeza.

Trata con lo siguiente:
.- Prueba subiendo el valor del capacitor del pin 14 a unos 470nF.
.- Cuando ocurre un error al conectar el dispositivo y es mal detectado, tienes que reiniciar la PC.
Esto sucede cuando el PIC no está trabajando a la frecuencia requerida.
.- Realiza un simple programa ejecutandose a 48MHz. (Hacer destellar un LED a 500Ms. Por ejemplo)
Eso descarta algo mal palabra de configuración.
Si notas que el LED destella a otra frecuencia, entonces debes corregirla.
.- Revisa compatibilidades sobre la versión del compilador.

Suerte.


----------



## deadsistem (Jul 19, 2014)

D@rkbytes dijo:


> Posiblemente tengas algo mal conectado, si usas protobord revisa falsos contactos.
> Existen algunos que no hacen buen contacto y dan muchos dolores de cabeza.



estoy usando placa..


> Trata con lo siguiente:
> .- Prueba subiendo el valor del capacitor del pin 14 a unos 470nF.
> .- Cuando ocurre un error al conectar el dispositivo y es mal detectado, tienes que reiniciar la PC.
> Esto sucede cuando el PIC no está trabajando a la frecuencia requerida.
> ...



la frecuencia bien,hice parpadear leds a 1 segundo y todo bien... cargue de nuevo el bootloader e hice todo eso que me dijiste y nada.. la compu no lo detecta, me sorprende que aunque lo conecte en otra compu tampoco lo reconoce, si enciende y todo pero nada...
tiene algo que ver que el bootloader no tenga el PIN SENSE (no se para que sea pero no lo tiene) he visto que otros bootloaders si lo tienen.

Tengo que borrar algun driver USB to UART instalado? como hago eso?


----------



## TRILO-BYTE (Jul 19, 2014)

si estas usando el bootloader de CCS cuando lo conectas dira dispositivo desconocido
y un simbolo con una interrogacion en el panel de control.

lo que sigue es ir a la carpeta del CCS y buscar el Driver deberia detectarlo recuerdo que hise eso una vez


----------



## D@rkbytes (Jul 19, 2014)

deadsistem dijo:


> La frecuencia bien, hice parpadear leds a 1 segundo y todo bien.
> Cargué de nuevo el bootloader e hice todo eso que me dijiste y nada.
> La compu no lo detecta, me sorprende que aunque lo conecte en otra compu tampoco lo reconoce, si enciende y todo pero nada.


No sé a que se deba que no lo pueda reconocer otra PC, hice una prueba con los programas que subiste tras haber modificado la palabra de configuración y si lo detectó mi PC.
Sin embargo me pide controladores que jamás he podido encontrar y los que vienen con la versión que yo tengo de PICC, no funcionan.

Adjunto un vídeo para que veas como si es detectado el dispositivo en mi PC con esos programas.
Por eso se me ocurre que sigues teniendo algo mal conectado o algo que estés pasando por alto.
Capacitores del cristal, filtraje, lo básico, etc.


deadsistem dijo:


> ¿Tiene algo que ver que el bootloader no tenga el PIN SENSE (no sé para  que sea pero no lo tiene) He visto que otros bootloaders si lo tienen.


Mira más atrás en el *post #7* dentro del archivo EX_USB_BOOTLOADER.C se explica eso.


deadsistem dijo:


> ¿Tengo que borrar algun driver USB to UART instalado? ¿Cómo hago eso?


Cuando se instala correctamente un dispositivo o un controlador, es mostrado en el administrador de dispositivos.
Como no puedes instalar correctamente el dispositivo, lo más seguro es que no te aparezca nada o te aparezca el dispositivo con un signo de interrogación o advertencia.
Pero verifica si te aparece algo nuevo referente a HID, si es así desinstálalo. _*Mira por aquí.*
_ No hay problema si remueves algún otro controlador, cuando reinicias, el sistema los vuelve a buscar, y si no los encuentra te los pedirá nuevamente.


----------



## deadsistem (Jul 19, 2014)

> Adjunto un video para que veas como si es detectado el dispositivo en mi PC con esos programas.
> Por eso se me ocurre que sigas teniendo algo mal conectado o algo que estés pasando por alto.
> Capacitores del cristal, filtraje, lo básico, etc.



muchisismas gracias por los comentarios pero aun sigue sin funcionar....tengo que ponerle resistencias de pull UP al D+ y D- del USB del PIC? si no es mucha molestia, me puedes pasar el diagrama que utilizaste para que lo reconociera tu PC? estoy pensando que incluso puede ser que mi pic se le quemaron los pines del USB,,, le he cargado otro programa para probar si aun funciona el pic y todo bien, pero supongo que por alguna extraña razon esos pines del USB ya no funcionan.... ire a comprar otro pic18f2550 y probare nuevamente...



> si estas usando el bootloader de CCS cuando lo conectas dira dispositivo desconocido
> y un simbolo con una interrogacion en el panel de control.
> 
> lo que sigue es ir a la carpeta del CCS y buscar el Driver deberia detectarlo recuerdo que hise eso una vez


eso debería pasar, pero ni si quiera lo detecta aunque ya reinicie la PC, elimine los drivers anteriores y nada... 

he revisado un poco los archivos que se incluyen en el bootloader y no encuentro la funcion USB_INIT(); que se incluye en el main() del bootloader principal, ha de ser algo que no anda bien en los archivos, o en el usb_enumeratd(); pero no se que es..... 
ahora me nace otra duda: el bootloader que trato de usar es HID o simula una comunicacion RS232? 
hablo del codigo que puse del bootloader en el comentario https://www.forosdeelectronica.com/f24/bootloader-pic18f2550-ccs-pic-c-compiler-76134/#post935435 #18


----------



## D@rkbytes (Jul 19, 2014)

deadsistem dijo:


> Muchísimas gracias por los comentarios pero aun sigue sin funcionar.
> ¿Tengo que ponerle resistencias de pull UP al D+ y D- del USB del PIC?
> Si no es mucha molestia, ¿me puedes pasar el diagrama que utilizaste para que lo reconociera tu PC?


No necesitas colocar resistencias pull-up, así como está en el esquema adjunto es como lo probé.

Mira esta parte del código, es importante para que se inicie el reconocimiento del dispositivo.

```
[COLOR=Blue]void [/COLOR]main([COLOR=Blue]void[/COLOR]) 
{
   [COLOR=Blue]if[/COLOR](!input(BTLDR))             [COLOR=DimGray]// Si el pin RC2 está en 0 entonces...[/COLOR]
   {
      ON(LEDR);                 [COLOR=DimGray] // Se enciende el LED del pin RC1[/COLOR]
      g_InBootloader = TRUE;     
      usb_cdc_init();           [COLOR=DimGray] // Se inicia el USB CDC[/COLOR]
      usb_init();               [COLOR=DimGray] // Inicialización USB[/COLOR]
     [COLOR=Blue] while[/COLOR](!usb_enumerated());  [COLOR=DimGray]// Esperar mientras el dispositivo se enumera...[/COLOR]
      load_program();           [COLOR=DimGray] // Cargar el programa.[/COLOR]
   }
   g_InBootloader = FALSE;
   OFF(LEDR);
   [COLOR=Red]#ASM[/COLOR]
      [COLOR=Blue]goto[/COLOR] APPLICATION_START
  [COLOR=Red] #ENDASM[/COLOR]
}
```
Verifica que el pin RC2 esté en 0, yo le puse una resistencia de 4.7k hacia VDD como pull-up.
Para mantenerlo en estado bajo, únicamente coloqué un puente hacia VSS.
Si esté pin se encuentra flotante o en estado alto, la PC nunca reconocerá el dispositivo.

Suerte.


----------



## deadsistem (Jul 19, 2014)

ya correjí el problema , desafortunadamente no se que era .. ya que cambie todo nuevo , pero ahora lo armé en protoboard y funcionó correctamente con tu diagrama Darkbytes gracias ... le cargue el bootloader que coloqué anteriormente en este tema para el pic18f2550 cambiando el siguiente codigo:

```
#fuses HSPLL,PLL2,USBDIV,CPUDIV1,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,VREGEN,PUT,MCLR,NOPBADEN
#use delay(clock=48MHz)
#define __USB_PIC_PERIF__ 1
#define (__PCH__)
```

porque uso un cristal de 8MHz, y las demas definiciones se las agregué porque no las tenia y en el USB_BOOTLOADER.H las pide y no estaban definidas... 

y ya lo reconoce en el COM9 porque ya tenia instalado el driver que trae el CCS compiler en la direccion C:\Program Files (x86)\PICC\Drivers\NT,2000,XP,VISTA,7... TODO bien hasta ahora...

solo tengo una pregunta mas que refiere a lo siguiente: las direcciones de memoria en las que se carga este bootloader segun son: desde 0x0 hasta 0x1FFF, entonces entiendo que:
 el firmware que yo cargue a travez del bootloader empieza desde 0x2000 hasta -1 del final de la memoria de programa del pic, y que las interrupciones de la aplicación empiezan +0x08 a partir del inicio del programa, es decir:


```
#define LOADER_SIZE        (0x1FFF)
#define LOADER_START       (0)
#define LOADER_END         (LOADER_SIZE)
#define APPLICATION_START  (LOADER_SIZE+1)
#define APPLICATION_END    (getenv("PROGRAM_MEMORY")-1)
#define APPLICATION_ISR    (APPLICATION_START+8)
```

1.- entonces como voy a saber cuanto tengo aun de espacio para hacer mi firmware? porque al compilar el bootloader me dice que tiene RAM 31% y ROM 19%, y mi firmware tiene RAM 23% y ROM 65%.


----------



## D@rkbytes (Jul 20, 2014)

deadsistem dijo:


> Ya corregí el problema , desafortunadamente no sé que era  ya que cambie todo nuevo.
> Pero ahora lo armé en protoboard y funcionó correctamente con tu diagrama D@rkbytes, gracias. ... le cargue el bootloader que coloqué anteriormente en este tema para el pic18f2550 cambiando el siguiente código:
> 
> ```
> ...


OK, que bien que ya pudiste hacer que la PC lo reconociera.
Aunque en el post #18 comentaste que estabas usando un cristal de 20MHz. 


deadsistem dijo:


> les comento que mi diagrama únicamente tiene un *cristal de 20Mhz*


Por ese motivo fue que corregí la palabra de configuración en tu programa. 


deadsistem dijo:


> ya lo reconoce en el COM9 porque ya tenia instalado el driver que trae  el CCS compiler en la direccion C:\Program Files  (x86)\PICC\Drivers\NT,2000,XP,VISTA,7... TODO bien hasta ahora.


Si no es molestia, adjunta los controladores que usaste, porque los que yo tengo no funcionan (Posible incompatibilidad de versión)
A muchas personas nos pueden servir, ya que hemos tenido problema con esos controladores.


deadsistem dijo:


> ¿Entonces cómo voy a saber cuanto tengo aún de espacio para  hacer mi firmware? porque al compilar el bootloader me dice que tiene  RAM 31% y ROM 19%, y mi firmware tiene RAM 23% y ROM 65%.


Como los programas para Bootloaders son muy diferentes y tienen diferentes tamaños, es difícil decir cuanto espacio disponible te quedará tras haberlo cargado.
Lo que yo hago es mirar el archivo hex y me fijo hasta que dirección llega.
De ahí en adelante es el espacio que tendrás disponible.
Algunos tienen dos direccionamientos y también ese espacio se debe tener en cuenta.

Saludos.


----------



## deadsistem (Jul 20, 2014)

no es ninguna molestia... espero les sirva, mi LAP es Windows 7 Pro x64 y si funciona bien, les dejo el driver...

estoy intentando cargar el firmware en el PIC con el SIOW (desde la opción DOWNLOAD SOFTWARE) del CCs y me da error mientras descarga: dice TIMEOUT WHILE DOWNLOADING y a penas y hace una linea transferida de 1339... que puede ser? los fuses son iguales de mi firmware y del bootloader... 

otra pregunta, como le cambio el nombre de CCS BOOTLOADER que viene en el usb_bootloader.h? quiero poner algo como "Nuevo Dispositivo V3.3"...


----------



## TRILO-BYTE (Jul 20, 2014)

el bootloader .h como que mueve los vectores de interrupcion
cuando quieres hacer eso de cambiar nombre
debes ir al USB descriptor y lo que va entre comillas es el texto que debe salir


----------



## deadsistem (Jul 20, 2014)

> el bootloader .h como que mueve los vectores de interrupcion
> cuando quieres hacer eso de cambiar nombre
> debes ir al USB descriptor y lo que va entre comillas es el texto que debe salir


 gracias TRILO-BYTE lo checaré bien porque hay asignaciones de tamaños antes de cada string y hasta ahora no le entiendo... 

*respecto al problema del SIOW* a veces se friqueaaa (falla)... solo hay que cerrar el SIOW y resetear el PIC y que entre en modo boot de nuevo.. esperamos unos 10 segundos a que lo reconozca bien el sistema operativo y entonces volvemos a correr el SIOW.exe y entonces si detectará automaticamente el COM donde esta instalado el driver... entonces volvemos a cargar nuestro firmware con el DOWNLOAD SOFTWARE...

SALUDOS Y MUCHAS GRACIAS A TODOS... espero que esto sirva de mucha ayuda a quienes estan empezando ya que a mi me ha servido un monton... saludos


----------



## aragujo12 (Mar 23, 2015)

Disculpen alguien me puede ayudar...estoy en un proyecto de la escuela y queria utilizar un bootloader para cargar en el 18f4550...pueden subirlo???estoy utilizando ccsc compiler...no se cual utilizar que no cambie el lenguaje...como son los pinguinos


----------



## D@rkbytes (Mar 23, 2015)

El programa adjunto es el que se ha tratado en este tema, pero con la palabra de configuración para un 18F4550.

A mi no me ha funcionado, aunque he probado con varios controladores. (Uso XP SP3)


----------



## Grafeno94 (Ago 9, 2015)

Colegas, yo estoy haciendo el hardware del Bootloader y es completamente funcional.
La PC lo reconoce y carga los archivos HEX si problemas.

El problema es que los programas están mal sincronizados.
Me explico; hice un programa que prende y apaga un led durante un segundo con un cristal de 8 Mhz.
Cuando cargo el HEX al PIC con el Bootloader y empieza a correr el programa el led no prende y apaga en los 1 segundos que programé, se demora un poco más.
Así que pensé que sería porque el Bootloader fue grabado con una frecuencia de 48 Mhz y el HEX con uno de 8 Mhz.
Cambié la frecuencia del HEX a 48 Mhz y me funciona, pero cuando hago el mismo programa con interrupciones, los tiempos no concuerdan con los 1 segundos que programé.

¿Qué puede estar pasando? ¿Qué tengo que configurar?
¿Los archivos HEX a cargar deben tener todos la frecuencia a 48 Mhz.?


----------



## TRILO-BYTE (Ago 9, 2015)

pues es que todo eso suena a un problema de configuracion de los fuses

no se que cristal usas en el bootloader pero respecto al cristal debes hacer cambio en el fuses 

otra cosa no se por que pero en CCS con el bootloader del 18f4550 si usas muchas variables el programa no corre por eso no siempre es bueno trabajando con botloader


----------



## D@rkbytes (Ago 9, 2015)

Ya tenía esto olvidado porque no lograba que controladores se reconocieran, pero hace poco logré que funcionara.


Grafeno94 dijo:


> ¿Los archivos HEX a cargar deben tener todos la frecuencia a 48mhz?


Por lógica, si el Bootloader se ejecuta a una frecuencia de 48 MHz, también el programa que cargues debe ejecutarse a 48 MHz.

Esta es la configuración que usé para un programa de prueba:

```
#include <18F4550.h>
#fuses   NOFCMEN,NOIESO
#use     delay(clock=48MHz,crystal=4MHz,USB_FULL)

#include "usb_bootloader.h"
```



Grafeno94 dijo:


> Cuando hago el mismo programa pero con  interrupciones los tiempos no concuerdan con los 1 segundos que  programé.
> ¿Qué puede estar pasando?


Si te es posible, adjunta el programa que mencionas para revisarlo.


----------



## rakzorgenyo (Mar 16, 2016)

Miré este post en la búsqueda de qué andaba mal con el ejemplo, igual y puede ser el fuse o porque estoy usando el reloj interno.
Yo utilizo la comunicación RS-232, no utilizo los controladores USB, uso un FTDI para la comunicación serial con los ejemplos ex_bootload y ex_bootloade

El problema es que al mandar el programa por Tera Term (configurando el Xon/Xoff que especifica como requerimiento) el PIC me responde correctamente con el ACK y con la solicitud del buffer  lleno y vacío que son Xon y Xoff
Al menos eso parece en el osciloscopio, pero al final de la carga no parece ejecutarse el programa que se compiló, en este caso una impresión de la suma de un número por serial (ya lo probé ejecutándolo en el PIC por separado)

No sé si tenga problemas el direccionamiento de memoria o falte ejecutar algo más para que se logre cargar el programa.

*Aquí les dejo un vídeo del problema.*

El vídeo es pesado como para cargarlo. Una disculpa.

Esta configuración la utilizo para ambos programas. Los fuses son genéricos, puestos por el CCS C Compiler.

```
#elif defined(__PCH__)
#include <18F2550.h> 
#fuses NOWDT,INTRC,NOLVP,NOXINST,NOVREGEN 
#use delay(internal=8000000) 
#use rs232(baud=9600,parity=N,xmit=PIN_B0,rcv=PIN_B1,bits=8,stream=PORT1)
#define PUSH_BUTTON PIN_A1
#endif
```


----------



## D@rkbytes (Mar 18, 2016)

¿Ya probaste usando el SIOW? Es el mismo programa que la empresa recomienda para descargar el programa al microcontrolador.
Se encuentra en la carpeta de instalación del compilador.

Yo también lo he probado con el oscilador interno a 8 MHz. y usando un FT232RL, sin ningún problema.


----------



## rakzorgenyo (Mar 30, 2016)

Si eh intentado usar el siow tambien pero me hace lo mismo que el tera, le configuro el xon/xoff a 9600.

no se si sea un problema en las conexiones el dtr y cts del ftdi deben conectarse al pic para este procedimiento?


----------



## D@rkbytes (Mar 30, 2016)

rakzorgenyo dijo:


> ¿El dtr y cts del ftdi deben conectarse al pic para este procedimiento?


No, únicamente Tx y Rx.
Tal vez tengas algo mal en el código que estás usando.

Dos opciones:
Sube el programa que estás usando para el Bootloader, o si gustas subo el que yo tengo funcionando.


----------



## rakzorgenyo (Mar 30, 2016)

Saludos.

He estado usando el ejemplo del ex_bootloader, le quite la identificación del 16f por ahora, por si eso me causaba algún conflicto.


```
#include <18F2550.h> 
#fuses NOWDT 
#use delay(clock=8000000,internal=8000000) 
// #use delay(crystal=20MHz) 
#use rs232(baud=9600, xmit=PIN_B0, rcv=PIN_B1,errors) 
#define PUSH_BUTTON PIN_A1 
#define LED1 PIN_C0

#define _bootloader 

#include <bootloader.h> 
#include <loader.c> 

#org LOADER_END+2,LOADER_END+4 

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

void main(void) { 
   printf("\r\nTest 1.0\r\n"); 
   delay_ms(2000); 
   if(!input(PUSH_BUTTON)) 
   { 
      //printf("\r\nBootloader Version 1.0\r\n"); 
    
      // Let the user know it is ready to accept a download 
      printf("\r\nWaiting for download..."); 
      load_program(); 
   } 

   application(); 
} 

#int_global 
void isr(void) { 
   jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8)); 
}
```
Este es el código que cargo al pic:

```
#include <18F2550.h> 
#fuses NOWDT 
#use delay(clock=8000000,internal=8000000) 
#use rs232(baud=9600, xmit=PIN_B0, rcv=PIN_B1,errors) 
#define LED_PIN PIN_C0 

#include <bootloader.h> 


void main(void) { 
   int i = 0; 
   while(true){ 
      printf("Test %u\r\n",i++); 
      output_toggle(LED_PIN); 
      delay_ms(500); 
      output_toggle(LED_PIN); 
      delay_ms(500); 
   } 
}
```
Este es el que intento cargar mediante siow o teraterm:

En el principio del código del bootloader.h y loader.c solo puse esto para que tenga la misma configuración:

```
#include <18F2550.h> 
#fuses NOWDT 
#use delay(clock=8000000,internal=8000000) 
// #use delay(crystal=20MHz) 
#use rs232(baud=9600, xmit=PIN_B0, rcv=PIN_B1) 
#define PUSH_BUTTON PIN_A1
```
En el loader.c he puesto que se encienda y apague un led para ver si entra a las rutinas de buffer y si parpadea respectivamente, igual en el osciloscopio. 

No sé si sea un problema al cargarse y hacer el reset del pic-


----------



## D@rkbytes (Mar 30, 2016)

OK. Lo que está mal es la palabra de configuración.

Este es el programa para el Bootloader que yo uso:

```
#include <18f2550.h>
#fuses   NOUSBDIV,PLL2,NOVREGEN,NOFCMEN
#use     delay(internal = 8MHz)
#use     rs232(UART1)

#define  PUSH_BUTTON PIN_A0

#ignore_warnings  205

#define _bootloader
//#define BOOTLOADER_MODE2X

#include <bootloader.h>
#include <loader.c>

#org LOADER_END + 2,LOADER_END + 4

void bucle_programa (void)
{
   while (true);
}


void main(void)
{
   delay_ms(2000);            // Dar un tiempo para que se presione el botón.
   
   if(!input(PUSH_BUTTON))
   {
      printf("\r\nCCS Bootloader V1.0\r\n");
      // Indicar al usuario que se está listo para recibir una descarga.
      printf("\r\nEsperando la descarga del programa...\r\n");
      load_program();
   }

   bucle_programa();
}

#int_global
void isr(void)
{
   jump_to_isr(LOADER_END + 5 * (getenv("BITS_PER_INSTRUCTION") / 8));
}
```
Lo modifiqué un poco, pero un detalle importante es el retardo que puse para dar tiempo de que se presione el pulsador después de dar el reset.
Sin ese retardo, recuerdo que el SIOW mostraba varios mensajes de error.

Como programa de prueba, usé este:

```
#include <18f2550.h>
#fuses   NOUSBDIV,PLL2,NOVREGEN,NOFCMEN
#use     delay(internal = 8MHz)
#use     rs232(UART1)

//#define BOOTLOADER_MODE2X

#include <bootloader.h>

void main (void) 
{   
   delay_ms(100);
   
   puts("\r\nPrograma de prueba ejecutandose.\r\n");
   puts("Debe destellar un LED por el pin RA3 cada 250 ms.\r\n");

   while(TRUE)
   {
      output_toggle(PIN_A3);
      delay_ms(250);
   }
}
```
Así como están funcionan correctamente a 8 MHz con oscilador interno y también usando un adaptador de USB a RS-232 (TTL)

Suerte.


----------



## rakzorgenyo (Mar 31, 2016)

D@rkbytes dijo:


> OK. Lo que está mal es la palabra de configuración.
> 
> Este es el programa para el Bootloader que yo uso:
> 
> ...



saludos, gracias por la respuesta.

había probado la siguiente configuración y lo probe por partes desde ver el tiempo con un led, hasta identificar un caracter del serial para verificar que la comunicación y todo estuviera funcionando por separado 


```
#include <18F2550.h> 

#FUSES NOWDT          //No Watch Dog Timer 
#FUSES CPUDIV1        //No System Clock Postscaler 
#FUSES NOBROWNOUT     //No brownout reset 
#FUSES NOLVP          //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O 
#FUSES NOXINST        //Extended set extension and Indexed Addressing mode disabled (Legacy mode) 
#fuses PLL1           //No PLL PreScaler
#fuses NOUSBDIV       //USB clock source comes from primary oscillator
#fuses INTRC          //Internal RC Osc
#fuses HS             //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#fuses NOPUT          //No Power Up Timer
//#fuses NOMCLR         //Master Clear pin used for I/O
#fuses MCLR           //Master Clear pin enabled
#fuses NOSTVREN       //Stack full/underflow will not cause reset
#fuses NOWRTB         //Boot block not write protected
#fuses NOWRTD         //Data EEPROM not write protected
#fuses NOWRTC         //Configuration registers not write protected
#fuses NOWRT          //Program memory not write protected
#fuses NOEBTR         //Memory not protected from table reads
#fuses NOEBTRB        //Boot block not protected from table reads

#use delay(internal=8MHz) 

#use FIXED_IO( A_outputs=PIN_A1,PIN_A0 ) 
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PC,ERRORS) 

#define PUSH_BUTTON PIN_A1
```

los ultimos registros se los puse por si tenía bloqueada alguna instrucción de escritura, lo que me hacía en el siow despues de copiar el codigo HEX y pegarlo en la terminal es que veía que respodía el pic pero al finalizar no cargaba el programa.

Usando la terminal tera term, me cargaba el archivo y se reiniciaba el pic pero aún así cargaba el mismo programa y no el nuevo.

Probe el código que proporcionas solo le agreuge esta línea


```
#use     rs232(UART1,ERRORS)
```

ya que sino lo ponía el serial se trababa y ya no recibía ni enviaba datos. Esto lo probé con un programa aparte usando un osciloscopio para verificarlo.

al cargar el bootloader y ponerlo en espera, le mando el archivo por siow y veo que si responden los XON y XOFF al visualizar el rx y tx pero me sigue el mismo problema que al finalizar la transmisión el pic no se reinicia con el archivo enviado. el flow control lo pongo en both y si concuerdan el xon y xoff del siow con la del bootloader.h

tengo que inicializar los fuses en algún otro lado? lo intenté poniendo en el bootloader.h ya que algunos mencionaban que se debía poner ahí pero con el mismo resultado


----------



## D@rkbytes (Mar 31, 2016)

rakzorgenyo dijo:


> ¿Tengo que inicializar los fuses en algún otro lado? Lo intenté poniendo en el bootloader.h, ya que algunos mencionaban que se debía poner ahí pero con el mismo resultado.


No, no hay que configurar nada extra, ni agregar cosas extra.
Así como está el código que subí, funciona.

Prueba con el archivo .hex que adjunto, y si te funciona, debes actualizar tu compilador.
Si no te funciona, entonces tienes un problema de hardware.


----------



## rakzorgenyo (Abr 5, 2016)

D@rkbytes dijo:


> No, no hay que configurar nada extra, ni agregar cosas extra.
> Así como está el código que subí, funciona.
> 
> Prueba con el archivo .hex que adjunto, y si te funciona, debes actualizar tu compilador.
> Si no te funciona, entonces tienes un problema de hardware.



tengo la versión 5.050 del ccs c compiler del siow el 1.2.9

probe el programa que pusiste y lo pongo en modo bootloader y mido el RX y TX para ver si se transfiere pero creo que no está respetando el XOn y Xoff podría ser que este fallando algo en las versiones?


----------



## D@rkbytes (Abr 5, 2016)

rakzorgenyo dijo:


> ¿Podría ser que esté fallando algo en las versiones?


No. Por la versión del compilador no es el problema.
Yo utilicé ese mismo programa desde la versión 4 y algo. Ahora tengo la 5.054 y sigue funcionando bien.

Vi algo importante que no había visto antes en una de las imágenes que enviaste.
Veo que usaste el puerto 12 anteriormente y ahora el 14, o sea que tienes puertos virtuales instalados.
Cuando tienes puertos virtuales, por alguna razón el SIOW y otros programas no logran comunicarse con el microcontrolador.
Elimina temporalmente todos los puertos virtuales y haz una prueba.
Posiblemente con eso ya logres realizar la carga del programa.

Suerte.


----------



## rakzorgenyo (Abr 6, 2016)

Saludos,

ya pude hacer funcionar el ejemplo y ya carga el bootloader para poder cargar un nuevo programa multiples veces por r232.

Quisiera saber si hay opción de ampliar el tamaño del bootloader para agregarle código extra. eh intentado modificar el parámetro del #define LOADER_SIZE de loader.c y #define LOADER_END del bootloader.h



> #build (reset=0x400, interrupt=0x408)
> #org 0, 0x3FF {}



Eh visto que algunos ponen este código para mover el vector de interrupciones y guardar el lugar del bootloader.

eh modificado los parametros pero no eh podido quitar el error de compilación del ROM. hay forma de ver más a detalle como hacer esta modificación?


----------



## oscaraen (Abr 22, 2016)

Hola, tengo una duda, estoy cargando el bootloader que viene para CCS en el ejemplo EX_USB_BOOTLOADER con las modificaciónes necesarias para el pic18f2550, lo que sucede es que carga el bootloader y los programas cuando los cargo desde SIOW cargan correctamente, a excepcion de los programas que hago con comunicación USB, acaso ¿no se puede usar la comunicación USB cuando tengo un bootloader?, se que no deberia ser así pero les pido su ayuda si alguno ya lo ha logrado por que los programas que tienen comunicación CDC USB no me funcionan

muchas gracias


----------



## D@rkbytes (Abr 22, 2016)

Lo más probable es que no estés definiendo bien la palabra de configuración.
Ésta depende de la frecuencia del cristal que vas a usar, ya que hay que llevar el CPU a 48 MHz. por medio de configuración del prescaler y el postescaler.

Si no usas la configuración correcta, la PC no podrá reconocer el dispositivo porque el módulo USB no estará funcionando correctamente.


----------

