Estoy armando un gestor de arranque simple para el atmega8, principalmente utilizando ejemplos de código de la documentación de libc. Se supone que el gestor de arranque se encuentra en la sección del gestor de arranque de la memoria flash. Una aplicación en la dirección inferior debe llamar al gestor de arranque.
makefile:
LDFLAGS += -Wl,--section-start=.text=$(BOOTLOAD)
LDFLAGS += -Wl,--section-start=.test=0
test.c:
__attribute__ ((section (".test"))) int main(int argc, char **argv)
{
usart_init();
char msg[] = "Loading bootloader in 3 seconds.";
send_block(sizeof(msg), msg);
_delay_ms(3000);
typedef void (* fn_ptr_t) (void);
fn_ptr_t my_ptr = (void *)0x1800;
my_ptr();
}
Pero no podría vincular bootloader.o
y test.o
en un solo archivo .hex, porque main()
está duplicado.
¿Dónde debería ubicarse realmente main()
? ¿Y cómo se ejecutaría el otro programa (porque, lógicamente, esos son dos programas separados: aplicación y cargador de arranque)?
Una vez más, la idea es que se instale una pequeña 'prueba' de aplicación en la dirección flash 0, junto con el cargador de arranque en la memoria flash superior. En el encendido, la aplicación salta al cargador de arranque, el usuario carga su aplicación real, que a su vez debe tener cuidado de llamar al cargador de arranque en los momentos apropiados.
En realidad, el mismo documento que vinculo bajo mi pregunta se describe cómo lo que describo no puede llamarse un gestor de arranque. Aquí está mi caso de uso. Esta es una pequeña aplicación de fabricación casera, dudo que alguna vez distribuya el dispositivo a alguien. Para mi PCB, puedo agregar un encabezado ISP (5 cables desordenados adicionales) o programar el dispositivo a través del mismo canal que utilizo para la depuración: conexión serie. Ni siquiera tengo un jtag y estoy depurando completamente a través de llamadas printf (). Dicho esto, si surge la necesidad algún día, debería ser fácil llamar al "gestor de arranque" bien probado de alguna otra manera.