programmazione microcontrollore vs programmazione orientata agli oggetti


11

Ho fatto alcune programmazioni di base orientate agli oggetti con C ++ (creazione di un B-Tree, algoritmi di hash, liste doppie collegate) e ho realizzato piccoli progetti in C (come fare un calcolatore scientifico ecc.)

Quanto è diversa la programmazione hardware (in particolare per i microcontrollori) dalla programmazione orientata al software / agli oggetti in termini di mentalità e "pensiero" che il programmatore deve avere?

Uno di solito è considerato più difficile dell'altro la mia maggior parte delle persone?

Con il mio background (come descritto sopra) avrei bisogno di molta preparazione per entrare nella programmazione hardware o posso immergermi direttamente senza troppa preparazione?


4
La più grande curva di apprendimento sarà come guidare l'hardware specifico nel tuo micro. Ciò comporterà l'analisi delle schede tecniche per ore. Sfortunatamente, non c'è via d'uscita facile.
drxzcl,

@rrazd, ho notato che hai incluso il tag arduino. È perché vuoi usare il linguaggio di cablaggio di arduino e le librerie? O scriverai le tue applicazioni incorporate in puro C? Se hai intenzione di rimanere con l'ambiente arduino, è abbastanza sicuro e facile da giocare in quanto hanno fatto alcune astrazioni lontano dall'hardware.
Jon L

@Jon ho intenzione di usare una scheda arduino per cominciare. Non è simile al linguaggio C? Pensavo coinvolgesse gli stessi concetti di base ...
rrazd,

1
Mi chiedo se intendi ciò che molte persone chiamerebbero "programmazione I / O" o se prevedi di riorganizzare l'hardware con il codice. L'arduino è decisamente il primo; quest'ultimo sarebbe il dominio degli FPGA.
JustJeff,

1
@rrazd - Ho cambiato il titolo; La "programmazione hardware" suona troppo come HDL (Hardware Description Language), ad esempio VHDL e Verilog, che vengono utilizzati per programmare FPGA e CPLD.
Stevenvh,

Risposte:


10

Dovrai abbandonare completamente il paradigma orientato agli oggetti quando hai a che fare con la maggior parte dei microcontrollori.

I microcontrollori sono generalmente limitati al registro e alla RAM, con frequenze di clock lente e nessun percorso di pipeline / parallel code. Ad esempio, puoi dimenticare Java su un PIC.

Devi entrare in una mentalità del linguaggio assembly e scrivere proceduralmente.

Devi mantenere il codice relativamente piatto ed evitare la ricorsione, poiché le limitazioni della RAM possono spesso portare a problemi di stack.

Devi imparare a scrivere routine di servizio di interruzione che siano efficienti (di solito in linguaggio assembly).

Potrebbe essere necessario eseguire il refactoring di parti del codice manualmente, nel linguaggio assembly, per implementare funzionalità che il compilatore non supporta (o supporta male).

Devi scrivere un codice matematico che tenga conto della dimensione delle parole e della mancanza di capacità FPU della maggior parte dei microcontrollori (ovvero facendo una moltiplicazione a 32 bit su un micro = male a 8 bit).

È un mondo diverso. Per me, avere un background informatico o di programmazione professionale può essere tanto un ostacolo quanto non avere alcuna conoscenza quando si tratta di microcontrollori.


1
Non è necessario abbandonare del tutto il paradigma orientato agli oggetti, ma su microprocessori più piccoli potrebbe essere necessario abbandonare le implementazioni di oggetti pesanti e pensare davvero a quale sia il modo migliore per risolvere ogni problema. Spesso si tratta di oggetti procedurali, ma leggeri, ben implementati (di solito a mano), a volte possono ridurre le dimensioni di complicati progetti di microcontrollori.
Chris Stratton,

6
Tutto ciò è vero tranne l'abbandono dell'orientamento agli oggetti. Probabilmente non userai un linguaggio con funzionalità OO ma ciò non esclude l'orientamento agli oggetti. Per i microcontrollori scriverai i driver per tutte le periferiche hardware (ADC, controller del bus seriale, PWM, ecc. Ecc.). Tale driver dovrebbe sempre essere scritto in modo orientato agli oggetti in modo che sia 1) autonomo e non sappia / si preoccupi del resto del programma e 2) implementando l'incapsulamento privato in modo che il resto del programma non possa entrare e giocherellare con esso. Ciò è possibile al 100% in C e non influirà sulle prestazioni.
Lundin,

1
Non sono molto d'accordo con la prima frase, tutti i miei progetti di microcontrollore sono stati realizzati con C ++ e un approccio orientato agli oggetti, e i micro che abbiamo usato non erano molto grandi (32kB di ROM), anche il bootloader orientato agli oggetti era in meno di 2kB, I non vedo davvero limitazione. Non puoi fare cose folli ma il design può essere orientato agli oggetti senza problemi.
Arsenale,

@Arsenal Nota Ho detto 'most', e nota che stai commentando un thread di quattro anni. :)
Adam Lawrence,

Non sono completamente d'accordo con la prima e l'ultima frase. E anche l'assembly viene usato abbastanza raramente e, soprattutto, solo per MCU a 8 bit (basta controllare questo forum, quanti post con codice assembly puoi trovare?). Sicuramente puoi e (IMHO) scrivere in stile OO per MCU a 32 bit
Andrejs Gasilovs

10

Devi pensare a diverse cose:

  • Utilizzerai C come lingua
  • Puoi ancora creare una sensazione di orientamento dell'oggetto usando i puntatori a funzione in modo da poter sovrascrivere le funzioni ecc. Ho usato questo metodo in passato e in progetti attuali e funziona molto bene. Quindi OO è parzialmente presente ma non in senso C ++.

Ci sono altre limitazioni che entreranno in gioco come velocità e memoria limitate. Quindi, come linea guida generale, evito:

  • Usando heap, se esiste un modo per risolvere il problema senza Malloc, lo faccio. Ad esempio, prealloco i buffer e li utilizzo.
  • Riduco intenzionalmente la dimensione dello stack nelle impostazioni del compilatore per affrontare i problemi di dimensione dello stack all'inizio, ottimizzandolo attentamente.
  • Suppongo che ogni singola riga di codice verrà interrotta da un evento, quindi evito il codice non rientrante
  • Presumo che anche gli interrupt siano nidificati, quindi scrivo quel codice di conseguenza
  • Evito di utilizzare il sistema operativo a meno che non sia necessario. Il 70% dei progetti incorporati non ha davvero bisogno di un sistema operativo. Se devo usare un sistema operativo, utilizzo solo qualcosa con codice sorgente disponibile. (Freertos ecc.)
  • se sto usando un sistema operativo, quasi sempre astraggo le cose in modo da poter cambiare il sistema operativo nel giro di poche ore.
  • Per i driver, ecc. Userò solo le librerie fornite dal venditore, non ho mai manipolato direttamente i bit, a meno che non abbia altra scelta. Ciò rende il codice leggibile e migliora il debug.
  • Guardo i loop e altre cose, specialmente in ISR, per assicurarmi che siano abbastanza veloci.
  • Tengo sempre a portata di mano alcuni GPIO per misurare cose, cambio di contesto, tempo di esecuzione ISR ecc.

L'elenco continua, probabilmente sono al di sotto della media in termini di programmazione software, sono sicuro che ci sono pratiche migliori.


3
+1 per "puoi usare i paradigmi OO se vuoi". Quello che devi controllare alla porta non è il design OO. OOD è solo una filosofia che ti incoraggia a tenere insieme codice e dati correlati. Quello che devi lasciare alle spalle è il modo in cui OO viene implementato nei sistemi aziendali, con più livelli di astrazione, inversione di controllo e tutto quel jazz. Il compito del tuo firmware è guidare l'hardware, tutto qui.
drxzcl,

7

Faccio entrambe le cose, quindi ecco il mio punto di vista.

Penso che l'abilità più importante in assoluto sia la tua capacità di debug. La mentalità richiesta è molto diversa in quanto molto di più può andare storto e devi essere molto aperto a considerare tutti i diversi modi in cui ciò che stai cercando di fare può andare storto.

Questo è il problema principale per i nuovi sviluppatori embedded. Le persone di PC tendono ad averlo più rozzo, poiché sono abituate a lavorare così tanto per loro. Tenderanno invece a perdere molto tempo a cercare strumenti per fare le cose per loro (suggerimento: non ce ne sono molti). Ci sono molte teste che sbattono ancora e ancora nei muri, non sapendo cos'altro fare. Se ti senti bloccato, fai un passo indietro e scopri se riesci a identificare cosa potrebbe andare storto. Passa sistematicamente attraverso il restringimento del tuo elenco di potenziali problemi fino a quando non lo capisci. Da questo processo deriva direttamente che è necessario limitare la portata dei problemi non cambiando troppo in una volta.

Le persone embedded con esperienza tendono a dare per scontato il debug ... la maggior parte delle persone che non riescono a farlo bene non durano a lungo (o lavorano in grandi aziende che accettano semplicemente "il firmware è difficile" come risposta al perché una determinata funzionalità è in ritardo di anni)

Stai lavorando su un codice che gira su un sistema esterno al tuo sistema di sviluppo, con vari gradi di visibilità sul tuo target da una piattaforma all'altra. Se sotto il tuo controllo, cerca aiuti allo sviluppo per aumentare questa visibilità nel tuo sistema di destinazione. Usa le porte seriali di debug, l'output di debug del bit banging, la famosa luce lampeggiante, ecc. Sicuramente come minimo impara come usare un oscilloscopio e usa l'I / O pin con l'ambito per vedere quando alcune funzioni entrano / escono, fuoco ISR, ecc. Ho visto le persone lottare per anni letteralmente più a lungo del necessario semplicemente perché non si sono mai preoccupati di impostare / imparare come utilizzare un collegamento debugger JTAG corretto.

È molto più importante essere molto consapevoli di quali risorse hai in relazione a un PC. Leggi i fogli dati con attenzione. Considera il "costo" delle risorse per tutto ciò che stai cercando di fare. Scopri i trucchi di debug orientati alle risorse come riempire lo spazio dello stack con un valore magico per tenere traccia dell'utilizzo dello stack.

Sebbene sia richiesto un certo grado di debug sia per PC che per software embedded, è molto più importante con embedded.


5

Presumo che la tua esperienza in C ++ sia basata su PC.

Un errore spesso commesso da programmatori che si spostano dal PC al microcontrollore è che non si rendono conto di quanto possano essere limitate le risorse . Su un PC nessuno ti fermerà quando crei una tabella con 100000 voci o scrivi un programma che compila 1 MB di codice macchina.
Ci sono microcontrollori che hanno una grande quantità di risorse di memoria, specialmente nella fascia alta, ma è ancora molto lontano da ciò a cui sarai abituato. Per un progetto hobby probabilmente puoi sempre cercare il massimo, ma in un progetto professionale sarai spesso costretto a lavorare con il dispositivo più piccolo perché è più economico .
In un progetto stavo lavorando con un TI MSP430F1101. 1 KB di memoria del programma, 128 byte di configurazione Flash, 128 byte di RAM. Il programma non si adattava all'1K, quindi ho dovuto scrivere una funzione di 23 byte nella configurazione Flash. Con questi piccoli controller si calcola per byte . In un'altra occasione la memoria del programma era troppo piccola di 4 byte. Boss non mi avrebbe permesso di usare il controller con più memoria, ma invece ho dovuto ottimizzare un codice macchina già ottimizzato (era già scritto in assembler) per adattarsi ai 4 byte extra. Ottieni l'immagine.

A seconda della piattaforma su cui stai lavorando, dovrai occuparti di I / O di livello molto basso . Alcuni ambienti di sviluppo hanno funzioni da scrivere su un LCD, ma su altri sei da solo e dovrai leggere il foglio dati dell'LCD dall'inizio alla fine per sapere come controllarlo.
Potrebbe essere necessario controllare un relè, è più semplice di un LCD, ma richiederà di passare al livello di registrazione del microcontrollore. Ancora una scheda tecnica o manuale utente. Dovrai conoscere la struttura del microcontrollore, che troverai in uno schema a blocchi, sempre nel foglio dati. Ai tempi del microprocessore abbiamo parlato di un modello di programmazione, che era sostanzialmente una linea di registri del processore. I microcontrollori di oggi sono così complessi che una descrizione di tutti i registri può prendere la parte migliore di una scheda tecnica di 100 pagine. IIRC solo la descrizione del modulo orologio per MSP430 era lunga 25 pagine.

Spesso dovrai occuparti della gestione degli eventi in tempo reale . Un interrupt che devi gestire entro 10 s, per esempio, e durante quello ha un altro interrupt che richiede la stessa accuratezza di temporizzazione. μ

I microcontrollori sono spesso programmati in C . Il C ++ è piuttosto affamato di risorse, quindi di solito è fuori. (La maggior parte delle implementazioni C ++ per i microcontrollori offre un sottoinsieme limitato di C ++.) Come ho detto, a seconda della piattaforma potrebbe essere disponibile una vasta libreria di funzioni che potrebbero farvi risparmiare un po 'di tempo di sviluppo. Vale la pena prenderti del tempo per studiarlo, potrebbe farti risparmiare molto tempo in seguito se sai cosa è disponibile.


Ho scritto giochi per l'Atari 2600, che è una piattaforma piuttosto limitata; il mio primo gioco pubblicato era essenzialmente un codice 4K (dato che avevo un carrello da 32K, ho aggiunto alcuni extra extra, ma la versione 4K era interamente giocabile); La RAM è di 128 byte. Trovo interessante contemplare che nell'anno in cui ho scritto quel gioco (2005), sono stati pubblicati altri giochi che erano, letteralmente, milioni di volte più grandi.
supercat

@supercat - Sì, ma era prevedibile, nel 2005 l'Atari 2600 aveva già 200 anni! Non ho mai giocato a giochi d'azione come gli FPS, ma quando guardo ciò che è necessario per giocarli, una GPU molto più potente della tua CPU, sia a livello di programmazione che elettrica, non posso fare a meno di scuotere la testa :-). Ho giocato a scacchi (Sargon) su un 16k TRS-80 IIRC. Il simulatore di volo di mio fratello non aveva bisogno di altro.
Stevenvh,

Non abbastanza di 200 anni. Ha debuttato nel 1977, quindi non era nemmeno 30. Mentre sono d'accordo sul fatto che è stato eoni fa in termini tecnologici, sono ancora sorpreso dal fatto che non c'è solo un aumento di cento hold, né un aumento di mille volte , ma un aumento di MILIONI di volte sia nella RAM che nella dimensione del codice. La velocità non ha avuto un tale incremento, dato che il 2600 era a 1,19 MHz e i sistemi più recenti sono solo nella gamma a basso GHz. Possono fare molto di più per ciclo rispetto ai 2600 (che potrebbero - e dovevano - generare 1/76 di una linea video per ciclo) ma non credo che siano 1.000.000 volte più veloci.
supercat

3

"programmazione hardware" può significare molte cose. Programmare un chip molto piccolo (si pensi a 10F200, 512 istruzioni, pochi byte di RAM) può essere quasi come progettare un circuito elettronico. Dall'altro lato, la programmazione di un grande microcontrollore Cortex (1 Mb FLASH, 64 kB di RAM) può essere molto simile alla programmazione PC / GUI, utilizzando un grande toolkit GUI. IMHO, un buon programmatore integrato / in tempo reale ha bisogno di competenze sia dal punto di vista dell'ingegnerizzazione del software sia dal punto di vista della progettazione del circuito. Per il più grande uC C ++ è una buona scelta linguistica, per quelli molto piccoli C potrebbe essere l'unica scelta. La conoscenza dell'assemblaggio può essere utile, ma non consiglierei di realizzare progetti seri interamente in assemblaggio.

Ho svolto un serio lavoro integrato con persone di entrambe le parti (SWI ed EE). In genere preferisco le persone SWI, purché abbiano una certa esperienza con la programmazione multi-thread.

La tua domanda sembra che tu voglia immergerti nella programmazione integrata. Certamente. Per gli aspetti di basso livello (interfacciamento delle periferiche nel chip e dell'hardware circostante) è necessario apprendere alcune nuove competenze, ma è solo un sacco di lavoro senza molti nuovi concetti. Per i livelli più alti dei tuoi progetti puoi attingere al tuo knwoledge esistente.


1

Per ogni metodo di libreria arduino che chiami c'è una grande quantità di codice C / C ++ che lo rende possibile, è semplicemente ben confezionato per essere usato come API. Dai un'occhiata al codice sorgente di arduino nella directory hardware / arduino / * e vedrai tutto il C / C ++ scritto per te che interagisce direttamente con i registri del microcontrollore AVR. Se il tuo obiettivo è imparare a scrivere cose come queste (direttamente per l'hardware), c'è molto da trattare. Se il tuo obiettivo è far funzionare qualcosa usando le loro librerie, allora potrebbe non esserci molto di cui parlare poiché la maggior parte del duro lavoro è fatto per te e le loro librerie e l'ambiente di sviluppo sono molto facili da usare.

Alcune regole pratiche, tuttavia, quando si lavora con dispositivi con risorse limitate che potrebbero applicarsi all'ambiente arduino o ad altri:

Sii consapevole di quanta memoria stai usando. Sia la dimensione del codice (che va alla memoria flash) sia l'utilizzo della RAM statica (costanti nel codice che saranno sempre presenti nella RAM). Direi che l'utilizzo della RAM statica è un po 'più importante all'inizio, poiché è facile da guardare. Non è raro che tu abbia solo 1000 byte con cui lavorare per il tuo stack, heap e costanti. Sii saggio su come lo spendi, quindi evita cose come lunghe matrici di numeri interi (4 byte ciascuno) quando saranno sufficienti byte o caratteri non firmati (1 byte ciascuno). Un'altra risposta qui si estende su alcuni altri punti importanti molto bene quindi mi fermo qui, ho principalmente voluto ottenere il punto attraverso che c'è un sacco di copertura se non si sta usando la libreria Arduino e scrivere i propri librerie C.


0

Per quanto riguarda la programmazione di microcontrollori vs OOP, non sono qualcosa di opposto. È vero che tutte le librerie dei fornitori sono in C semplice, ma tutte le piattaforme supportano anche C ++ OOP. Gli sviluppatori possono inoltre creare e compilare librerie di alto livello C ++ e firmware del dispositivo. Il buon esempio sono le librerie Arduino, create ufficialmente e dall'utente - principalmente classi C ++. Forse non tutti i vantaggi di OOP possono essere pienamente utilizzati in ambiente embedded, ma anche i noti vantaggi C ++ vs C sono validi anche qui.

Per quanto riguarda la mentalità e il pensiero, come notato in altre risposte, i microcontrollori sono piattaforme molto limitate dalle risorse (specialmente nella RAM, meno veloci) - cose come l'allocazione dinamica della memoria, le eccezioni C ++ sono generalmente escluse. Dato l'hardware giusto scelto, è facile adottare queste limitazioni e utilizzare altre tecniche (ampiamente utilizzate anche su altre piattaforme).

Dal mio punto di vista, la sfida più difficile potrebbe essere un'altra dimensione extra trovata nella programmazione integrata: i tempi. Questo perché di solito il software incorporato gestisce molto gli eventi in tempo reale, i protocolli strettamente temporizzati per guidare l'hardware periferico e l'attività generale stessa (questi sono alcuni parallelismi anche in altre piattaforme di "alto livello", come le applicazioni multi-thread).

Preparati a leggere molti fogli di dati quando ti occupi di nuovo hardware - Immagino che potrebbe essere correlato alla parte della domanda "mentalità" :) Sicuramente sarebbero necessarie alcune conoscenze EE e hardware.

Inoltre, vorrei notare che in questi giorni lo sviluppo di software embedded non richiede un linguaggio assembly. In effetti Java (BTW è OOP di default) è già qui e sta diventando più forte (almeno per qualche classe di dispositivi integrati, ad esempio dispositivi IoT, potrebbe avere un futuro molto luminoso).


In termini di preoccupazioni, coloro che si occupano della (ri) allocazione della memoria dinamica tendono ad essere un ostacolo maggiore all'OO tradizionale rispetto ai tempi .
Chris Stratton,

Forse hai ragione. Ma ci sono persone che hanno programmato negli anni 80-90 per il software in modalità reale MSDOS, con 64K di spazio RAM disponibile (segmento di memoria dati) e per loro era "naturale". Forse il PC MSDOS era un ambiente più "incorporato" di oggi STM32F4 :)
Flanker

L'STM32F4 in genere ha più memoria di programma sotto forma di flash, ma il PC è in genere dotato di molta più memoria RAM per archiviare oggetti di runtime mutabili. Mentre l'intera cosa del puntatore lontano forzata dall'indirizzamento segmentato è stata una seccatura, entrambi mancano di un vero MMU, e questo sarà ancora più preoccupante per il sistema con meno RAM, che è l'STM32F4. Anche i tempi di attività dei PC tendevano ad essere più brevi e i tassi di errore accettabili più alti.
Chris Stratton,
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.