/*
*****************************
* Bootloader USB
* Versión 1.0 *
*****************************
*/
//#define DEBUG_ICD
#define __USB_PIC_PERIF__ 1
#if !defined(__PCH__)
#error USB CDC Library requires PIC18
#endif
#include <18F4550.h>
#ifdef DEBUG_ICD
#device ICD=TRUE
#fuses XTPLL,NOWDT,NOPROTECT,NOLVP,DEBUG,USBDIV,PLL1,CPUDIV1,VREGEN
#else
#fuses XTPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN
#endif
#use delay(clock=48000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
/////////////////////////////////////////////////////////////////////////////
//
// 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 the 18F4550 development kit has this pin
#if __USB_PIC_PERIF__ && defined(__PCH__)
#define USB_CON_SENSE_PIN PIN_C1
#endif
// Archivos y librerías asociadas
#include <LCD.C>
#define _bootloader
#include <usb_bootloader pablo.h>
#define LOADER_ISR 0x28
#build(interrupt=LOADER_ISR)
#include <usb_cdc boot.h>
// Valor en EEPROM que activa modo carga otro ejecuta la aplicación
#rom 0xF000FF={0x97}
// Configuración de Pines
#define LED PIN_B4
#define LED_OFF output_low
#define LED_ON output_high
// El puerto D es configurado para el LCD en el archivo LCD.C como sigue:
// D0 enable
// D1 rs
// D2 rw
// D4 D4
// D5 D5
// D6 D6
// D7 D7
//Definición de constantes
#define VER (LOADER_SIZE -5)
#rom VER={0,3,8} //Versión del bootloader y ID del equipo
/*
Salta a la isr que corresponda, bootloader o aplicacion
*/
#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
}
}
// Envía la versión de bootloader por USB
void Version(void)
{
int8 Buffer [3];
int8 i;
read_program_memory((VER),Buffer,3);
//usb_cdc_putc('v');
for(i=0; i<3; i=i+2)
{
usb_cdc_putc(Buffer[i]);
}
}
// Envia el ID del equipo
void ID_Equipo(void)
{
int8 Buffer[1] ;
read_program_memory((VER+4),Buffer,1);
usb_cdc_putc(Buffer[0]);
}
void Bootloader(void)
{
char c;
BYTE Buffer[256];
int32 address_flash; //Direccion memoria flash
int16 cant_datos; //Cantidad de datos a TX o RX
int16 i; //Contador para bucles
BYTE address_eeprom;
lcd_putc("\f");
lcd_gotoxy(4,1);
printf(lcd_putc
,"Modo Carga"); usb_cdc_init(); //Inicializa USB
usb_init();
while(!usb_enumerated());
do
{
usb_task(); //Sensa si se conectó al USB, si se usa el PIN de sensado
if (usb_enumerated())
{
if (usb_cdc_kbhit())
{
c=usb_cdc_getc();
switch (c)
{
case 'A':
//Envia versión de bootloader y ID equipo
Version();
ID_Equipo();
break;
case 'B':
//Lee flash (hasta 256Bytes)
address_flash=65536 * usb_cdc_getc();
address_flash+=256 * usb_cdc_getc();
address_flash+=usb_cdc_getc();
cant_datos=usb_cdc_getc();
if (cant_datos==0) {cant_datos=256;}
read_program_memory(address_flash,Buffer,cant_datos);
for(i=0; i<cant_datos; i++)
{
usb_cdc_putc(Buffer[i]);
}
break;
case 'C':
//Escribe Flash (HASTA 256Bytes EN BLOQUES DE 8BYTES)
address_flash=65536 * usb_cdc_getc();
address_flash+=256 * usb_cdc_getc();
address_flash+=usb_cdc_getc();
cant_datos=usb_cdc_getc();
if (cant_datos==0) {cant_datos=256;}
for (i=0;i<cant_datos;i++)
{
Buffer[i]=usb_cdc_getc();
}
write_program_memory(address_flash,buffer,cant_datos);
usb_cdc_putc('J');
break;
case 'D':
//Borra Flash (64 bytes)
address_flash=65536* usb_cdc_getc();
address_flash+=256 * usb_cdc_getc();
address_flash+=usb_cdc_getc();
erase_program_eeprom(address_flash);
usb_cdc_putc('J');
break;
case 'E':
//Lee EEPROM
usb_cdc_putc(read_eeprom(usb_cdc_getc()));
break;
case 'F':
//Escribe EEPROM
address_eeprom=usb_cdc_getc();
write_eeprom(address_eeprom,usb_cdc_getc());
usb_cdc_putc('J');
break;
case 'J':
//Ejecuta Programa
write_eeprom(0xFF,0);
delay_ms(2000);
reset_cpu();
break;
}
}
}
} while (TRUE);
}
void main(void)
{
g_InBootloader = TRUE;
LED_ON(LED);
lcd_init(); //Inicializa LCD
delay_ms(6);
if (read_eeprom(0xFF)==0x97)
{
Bootloader();
}
g_InBootloader = FALSE;
LED_OFF(LED);
#ASM
goto APPLICATION_START
#ENDASM
}
//************************************
// usb_bootloader pablo.h
//************************************
//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.
#define LOADER_SIZE (0x17FF)
//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)
#define APPLICATION_END (getenv("PROGRAM_MEMORY")-1)
#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 aplicacion(void)
{
while(TRUE);
}
//we need to prevent the loader from using application space
#if APPLICATION_END>0xFFFF
#org APPLICATION_START+0x10, 0xFFFF {}
#if APPLICATION_END>0x1FFFF
#org 0xFFFF, 0x1FFFF {}
#else
#org 0xFFFF, APPLICATION_END {}
#endif
#else
#org APPLICATION_START+0x10, APPLICATION_END {}
#endif
#endif
#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