Già mi immagino i primi pensieri degli utenti che leggono il titolo del topic. No non voglio creare una libreria C tutti insieme e che sono curioso e vado curiosando nei sorgenti altrui e mi faccio tante troppe domande.
Il core Arduino usa un sistema per mappare i pin e automatizzare le cose, esempio se metto ad 1 un pin con il core questo automaticamente lo imposta come pin di output (non sono sicuro che funzioni così), tuttavia mappa i pin in memory flash che necessita di tempo per essere letta, l'alternativa e quella di usare la macro _BV e le macro DDRB, PORTB e PINB.
Tutti gli header descritti qui sono all'interno di avr-libc e sono tutti publici
Ma cosa sono queste macro?, cosa contengono? allora sono andato a guardare il file iom328p.h dove c'è la definizione di questa macro
#define PINB _SFR_IO8(0x03)
Ok altra domanda? ma cosè _SFR_IO8?
Io mi aspettavo fosse una funzione builtin di avr-gcc, invece è una macro definita in sfr_defs.h, allora vediamo sta macro:
#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)
#define _SFR_IO16(io_addr) ((io_addr) + __SFR_OFFSET)
Si vede che io_addr è un argomento nel caso di esempio è 0x03 + _SFR_OFFSET vale 0x20, sempre se __AVR_ARCH è minore di 100 come si vede da questo codice:
# if __AVR_ARCH__ >= 100
# define __SFR_OFFSET 0x00
# else
# define __SFR_OFFSET 0x20
# endif
Quindi questa macro non fa altro che sostituire ((0x03) + 0x20 quando io uso la macro PINB, quindi 0x23 è l'indirizzo di memoria a cui è mappata la porta B, in verità è l'indirizzo di memoria RAM in cui risiede il registro PINB (nome simbolico).
Ora supponiamo che io voglia mappare tutti i pin IO in modo efficiente, come posso fare?
So per certo che se passo un solo indirizzo si impiega meno tempo che passarne tanti (3 nel caso di DDRx, POTRx e PINx), quindi penso ad una struttura di 3 capi ed ognuno punta all'indirizzo di memoria. Ma in realtà mi viene che i campi della struttura risiedono in una porzione di memoria diversa da quella es 0x03, invece io voglio che ogni campo della struttura sia già la memoria all'indirizzo 0x03 e io non conosco alcun modo per farlo.
Se scrivo :
// DDRx, PORTx, PINx
#define GPIO_B0 &_SFR_IO8(0x04), &_SFR_IO8(0x05), &_SFR_IO8(0x03)
definisco una macro composta e con un solo nome (GPIO_XX) passo 3 parametri ad una funzione. Dal momento che questi dovrebbero essere indirizzi visto che c'è il dereferenziatore "&" non ci dovrebbe essere grande consumo di risorse, ma sono costretto a passare la stessa macro anche se poi la funzione usa solo uno dei parametri. Chissa se il compilatore ottimizza e non passa gli altri due argomenti visto che non li uso.
Ora vi starete chiedendo, ma cosa vuole mauro? niente, se avete qualcosa da dire in merito fate pure, magari ne esce qualcosa di interessante per qualcuno.
Ciao.