Logger
Per il logger, date un'occhiata Log.cpp e Log.h.
Di pro rispetto a quello di gabriele c'è che non usa ostream, il quale ha un peso non indifferente sulla code size. L'idea sarebbe di riuscire a levare completamente iostream e amici dalla code base.
Altro pro del mio, si usa con la sintassi della printf, che personalmente trovo 100k volte più comoda degli operatori << e >>. (lo so, non si può fare l'overload per altre classi... si può sempre creare un metodo toString() :P)
Ultimo pro, LOG_DEBUG(), LOG_INFO(), ... son piu' veloce da scrivere rispetto a Logger::Logger::Antani<Antani::lol::blabla>().
Event scheduler
L'event scheduler è per driver o cose da temporizzare.
Alcune cose da ricordare a riguardo sono:
-
Chi esegue il codice quando scatta l'evento? Attualmente il codice viene eseguito (se non erro) nel thread dell'event scheduler.
- Questo implica che se il codice va il loop o ci mette troppo, tutti ne risentono. Un'alternativa potrebbe essere di usare un thread separato per ogni task. Ma anche qua troppi thread attivi potrebbero far danni.
- Una delle idee IMHO migliori sarebbe quella di fare in modo che ogni task ha una proprietà che specifica dove essere eseguito.
-
L'SPI/I2C/DMA è uno solo, facendo andare più event scheduler in parallelo la gestione dell'hw inizia ad essere più tricky. In teoria dei mutex ben piazzati sistemano tutto, ma in caso di stallo di uno si rischia il blocco di tutti. Diciamo che è fattibile ma bisogna pensarci un po' su.
SBS Fault Headers
Il generate fault header è perche volevamo dichiarare tutti i possibili fault counter in un file csv, con anche la descrizione da mostrare sul pc di terra. Poi da quelli generiamo il .h contenente la lista degli attuali. e.. a fare il lavoro 2 volte (ground e razzo) finiamo che ci dimentichiamo qualcosa e ci son inconsistenze
Cos'è --gen-faults di sbs? Cos'e data/fault.csv?
Per evitare inconsistenze, abbiamo fatto un csv con tutti i fault counters, descriizoni e altro (apribile tranquillamente con excel) e lanciando ./sbs -g, questo csv viene convertito in un header file che viene incluso nella cartella dei fault counter.
Durante la generazione il csv viene modificato; c'e 'Generated name' (colonna) che viene impostata e non viene piu toccata se è gia scritta, questo implica che se non vi piace un nome generato lo potete cambiare (todo: da verificare se ho fatto veramente cosi lol)
Licenza
C'è un po' una battaglia interna (:P) sulla licenza da usare. Io tutt'ora spingo per usare MIT in ogni nostro file, in modo che se in futuro questo codice potrà essere utile a noi o altri (per altri progetti, magari closed) potra essere usato senza problemi. Federico invece preferisce GPLv2.
GPL personalmente non mi piace perche è un cancro. Per intenderci, anche all'ESA prendono tanti software o sorgenti open dal web, ma appena leggono GPL, cestinano e sperano ce ne sia un altro.
Per ora il linter controlla che ci sia la licenza MIT, infatti si arrabbia sui files del driver i2c che (spero) presto verranno inseriti in miosix e tolti da lì.
Ditemi cosa ne pensate.
BusTemplate aka Il Demonio
(scusate la confusione, l'ultima volta che ho letto BusTemplate e stato 1 anno fa)
L'idea iniziale era di scrivere device driver usando la componibilità dei template, in modo da renderli riusabili se lo stesso componente viene collegato in una scheda diversa e magari attraverso i2c invece di spi.
Vediamo se riesco a spiegarmi velocemente con un esempio inventato..
Un driver viene inizializato così:
DriverMAX12345<ProtocolSPI<BusSPI<1,..>>> blaa;
dove DriverMax12345 chiama metodi WriteReg/ReadReg di ProtocolSPI e ProtocolSPI chiama metodi Write/Read di BusSPI1.
I pro di questo sistema è che se cambiamo scheda e un sensore MAX12345 viene collegato via i2c, non bisogna riscrivere tutto da zero ma basta fare DriverMAX12345<ProtocolI2C123<BusI2C<2,...>>> blaa;
(quando dico ProtocolSPI intendo anche il corrispettivo ProtocolI2C) ProtocolSPI è quello che si occupa dell'ordine con cui tirare su i pin/quali pin per fare scrittura/lettura + header o simili. Ad esempio ChipSelect::on(); scrivo; ChipSelect::Off();
Ora, questo design ci ha causato più problemi che altro. Provate a chiedere a silvano/teo_piaz per più dettagli perche non li ricordo tutti.
Un errore (+ soluzione) che ricordo è stato fatto (se non erro) è che ProtocolSPI si occupa di 2 cose:
- Ordine di Pin da muovere
- Differenze a livello di bit da mandare per read/write.
Nella pratica abbiamo trovato alcuni sensori che vogliono una sequenza di bit diversa (ad esempio (invento), tutti i sensori vogliono il primo bit a 1 per scrivere e 0 per leggere; il sensore X li vuole al contrario) vanificando completamente il 99% del codice di ProtocolSPI.
Ricordo anche che ci sono "inconsistenze" di nomi in ProtocolSPI, dove c'erano alcuni punti in cui si leggeva cose tipo
void Write()
{
blabla = yxyz;
Read(); // WTF?
blabla = abc;
}
Perchè non vanno messi using namespace nei .h
Semplicemente perchè includendo quei .h ti trovi cose non aspettate in ::
.
Qua è spiegato meglio: https://stackoverflow.com/questions/4872373/why-is-including-using-namespace-into-a-header-file-a-bad-idea-in-c
Se riuscite, evitate anche di usare using namespace nei .cpp Una cosa carina che ho visto fare in giro è:
void a()
{
namespace lol = std::qualcosa::antani::blabla;
lol::classe x;
std::vector<lol::...> xyz;
}
Un'overview di scripts/
Innanzitutto, questi script sono pensati per essere eseguiti avendo come working
directory la root del repo (aka lanciateli con ./scripts/qualcosa
e non
cd scripts && ./qualcosa
)
Lista:
- anakin.sh: flashare la anakin via seriale
- gen_fault_headers: (se non erro) chaimato da sbs --gen-qualcosa
- linter.sh: il mio migliore amico
- anakin_client_curses: un client ncurses per vedere i dati dei sensori che vengono mandati via seriale da anakin-test-dma
- start_openocd.sh: avvia openocd (da tenere in background)
- openocd-flash.sh : si connette a openocd (che e in background) usando gdb e pilota gdb per flashare e riavviare la scheda. un'ottima alternativa a tutto il boilerplate da fare che e scritto sulla wiki di miosix (scusate, sono pigro e non avevo voglia di rifare tutto ogni volta).
Serializzazione:
Anche qua c'e stata una litig.. discussione animata interna su cosa usare per serializzare classi, oggetti, ecc da mandare in ground station Io voto per flatbuffers teo_piaz per mavlink fede terraneo per cereal
- flatbuffers:
permette di definire struct in un linguaggio suo e da quello genera header
files e sorgenti per leggere e scrivere quelle struct.
- pro: pensato per campo videogames, sviluppato da google, usato da facebook messenger o simili; veloce e leggero.
- contro: non permette di imporre range di valori ammissibili per un campo. cioe`, se dichiaro che una var e int16, posso mettere tutto int16, non solo i numeri da 15 a 28, per dire.
- mavlink:
teo_piaz dovrebbe star facendo roba con questo. a che punto e`?
chiedeteglielo :)
- pro: usato per i droni e permette di specificare range
- contro: tutte le specifiche vanno fatte in XML.
- cereal:
serializza classi intere di C++
- pro: piu immediato da usare di altri
- contro: vincola a fare la parte che riceve della ground station in c++ (non penso ma.. ci son problemi se le due architetture son diverse?)
TODO:
- spiegare come son fatte le classi dei sensori
- spiegare math/
- spiegare cpumeter/
- spiegare gotcha di singleton