Come passare dai microcontrollori "Basic" a ARM Cortex?


22

Ho molti anni di esperienza con core a 8 bit di vari produttori - vale a dire 8051, PIC e AVR - e ora ho un Cortex M0 da capire. In particolare questo , ma spero che possiamo essere più generici di così.

Si sta rivelando un po 'più di quanto mi aspettassi, con più documenti che descrivono diverse parti del sistema in diversi livelli di dettaglio e nessuno che io abbia mai visto connettere tutto insieme. Questo rispetto ad avere un foglio dati che spiega tutto. Capisco di avere molte più cose da documentare in primo luogo, ma il cambio di formato mi sta gettando in loop.

Il sito Web sopra ha un documento che è una buona panoramica di ogni sottosistema e periferica in isolamento, e un altro che descrive ogni registro in dettaglio, e ho tutto il codice sorgente per il loro SDK compresi i file di intestazione e alcuni esempi complessi, ma continuo a vedere niente che descriva come tutto si connette insieme.

Esiste una sintesi concisa dell'architettura Cortex che spiega la funzione di cose che i controller più piccoli non hanno - come più strati di bus dalla CPU alle periferiche, ognuno con il proprio timer watchdog - e come si collegano tutti insieme?


Non posso dire da quello che hai descritto se dal produttore hai ottenuto la scheda tecnica / il manuale dell'utente per il processore. Questo dovrebbe darti una buona immagine generale e dettagli. Da una delle immagini sul sito che hai collegato sembra un processore NXP. Guarda il numero di parte del produttore e cerca la documentazione del processore sul loro sito. C'è anche il sito ARM arm.com/products/processors/cortex-m/cortex-m0.php .
DigitalNinja,

Ci scusiamo per il ritardo nel tornare a questo; Sono stato impegnato con altri progetti. Grazie @Adam per la voce dell'esperienza.
AaronD

E grazie a @Richard per la panoramica di come pensarci e la nota sulla stampa della configurazione dei pin. Ho votato entrambi.
AaronD

Non tornerai mai indietro, tranne se trovi alcuni requisiti di prezzo estremi . E anche allora sarai tentato, dal momento che ci sono un po 'di sporco Cortex-M economico.
Ronan Paixão,

Risposte:


40

Ho lavorato su AVR e MCU basate su ARM Cortex-M3 / M4 / R4. Penso di poter offrire alcuni consigli generali. Ciò presupporrà che stai programmando in C, non in assembly.

La CPU è in realtà la parte facile. I tipi di dati C di base avranno dimensioni diverse, ma stai comunque usando uint8 / 16 / 32_t, giusto? :-) E ora tutti i tipi di numeri interi dovrebbero essere ragionevolmente veloci, con 32 bit (int) essere il più veloce. Probabilmente non hai una FPU, quindi continua ad evitare float e doppi.

Innanzitutto, lavora sulla tua comprensione dell'architettura a livello di sistema. Ciò significa IO, clock, memoria, ripristini e interruzioni. Inoltre, è necessario abituarsi all'idea di periferiche mappate in memoria. Su AVR puoi evitare di pensarci perché i registri hanno nomi univoci con variabili globali uniche definite per loro. Su sistemi più complessi, è comune fare riferimento ai registri con un indirizzo di base e un offset. Tutto si riduce all'aritmetica del puntatore. Se non ti senti a tuo agio con i puntatori, inizia subito a imparare.

Per gli IO, capire come viene gestito il muxing periferico. Esiste un controllo mux centrale per selezionare quali pin sono segnali periferici e quali GPIO? Oppure imposti i pin in modalità periferica usando i registri periferici? E ovviamente dovrai sapere come configurare i GPIO come input e output e abilitare la modalità open-drain e pull-up / down. Gli interrupt esterni di solito rientrano anche in questa categoria. I GPIO sono piuttosto generici, quindi la tua esperienza dovrebbe esserti utile qui.

Il clock si riduce a poche cose. Si inizia con una sorgente di clock, in genere un oscillatore RC interno o cristallo. Viene utilizzato per creare uno o più domini di clock a livello di sistema. I chip ad alta velocità useranno un PLL, che puoi pensare come un moltiplicatore di frequenza. Ci saranno anche divisori di clock in vari punti. Le cose chiave da considerare sono la frequenza di clock della CPU e le velocità in bit necessarie per le periferiche di comunicazione. Di solito questo è piuttosto flessibile. Quando avanzi di più, puoi imparare cose come le modalità a basso consumo, che di solito si basano sul clock gating.

Memoria significa flash e RAM. Se hai abbastanza RAM, spesso è più veloce mantenere il tuo programma lì durante lo sviluppo iniziale, quindi non devi programmare il flash più e più volte. Il grosso problema qui è la gestione della memoria. Il fornitore dovrebbe fornire script di linker di esempio, ma potrebbe essere necessario allocare più memoria a codice, costanti, variabili globali o stack a seconda della natura del programma. Argomenti più avanzati includono la sicurezza del codice e la programmazione flash runtime.

I ripristini sono piuttosto semplici. Di solito devi solo cercare il timer del watchdog, che può essere abilitato per impostazione predefinita. I ripristini sono più importanti durante il debug quando si esegue ripetutamente lo stesso codice. È facile perdere un bug a causa di problemi di sequenziamento in quel modo.

Ci sono due cose che devi sapere sugli interrupt: come abilitarli e disabilitarli e come configurare i vettori di interrupt. AVR-GCC fa quest'ultimo con le macro ISR (), ma su altre architetture potrebbe essere necessario scrivere manualmente un indirizzo di funzione in un registro.

Le periferiche del microcontrollore sono generalmente indipendenti l'una dall'altra, quindi puoi impararle una alla volta. Potrebbe essere utile scegliere una periferica e utilizzarla per apprendere parte delle cose a livello di sistema. Le periferiche di comunicazione e PWM sono utili per il clock e gli IO, mentre i timer sono utili per gli interrupt.

Non lasciarti intimidire dal livello di complessità. Quei microcontrollori "di base" ti hanno già insegnato molto di ciò che devi sapere. Per favore fatemi sapere se avete bisogno di me per chiarire qualcosa.


4
Buona risposta. Un'altra cosa a cui prestare attenzione sono le periferiche DMA, che nella mia esperienza tendono ad avere interfacce complicate e sotto documentate.
Doug McClean,

3
"E ora tutti i tipi di numeri interi dovrebbero essere ugualmente veloci." In realtà, a causa delle regole di promozione dei numeri interi in C, l'uso di tipi a 8/16 bit può comportare un sacco di estensione segno / zero e può essere un problema quando la memoria Flash è bassa. Quindi, se c'è della RAM da risparmiare, potrebbe essere utile utilizzare più tipi a 32 bit o almeno preferire int/ int_leastN_Ttipi per le variabili dello stack.
user694733,

Ha fatto un errore sul mio commento. Intendevo dire; usa int_fastN_ttipi, non int_leastN_ttipi.
user694733

@ user694733: Vorrei che lo standard C consentisse al codice di chiedere un numero intero che occupa una determinata dimensione in memoria e possa operare su valori all'interno di un intervallo particolare, ma con semantica vagamente specificata quando si va oltre quell'intervallo. Su qualcosa come ARM, int16_tspesso sarà veloce quanto int32_tper i valori archiviati in memoria, ma lo standard richiede che su piattaforme con int17 bit o più, int16_t x=32767; x+=2;debba essere impostato xsu -32767, che spesso richiede istruzioni per l'estensione del segno anche se il codice sarebbe non fare mai uso del comportamento di avvolgimento.
supercat,

Lo standard C @supercat richiede il comportamento di wrapping solo per i tipi senza segno. Per i tipi firmati qualsiasi avvolgimento è UB, a causa delle diverse rappresentazioni possibili. Quindi x+=2, sarebbe legale usare le istruzioni per i tipi a 16 bit, perché il compilatore potrebbe presumere che il valore non andrà a capo, e quindi usarlo non cambierebbe il comportamento osservabile. Ma penso che ARM non abbia istruzioni ADD a 16 bit che lo renderebbero possibile. (Potrei sbagliarmi, la mia conoscenza sul set di istruzioni ARM non è così buona.)
user694733

8

È utile ricordare che ARM possiede la proprietà intellettuale del microprocessore, ma in realtà non produce parti. Al contrario, i produttori concedono in licenza le varie versioni di processori ARM e producono le proprie parti uniche con singoli mix di funzionalità e periferiche.

Detto questo, se sei nuovo nell'architettura, probabilmente avrebbe senso iniziare con la documentazione ARM che è, essenzialmente, la documentazione di base per tutti questi microprocessori.

Ad esempio, Cortex-M0 è descritto sul sito Web di ARM .

C'è anche un elenco di libri relativi a ARM che si rivolge a una vasta gamma di esigenze e interessi.

Infine, ci sono le schede tecniche specifiche del produttore. Per M0, Cypress, NXP e STMicroelectronics sono solo tre dei numerosi produttori di componenti reali basati su Cortex-M0.

(E no, non lavoro per ARM e non l'ho mai fatto.)


1
Questa è una risposta piuttosto generica che non fa altro che un collegamento ad alcuni documenti Cortex-M0, che sono sicuro che l'OP può trovare da solo.
Jay Carlson,

1
Affronta direttamente la domanda che ha chiesto aiuto per trovare la documentazione generale. Questa risposta risponde direttamente a ciò che è necessario e spiega perché le cose sono come sono.
Edward,

8

Una grande differenza è l'uso delle librerie fornite dal fornitore. Per i PIC, Atmels, ecc., Le librerie di base (per gpio, timer, adc, ecc.) Non sono state utilizzate molto dalla maggior parte degli sviluppatori. Nella mia esperienza, le persone li userebbero (al massimo) come guide quando scrivono il proprio codice.

Tuttavia, con ARM, le librerie sono quasi sempre utilizzate. Esiste uno standard, "CMSIS", che i produttori sono invitati a seguire. Molti lo fanno. Aiuta nella portabilità del codice (tra diversi ARM e tra produttori) e offre un metodo "standardizzato" per strutturare il codice. Le persone si abituano a vedere e comprendere le funzioni della biblioteca.

Certo ci sono alcuni sviluppatori che accedono direttamente ai registri, ma sono i valori anomali :)

Per rispondere alla tua domanda, ho trovato molto utile leggere la documentazione della Biblioteca. ST ha un codice ben sviluppato, con un grande file di aiuto creato da Doxygen. Puoi vedere quali sono tutte le opzioni per ciascun modulo hardware.

Per utilizzare GPIO come esempio, la funzione di inizializzazione gestisce:

  • Direzione (dentro o fuori)
  • pullups / pulldowns
  • a collettore aperto / push-pull
  • velocità di risposta
  • eccetera.

Osservando le opzioni, puoi vedere cosa è possibile. E, naturalmente, imparerai come passare queste opzioni nella funzione Init!

OK, ora che ho detto questo, vedo che il tuo ARM specifico non ha librerie conformi a CMSIS. Invece, hanno il loro SDK proprietario disponibile per il download. Vorrei iniziare a cercare i loro documenti SDK.

Se non sei sposato con questo prodotto specifico, ti consiglio di trovare un fornitore diverso con librerie più conformi. Salirai comunque una curva di apprendimento, quindi potresti anche rendere il tuo investimento più portatile ...

Gli ARM sono divertenti! Non ho guardato indietro.


"Per i PIC, Atmels, ecc., Le librerie non sono state utilizzate molto dalla maggior parte degli sviluppatori." Non sono sicuro da dove provenga. Ho usato solo PIC, non AVR, ma certamente non vorrei scrivere la mia libreria, ad esempio, per l'interfaccia host USB, lo stack TCP o il file system della scheda SD. Le librerie di Microchip per tutte queste sembrano abbastanza adeguate.
Tcrosley,

Ah, @tcrosley, hai sicuramente ragione. Stavo solo cercando di fare riferimento alla funzionalità coperta dalle periferiche di base: gpio, timer, adc, ecc.
bitsmack,

Accetto, di solito accedo direttamente a GPIO, timer, orologi e UART R / W. A volte uso le loro chiamate in libreria per I2C, SPI, ADC e UART, ma non sempre. Molti registri, che si tratti di PIC (e in particolare PIC32) o ARM.
Tcrosley,

Penso che questa risposta sia la più pragmatica elencata per questa domanda, anche se non si applica al controller specifico del PO. Penso che si possa fare un bel po 'di buona ingegneria integrata senza comprendere AHB o NVIC.
Jay Carlson,

@JayCarlson Grazie! La tua modifica a questa risposta è stata respinta perché non dovremmo cambiare i post di altre persone in modo così significativo. Ma è stata davvero una buona informazione! Ti suggerisco di pubblicarlo come risposta personale, in modo da aiutare le persone e ottenere anche il voto :)
bitsmack

5

Buon momento di muoversi; gli 8 bit stanno morendo rapidamente; quando puoi acquistare una scheda da $ 5 con (ad esempio) un STM32F103 che è un microcontrollore ARM a 32 bit piuttosto capace (anche con USB!), non c'è dubbio che i tempi siano cambiati.

Hai già avuto delle risposte eccellenti, ma soprattutto direi "dimentica assemblaggio" e quasi "dimentica di preoccuparti di come funziona la cpu a basso livello" - un giorno ci sarà un caso d'angolo in cui devi scavare (un'ottimizzazione specifica o per il debug) ma i core ARM eseguono il codice C in modo eccezionalmente buono (in base alla progettazione) e raramente è necessario avventurarsi in profondità nelle viscere.

Ciò significa che trascorrerai un certo tempo a sbattere la testa contro problemi con compilatori (e in particolare linker e makefile) che ti segnalano errori oscuri ma sono tutti superabili.

Il coraggio di come funzionano gli ARM (ovvero i libri della CPU ARM) è denso e non molto interessante fino al giorno in cui devi effettivamente ottimizzare (e rimarrai stupito di quanto raramente si abbiano registri a 32 bit e il tuo PLL ' d Il clock della CPU è nella regione di 100mhz).

Il set di istruzioni ARM "old skool" è molto più facile da leggere di un disassemblaggio rispetto al nuovissimo "Thumb2" - che è quello che trovi sulla maggior parte dei moderni ARM (Cortex) a livello di microcontrollore - ma di nuovo le viscere delle istruzioni del linguaggio assembly si dissolvono principalmente sullo sfondo; se hai il set di strumenti giusto (specialmente un debugger a livello di sorgente decente con punti di interruzione / singolo passaggio ecc.) non ti interessa affatto che sia ARM.

Una volta che sei nel mondo dei registri a 32 bit e della larghezza del bus dati a 32 bit e di tutto ciò che avresti sempre desiderato disponibile su chip, non vorrai più tornare a una CPU a 8 bit; fondamentalmente spesso non c'è penalità per "prendersela comoda" e scrivere il codice per renderlo più leggibile che efficiente.

Tuttavia ... periferiche ... sì e c'è il problema.

Avrai sicuramente un sacco di cose con cui giocare sui moderni MCU e molte cose sono piuttosto fantasiose; spesso trovi un mondo di raffinatezza molto, molto al di là delle periferiche on-chip AVR, PIC e 8051.

Un timer programmabile? No, ne ho otto! DMA? Che ne dici di 12 canali con priorità programmabile e modalità burst e modalità concatenata e ricarica automatica e .. e .. e ...

I2C? I2S? Dozzine di opzioni di muxing dei pin? Quindici modi diversi di riprogrammare il flash on-chip? Sicuro!

Sembra spesso che tu sia passato dalla carestia alla festa con le periferiche ed è comune che ci siano interi pezzi di un chip che ammirerai ma che utilizzerai a malapena (quindi; orologio).

La quantità di hardware on-chip (e le variazioni su quello in una sola linea di chip di un fornitore) è oggi alquanto sbalorditiva. Ovviamente un fornitore di chip tenderà a riutilizzare i blocchi IP, quindi una volta acquisito familiarità con un determinato marchio diventa più facile, ma "la merda è diventata pazzesca al giorno d'oggi".

Semmai le periferiche e le loro interazioni (e DMA e interrupt e allocazione del bus e e ...) sono così complesse (e, a volte, non esattamente come descritto nei fogli dati) che gli ingegneri hanno spesso una gamma preferita di MCU ARM e tendono a voler attenersi semplicemente perché hanno familiarità con le periferiche e gli strumenti di sviluppo.

Buone librerie e strumenti di sviluppo (ad es. Compilazione veloce + ciclo di debug con un debugger adeguato) e una vasta serie di progetti di codice di esempio funzionanti sono assolutamente cruciali per la tua scelta MCU ARM al giorno d'oggi. Sembra che la maggior parte dei fornitori abbia schede di valutazione estremamente economiche (

Come sono certo che hai notato, una volta superato il livello del microcontrollore con ARM e nel livello SOC (ad esempio SOC in stile Raspberry Pi / etc), le regole cambiano completamente ed è tutto su quale tipo di Linux stai andando per correre, perché - con eccezionalmente poche eccezioni - saresti abbaiare pazzo per tentare qualsiasi altra cosa.

Fondamentalmente; indipendentemente dalla CPU che (potrebbe) essere stata preselezionata per te in questo concerto, comprati una manciata di schede di valutazione basate su Cortex super-economiche da alcuni fornitori diversi (TI, STM, Freescale e altro ancora in mente) e avere un trucco con il codice di esempio fornito.

Ultimo consiglio; una volta trovate la pagina o tre nel foglio dati che descrive le opzioni di pin-muxing per l' esatto numero di parte del chip con cui si sta lavorando, si consiglia di stamparlo e incollarlo sul muro. Scoprire in ritardo in un progetto che una certa combinazione di periferiche è impossibile a causa del muxing dei pin non è divertente, e a volte quelle informazioni sono così nascoste che giureresti che stanno cercando di nasconderle :-)


un rapido addendum - se il tuo progetto è molto più che il controller più semplicistico, pensa all'utilizzo di un RTOS - c'è qualcosa di una curva di apprendimento con qualunque cosa tu scelga, ma anche i più piccoli ARM hanno un sacco di grinta al giorno d'oggi per eseguire un sistema operativo multithread. Personalmente ho trovato ChibiOS un ottimo mix di funzionalità snelle ma capaci (specialmente in esecuzione su STM32 dove viene fornito con una bella libreria periferica) ma ci sono diverse scelte.
Richard Aplin,

4

Vengo anche da AVR e ora di solito seguo STM32 (Cortex-M). Ecco cosa raccomando per i principianti e riflette le mie difficoltà quando ho iniziato:

  1. Ottieni una scheda con un debugger o almeno un connettore JTAG (e quindi acquista un debugger JTAG). Ce ne sono molti economici e risparmierai molto tempo utilizzandolo.

  2. Ottieni un buon IDE con tutto incluso. Ho consigliato CooCox CoIDE molto tempo fa. Da allora ha interrotto e riavviato lo sviluppo, quindi non sono sicuro di come sia adesso. "Un buon IDE" ti consente di far lampeggiare il LED Hello World di base in pochissimo tempo.

  3. "Un buon IDE" dovrebbe impostare le intestazioni CMSIS del produttore. Queste sono fondamentalmente le mappe dei registri che consentono una scrittura più semplice dei programmi C / C ++, con nomi di variabili anziché numeri e puntatori semplici.

  4. Prova a utilizzare le librerie periferiche del produttore, se non hai bisogno delle migliori prestazioni in assoluto. In realtà non lo fai per ora, poiché stai imparando. Se in seguito ti accorgi di dover spremere di più, guarda nel codice della libreria per vedere come fa cosa. La cosa buona delle librerie è anche che di solito ti permettono di usare molti chip diversi dello stesso produttore con lo stesso codice.

  5. A differenza dell'AVR, i chip ARM iniziano con le periferiche disabilitate. Devi prima abilitarli. Una buona libreria di periferiche avrà esempi su come utilizzare correttamente le periferiche e puoi ottenere ulteriori informazioni dal foglio dati del dispositivo. Quindi, ricorda di abilitare gli orologi e le periferiche prima di utilizzarli. Sì, anche le porte I / O sono considerate periferiche.

  6. Codice mentre impari. Non cercare di fare il brontolone tutto in una volta, dal momento che è davvero abbastanza complesso. Comincerei imparando l'albero degli orologi (bus APB, AHB, ecc.) E come interagiscono orologi e divisori. Quindi guarderei dove l'IDE memorizza gli script del linker e il codice di avvio per il tuo dispositivo. Lo script del linker è praticamente il modo in cui organizzi la memoria (dove sono RAM, flash, tabella vettoriale ISR, ecc.). Lo script di avvio configura il tuo programma (cose come la copia di inizializzatori di variabili globali da flash a RAM). Alcuni IDE hanno script di avvio in ASM e altri in C. A volte puoi cercare Google per un altro, nella lingua che preferisci.

  7. Avvia il debugger il prima possibile. È abbastanza comune commettere un errore all'inizio, facendo alcune cose (di solito l'inizializzazione dell'hardware) in un ordine diverso da quello che si dovrebbe. Questo a volte attiva un'eccezione ISR che ti porta in while(1);un ciclo infinito (implementazione predefinita per quell'ISR) che arresta il tuo programma ed è difficile da tracciare anche con un debugger. Immagina senza un debugger.

  8. Parlando di un debugger, prova a far funzionare anche l'UART, quindi usa un adattatore seriale-USB per leggerlo. printf()il debug è sempre utile :-)


3

Non ho lavorato molto su 8051, AVR o PIC. Ma recentemente ho iniziato a guardare la linea di processori ARM Cortex MX. Pertanto non posso dirti molto sulla transizione da 8051, AVR o PIC, ma soprattutto dal punto di vista di un principiante.

Il processore ARM®Cortex ™ -M4 si basa sull'architettura Harvard, quindi ha bus dati e istruzioni separati. Di seguito un'immagine di alto livello.

inserisci qui la descrizione dell'immagine

Questa settimana rappresentanti della NXP visiteranno la nostra struttura. Verificherò con loro eventuali risorse NXP ARM-Cortex Mx e le pubblicherò qui. Freescale ha un microcontrollore (MCU) a 32 bit a bassa potenza Kinetis basato su core ARM® Cortex®-M , a quanto pare hanno anche guide simili all'apprendimento dei processori ARM. Purtroppo non li ho ricercati.


Riferimenti:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.