Je code quelque chose en utilisant le contrôle direct de GPIO, il existe de bonnes ressources pour cela, comme http://elinux.org/RPi_Low-level_peripherals#GPIO_hardware_hacking ; le processus implique l'ouverture ("/ dev / mem"), puis une opération mmap mappe efficacement l'adresse physique souhaitée dans votre espace d'adressage virtuel. Ensuite, vous lisez la section 6 de ce http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf pour savoir comment les E / S sont contrôlées.
Pour passer à la fonction d'une broche (entrée, sortie ou diverses fonctions spéciales), vous devez modifier ces champs de 3 bits dans les registres d'E / S GPFSELx (000 = entrée, 001 = instance de sortie ennemi). Ces opérations de modification sont compilées en opérations avec une charge et un stockage ordinaires (par exemple, pour changer GPIO0 en entrée: * (regptr) & = ~ 7; qui se compile en quelque chose comme
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)
Le problème est le suivant: si une interruption se produit entre la charge et le stockage, et qu'un autre processus ou ISR modifie le même registre d'E / S, l'opération de stockage (basée sur une lecture périmée dans r2) inversera les effets de cette autre opération. La modification de ces registres d'E / S doit donc être effectuée avec une opération de lecture / modification / écriture atomique (verrouillée). Les exemples que j'ai vus n'utilisent pas une opération verrouillée.
Étant donné que ces registres d'E / S ne sont généralement modifiés que lors de la configuration de quelque chose, il est peu probable que des problèmes se produisent, mais «jamais» vaut toujours mieux que «peu probable». De plus, si vous avez une application où vous dénigrez des bits pour émuler une sortie à collecteur ouvert, cela (pour autant que je sache) implique de programmer la sortie sur 0, puis de la basculer entre la sortie (pour le bas) ou l'entrée ( pour off / high). Donc, dans ce cas, il y aurait des mods fréquents dans ces registres d'E / S, et des modifications dangereuses seraient beaucoup plus susceptibles de causer un problème.
Donc, il y a probablement un ARM `` comparer et définir '' ou une opération similaire qui peut être utilisée ici pour faire cela, quelqu'un peut-il m'indiquer cela et comment y arriver à partir du code C?
[Remarque, rien de spécial n'est nécessaire lorsque vous avez programmé une E / S en sortie et que vous la modifiez simplement de 0 à 1 ou vice versa; car il y a un registre d'E / S sur lequel vous écrivez, pour mettre les bits sélectionnés à 1 et un autre pour effacer les bits sélectionnés à 0. Aucune lecture / écriture n'est nécessaire pour cette opération, donc il n'y a aucun risque d'interruption].
/dev/mem
il semble que votre code soit du code de l'espace utilisateur. Je ne pense pas que dans un système d'exploitation moderne, il faut faire attention aux interruptions qui changent les valeurs des registres dans le code de l'espace utilisateur. Je crois que ce ne serait pas un problème, même dans le code de l'espace noyau, car Linux restaure tous les registres lorsque le gestionnaire d'interruption termine son travail.