Saya mengode sesuatu menggunakan kontrol langsung GPIO, ada beberapa sumber daya yang bagus untuk ini, seperti http://elinux.org/RPi_Low-level_peripherals#GPIO_hardware_hacking ; prosesnya melibatkan open ("/ dev / mem") dan kemudian operasi mmap secara efektif memetakan alamat fisik yang diinginkan ke dalam ruang alamat virtual Anda. Kemudian Anda membaca bagian 6 dari http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf ini untuk mengetahui bagaimana I / O dikontrol.
Untuk mengubah ke fungsi pin (input, atau output, atau berbagai fungsi khusus) Anda memodifikasi bidang 3-bit ini di register I / O GPFSELx (000 = input, 001 = output musuh contoh). Operasi modifikasi ini dikompilasi ke operasi dengan pemuatan dan penyimpanan biasa (mis. Untuk mengubah GPIO0 menjadi input: * (regptr) & = ~ 7; yang mengkompilasi ke sesuatu seperti
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)
Masalahnya adalah ini: jika terjadi interupsi antara beban dan penyimpanan, dan proses lain atau ISR memodifikasi register I / O yang sama, operasi penyimpanan (berdasarkan basi yang dibaca dalam r2) akan mengembalikan efek dari operasi lainnya. Jadi mengubah register I / O ini benar-benar perlu dilakukan dengan operasi baca / modifikasi / penulisan atom (terkunci). Contoh yang saya lihat tidak menggunakan operasi yang terkunci.
Karena register I / O ini umumnya diubah hanya ketika mengatur sesuatu, kecil kemungkinan masalah akan terjadi, tetapi 'tidak pernah' selalu lebih baik daripada 'tidak mungkin'. Juga, jika Anda memiliki aplikasi di mana Anda bit-bashing untuk meniru keluaran kolektor terbuka, maka (sejauh yang saya tahu) ini melibatkan pemrograman output ke 0 dan kemudian beralih antara output (untuk rendah) atau input ( untuk off / high). Jadi dalam hal ini akan sering ada mod untuk register I / O ini, dan modifikasi yang tidak aman akan jauh lebih mungkin menyebabkan masalah.
Jadi, mungkin ada 'bandingkan dan set' ARM atau operasi serupa yang dapat digunakan di sini untuk melakukan ini, adakah yang bisa mengarahkan saya ke sana, dan bagaimana membuat itu terjadi dari kode C?
[Catatan, tidak ada hal khusus yang diperlukan ketika Anda memprogram I / O sebagai output dan hanya mengubahnya dari 0 menjadi 1 atau sebaliknya; karena ada register I / O tempat Anda menulis, untuk mengatur bit yang dipilih menjadi 1 dan yang lain untuk menghapus bit yang dipilih menjadi 0. Tidak diperlukan baca / tulis untuk operasi ini, sehingga tidak ada bahaya dari interupsi].
/dev/mem
, sepertinya kode Anda adalah kode userspace. Saya tidak berpikir bahwa dalam OS modern kita harus berhati-hati tentang interupsi perubahan nilai register dalam kode userspace. Saya percaya bahwa ini tidak akan menjadi masalah bahkan dalam kode ruang kernel karena Linux mengembalikan semua register ketika interrupt handler menyelesaikan tugasnya.