He estado tratando de pasar de mi cargador de arranque a una aplicación por un tiempo, pero no puedo entender qué es lo que está mal. Espero que alguien aquí pueda ayudarme.
Estoy usando CC2652 de Texas Instrument y Code Composer Studio de Texas Instrument para desarrollar y actualizar el gestor de arranque. El siguiente código es el código que uso para saltar a la aplicación.
void startApp(uint32_t prgEntry) {
static uint32_t temp;
temp = prgEntry;
// Reset the stack pointer,
temp +=4;
asm(" LDR SP, [R0, #0x0] ");
((void (*)(void))(*((uint32_t*)temp)))();
}
Cuando ejecute este código, terminaré en FaultISR. Aquí puedo usar el depurador para mirar los registros. En el CFSR (Registro de estado de falla configurable) puedo ver que los bits STKERR e IBUSERR están establecidos.
prgEntry es 0x2E000 en este caso. Definí esta dirección como el inicio de la aplicación en los archivos de comando del enlazador tanto del gestor de arranque como de la aplicación. Copié los archivos de comando más abajo.
La aplicación a la que intento acceder primero se carga en el dispositivo en formato hexadecimal de Intel y tiene este aspecto: https://pastebin.com/DAerFkXr . Texas Instruments tiene una aplicación Flash Programmer para Windows con la que puedo leer un rango de direcciones desde el flash interno del dispositivo. Revisé el archivo hexadecimal de Intel a mano y lo comparé con lo que vi en la aplicación Flash Programmer y creo que todo está colocado en la ubicación correcta. Publiqué una captura de pantalla de la salida del Programador Flash debajo de los archivos de comando.
Cuando actualizo la aplicación en el dispositivo usando Code Composer Studio sin mi cargador de arranque, puedo ver que la aplicación se ejecuta normalmente, así que sé que no es un problema con la aplicación.
Archivo de comandos de la aplicación:
--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 BOOT_BASE 0x0
#define BOOT_SIZE 0x8000
#define FLASH_BASE 0x2E000
#define FLASH_SIZE 0x2A000
#define RAM_BASE 0x20000000
#define RAM_SIZE 0x14000
#define GPRAM_BASE 0x11000000
#define GPRAM_SIZE 0x2000
/* System memory map */
MEMORY
{
/* Application stored in and executes from internal flash */
FLASH (RX) : origin = FLASH_BASE, length = FLASH_SIZE
/* Application uses internal RAM for data */
SRAM (RWX) : origin = RAM_BASE, length = RAM_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
}
/* Section allocation in memory */
SECTIONS
{
.intvecs : > FLASH_BASE
.text : > FLASH
.TI.ramfunc : {} load=FLASH, run=SRAM, table(BINIT)
.const : > FLASH
.constdata : > FLASH
.rodata : > FLASH
.binit : > FLASH
.cinit : > FLASH
.pinit : > FLASH
.init_array : > FLASH
.emb_text : > FLASH
.ccfg : > FLASH (HIGH)
.vtable : > SRAM
.vtable_ram : > SRAM
vtable_ram : > SRAM
.data : > SRAM
.bss : > SRAM
.sysmem : > SRAM
.stack : > SRAM (HIGH)
.nonretenvar : > SRAM
.gpram : > GPRAM
}
Archivo de comando del cargador de arranque:
--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 BOOT_BASE 0x0
#define BOOT_SIZE 0x8000
#define FLASH_BASE 0x2E000
#define FLASH_SIZE 0x2A000
#define RAM_BASE 0x20000000
#define RAM_SIZE 0x14000
#define GPRAM_BASE 0x11000000
#define GPRAM_SIZE 0x2000
/* System memory map */
MEMORY
{
/* The bootloader will be stored and executed from this location in internal flash */
BOOT (RX) : origin = BOOT_BASE, length = BOOT_SIZE
/* Application stored in and executes from internal flash */
FLASH (RX) : origin = FLASH_BASE, length = FLASH_SIZE
/* Application uses internal RAM for data */
SRAM (RWX) : origin = RAM_BASE, length = RAM_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
}
/* 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 : > BOOT (HIGH)
.vtable : > SRAM
.vtable_ram : > SRAM
vtable_ram : > SRAM
.data : > SRAM
.bss : > SRAM
.sysmem : > SRAM
.stack : > SRAM (HIGH)
.nonretenvar : > SRAM
.gpram : > GPRAM
}
Captura de pantalla de Flash Programmer:
Descripción de STKERR: el apilamiento desde una excepción ha causado una o más fallas de bus. El SP todavía está ajustado y los valores en el área de contexto en la pila pueden ser incorrectos. BFAR no está escrito.
Descripción de IBUSERR: indicador de error del bus de instrucciones. Este indicador se establece mediante un error de captación previa. La falla se detiene en la instrucción, por lo que si el error ocurre bajo una sombra de rama, no ocurre ninguna falla. BFAR no está escrito.
Editar:
Este es el desmontaje de la función startApp:
void startApp(uint32_t prgEntry) {
startApp():
push {r3, r14}
str r0, [r13]
temp = prgEntry;
ldr r1, [pc, #0x18]
ldr r0, [r13]
str r0, [r1]
temp +=4;
ldr r1, [pc, #0x14]
ldr r0, [r1]
adds r0, r0, #4
str r0, [r1]
asm(" LDR SP, [R0, #0x0] ");
ldr.w r13, [r0]
((void (*)(void))(*((uint32_t*)temp)))();
ldr r0, [pc, #8]
ldr r0, [r0]
ldr r0, [r0]
blx r0
}
Creo que deberías pasar un solo paso por este código para ver qué hay R0
justo antes del archivo LDR SP, [R0]
. Recuerde que el valor in R0
se interpreta como una dirección, y la instrucción obtiene lo que sea que esté en esa dirección y lo coloca en el puntero de la pila.
Me parece que su código toma el valor 0x0002E004 y lo usa como dirección. Cualquier valor que se almacene en 0x0002E004 se almacena en el puntero de pila. ¿Es eso lo que pretendías?
Dependiendo de la frecuencia, parece que el SP obtiene 0x1F1F1F00 o 0x001F1F1F.
Lundin
startApp
y ver qué está pasando, luego ver si el código de máquina generado coincide con la convención de llamadas de su compilador en particular. En general, el código C no existe en un estado predecible hasta que se inicializa el SP, ni tampoco coexiste en la misma función con el código que configura manualmente el SP.Vicente Kenbeek
Lundin
Vicente Kenbeek