SE – uC: El Cargador de Arranque (Boot Loader)

El cargador de arranque o en inglés Boot Loader (BL) es un programa (firmware) que va alojado en el uC, permitiendo reprogramar el uC sin necesidad de un costoso programador especial, facilitando las pruebas y actualizaciones del dispositivo. El uC utiliza el BL para comunicarse con un programa especializado que se encuentra en una computadora y recibir el firmware al que se desea actualizar.

La carga del nuevo programa se puede realizar por alguno de los periféricos de comunicación con las que cuentan los uC como: I/O Pin, Serial (RS-232), CAN, Ethernet, USB, etc.

Las ventajas de utilizar un BL son:

  • No se requiere de un programador especial
  • Carga más rápida el firmware nuevo (Si se utiliza un periférico de alta velocidad como USB)
  • No se requiere retirar el uC de la tablilla para ser reprogramado
  • El firmware puede ser actualizado hasta por el cliente final si así se requiere
  • El BL no se borra, escribe o modifica durante la carga del firmware nuevo

Las desventajas son:

  • Solo la primera vez se requiere de un programador especial para cargar el BL
  • El BL ocupa memoria de programa
  • Depende en que región se encuentre alojado puede requiere una reubicación de los vectores de interrupción

Actualmente existen muchos BL para PIC18, la mayoría de uso libre y otros con algún costo. En la siguiente tabla se muestra una comparativa entre algunos BL libres.

Microchip HID Boot Loader

El BL que utilizaremos en este documento será el de Microchip por USB utilizando la clase HID. Este BL es gratis y sencillo de utilizar, la única desventaja es que ocupa los primeros 4 KB de memoria, esto quiere decir que utiliza ¼ de memoria de programa quedando solamente 12 KB para el firmware de usuario, a pesar de esta desventaja es suficiente para los proyectos descritos en este documento.

Los vectores de interrupción son re alocados, esto quiere decir que cada vez que brinque el programa a su dirección de interrupción este brincara a su dirección re alocada de la siguiente manera:

  • High Interrupt Vector:0x0008 -> 0x1008
  • Low Interrupt Vector:0x0018 -> 0x1018

El siguiente diagrama representa la organización del BL y el FW de usuario en la memoria de programa.

El siguiente diagrama de estados representa el comportamiento del BL.

Requisitos de HW

Este BL utiliza los siguientes componentes de HW:

  1. Una entrada digital con un botón para darle entrada al BL si este se encuentra presionado, por predeterminado se utiliza el pin RB4.
  2. Dos salida digitales para LEDs, se utilizan para representar la actividad del BL, por predeterminado se utilizan las salidas RC0 y RC1.
  3. El puerto USB del uC que se utiliza para la actualización del FW.

Como obtener el BL

Para obtener el BT seguiremos los siguientes tres pasos:

  1. Lo primero que se requiere es descargar las librerías donde viene el BT HID USB y la aplicación de la PC. El archivo se llama “Microchip Libraries for Aplications” y hay que descargarlo de aquí.
  2. Instalar las librerías y copiar la carpeta del proyecto del BT que se encuentra en: “C:\Microchip Solutions v2012-10-15\USB\Device – Bootloaders\HID\Firmware – PIC18 Non-J” a cualquier lugar donde lo trabajaras.
  3. Abrir el proyecto “HID Bootloader PIC18F14K50 Family”.

Cambios en el FW del BL

  1. Lo primero es habilitar el /MCLR:
  2. 	main.c
    	#elif defined(LOW_PIN_COUNT_USB_DEVELOPMENT_KIT)
            //14K50
            #if !defined(__18F14K50) && !defined(__18F13K50) && !defined(__18LF14K50) && !defined(__18LF13K50)
                #error Wrong processor selected for the selected demo board.
            #endif
            #pragma config MCLRE = ON // Activate the MCLRE
    	
  3. Luego debemos cambiar el registro ANSELH a ceros para definir que el PORTB será digital y no análogo.
  4. 	main.c
    	void main(void)
    	{   
    		//Need to make sure RB4 can be used as a digital input pin.
    		#if defined(PIC18F4550_PICDEM_FS_USB_K50)
    			...
    		#else
    			//ADCON1 = 0x0F;		//Need to make sure RB4 can be used as a digital input pin
    			ANSELH = 0x00;			// RB4 need to be digital
    		#endif
    		...
    			//Restore default "reset" value of registers we may have modified temporarily.
    				#if defined(PIC18F4550_PICDEM_FS_USB_K50)
    				...
    				#else
    				//ADCON1 = 0x07;	//Restore "reset value" of the ADCON1 register
    				ANSELH = 0x0F;		// Restore reset value
    		#endif
    		...
    	}
    	
  5. Las salidas definidas para los LEDs tenemos que cambiarlas de RC0 a RC4 y RC1 a RC5, también debemos cambiar la entrada del interruptor de RA3 a RB4.
  6. 	io_cfg.h
    	#elif defined(LOW_PIN_COUNT_USB_DEVELOPMENT_KIT)
    		#define mLED_1              LATCbits.LATC4
    		#define mLED_2              LATCbits.LATC5
    		#define sw2                 PORTBbits.RB4
    	
  7. Por ultimo compilamos el proyecto y obtenemos el archivo: “HID Bootloader PIC18F14K50 Family.hex”

1.1.4. Programar el BL al uC

Ahora procederemos a programar el BL al uC, para esto requerimos:

  • El programador JDM
  • La tablilla de desarrollo
  • Cables para conexión
  • Computadora con el programa PICPgm Development Programmer
  • El programador de Microchip para el BL USB HID Bootloader v2.90a

Seguir los siguientes pasos para realizar la programación y verificación:

  1. Lo primero es conectar el programador a la tablilla de desarrollo utilizando los cables de conexión. Hay que utilizar el puerto ICSP de la tablilla. Luego conectamos el programador JDM por puerto serial a la computadora.
  2. Abrimos el programa PICPgm, este debe detectar automáticamente el programador y el uC.
  3. Procedemos a cargar el archivo *.hex del BL al uC, asegurarse de que todo salió bien.
  4. Procedemos a probar que el uC entre en el BL, desconectamos el programador JDM y conectamos el uC a la PC por USB, dejando presionado el botón sw2 de la tablilla. Como se puede observar en la siguiente imagen apareció un nuevo dispositivo HID con el VID=04D8 y PID=003C que corresponden al uC con BL.
  5. Por ultimo abrimos el programa de microchip diseñado especialmente para el BL y vemos que ha detectado el dispositivo y está listo para cargar el firmware de usuario. Hasta este punto el BL está listo para ser utilizado.

Cambios en FW de Usuario

En cada aplicación de usuario que se dese utilizar con este BL se le deben realizar los siguientes cambios para que funcione correctamente.

  1. Desactivar los bits de configuración para evitar modificar el oscilador del BL y que este funcione incorrectamente.
  2. 	// We must not change configurations bits, because BL may not work correctly.
    	//#include "pic18f14k50_cbits.h"
    	
  3. Se debe añadir el archivo link modificado del PIC que se está utilizando al proyecto, este archivo se encuentra dentro de la carpeta del BL y se llama: “rm18f14k50.lkr”.
  4. Este archivo se debe añadir para asegurar que el programa de usuario compilado sea almacenado a partir de la dirección 0x1000 y no desde 0x0000 como es predeterminadamente.

    	rm18F14K50.lkr
    	// $Id: 18f14K50.lkr,v 1.1.4.1 2005/07/25 18:23:28 nairnj Exp $
    	// File: 18f14K50.lkr
    	// Sample linker script for the PIC18f14k50 processor
    
    	LIBPATH .
    
    	FILES c018i.o
    	FILES clib.lib
    	FILES p18f14k50.lib
    
    	// Bootloader
    	//CODEPAGE   NAME=vectors    START=0x0          END=0x29            PROTECTED
    	//CODEPAGE   NAME=bootloader START=0x2A         END=0xFFF           PROTECTED
    	//CODEPAGE   NAME=page       START=0x1000       END=0x3FFF
    
    	// Application
    	CODEPAGE   NAME=boot       START=0x0            END=0x1F            PROTECTED
    	CODEPAGE   NAME=vectors    START=0x1000         END=0x1029          PROTECTED
    	CODEPAGE   NAME=page       START=0x102A         END=0x3FFF
    
    	CODEPAGE   NAME=idlocs     START=0x200000       END=0x200007        PROTECTED
    	CODEPAGE   NAME=config     START=0x300000       END=0x30000D        PROTECTED
    	CODEPAGE   NAME=devid      START=0x3FFFFE       END=0x3FFFFF        PROTECTED
    
    	ACCESSBANK NAME=accessram  START=0x0            END=0x5F
    	DATABANK   NAME=gpr0       START=0x60           END=0xFF
    	DATABANK   NAME=gpr1       START=0x100          END=0x1F3
    	DATABANK   NAME=usb2       START=0x200          END=0x2FF           PROTECTED
    	DATABANK   NAME=sfr15      START=0xF40          END=0xF5F           PROTECTED
    	ACCESSBANK NAME=accesssfr  START=0xF60          END=0xFFF           PROTECTED
    
    	SECTION    NAME=CONFIG     ROM=config
    	SECTION    NAME=GP0        RAM=gpr0
    	SECTION    NAME=GP1        RAM=gpr1
    	SECTION    NAME=usbram2    RAM=usb2
    
    	SECTION    NAME=USB_VARS   RAM=usb2
    
    	STACK SIZE=0x40 RAM=gpr1
    	
  5. Para re ubicar los vectores de interrupción utilizaremos una cabecera que realice llamada: “hid_bl.h”.
  6. 	hid_bl.h
    	/*
    	 *	Copyright (c) 2011-2013, http://www.proprojects.wordpress.com
    	 *	All rights reserved.
    	 *
    	 * 	Redistribution and use in source and binary forms, with or without modification, 
    	 *	are permitted provided that the following conditions are met:
    	 *
    	 *	1.- Redistributions of source code must retain the above copyright notice,
    	 *		this list of conditions and the following disclaimer.
    	 *	2.- Redistributions in binary form must reproduce the above copyright notice, 
    	 *		this list of conditions and the following disclaimer in the documentation 
    	 *		and/or other materials provided with the distribution.
    	 *
    	 *	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
    	 *	EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
    	 *	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
    	 *	IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
    	 *	INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    	 *	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
    	 *	OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
    	 *	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
    	 *	WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    	 */
    
    	/*********************************************************************
    	 * By:              Omar Gurrola
    	 * Company:         http://www.proprojects.wordpress.com/
    	 * Processor:       PIC18
    	 * Compiler:        C18 3.45
    	 * File Name:       hid_bl.c
    	 * Description:     Header to use BL
    	 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    	 * Rev.     Date        Comment
    	 * 1.0      01/28/13    Initial version
    	  ********************************************************************/
    
    	#ifndef HID_BL_H
    	#define HID_BL_H
    
    	/** G E N E R A L  D E F I N E S ************************************/
    		// Define if this FW will be programmed with the HID Bootloader
    		#define PROGRAMMABLE_WITH_USB_HID_BOOTLOADER
    
    		/** VECTOR REMAPPING ***********************************************/
    		// We have to declare ISR Prototypes
    		void HighPriorityISR();
    		void LowPriorityISR();
    
    		#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)
    			#define RM_RESET_VECTOR_ADDRESS				0x1000
    			#define RM_HIGH_INTERRUPT_VECTOR_ADDRESS	0x1008
    			#define RM_LOW_INTERRUPT_VECTOR_ADDRESS		0x1018
    
    			// Declare _startup extern because we will need here
    			extern void _startup (void);
    			// Redefine Reset Function to go _startup
    			#pragma code RESET_APP = RM_RESET_VECTOR_ADDRESS
    				void ResetApp(void){
    						_asm goto _startup _endasm
    				} // end ResetApp()
    
    			// Declare HI & LI RM Vectors
    			#pragma code RM_HIGH_INTERRUPT_VECTOR = RM_HIGH_INTERRUPT_VECTOR_ADDRESS
    				void RM_High_Interrupt(void){
    						_asm goto HighPriorityISR _endasm
    				} // end RM_High_Interrupt()
    			#pragma code RM_LOW_INTERRUPT_VECTOR = RM_LOW_INTERRUPT_VECTOR_ADDRESS
    				void RM_Low_Interrupt(void){
    						_asm goto LowPriorityISR _endasm
    				} // end RM_Low_Interrupt()
    		#else
    		
    			#define RESET_VECTOR_ADDRESS			0x0000
    			#define HIGH_INTERRUPT_VECTOR_ADDRESS	0x0008
    			#define LOW_INTERRUPT_VECTOR_ADDRESS	0x0018
    			
    			// Interrups default locations without BL HID program
    			#pragma code HIGH_INTERRUPT_VECTOR = HIGH_INTERRUPT_VECTOR_ADDRESS
    				void High_Interrupt(void){
    						_asm goto HighPriorityISR _endasm
    				} // end High_Interrupt()
    			#pragma code LOW_INTERRUPT_VECTOR = LOW_INTERRUPT_VECTOR_ADDRESS
    				void Low_Interrupt(void){
    						_asm goto LowPriorityISR _endasm
    				} // end Low_Interrupt()
    					
    	#endif // HID_BL_H
    	
  7. Por ultimo añadimos las cabeceras y la definición de los vectores de interrupción en main.c.
  8. 	main.c
    	#include <p18f14k50.h>
    	//#include "pic18f14k50_cbits.h" // We must not change configurations bits, because BL may not work correctly.
    	#include "stdvars.h"
    	#include "hid_bl.h"
    
    	// Put this code in program memory section
    	#pragma code
    	void HighPriorityISR(){
    
    	} //This return will be a "retfie fast", since this is in a #pragma interrupt section
    
    	void LowPriorityISR(){
    
    	} //This return will be a "retfie fast", since this is in a #pragma interrupt section
    
    	void main(){
    		while(true){
    		// Forever loop
    		};
    	}
    	

Referencias:

Galería

One Response to SE – uC: El Cargador de Arranque (Boot Loader)

  1. Alejandro López Briones says:

    Hola, excelente tutorial. Estoy trabajando en este tema pero con el XC8 y no encuentro la manera de remapear las ISR. ¿Me puedes ayudar?

    Se que se debe agregar este segmento de programa en el bootloader… pero nada
    #asm
    PSECT intcode
    goto REMAPPED_APPLICATION_HIGH_ISR_VECTOR
    PSECT intcodelo
    goto REMAPPED_APPLICATION_LOW_ISR_VECTOR
    #endasm

Leave a comment