Tôi đang mã hóa thứ gì đó bằng cách sử dụng kiểm soát trực tiếp GPIO, có một số tài nguyên tốt xung quanh việc này, chẳng hạn như http://elinux.org/RPi_Low-level_perodesals#GPIO_hardware_hacking ; quá trình này bao gồm mở ("/ dev / mem") và sau đó thao tác mmap ánh xạ hiệu quả địa chỉ vật lý mong muốn vào không gian địa chỉ ảo của bạn. Sau đó, bạn đọc phần 6 của http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Perodesals.pdf để tìm hiểu về cách I / O được kiểm soát.
Để thay đổi chức năng của pin (đầu vào hoặc đầu ra hoặc các chức năng đặc biệt khác nhau), bạn sửa đổi các trường 3 bit này trong các thanh ghi I / O GPFSELx (000 = đầu vào, 001 = ví dụ kẻ thù đầu ra). Các hoạt động sửa đổi này được biên dịch thành các hoạt động với tải và lưu trữ thông thường (ví dụ: thay đổi GPIO0 thành đầu vào: * (regptr) & = ~ 7; sẽ biên dịch thành một cái gì đó như
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)
Vấn đề là ở đây: nếu xảy ra gián đoạn giữa tải và lưu trữ, và một quá trình khác hoặc ISR sửa đổi cùng một thanh ghi I / O, thì thao tác lưu trữ (dựa trên đọc cũ vào r2) sẽ hoàn nguyên các tác động của hoạt động khác đó. Vì vậy, việc thay đổi các thanh ghi I / O này thực sự cần phải thực hiện với thao tác đọc / sửa đổi / ghi nguyên tử (bị khóa). Các ví dụ tôi đã thấy không sử dụng thao tác bị khóa.
Vì các thanh ghi I / O này thường chỉ thay đổi khi thiết lập một cái gì đó, nên không có khả năng xảy ra sự cố, nhưng 'không bao giờ' luôn tốt hơn 'không thể xảy ra'. Ngoài ra, nếu bạn có một ứng dụng mà bạn đang bash bit để mô phỏng đầu ra của trình thu thập mở, thì (theo như tôi có thể nói) điều này liên quan đến việc lập trình đầu ra thành 0 và sau đó chuyển đổi giữa đầu ra (ở mức thấp) hoặc đầu vào ( cho tắt / cao). Vì vậy, trong trường hợp đó sẽ có các mod thường xuyên cho các thanh ghi I / O này và các sửa đổi không an toàn sẽ có nhiều khả năng gây ra sự cố.
Vì vậy, có thể có một hoạt động 'so sánh và thiết lập' ARM hoặc hoạt động tương tự có thể được sử dụng ở đây để làm điều này, bất cứ ai cũng có thể chỉ cho tôi điều đó và làm thế nào để điều đó xảy ra từ mã C?
[Lưu ý, không có gì đặc biệt là cần thiết khi bạn đã lập trình I / O làm đầu ra và chỉ thay đổi từ 0 thành 1 hoặc ngược lại; vì có một thanh ghi I / O mà bạn ghi vào, để đặt các bit được chọn thành 1 và một bit khác để xóa các bit đã chọn thành 0. Không cần đọc / ghi cho thao tác này, do đó không có nguy cơ bị gián đoạn].
/dev/mem
nên dường như mã của bạn là mã không gian người dùng. Tôi không nghĩ rằng trong bất kỳ hệ điều hành hiện đại nào, người ta phải cẩn thận về việc thay đổi giá trị đăng ký trong mã không gian người dùng. Tôi tin rằng đây sẽ không phải là vấn đề ngay cả trong mã không gian kernel vì Linux khôi phục tất cả các thanh ghi khi trình xử lý ngắt hoàn thành công việc của nó.