Ich versuche seit einiger Zeit, von meinem Bootloader zu einer Anwendung zu springen, aber ich kann nicht herausfinden, was schief läuft. Ich hoffe, dass mir hier vielleicht jemand helfen kann.
Ich verwende CC2652 von Texas Instruments und Code Composer Studio von Texas Instruments, um den Bootloader zu entwickeln und zu flashen. Der folgende Code ist der Code, den ich verwende, um zur Anwendung zu springen.
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)))();
}
Wenn ich diesen Code ausführe, lande ich im FaultISR. Hier kann ich den Debugger verwenden, um mir die Register anzusehen. Im CFSR (Configurable Fault Status Register) sehe ich, dass die Bits STKERR und IUSERR gesetzt sind.
prgEntry ist in diesem Fall 0x2E000. Ich habe diese Adresse als Start der Anwendung in den Linker-Befehlsdateien sowohl des Bootloaders als auch der Anwendung definiert. Ich habe die Befehlsdateien weiter unten kopiert.
Die Anwendung, zu der ich zu springen versuche, wird zuerst im Intel-Hex-Format auf das Gerät hochgeladen und sieht so aus: https://pastebin.com/DAerFkXr . Texas Instruments hat eine Flash Programmer-Anwendung für Windows, mit der ich eine Reihe von Adressen aus dem internen Flash des Geräts lesen kann. Ich bin die Intel-Hex-Datei von Hand durchgegangen und habe sie mit dem verglichen, was ich in der Flash Programmer-Anwendung gesehen habe, und ich glaube, dass alles an der richtigen Stelle abgelegt ist. Ich habe einen Screenshot der Ausgabe des Flash-Programmierers unter den Befehlsdateien gepostet.
Wenn ich die Anwendung mit Code Composer Studio ohne meinen Bootloader auf das Gerät flashe, kann ich sehen, dass die Anwendung normal ausgeführt wird, sodass ich weiß, dass es kein Problem mit der Anwendung gibt.
Anwendungsbefehlsdatei:
--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
}
Bootloader-Befehlsdatei:
--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
}
Screenshot vom Flash-Programmierer:
Beschreibung von STKERR: Stacking von Ausnahme hat einen oder mehrere Busfehler verursacht. Der SP wird immer noch angepasst und die Werte im Kontextbereich auf dem Stack sind möglicherweise falsch. BFAR wird nicht geschrieben.
Beschreibung von IBUSERR: Befehlsbus-Fehlerflag. Dieses Flag wird durch einen Prefetch-Fehler gesetzt. Der Fehler stoppt bei der Anweisung, sodass kein Fehler auftritt, wenn der Fehler unter einem Zweigschatten auftritt. BFAR wird nicht geschrieben.
Bearbeiten:
Dies ist die Disassemblierung der startApp-Funktion:
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
}
Ich denke, Sie sollten diesen Code in Einzelschritten durchlaufen, um zu sehen, was R0
direkt vor der LDR SP, [R0]
. Denken Sie daran, dass der Wert in R0
als Adresse interpretiert wird und die Anweisung holt, was auch immer an dieser Adresse ist, und es in den Stapelzeiger schiebt.
Es scheint mir, dass Ihr Code den Wert 0x0002E004 nimmt und als Adresse verwendet. Welcher Wert auch immer bei 0x0002E004 gespeichert ist, wird dann im Stapelzeiger gespeichert. Ist das so beabsichtigt?
Je nach Endianess sieht es so aus, als ob der SP 0x1F1F1F00 oder 0x001F1F1F bekommt.
Lundin
startApp
und sehen, was los ist, und dann sehen, ob der generierte Maschinencode mit der Aufrufkonvention Ihres speziellen Compilers übereinstimmt. Im Allgemeinen existiert C-Code nicht in einem vorhersagbaren Zustand, bis der SP initialisiert ist, noch existiert er in derselben Funktion wie der Code, der den SP manuell einstellt.Vinzenz Kenbeek
Lundin
Vinzenz Kenbeek