Sto codificando qualcosa usando il controllo diretto di GPIO, ci sono alcune buone risorse in giro per questo, come http://elinux.org/RPi_Low-level_peripherals#GPIO_hardware_hacking ; il processo prevede open ("/ dev / mem") e quindi un'operazione mmap mappa in modo efficace l'indirizzo fisico desiderato nel tuo spazio di indirizzi virtuale. Quindi leggi la sezione 6 di questo http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf per scoprire come sono controllati gli I / O.
Per passare alla funzione di un pin (input, o output o varie funzioni speciali), modificare questi campi a 3 bit nei registri I / O GPFSELx (000 = input, 001 = output dell'istanza del nemico). Queste operazioni di modifica vengono compilate per operazioni con carico e archivio ordinari (ad esempio per modificare GPIO0 in input: * (regptr) & = ~ 7; che viene compilato in qualcosa di simile
ldr r2, [r3, #0] ; r = *ptr (load r2 from I/O register)
bic r2, r2, #7 ; r2 &= ~7
str r2, [r3, #0] ; *ptr = r2 (store r2 to I/O register)
Il problema è questo: se si verifica un interruzione tra il carico e l'archivio e un altro processo o ISR modifica lo stesso registro I / O, l'operazione di archiviazione (basata su una lettura non aggiornata in r2) ripristinerà gli effetti di quell'altra operazione. Pertanto, la modifica di questi registri I / O deve davvero essere eseguita con un'operazione di lettura / modifica / scrittura atomica (bloccata). Gli esempi che ho visto non usano un'operazione bloccata.
Poiché questi registri I / O vengono generalmente modificati solo durante l'impostazione, è improbabile che si verifichino problemi, ma "mai" è sempre meglio di "improbabile". Inoltre, se si dispone di un'applicazione in cui si sta basando i bit per emulare un output open collector, quindi (per quanto ne so), ciò comporta la programmazione dell'output su 0 e quindi il passaggio tra output (per basso) o input ( per spento / alto). Quindi in quel caso ci sarebbero frequenti modifiche a questi registri I / O e modifiche non sicure avrebbero molte più probabilità di causare un problema.
Quindi, probabilmente c'è un ARM "confronta e imposta" o un'operazione simile che può essere utilizzata qui per fare questo, qualcuno può indicarmi questo e come farlo accadere dal codice C?
[Nota, non è necessario nulla di speciale quando si è programmato un I / O come uscita e lo si sta semplicemente cambiando da 0 a 1 o viceversa; poiché è presente un registro I / O in cui si scrive, per impostare i bit selezionati su 1 e un altro per cancellare i bit selezionati su 0. Non è necessaria alcuna lettura / scrittura per questa operazione, quindi non vi sono rischi di interruzioni].
/dev/mem
sembra che il tuo codice sia il codice userpace. Non penso che in nessun sistema operativo moderno si debba fare attenzione agli interrupt che cambiano i valori dei registri nel codice dello spazio utente. Credo che questo non sarebbe un problema anche nel codice spaziale del kernel poiché Linux ripristina tutti i registri quando il gestore di interrupt termina il suo lavoro.