Integrar un bootloader en un PIC de 8-bit y MCC Classic debería ser una tarea sencilla, pero presenta algunos problemas que se cubrirán en esta entrada.
Introducción
Los bootloader alargan el ciclo de vida de una solución al facilitar actualizaciones de firmware.

La idea del bootloader es simple: capacidad de auto-programarse. Casi parece histórico el hardware donde era absolutamente obligatorio conectar un programador o sustituir memorias para actualizar firmware (aunque aún está más presente de lo que Arduino® nos ha hecho creer).
Mientras algunas tecnologías implementan algún bootloader mediante hardware, como Infineon® o Texas Instruments®, en otras ocasiones será el usuario quien lo tenga que implementar mediante software. Este último es el caso de los PIC de 8 bit de Microchip®.
Esta entrada es un How-to práctico donde al final se tendrá una base para una solución con un PIC de 8-bit y bootloader mediante UART.
Soporte de Microchip® al bootloader del MCC Classic
Toda la información y software de partida se encuentra en: Microchip®: 8-bit Bootloader.
El plugin MCC Classic debería facilitar esta integración, y aunque lo hace, lo cierto es que presenta problemas desde prácticamente su lanzamiento. La última actualización de esta librería es del 2016, por lo que se intuye que Microchip® habría dejado de dar soporte a esta librería (si es que alguna vez lo tuvo).

Creación del bootloader
Crear un Standalone Project y abrir el MCC, para este tutorial se utilizará el PIC16F1825. Aquí se podrá encontrar el primer warning con las últimas versiones de MPLAB (6.05) y MCC (5.2.2) que existen.

Este aviso no tiene que ver con el bootloader, ignorarlo pulsando cualquiera de las opciones. En las siguientes ventanas seleccionar MCC Classic. Debido al warning anterior el proyecto comienza con un recordatorio del mismo, aunque pueda ignorarse es cierto que cosas así menoscaban la reputación de cualquier compañía.

Antes de continuar con el PIC bootloader 8-bit y MCC se debe configurar el reloj, esto es algo particular de cada implementación y no se entra en detalle. Simplemente y como curiosidad se utiliza el reloj interno de 8MHz y el PLL x4 para conseguir una frecuencia de 32MHz.
Configuración del bootlaoder PIC 8-bit en MCC Classic
Agregar las siguientes librerías al proyecto

- EUSART: Elegir una configuración lo más simple posible, las interrupciones no serán necesarias
- MEMORY: Añadir las rutinas DataEE si queremos que el bootloader pueda manipular la EEPROM (si el PIC disposueira de ella)
- Bootloader Generator:
Existen varias posibilidades, por ahora se busca que la implementación sea lo menos intrusiva posible, sin gastar pines del PIC, protección de software, etc.

En este punto aparecen los siguientes Warning, los cuales de nuevo no tienen mucho sentido y deben ignorarse.

Nota: Es importante que en el apartado del MCC Pin module se active la opción Start High, en ocasiones aparecerá un warning advirtiendo esto, pero otras veces no.
Una vez configuradas las librerías generar el código mediante el MCC Classic.
Configurar el linker del proyecto bootloader
Esta es una acción necesaria a futuro, para evitar errores en el linkado del archivo de producción.
- Abrir las propiedades del proyecto
- Configurar en XC8 Linker el ROM ranges del menú Memory Model a 0-2ff
- En Manage Configurations… renombrar la configuración a «With_Configurations»
- Duplicar la configuración y renombrarla a «No_Configurations»
- En XC8 Compiler de «No_configurations» crear la macro OMIT_CONFIGURATIONS
- Desmarcar la opción Program the device with default config words
- Crear las directivas de compilación condicional en «device_config.c» o donde se hayan generado los #pragma de los fusibles de configuración




Creando un proyecto con bootloader
Mediante un proyecto sencillo tipo «Hola mundo» se muestra cómo interactuar con el bootloader en una aplicación real.
Se crea un Standalone Project, para este ejemplo la aplicación enviará mediante UART un «Hola bootloader APP» al iniciar y posteriormente el valor de una variable que se incrementará o decrementará cada segundo. Sin embargo, lo que haga la aplicación a priori no es relevante para integrarse con el bootloader.
void main(void){ // Initialize the device SYSTEM_Initialize(); INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); __delay_ms(200); printf("\r\nHola Bootloader APP\r\n"); uint16_t i = 0; while (1){ #ifdef OFFSET printf("%05d\r", i++); #else printf("%05d\r", i--); #endif if(EUSART_is_rx_ready()){ switch(EUSART_Read()){ case 'F': //Si recive una 'F' //lanza el bootloader printf("\r\nGO"); uint16_t Buf[ERASE_FLASH_BLOCKSIZE]; FLASH_WriteWord(0x300, Buf, 0x3FFF); NOP(); NOP(); RESET(); break; default: break; } } __delay_ms(1000); } }
Al incluir compilación condicional es posible generar distintos binarios en función de la configuración utilizada, para que esto funcione es obligatorio añadir la macro OFFSET tal como se hizo anteriormente para las Config Word.
Por otro lado la forma de lanzar el bootloader en el PIC es que reciba ‘F’ en la UART.
Configurar linker de la aplicación final
Para que el proyecto sea práctico en la fase de desarrollo deberían crearse tres configuraciones, tal y como recomienda la propia Microchip®. Aquí se usarán las mismas nomenclaturas:

Standalone
Cuando sea necesario depurar la aplicación principal será más sencillo sin la interacción del bootloader. Con esta configuración se trabajará únicamente en la aplicación principal y no existirá el bootloader.
Offset
Con esta configuración se generará el archivo para ser cargado por el bootloader. Se utilizará cuando sea necesario actualizar el firmware sin conectar el programador.

Esta configuración también es necesario realizarla en el siguiente caso.
Combined
Al finalizar del desarrollo de la aplicación se necesitará un archivo de producción que incluya la aplicación final y el bootloader. Para conseguirlo debe combinarse en un único archivo el proyecto del bootloader y el de la aplicación final. En el apartado Loading debe introducirse

Error fusionando proyectos. (1600) data in (…) conflicts with existing data at address
Si has seguido el User’s Guide de Microchip® al pie de la letra tendrás un mensaje de error en el linkado como el siguiente:
(1600) «../Bootloader16F1825.X/dist/No_Configurations/production/Bootloader16F1825.X.production.hex» argument : data in «../Bootloader16F1825.X/dist/No_Configurations/production/Bootloader16F1825.X.production.hex» conflicts with existing data at address 0x1000E
El error es provocado por el argumento que se pasa por defecto al linker -mdefault-config-bits, el cual debe desaparecer para que no entre en conflicto con las config word de la aplicación final.
Probando el bootloader
La aplicación Host se puede crear estudiando el protocolo del bootloader e integrarse en cualquier software vinculado a la solución. Por otro lado, Microchip® provee una aplicación en Java que ya hace esto: UnifiedHost-1.19.0.

Descargar la que especifica (MCC Classic), ya que la otra da errores con el bootloader de 8-bit.

Es una aplicación de escritorio bastante intuitiva que dispone de una consola para ver información relevante.
Bootloader Offset (Byte Address): Los PIC16 son word-oriented, mientras que los archivos Intel-HEX son byte-oriented, se debe tener en cuenta para configurar las direcciones de inicio. Como en este caso, si se ha configurado la librería para que el offset se encuentre en 0x300, habrá que multiplicar por 2 las direcciones del Intel-HEX para relativizarlas al PIC.
Cargar únicamente el bootloader en el microcontrolador
El proyecto del bootloader y la configuración: With Configurations sirve para generar un firmware de preproducción. Con esto el PIC se quedará esperando a que un Host envíe la aplicación, lo cual es interesante si es necesario lanzar la fabricación del hardware mientras se trabaja en el software.
Cuando la aplicación final esté lista, basta con abrir el .hex generado mediante la configuración Offset y que el bootloader lo programe en el PIC.

Failure Hint UnifiedHost
Es posible que en la consola se vean varios Failure Hint, es algo que puede ignorarse siempre que aparezca el mensaje: FULL Bootloader SUCCESSFUL.

Este aviso apareció a partir de alguna actualización, por ejemplo no aparecerá usando el UnifiedHost-0.1.14. Es posible que simplemente se haya modificado el tipo de mensajes que aparecen con el .level = FINEST en archivo logging.properties de la aplicación.
El archivo de producción
Es el firmware con bootloader y aplicación final integradas para cargar en el PIC. Si en el futuro es necesaria una actualización bastará utilizar el bootloader sin tener que conectar un programador, es lo que se conoce como firmware de producción.
La verificación se hace cargando un archivo de producción (contaje hacia atrás) y mediante el bootloader se actualiza el código (contaje hacia delante).
Error compilando y linkando Bootloader en PIC 8-bit y MCC con la opción free
Una de las sorpresas más desagradables utilizando la librería Bootloader de Microchip® es el gasto en espacio de programa. Algo sorprendente es que a día de hoy no será posible seguir el User Guide oficial sin comprar la licencia del compilador XC8.

En la imagen anterior se muestra el espacio utilizado por el bootloader en función del optimizador respecto a toda la memoria del PIC16F1825. De izquierda a derecha: sin optimizar, nivel 2 y priorizando espacio.
Si no se dispone del optimizador, una opción es aumentar el rango del Linker en Memory Model, al final este rango tiene el objetivo de que el firmware del bootloader esté contenido, avisando en caso contrario. ¿Cuánto aumentarlo? Lo mínimo posible.
Utilizando la configuración «With configurations» del proyecto del bootloader, se puede eliminar el rango del Linker en Memory Model y observar cuánto espacio consume. La imagen anterior muestra que sin optimización el bootloader necesita 0x38D words, por tanto podría configurarse el rango 0-400. Recordar modificar en la aplicación Host el Bootloader Offset a 0x800.
Distintas Word Configuration en bootloader y aplicación final
Dependiendo del PIC puede ser necesario prever las Word Configuration desde la concepción misma del bootloader. No todo se puede cambiar en tiempo de ejecución o, como diría algún Gestor fanático de los FaultyProject: «Eso se trabajará en post-producción».