Sto scrivendo un sistema operativo in tempo reale per microcontrollori in C ++ 11 - distortos . Attualmente sto pensando a un framework C ++ per varie periferiche. La periferica più elementare che mi piacerebbe avere ci sono i pin di input / output. Poiché tali pin di input / output possono essere incorporati nel chip o essere esterni (espansioni I2C, registri a scorrimento, ...) ho intenzione di implementare interfacce per loro con classi astratte pure.
Questi sono alcuni dei miei requisiti:
- alcuni pin possono essere solo ingressi e non dovrebbe essere possibile (facilmente) modificare la loro direzione - ad esempio se si modifica la direzione del pin collegato a pulsante a "output" si può danneggiare irreversibilmente il chip, il scheda o il dispositivo collegato all'altro lato del cavo;
- alcuni pin possono essere solo output e non dovrebbe essere possibile (facilmente) modificare la loro direzione - se si utilizza un registro a scorrimento HC595, questo può essere solo "output" e nient'altro;
- alcuni pin possono cambiare liberamente direzione: ciò è necessario se si desidera implementare il software I2C o il software 1-wire;
Inizialmente ho pensato di farlo in questo modo:
- La classe di interfaccia più semplice sarebbe
InputPin
- supporterebbe solo "la lettura" dello stato del pin. - La seconda classe di interfaccia sarebbe
OutputPin
- erediterà da InputPin (come puoi leggere il valore di pin configurato come output) e aggiungerai anche la possibilità di "scrivere" il valore. - Terza classe di interfacce -
InputOutputPin
erediterà daOutputPin
e fornirà anche una funzione per cambiare direzione.
Tale approccio ha una caratteristica molto bella che posso usare usare qualsiasi classe derivata in funzione che richiede una delle basi. Ma in realtà c'è una sostituzione che non è sempre corretta: usare InputOutputPin
in una funzione che richiede OutputPin
può essere un problema quando l'istanza di InputOutputPin
è attualmente configurata per essere un input ...
Ho provato a cercare su google per qualche ispirazione e sembra che non ci sia molto da usare. Il framework mbed di ARM ha 3 classi completamente non correlate (non vi è alcuna eredità) - una per "in", una per "out" e una per "in / out". La maggior parte del codice che ho trovato ha solo una classe che è per "in / out". In realtà ho trovato un articolo sullo stesso problema che sto affrontando: link . La soluzione presentata non soddisfa le mie esigenze: in un ambiente multi-thread l'operazione di modifica della direzione del pin non è così semplice e di solito richiede l'accesso esclusivo ai registri di configurazione (la modifica è un'operazione di lettura-modifica-scrittura) .
Non vorrei implementare alcuna soluzione in cui le funzioni potrebbero fallire (ad esempio, restituire i codici di errore quando l'operazione non è possibile) - questo complicherebbe davvero l'utilizzo.
Implementazione di un operatore di conversione del tipo - in modo che la conversione da InputOutputPin
a OutputPin
venga eseguita in una funzione che assicura anche che la direzione sia corretta - è soggetta a errori, poiché il riferimento a OutputPin
può essere memorizzato per un uso successivo e in quel momento la direzione potrebbe essere cambiata di nuovo.
Forse dovrei semplicemente semplificare la gerarchia - OutputPin
e InputOutputPin
erediteranno entrambi da InputPin
(questo sarebbe sempre corretto), quindi OutputPin
non sarebbe una base per InputOutputPin
. Questo perde un po 'della flessibilità, ma non sono sicuro che tale sostituzione sarebbe necessaria comunque.