18F4550 Bootloader enter via eeprom setting


Closed Thread
Results 1 to 4 of 4
  1. #1
    Join Date
    Aug 2008
    Posts
    13

    Default 18F4550 Bootloader enter via eeprom setting

    Hello all,

    I've been stalking around this board for a couple months sucking knowledge from so many great minds. I wanted to do something I couldn't find, after I figured it out I thought I'd share my code. I wanted to use an EEPROM byte to control on boot if I should enter bootloader mode or jump up to Pic basic code.

    I loaded the new MCHPFSUSB v2.3 (just release 6 weeks or so ago) and modified the HID Bootloader C code to do exactly what I want.

    In my Pic I'm doing the following

    Code:
        
    If ProgramMe = 1 then   'Put the chip into programming mode via a ProgramMe variable i'm passing across the USB
            Write 1, 255  'Set eeprom byte 1 back to FF
            pause 250     'I small pause for no good reason, probably not needed
            @ Reset        'reset/reboot the PIC
    ENDIF

    I then modified the main.c in the "C:\Microchip Solutions\USB Device - Bootloaders\HID - Bootloader\HID Bootloader - Firmware for PIC18 Non-J Devices" to the following

    Code:
    /*********************************************************************
     *
     *   Microchip USB HID Bootloader for PIC18 (Non-J Family) USB Microcontrollers
     *
     *********************************************************************
     * FileName:        main.c
     * Dependencies:    See INCLUDES section below
     * Processor:       PIC18
     * Compiler:        C18 3.20+
     * Company:         Microchip Technology, Inc.
     *
    
    
    
    /** I N C L U D E S **********************************************************/
    #include <p18cxxx.h>
    #include "typedefs.h"                   
    #include "usb.h"                         
    #include "io_cfg.h"                     
    #include "BootPIC18NonJ.h"
    
    
    #if defined(PIC18F4550_PICDEM_FS_USB)	
            #pragma config PLLDIV   = 5     
            #pragma config CPUDIV   = OSC1_PLL2	
            #pragma config USBDIV   = 2     
            #pragma config FOSC     = HSPLL_HS
            #pragma config FCMEN    = OFF
            #pragma config IESO     = OFF
            #pragma config PWRT     = OFF
            #pragma config BOR      = ON
            #pragma config BORV     = 3
            #pragma config VREGEN   = ON	
            #pragma config WDT      = OFF
            #pragma config WDTPS    = 32768
            #pragma config MCLRE    = ON
            #pragma config LPT1OSC  = OFF
            #pragma config PBADEN   = OFF		
    
    
            #pragma config STVREN   = ON
            #pragma config LVP      = OFF
    
            #pragma config XINST    = OFF       
            #pragma config CP0      = OFF
            #pragma config CP1      = OFF
            #pragma config CPB      = OFF
    
            #pragma config WRT0     = OFF
            #pragma config WRT1     = OFF
            #pragma config WRTB     = OFF       // Boot Block Write Protection
            #pragma config WRTC     = OFF
    
            #pragma config EBTR0    = OFF
            #pragma config EBTR1    = OFF
            #pragma config EBTRB    = OFF
    
    #elif defined(LOW_PIN_COUNT_USB_DEVELOPMENT_KIT)
            //14K50
            #pragma config CPU_DIV = NoClkDiv, USB_LSCLK = OFF             
            #pragma config FOSC = HS, PLL_EN=ON, FCMEN = OFF, IESO = OFF   
            #pragma config PWRT = OFF, BOREN = OFF, BORV = 30, VREGEN = ON
            #pragma config WDTEN = OFF, WDTPS = 32768                     
            #pragma config MCLRE = OFF, HFOFST = OFF				      
            #pragma config STVREN = ON, LVP = OFF, XINST = OFF, BBSIZ=OFF
            #pragma config CP0 = OFF, CP1 = OFF						     
            #pragma config CPB = OFF                                    			    
            #pragma config WRT0 = OFF, WRT1 = OFF						                
            
            #pragma config WRTB = OFF, WRTC = OFF                            			
            #pragma config EBTR0 = OFF, EBTR1 = OFF							           	
            #pragma config EBTRB = OFF                                                  
            
            
            #ifdef __DEBUG
                #pragma config BKBUG = ON 
            #endif
            #ifndef __DEBUG
                #pragma config BKBUG = OFF
            #endif   
    #else
    	#error Not a supported board (yet), make sure the proper board is selected in usbcfg.h, and if so, set configuration bits in __FILE__, line __LINE__
    #endif
    
    /** V A R I A B L E S ********************************************************/
    #pragma udata
    
    /** P R I V A T E  P R O T O T Y P E S ***************************************/
    static void InitializeSystem(void);
    void USBTasks(void);
    #if !defined(__18F14K50) && !defined(__18F13K50) && !defined(__18LF14K50) && !defined(__18LF13K50)
        void BlinkUSBStatus(void);
    #else
        #define BlinkUSBStatus()
    #endif
    
    /** V E C T O R  R E M A P P I N G *******************************************/
    #pragma code high_vector=0x08
    void interrupt_at_high_vector(void)
    {
        _asm goto 0x1008 _endasm
    }
    #pragma code low_vector=0x18
    void interrupt_at_low_vector(void)
    {
        _asm goto 0x1018 _endasm
    }
    #pragma code
    
    
    /** D E C L A R A T I O N S **************************************************/
    #pragma code
    /******************************************************************************
     * Function:        void main(void)
     *
     * PreCondition:    None
     *
     * Input:           None
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        Main program entry point.
     *
     * Note:            None
     *****************************************************************************/
    void main(void)
    {   
        
    	//read the first byte store in var eepTemp
    	signed char eepTemp;  	//setup a var to read the eep
    	EEADR = 0x0001; 		//location to read, I'm useing eeprom address 1
    	EECON1bits.EEPGD = 0; 
    	EECON1bits.CFGS = 0; 
    	EECON1bits.RD = 1; 
    	eepTemp = EEDATA; 
    
    	//write Byte "1" back to a 1, so no matter once bootloader code only enters once
        EEADR =0x0001; 
       	EEDATA =0x01;
       	Nop();
       	Nop();
        EECON1bits.EEPGD = 0;
       	EECON1bits.CFGS = 0;
       	EECON1bits.WREN = 1;
       	INTCONbits.GIE = 0;
       	EECON2 = 0x55;
       	EECON2 = 0xAA;
       	EECON1bits.WR = 1;
    	while(EECON1bits.WR); 
       	INTCONbits.GIE = 1;
       	EECON1bits.WREN = 0;
    	
    
        //Check Bootload Mode Entry Condition
    	if(eepTemp == 0x01)	//Check the eepTemp and see if it's 0x01, if so boot to the PIC Basic code at 0x1000
    	{
    		_asm
    		goto 0x1000			//If the user is not trying to enter the bootloader, go straight to the main application remapped "reset" vector.
    		_endasm
    	}
        InitializeSystem();
        while(1)
        {
    		ClrWdt();	
    	    USBTasks();         					// Need to call USBTasks() periodically
    	    										// it handles SETUP packets needed for enumeration
    
    		//BlinkUSBStatus();
    		
    	    if((usb_device_state == CONFIGURED_STATE) && (UCONbits.SUSPND != 1))
    	    {
     	       ProcessIO();   // This is where all the actual bootloader related data transfer/self programming takes place
     	    }				  // see ProcessIO() function in the Boot87J50Family.c file.
        }//end while
    }//end main
    
    /******************************************************************************
     * Function:        static void InitializeSystem(void)
     *
     **/
    static void InitializeSystem(void)
    {
    
    	#if defined(__18F87J50)||defined(__18F86J55)|| \
        	defined(__18F86J50)||defined(__18F85J50)|| \
        	defined(__18F67J50)||defined(__18F66J55)|| \
        	defined(__18F66J50)||defined(__18F65J50)
    
        unsigned int pll_startup_counter = 600;
        OSCTUNEbits.PLLEN = 1;  //Enable the PLL and wait 2+ms until the PLL locks before enabling USB module
        while(pll_startup_counter--);
    
    
        #else
    
        #endif
    
        #if defined(USE_USB_BUS_SENSE_IO)
        tris_usb_bus_sense = INPUT_PIN; // See io_cfg.h
        #endif
        #if defined(USE_SELF_POWER_SENSE_IO)
        tris_self_power = INPUT_PIN;
        #endif
        
        mInitializeUSBDriver();         // See usbdrv.h
        
        UserInit();                     // See user.c & .h
    
    }//end InitializeSystem
    
    /******************************************************************************
     * Function:        void USBTasks(void)
     */
    
    void USBTasks(void)
    {
        /*
         * Servicing Hardware
         */
        USBCheckBusStatus();                    // Must use polling method
        USBDriverService();              	    // Interrupt or polling method
    
    }// end USBTasks
    
    
    /******************************************************************************
     * Function:        void BlinkUSBStatus(void)
     * 
     * THIS FUNCTION WAS REMOVED TO MAKE ROOM FOR THE EEPROM READ AND WRITE CODE
     *
    Basically every time the pic boots I check EEPROM Byte 1. If the PICBasic code has set byte 1 back to 0xFF then the c code sets it back to 0x01 and runs the bootloader code for that boot. I then run the microchip HID bootloader and update the Pic Basic code.

    Upon reseting after upgrading Byte 1 has already been switched back to 0x01 so it bypasses the bootloader.

    No Switches to press... very simple upgrades. I send a command down to the pic, it reboots, I run the HID Bootloader, reboot after loading my new code. The PicBasic code Executes.

  2. #2
    Join Date
    Feb 2003
    Location
    Sydney, Australia
    Posts
    126


    Did you find this post helpful? Yes | No

    Default

    bradb,

    Nice solution - reminds me of the old serial bootloaders where they would look for a single character on the com port at startup and use that to enter bootloader mode.

    Giving the pic the ability to put itself into bootload mode rather than requiring a crazy key combination on reset, which some poor end user will manage to do while trying to mount a device in the wall is a great idea.

    I notice you removed the blinky led code in the HID Bootloader to code - how much bigger does the read and write eeprom code make the bootloader code ? - from memory the HID one is about 1100 bytes.

    Hmm, wonder if I could make it work with an I2C eeprom... I knew there was a reason the 18F2550 would be better than the 18f2450...

    Quick thought though - what happens if you PBP program gets trashed ? - how can you get the unit into bootloader mode to get new code into it? I am thinking bootload session that crashes out half way through or cable falls out etc. - would it be better to write the eeprom once the bootloader has completed sucessfully, say after the ProcessIO() call in the HID bootlader code ?

    Good work,
    bill

  3. #3
    Join Date
    Aug 2008
    Posts
    13


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by bcd View Post
    bradb,

    Nice solution - reminds me of the old serial bootloaders where they would look for a single character on the com port at startup and use that to enter bootloader mode.

    Giving the pic the ability to put itself into bootload mode rather than requiring a crazy key combination on reset, which some poor end user will manage to do while trying to mount a device in the wall is a great idea.

    I notice you removed the blinky led code in the HID Bootloader to code - how much bigger does the read and write eeprom code make the bootloader code ? - from memory the HID one is about 1100 bytes.

    Hmm, wonder if I could make it work with an I2C eeprom... I knew there was a reason the 18F2550 would be better than the 18f2450...

    Quick thought though - what happens if you PBP program gets trashed ? - how can you get the unit into bootloader mode to get new code into it? I am thinking bootload session that crashes out half way through or cable falls out etc. - would it be better to write the eeprom once the bootloader has completed sucessfully, say after the ProcessIO() call in the HID bootlader code ?

    Good work,
    bill
    I thought about adding the write byte1 = 1 code only after completing the firmware upgrade, but for my purpose I wanted the PIC to fall back to the Pic Basic code in the event of an aborted firmware upgrade attempt. I did not want to get stuck in pic upgrade loop. A quick power cycle aborts the upgrade procedure without even having to start the HID boot loader program. This was personal choice.

    I would like to add a counter to eprom byte 2.
    Every time the C code boots it would increment byte 2 by 1.
    If byte 2 > 5 then the C program would go into boot loader mode regardless of the status of eprom byte1.

    At the end of my Basic loop I would set eeprom byte2 back to 0, clearing the Eprom Byte 2 counter. 5 Failed boot attempts in a row would automatically send the PIC into boot loader mode, like hosed code from a failed upgrade. This gets around the failed upgrade issue with a handful of reboots.

    However, I'm going to have to find some place to get more code space from, I'm not at my work PC but from memory I think I only have about 8 bytes left under the first 1000h which is why I had to remove the USB Led Blink status to begin with. Either that or figure out if it’s possible to change the start vector of the pic basic to 1200h.

    Or, I can add an upgrade switch but because of the nature of the device I'm making I do not want the board or a switch field accessible. I really need to be able to upgrade these via a remote control solution, IE I remote desktop to a PC with the device attached via USB and then I can personally do the upgrade. I have the procedure in my VB program password protected so users can't send the pic into upgrade mode.

    This was a quick project today but it is working.

    The other mistake I can already see I made was writing byte 1 back to a every time even it’s already a 1, my code should be more like this:

    Code:
     
    void main(void)
    {   
        
    	//read the first byte store in var eepTemp
    	signed char eepTemp;  	//setup a var to read the eep
    	EEADR = 0x0001; 		//location to read, I'm using eeprom address 1
    	EECON1bits.EEPGD = 0; 
    	EECON1bits.CFGS = 0; 
    	EECON1bits.RD = 1; 
    	eepTemp = EEDATA; 
    
        //Check Bootload Mode Entry Condition
    	if(eepTemp == 0x01)	//Check the eepTemp and see if it's 0x01, if so boot to the PIC Basic code at 0x1000
    	{
    		_asm
    		goto 0x1000			//If the user is not trying to enter the bootloader, go straight to the main application remapped "reset" vector.
    		_endasm
    	}
    
    	//write Byte "1" back to a 1
        	EEADR =0x0001; 
       	EEDATA =0x01;
       	Nop();
       	Nop();
    	EECON1bits.EEPGD = 0;
       	EECON1bits.CFGS = 0;
       	EECON1bits.WREN = 1;
       	INTCONbits.GIE = 0;
       	EECON2 = 0x55;
       	EECON2 = 0xAA;
       	EECON1bits.WR = 1;
    	while(EECON1bits.WR); 
       	INTCONbits.GIE = 1;
       	EECON1bits.WREN = 0;
    
    
        InitializeSystem();
        etc ....
    I've only been programming PICs for a couple months... the possibilities are so endless. The 18F4550 with USB connection is the coolest thing since sliced bread..

  4. #4
    Join Date
    Feb 2003
    Location
    Sydney, Australia
    Posts
    126


    Did you find this post helpful? Yes | No

    Default

    ...the possibilities are so endless. The 18F4550 with USB connection is the coolest thing since sliced bread..
    I have to agree that the USB pics and the ease of using them with PBP has really got my excited again about dreaming up cool projects and making them a reality!

    bill.

Similar Threads

  1. Can't read sequential addresses in external EEPROM
    By tjkelly in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 18th February 2010, 14:46
  2. PICKit2 - warning about configuration words
    By flotulopex in forum mel PIC BASIC Pro
    Replies: 26
    Last Post: - 4th August 2009, 14:01
  3. How to write/read strings EEPROM/LCD
    By g-hoot in forum mel PIC BASIC Pro
    Replies: 22
    Last Post: - 11th February 2007, 06:26
  4. Bootloader and EEPROM
    By milestag in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 10th November 2005, 22:57
  5. word variable to 25lc640
    By TONIGALEA in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 6th July 2004, 19:59

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts