Estoy desarrollando un cargador de arranque y tengo algunos problemas para pasar del cargador de arranque a la aplicación. Por lo que puedo ver, el problema se debe a que estoy realizando ciertas inicializaciones en el cargador de arranque que luego también se realizan en la aplicación. Publiqué una pregunta sobre esto en los foros de TI ( https://e2e.ti.com/support/microcontrollers/other/f/908/p/894608/3308592#3308592 ) pero no recibo ninguna respuesta, así que busco para otra forma de arreglarlo.
Mi idea ahora es iniciar el gestor de arranque, descargar la imagen de la aplicación, guardarla en la memoria flash y luego, en lugar de saltar a la aplicación, quiero reiniciar el dispositivo y saltar a la aplicación antes de que se haya realizado ningún tipo de inicialización. No estoy seguro de si esto funcionará, pero he estado atascado en el salto del cargador de arranque a la aplicación por un tiempo y finalmente quiero hacer algún progreso.
Para que esto funcione, el cargador de arranque deberá saber de alguna manera que debe saltar a la aplicación antes de cualquier inicialización. Hasta donde sé, no es posible simplemente escribir en un solo byte en algún lugar de la memoria flash porque requerirá borrar un bloque completo y el tamaño del bloque en el dispositivo que estoy usando es de 8 KB. Parece un desperdicio reservar 8 KB en un dispositivo, solo para poder guardar un valor simple para transferir entre reinicios del sistema.
¿Alguien tiene algún consejo sobre cómo podría lograr esto?
Estoy desarrollando para CC2652R1F usando Code Composer Studio junto con el compilador TI v18.12.5.LTS.
EDITAR :
Intenté usar la situación de kkrambo pero parece que no funciona correctamente.
Edité el archivo de comandos de mi enlazador para incluir una sección .boot_cfg en la RAM con un tamaño de cuatro. Puse el nuevo archivo de comando del enlazador más abajo.
Luego creé una variable global uint32_t config
en mi archivo para #pragma DATA_SECTION(config, ".boot_cfg");
vincularlo a esa sección, pero no estoy seguro de haberlo hecho correctamente. Después de eso, intenté leer el valor, luego cambiar y luego reiniciar el sistema para ver si funcionaba. Este es el código que usé:
if (config == 0) {
GPIO_write(CONFIG_GPIO_LED_RED, CONFIG_GPIO_LED_ON);
sleep(2);
config = 2;
SysCtrlSystemReset();
} else {
GPIO_write(CONFIG_GPIO_LED_GREEN, CONFIG_GPIO_LED_ON);
while(1) {}
}
Cuando simplemente actualizo el gestor de arranque para no tener que reiniciar el dispositivo usando el depurador porque creo que podría reiniciar la alimentación. Veo que se enciende la luz roja, luego el valor debería cambiar y el sistema debería reiniciarse y luego, con suerte, vería la luz verde se enciende, pero ninguna de las luces se enciende. Así que creo que la SysCtrlSystemReset()
función podría no estar funcionando probablemente.
Así que intenté pasar por el cargador de arranque paso a paso, luego, después de la config = 2;
declaración, usé el botón de reinicio de la CPU en el IDE para volver al principio, pero luego, cuando vuelvo a la declaración if, el valor sigue siendo 0.
Archivo de comandos del enlazador:
--stack_size=1024 /* C stack is also used for ISR stack */
--heap_size=256
/* Retain interrupt vector table variable */
--retain=g_pfnVectors
/* Override default entry point. */
--entry_point ResetISR
/* Allow main() to take args */
--args 0x8
/* Suppress warnings and errors: */
/* - 10063: Warning about entry point not being _c_int00 */
/* - 16011, 16012: 8-byte alignment errors. Observed when linking in object */
/* files compiled using Keil (ARM compiler) */
--diag_suppress=10063,16011,16012
#define FLASH_BASE 0x0
#define FLASH_SIZE 0x58000
#define RAM_BASE 0x20000000
#define RAM_CFG_BASE 0x20013FFC
#define RAM_CFG_SIZE 0x4 // reserve 4 bytes of ram for bootloader config
#define RAM_SIZE 0x14000 - RAM_CFG_SIZE
#define GPRAM_BASE 0x11000000
#define GPRAM_SIZE 0x2000
#define FLASH_START FLASH_BASE
#define PAGE_SIZE 0x2000
#define BOOT_BASE 0x50000
#define BOOT_END FLASH_CCFG_START - 1
#define BOOT_SIZE ((BOOT_END) - (BOOT_BASE) + 1)
#define APP_BASE 0x0
#define APP_END BOOT_BASE
#define APP_SIZE BOOT_BASE
#define FLASH_CCFG_START 0x00057FA8
#define FLASH_CCFG_END (FLASH_START + FLASH_SIZE - 1)
#define FLASH_CCFG_SIZE ((FLASH_CCFG_END) - (FLASH_CCFG_START) + 1)
/* System memory map */
MEMORY
{
BOOT (RWX) : origin = BOOT_BASE, length = BOOT_SIZE
APP (RWX) : origin = APP_BASE, length = APP_SIZE
FLASH_CCFG (RX) : origin = FLASH_CCFG_START, length = FLASH_CCFG_SIZE
/* Application uses internal RAM for data */
SRAM (RWX) : origin = RAM_BASE, length = RAM_SIZE
RAM_CFG (RWX) : origin = RAM_CFG_BASE, length = RAM_CFG_SIZE
/* Application can use GPRAM region as RAM if cache is disabled in the CCFG
(DEFAULT_CCFG_SIZE_AND_DIS_FLAGS.SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM = 0) */
GPRAM (RWX): origin = GPRAM_BASE, length = GPRAM_SIZE
}
/* Create global constant that points to top of stack */
/* CCS: Change stack size under Project Properties */
__STACK_TOP = __stack + __STACK_SIZE;
/* Section allocation in memory */
SECTIONS
{
.intvecs : > BOOT_BASE
.text : > BOOT
.TI.ramfunc : {} load=BOOT, run=SRAM, table(BINIT)
.const : > BOOT
.constdata : > BOOT
.rodata : > BOOT
.binit : > BOOT
.cinit : > BOOT
.pinit : > BOOT
.init_array : > BOOT
.emb_text : > BOOT
.ccfg : > FLASH_CCFG (HIGH)
.boot_cfg : > RAM_CFG
.vtable : > SRAM
.vtable_ram : > SRAM
vtable_ram : > SRAM
.data : > SRAM
.bss : > SRAM
.sysmem : > SRAM
.stack : > SRAM (HIGH)
.nonretenvar : > SRAM
.gpram : > GPRAM
}
Puede crear una sección personalizada en la RAM que no se inicialice durante el inicio para que los valores anteriores al restablecimiento parcial o al salto permanezcan después. Esto funciona solo para restablecimientos parciales y saltos. Si se desconecta la alimentación (restablecimiento completo), los valores de esta sección no se inicializarán.
Su sistema tiene un código de inicio que configura el entorno de tiempo de ejecución de C antes de llamar a main. Su proyecto puede estar utilizando el código de inicio predeterminado proporcionado por su cadena de herramientas. El código de inicio predeterminado probablemente inicializa la sección .bss a cero e inicializa las variables en la sección .data copiando desde la sección .rodata. Si su cargador de arranque y la aplicación se compilan como proyectos separados, cada uno tiene su propio código de inicio, secciones de secciones .bss, .data y .rodata.
Su proyecto también puede estar utilizando el script de vinculación predeterminado proporcionado por su cadena de herramientas. El script del enlazador predeterminado proporciona las secciones de memoria, incluidos .bss, .data y .rodata. Puede personalizar la secuencia de comandos del enlazador para sus proyectos y agregar una sección personalizada denominada .myspecialsection. Puede ubicar .myspecialsection en una dirección y tamaño fijos para que tanto el cargador de arranque como la aplicación usen la misma memoria para esta sección. Puede hacer que .myspecialsection no sea inicializado por el código de inicio. Y puede asignar variables estáticamente y ubicarlas en .myspecialsection. Ahora el gestor de arranque o la aplicación pueden escribir un valor en .myspecialsection y realizar un reinicio por software o saltar al otro programa y los valores en .myspecialsection mantendrán sus valores.
Lea el manual del enlazador para obtener detalles sobre cómo crear una sección, cómo ubicarla y dimensionarla, cómo hacer que no se inicialice y cómo ubicar variables en la sección.
Además, considere usar una suma de verificación en los datos en .myspecialsection para evitar usar los datos cuando no están inicializados.
config
variable en el depurador. ¿Es la dirección dentro de la sección .boot_cfg como esperaba? También verifique si el código de inicio está inicializando la sección .boot_cfg. ¿Necesita algún tipo de modificador "NOINIT" en algún lugar del script del enlazador?TYPE=NOINIT
a la definición de la sección parece haberlo solucionado. Pero mientras buscaba formas de iniciar un reinicio por software, encontré que HAL_SYSTEM_RESET()
en sus comentarios dice que el sistema CC26xx no ha sido diseñado para manejar reinicios por software y los restablecimientos por software harán que el sistema sea inestable y que use restablecimientos completos en su lugar.
david tweed
Vicente Kenbeek
DKNguyen
david tweed
DKNguyen
Vicente Kenbeek
SPI_init()
y luegoSPI_open()
para abrir una interfaz específica. Puedo llamar al primero antes de cualquier otra inicialización, pero al llamarSPI_open()
antes de llamarBoard_init()
termino en el FaultISR. Creo que estoBoard_init()
está causando todos estos problemas, así que me gustaría saltar antes de llamarlo.david tweed
Board_init()
antes de hacer cualquier otra cosa? Si está haciendo algo que no desea, entonces debe modificarlo.Vicente Kenbeek
Board_init()
genera automáticamente Code Composer Studio en función de las definiciones en un archivo .syscfg. La aplicación también tiene su propioBoard_init()
método, por lo que primero se llama en el cargador de arranque y luego nuevamente en la aplicación. Eliminarlo de la aplicación me permitió tomar algunos pasos adicionales después de saltar usando el depurador. Por supuesto, eventualmente se rompió porque laBoard_init()
función debe llamarse antes de que se pueda usar cualquier API.