Domanda:
Le regioni di memoria su cui posso scrivere e su cui non posso scrivere, architettura ARM Cortex-M
muyustan
2020-06-17 13:08:54 UTC
view on stackexchange narkive permalink

Spero che il mio titolo abbia una terminologia corretta. Sto lavorando (imparando) con la scheda di scoperta STM32F4, che ha un microcontrollore STM32F407VGTx su di essa. Cerco davvero di trovare le risposte nel manuale di riferimento, ma a volte è davvero difficile trovare anche dove cercare. Forse a causa del fatto che è lungo più di 1700 pagine ...

Quindi, ecco la situazione, durante i miei test (codice C, il compilatore è arm-none-eabi-size), mi sono reso conto che posso scrivere qualsiasi valore nei registri periferici, ad esempio nei registri GPIOD. Ma usando lo stesso codice (per scrivere su un indirizzo), non sono in grado di scrivere, ad esempio, all'indirizzo 0x58 (0x00000058 in effetti). In caso di registri periferici, il documento indica chiaramente quali registri / bit sono abilitati alla scrittura e quali di sola lettura con annotazioni come "r", "rw". Tuttavia, per l'indirizzo 0x58, non sono riuscito a trovare il motivo per cui non posso scriverci.

Qualsiasi guida o spiegazione sarebbe apprezzata, grazie.


aggiornamento:

Contro domanda: perché dovresti essere in grado di scrivere a quell'indirizzo? Qualcosa è mappato a quello? - Marcus Müller

OK, è un po 'interessante. Ho appena iniziato a conoscere gli interrupt esterni e voglio fare tutto (compresi quindi gli interrupt esterni) a livello di registro, durante il mio apprendimento. Quindi, ecco perché non ho utilizzato alcuna funzione da HAL, SPL o CMSIS e nessuno di questi file è presente nella directory del progetto. In un certo senso ci sono riuscito, quindi avevo il registro in sospeso EXTI che si avviava correttamente, ma non sono riuscito a trovare un modo per collegare una funzione di callback all'interrupt che definirà il processo che voglio eseguire in caso di interrupt. Ispezionando la tabella NVIC (pagina 372) dal manuale di riferimento, è emerso che ogni interrupt è correlato a un indirizzo di memoria nell'ultima colonna. Quindi, ho pensato, forse, solo un'idea, quelle posizioni conterranno l'indirizzo di memoria (puntatore) alle funzioni del gestore di interrupt. Quindi, ho quindi pensato di definire una funzione e quindi scrivere l'indirizzo di quella funzione nella posizione di memoria 0x58. In modo che, quando arriva l'interruzione, il microcontrollore guarderà 0x58, che lo reindirizzerà alla posizione della funzione di interesse.

Sì, questo aggiornamento avrebbe potuto essere di per sé un'altra domanda. Dispiace per la confusione. Penso che si possa rispondere alla domanda senza questa storia, ma un commento mi ha fatto aggiungere anche questa ...

Contro domanda: perché * dovresti * essere in grado di scrivere a quell'indirizzo?Qualcosa è mappato a quello?
@MarcusMüller è un po 'interessante il motivo per cui avevo bisogno di mysef per poter scrivere a quell'indirizzo, era solo una cosa ipotetica nella mia mente, e probabilmente vedrei che non era come pensavo, se fossi riuscito a scriverea quell'indirizzo.Consentitemi di aggiungere la storia alla mia risposta e, quando avrò finito, vi informerò.
Non so se la storia conti molto, la domanda è se c'è qualcosa su cui puoi scrivere mappato a quell'indirizzo
ok, presumo che tu sappia perché non posso scrivere lì e fare una domanda retorica.In caso contrario, penso che il mio aggiornamento non ti darà molte informazioni su "È qualcosa mappato a quello" perché spiegherà perché ** ho pensato **, ** intendo ** scrivere qualcosa a quell'indirizzo di memoria.Come ho detto, non so esattamente se quella regione contenente 0x58 da qualche parte dovrei essere in grado di scrivere qualcosa oppure no.Potrei parlare totalmente di cose senza senso, ma il mio aggiornamento chiarirà almeno perché mi è venuta l'idea di scrivere a quell'indirizzo in primo luogo.
Quattro risposte:
awjlogan
2020-06-17 13:39:20 UTC
view on stackexchange narkive permalink

È necessario dare un'occhiata alla configurazione della memoria del processore.Il Cortex-M4 implementa l'architettura ARMv7-M.Ecco una panoramica della metà superiore della mappa di memoria (fastidiosamente questa è divisa in due pagine nel manuale di riferimento di M4).

enter image description here

Come puoi vedere, l'area 0x00000000 - 0x1FFFFFFF è assegnata a Code .L'implementazione STM non includerà un percorso accessibile sul bus AHB del sistema verso quell'area, quindi non è possibile scrivere a quell'indirizzo.

oh, ok, quindi quella regione è una sorta di disco rigido dei nostri soliti computer, dopo che il codice C è stato compilato e convertito in codice binario, verrà caricato in quella regione e il microcontrollore leggerà le istruzioni da lì.Sono almeno vicino al punto?
Il linker viene utilizzato per specificare le aree di memoria e i loro attributi.Dai un'occhiata a questo, _può_ aiutare http://www.keil.com/support/man/docs/armlink/armlink_pge1406297881263.htm Può essere un argomento confuso, ma parte del divertimento di usare i micro piuttosto che i sistemi completi:)
Marcus Müller
2020-06-17 13:40:48 UTC
view on stackexchange narkive permalink

È possibile che la tabella vettoriale sia riposizionata ;c'è un registro che memorizza l'indirizzo "0" di quella tabella e che può essere modificato.Questa è in realtà una funzionalità piuttosto utile: ti consente di impostare una tabella di gestione degli interrupt ovunque nella RAM, quindi con una scrittura su VTOR (che è all'indirizzo 0x08, penso), puoi passarea quella nuova tabella.

Vedi p.218 del manuale di programmazione stm32f4.

fammi provare io stesso se ti ho capito o meno.Quindi, `0x00000058` e i suoi dintorni non mi sono autorizzati a modificare, diciamo che l'indirizzo` 0x50000000` va bene con cui lavorare.Quindi scrivo "0x50000000" in "VTOR".Ora la tabella NVIC inizia da quell'indirizzo.Quindi, se scrivo l'indirizzo della mia funzione di gestione degli interrupt in `0x50000058`, otterrei ciò che intendevo?Lo proverò ora, nel frattempo aspetto il tuo commento.Grazie per la risposta btw.
@muyustan Devi copiare l'intera tabella vettoriale, altrimenti gli altri irq falliscono.E di solito puoi cambiare 0x58, durante la programmazione flash.
@Jeroen3 ma allora come faccio a sapere l'indirizzo della funzione che definirò?
Script Linker @muyustan che lo definisce o che utilizza l '"etichetta" in-assembly che useresti per JMP anche lì.
@MarcusMüller ok, immagino che dovrei lasciarlo andare per ora poiché la cosa prevista sembra un po 'oltre le mie conoscenze da realizzare.A proposito, ho provato la cosa che ho menzionato nel commento sopra ma non sono riuscito a trovare le regioni di memoria corrette da utilizzare.
@muyustan andrà bene qualsiasi regione RAM.Questa è la bellezza di una soluzione così flessibile.
@MarcusMüller ok, ho visto nel manuale di programmazione la parte relativa a VTOR che dice che l'indirizzo che può essere inserito in VTOR è limitato da 0x00000080 a 0x3FFFFF80.Quindi, la tua "qualsiasi regione RAM farà" una dichiarazione valida?Non sto giudicando, questa è una domanda diretta.Ciò che mi ha reso incapace anche di provare questo processo è che non sono riuscito a trovare quale intervallo di indirizzi è la parte che posso usare come RAM.È solo che ci sono molte informazioni in diversi documenti (rif. Man, prog. Man, datasheet, ...) che non sono riuscito a uscire da quella complessità.La maggior parte degli indirizzi che ho provato a .......
Effettuare un'operazione di scrittura in esso ha provocato errori, ovvero non sono riuscito a scrivere dati su di essi, osservando il browser della memoria in modalità di debug.
@muyustan è una buona domanda.Guarda qui: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439b/BEIBIBCC.html
@muyustan Per VTOR è possibile utilizzare qualsiasi regione RAM interna, non esterna.Se non usi il collegamento debole, leggi la documentazione del compilatore per gli attributi dell'indirizzo di collegamento che puoi dare alle funzioni.
@MarcusMüller qual è il set minimo di requisiti per comprendere questi documenti, voglio dire, penso di avere una conoscenza generale delle cose, ma quei documenti come quello che hai collegato ora mi sembra che siano stati scritti in cinese mandarino.Ad ogni modo, lo ispezionerò e cercherò di capire.Forse posterò un'altra domanda sulle mie confusioni, comprensioni e più probabilmente "non comprensioni" riguardo a questi problemi di memoria.Se lo faccio, ti taggerò lì, spero.Grazie per il tuo impegno.
@muyustan Penso che tu stia andando bene.I microcontrollori moderni sono computer incredibilmente complessi.Non è possibile capire tutto all'interno di un debole :) Continua!
@MarcusMüller ok, un'ultima cosa mi ha confuso, non ho mai guardato la struttura dei bit di VTOR fino a pochi minuti fa poiché non sono mai arrivato al punto di scrivere a VTOR.Tuttavia, l'ho appena guardato, prog.man page 227, e ho visto che ci sono solo 21 bit disponibili per scrivere su quel registro.Allora come si può scrivere arbitrariamente un indirizzo a 32 bit?
non puoi!a) non hai lo spazio degli indirizzi a 32 bit completo, come hai notato tu stesso (da 0x00000080 a 0x3FFFFF80), quindi i bit superiori non sono utili, eb) quando leggi il paragrafo sopra la tabella, vedi che quello inferiorei bit sono impossibili da scegliere.
@muyustan Posso ripetere ciò che ha detto Marcus, stai andando bene!I microcontrollori richiedono che tu lavori a un livello molto basso, comprendendo posizioni, protezioni, interruzioni, ecc. Queste cose vengono astratte quando lavori su un sistema ospitato.Inoltre, quando hai qualcosa come un Cortex-M4, hai il processore e quindi tutte le periferiche specifiche del fornitore con cui occuparti.E anche buone domande :)
Un'altra cosa: proprio come non proveresti a programmare il tuo PC senza un sistema operativo (impazziresti a inizializzare le cose prima di poterle usare - e poi a capire come mantenere le cose in esecuzione), davvero non lo usimicrocontrollori senza i loro HAL.Nella maggior parte dei casi, questi HAL sono davvero "astrazioni a costo zero", in quanto darebbero semplicemente i nomi degli indirizzi di registro con cui lavorare, o ti permetterebbero di chiamare una funzione nella ROM del produttore per scrivere nella flash invece di avereper implementare la stessa funzione.Sono d'accordo, è fantastico per imparare come funziona un processore cosa stai facendo,
ma devi capire che stai andando in questo modo più difficile di quanto farebbe lo sviluppatore medio per il firmware MCU.Se vuoi imparare come funzionano le CPU * in generale *, inizia con qualcosa di più semplice di una CPU ARMv7 a 32 bit come questa ... che devi effettivamente continuare a funzionare su hardware reale (che aggiunge uno strato di soddisfazione quando un LED lampeggia effettivamente, ma aggiunge anche una quantità enorme di complessità).Se vuoi imparare a gestire una CPU, forse inizia con una semplice CPU in un emulatore, il che semplifica la sperimentazione.Ti insegnerà ancora molte basi utili!
@awjlogan e Marcus, grazie ad entrambi per i vostri commenti / idee / suggerimenti, li considererò in dettaglio.
Bene, dopo decine di ore, posso dire di essere riuscito a spostare la tabella vettoriale in una posizione di memoria desiderata e utilizzare funzioni di routine del servizio di interruzione denominate in modo personalizzato.Tuttavia, ho notato qualcosa, il ripristino funzionava bene anche se ho spostato la tabella vettoriale.Il gestore di ripristino si trova sempre a un indirizzo fisso e non si sposta con la tabella vettoriale NVIC?
Jeroen3
2020-06-17 14:45:10 UTC
view on stackexchange narkive permalink

Quindi, ho pensato, forse, solo un'idea, quelle posizioni conterranno l'indirizzo di memoria (puntatore) alle funzioni del gestore di interrupt.

È così che funziona.C'è anche VTOR, come ha descritto Marcus.Tuttavia, i progetti semplici utilizzano qualcosa chiamato file assembler di avvio, di solito startup.s in cui lo stack, l'heap e la tabella vettoriale vengono messi nella loro posizione.
La tabella vettoriale in startup.s è debolmente collegata con un gestore predefinito che non fa nulla.
Se definisci una funzione con esattamente lo stesso nome da qualche altra parte, essa sovrascrive quella predefinita.

Questo è per il Cortex M4, che il tuo chip provenga dalla ST non ha ancora importanza.

Non so quale compilatore stai usando, ma ecco una descrizione dettagliata del file di avvio da parte di ARM: https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/decoding-the-startup-file-for-arm-cortex-m4

Grazie!cosa ne pensate del mio commento sotto la risposta di Marcus?Perché non sono riuscito a ottenere ciò che volevo.
Justme
2020-06-17 14:43:20 UTC
view on stackexchange narkive permalink

Questo indirizzo è il programma flash.Se vuoi scrivere su flash, è possibile, devi prima cancellarlo usando la periferica flash e non puoi davvero cancellare il programma che stai eseguendo, quindi non farlo.Ci sono due modi per farlo correttamente.È possibile copiare la tabella vettoriale in SRAM e dire a NVIC di puntare la tabella vettoriale in SRAM, in modo da poter modificare liberamente il vettore.Una soluzione più comune sarebbe quella di utilizzare un codice di interrupt fisso che prenda un indirizzo da una variabile e salti a quell'indirizzo, quindi puoi semplicemente cambiare dove punta la variabile.

grazie, ma non sono riuscito a capire esattamente cosa intendevi con "un codice di interruzione corretto"
o, se puoi, elabora un po 'di più la frase che inizia con "una soluzione più comune ...",
Lascia che i vettori rimangano in flash, punta il vettore al codice in flash, fai in modo che il codice in flash legga un puntatore da SRAM dove chiamare (o saltare).Aggiorna il puntatore in SRAM come desideri puntare a qualsiasi funzione che ti piace.In termini del linguaggio C, crea una routine di interrupt che chiama una funzione tramite un puntatore a funzione.


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 4.0 con cui è distribuito.
Loading...