|
|
------------------
|
|
|
### Debug
|
|
|
|
|
|
Secondo me il modo migliore e fare una serie di macro in stile
|
|
|
|
|
|
```C++
|
|
|
#ifndef NDEBUG
|
|
|
#define DEB(x) x
|
|
|
#else
|
|
|
#define DEB(x)
|
|
|
#endif
|
|
|
```
|
|
|
|
|
|
da usare con `DEB(printf("..."))`
|
|
|
|
|
|
O comunque usare questo metodo per usare il logger (come scritto ieri su slack)
|
|
|
oppure per le assert. Tra l'altro son quasi sicuro che le assert non vengono
|
|
|
compilate se si usa -DNDEBUG.
|
|
|
|
|
|
Il problema di questo approccio e' che bisogna ricordarsi di non fare mai
|
|
|
init dentro le assert:
|
|
|
|
|
|
```C++
|
|
|
assert( init_blabla(...) == true ); // non viene invocata init_blabla
|
|
|
// se NDEBUG e' definito.
|
|
|
```
|
|
|
|
|
|
Per il logger, date un'occhiata [Log.cpp](https://the.al/share/_/pqyewIt6b4r.txt)
|
|
|
e [Log.h](https://the.al/share/_/pWoTjUhaN.txt)
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
1) 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.
|
|
|
|
|
|
2) 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
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
### Linter
|
|
|
|
|
|
Esiste un linter che vi dice se il codice scritto contiene alcuni problemi
|
|
|
comuni.. anche cose nostre personali tipo se è stato scritto "Matteo Piazzolla"
|
|
|
invece di "matteo michele piazzolla" :P
|
|
|
|
|
|
Il linter si trova in ./scripts/linter.sh e va lanciato usando come working
|
|
|
directory skyward-boardcore. Praticamente
|
|
|
|
|
|
```
|
|
|
cd skyward-boardcore
|
|
|
./scripts/linter.sh
|
|
|
```
|
|
|
|
|
|
Cose che controlla:
|
|
|
- Max 80 colonne
|
|
|
- Evitare tripli \n\n\n
|
|
|
- Files senza copyright
|
|
|
- Tab invece di spazi
|
|
|
- Matteo Michele Piazzolla
|
|
|
- Lancia cppcheck e controlla che non dia warning (ora ne da tanti, plz fixate)
|
|
|
- Non ci siano header files con using namespace.
|
|
|
|
|
|
Diciamo che è un software molto molto semplice, è una collezione di chiamate
|
|
|
a comandi bash. Quindi puo produrre falsi positivi.
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
### Lincenza
|
|
|
|
|
|
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.
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
### Come funziona sbs e cos'e config/
|
|
|
|
|
|
Per usare un progetto miosix (senza sbs e simili) serve prendere miosix/config
|
|
|
metterla nella root assieme al makefile, decommentare alcune cose e poi lanciare
|
|
|
'make'.
|
|
|
|
|
|
Ora, dato che il miosix che usiamo noi ha qualche modifica in più, in passato
|
|
|
avevamo anche modifiche alla cartella config/, e questa è stata messa nella
|
|
|
root del nostro progetto, ma senza decommentare una board in particolare.
|
|
|
|
|
|
Quello che fa sbs e di avere un Makefile.template, che è simile al Makefile
|
|
|
di miosix (della root), sostituire le cose giuste al posto giusto (usando
|
|
|
placeholders), mettere il makefile "compilato" dentro build e lanciarlo.
|
|
|
Questo per ogni "board" definita in sbs.
|
|
|
|
|
|
Ad oggi ci stiamo sempre più avvicinando ad usare miosix originale, quindi in
|
|
|
futuro si potrebbe pensare di non mettere piu li config/ ma usare
|
|
|
direttamente quella in libs/miosix-kernel/miosix/config.
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
### Cosa manca in miosix mainline?
|
|
|
|
|
|
(Se non erro) Manca solo da mettere in mainline il fatto che per ogni board
|
|
|
devo compilare i file oggetto in obj/$nomeboard/... e idem per i binari.
|
|
|
(mi sa che per i binari manca tutt'oggi, e infatti e per questo che ogni
|
|
|
volta che viene lanciato ./sbs -v anche con tutto compilato, si vede che fa
|
|
|
ancora un briciolo di lavoro).
|
|
|
|
|
|
Btw, il fatto che miosix mette obj/binari di board diverse dentro le stesse
|
|
|
cartelle mi fa aver paura di bug strani che possono accadere dove per
|
|
|
qualche errore (che spero non avvenga mai!) viene linkato un file compilato
|
|
|
per un'arch nel binario di un'altra arch. O comunque, stessa architettura
|
|
|
ma in un eseguibile ci son alcune "define" definite, in altri no. ecc.
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
### Cos'e --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)
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
### 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ì:
|
|
|
```C++
|
|
|
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
|
|
|
```C++
|
|
|
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 <nomebinario>: 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).
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
### Come usare clang-format
|
|
|
|
|
|
Se avete un plugin per il vostro ide tanto meglio, altrimenti potete lanciarlo
|
|
|
da command line con
|
|
|
`cat source.cpp | clang-format > source_figo.cpp`
|
|
|
oppure
|
|
|
`clang-format -i source.cpp`
|
|
|
oppure
|
|
|
`find src/ -iname "*.cpp" -exec clang-format -i "{}" \;`
|
|
|
(ocio a tenere 'src/' se no reindenta tutto miosix XD)
|
|
|
|
|
|
clang-format cerca un file chiamato '.clang-format' nella cartella attuale
|
|
|
o va a guardare tutte tutte le cartelle sopra. Se non lo trova, usa una config
|
|
|
di default che non mi piace (lo vedert subito perche usa 2 spazi e parentesi
|
|
|
in linea).
|
|
|
|
|
|
Ho visto che ogni tanto (non capisco il criterio) decide di indentare male
|
|
|
le enum belle allineate. Potete evitare che tocchi qualche zona di codice
|
|
|
mettendola fra
|
|
|
```
|
|
|
// clang-format off
|
|
|
...codice da non toccare
|
|
|
// clang-format on
|
|
|
```
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
### Altre info random:
|
|
|
|
|
|
src/shared è passata con -I al compilatore, questo significa che se volete
|
|
|
includere src/shared/Common.h, basta fare #include <Common.h>
|
|
|
|
|
|
*pr0tip*: Invece di includere in vari header files <miosix.h> <pthread.h> o quel
|
|
|
che volete, guardate se questi sono in src/shared/Common.h e includete quello :D
|
|
|
|
|
|
*pr0tip*: #pragma once non è standard e piace solo a piazzolla, se riuscite usate
|
|
|
le solite include guard #ifndef X #define X ..... #endif
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
### 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 boards/
|
|
|
- spiegare cpumeter/
|
|
|
- esempio di uso di activeobject e singleton?
|
|
|
- spiegare gotcha di singleton |
|
|
\ No newline at end of file |