Sto usando un microcontrollore con processore ARM Cortex M4 e sto sviluppando un'applicazione bootloader su di esso.
- Compilatore: compilatore GCC- GNU ARM
- Dimensione flash del codice : 1 MB
- Interfaccia per il download del codice dell'applicazione: USB CDC Classe ACM
- Un software applicativo sul PC per trasferire il file binario del codice dell'applicazione su MCU o USB
- I hanno due codici: a. codice principale (codice di avvio), b. Codice dell'applicazione
- Nel codice dell'applicazione, viene scritta la funzione run_my_app ().
-
Il flusso del codice principale è il seguente:
reset- > inizializza MCU inizializza stato avvio USB = CLEAR; while (1) {aspetta il comando da USB: scrivi / cancella if (stato di avvio == BOOT_COMPLETE) {chiama un nome di funzione run_my_app () dal codice dell'applicazione; }} se si riceve il comando di cancellazione: cancella il codice dell'applicazione in una posizione flash 0x0020000 se si riceve il comando di scrittura: scrive il codice dell'applicazione nella posizione flash 0x0020000 dopo il completamento della scrittura riuscita, stato di avvio == BOOT_COMPLETE;
La mia domanda è come dovrei mappare la funzione run_my_app () dal codice dell'applicazione al codice di avvio? Come posso ottenere l'indirizzo della funzione run_my_code () in modo che usando il puntatore alla funzione posso chiamare quella funzione?
Ciao a tutti, devo modificare il punto di ingresso del codice dell'applicazione nella posizione 0x0020000 in flash dalla posizione 0x0000000 utilizzando lo script del linker. Il file di script del linker attualmente generato è:
MEMORY {FLASH (rx): ORIGIN = 0x00000000, LENGTH = 0x0100000 / * 1M * / RAM (rwx): ORIGIN = 0x20000000, LENGTH = 0x0030000 / * 192K * / DATA_FLASH (rx): ORIGIN = 0x40100000, LENGTH = 0x0004000 / * 16K * / QSPI_FLASH (rx): ORIGIN = 0x60000000, LENGTH = 0x4000000 / * 64M, Modifica nella sezione QSPI di seguito anche * /} ENTRY (Reset_Handler) SEZIONI {.text: {__ROM_Start =.;
/ * Anche se la tabella vettoriale non è lunga 256 voci (1KB), allochiamo ancora quello spazio * perché i registri ROM sono all'indirizzo 0x400 e c'è pochissimo spazio * nel mezzo. * / KEEP (* (. Vectors)) __Vectors_End =.; __Vectors_Size = __Vectors_End - __Vectors; __end__ =.; / * I registri ROM iniziano all'indirizzo 0x00000400 * /. = __ROM_Start + 0x400; KEEP (* (. Rom_registers *)) / * Riservare 0x100 byte di spazio per i registri ROM. * /. = __ROM_Start + 0x500; * (. text *) KEEP (* (. init)) KEEP (* (. fini)) / * .ctors * / * crtbegin.o (.ctors) * crtbegin? .o (.ctors) * (EXCLUDE_FILE (* crtend? .o * crtend.o) .ctors) * (SORT (.ctors. *)) * (. ctors) / * .dtors * / * crtbegin.o (.dtors) * crtbegin? .o (.dtors) * (EXCLUDE_FILE (* crtend? .O * crtend.o) .dtors) * (SORT (.dtors. *)) * (. Dtors) * (. Rodata *) KEEP (* (. Eh_frame *)) __ROM_End =. ; } > FLASH = 0xFF ............. ..........
Aggiunta di alcuni dettagli alla mia implementazione:
Una struttura "CodeInfoStruct" è definita sia nel codice di avvio che in quello dell'applicazione.
struct CodeInfoStruct {uint32_t RunCodeFunctionAddress;};
Nel codice dell'applicazione:
Qui, un'istanza della struttura viene creata in una posizione fissa "0x0020100" e l'indirizzo della funzione "run_my_app" è memorizzato lì.
const struct CodeInfoStruct CodeInformation __attribute __ ((section (". ARM .__ at_0x0020100"))); const struct CodeInfoStruct CodeInformation = {(uint32_t) run_my_app};
Inoltre, nel file linker, la ROM l'indirizzo iniziale viene modificato in 0x0020000:
MEMORY {FLASH (rx): ORIGIN = 0x00020000, LENGTH = 0x0100000 / * 1M * / RAM (rwx): ORIGIN = 0x20000000, LENGTH = 0x0030000 / * 192K * / DATA_FLASH (rx): ORIGIN = 0x40100000, LENGTH = 0x0004000 / * 16K * / QSPI_FLASH (rx): ORIGIN = 0x60000000, LUNGHEZZA = 0x4000000 / * 64 M, Modifica anche nella sezione QSPI sotto * /}
Nel codice di avvio:
il puntatore alla struttura di "COdeInfoStruct" è definito.
struct CodeInfoStruct * pCodeInfo = 0x0020100;
E poi, la funzione 'run_my_code' viene chiamata dal codice di avvio come segue:
void (* trgt_fnc) (void); trgt_fnc = (void (*) ()) (pCodeInfo->RunCodeFunctionAddress); trgt_fnc ();
Ma ottengo il valore zero in questo "trgt_fnc".È un modo corretto per condividere l'indirizzo della funzione run_my codice?Cosa c'è che non va qui?