Tham khảo: https://lwn.net/Articles/532714/
Trong kernel Linux, mỗi GPIO trong hệ thống được biểu diễn bằng một số nguyên không dấu đơn giản. Thông thường, một bo mạch có hàng trăm chân GPIO.
GPIO phải được phân bổ trước khi sử dụng, mặc dù hiện tại việc này không được thực thi bắt buộc. Hàm phân bổ cơ bản là:
int phan_bo_gpio(unsigned int chan_gpio, const char *nhan);
Tham số chan_gpio chỉ định GPIO cần thiết, trong khi nhan gắn một chuỗi với nó, chuỗi này sẽ xuất hiện trong sysfs sau này. Quy ước thông thường áp dụng: mã trả về 0 cho biết thành công; nếu không, giá trị trả về sẽ là số lỗi âm.
GPIO có thể được trả lại hệ thống bằng cách:
void giai_phong_gpio(unsigned int chan_gpio);
Các hàm này có một số biến thể; phan_bo_gpio_don() có thể được sử dụng để đặt cấu hình ban đầu của GPIO, phan_bo_mang_gpio() có thể yêu cầu và cấu hình một tập hợp GPIO trong một lần gọi. Cũng có các phiên bản "được quản lý" (ví dụ devm_phan_bo_gpio()), có thể tự động xử lý việc dọn dẹp khi nhà phát triển quên.
Một số GPIO được sử dụng cho đầu ra, những GPIO khác cho đầu vào. Các GPIO được kết nối thích hợp có thể hoạt động ở bất kỳ chế độ nào, nhưng chỉ có một hướng hoạt động tại một thời điểm nhất định. Mã kernel phải thông báo cho lõi GPIO cách sử dụng đường dây; điều này được thực hiện thông qua các hàm này:
int dinh_huong_vao(unsigned int chan_gpio);
int dinh_huong_ra(unsigned int chan_gpio, int gia_tri);
Trong cả hai trường hợp, chan_gpio là số GPIO. Trong trường hợp đầu ra, giá trị của GPIO (0 hoặc 1) cũng phải được chỉ định; GPIO sẽ được đặt tương ứng như một phần của lệnh gọi. Đối với cả hai hàm, giá trị trả về cũng là 0 hoặc số lỗi âm. Hướng của GPIO (có chức năng thích hợp) có thể thay đổi bất cứ lúc nào.
Đối với GPIO đầu vào, giá trị hiện tại có thể được đọc bằng cách:
int doc_gia_tri_gpio(unsigned int chan_gpio);
Hàm này trả về giá trị của chan_gpio được cung cấp; nó không có quy định về mã lỗi trả về. Giả sử (trong hầu hết các trường hợp là đúng) rằng bất kỳ lỗi nào sẽ được phát hiện khi gọi dinh_huong_vao(), do đó việc kiểm tra giá trị trả về của hàm này rất quan trọng.
Việc đặt giá trị cho GPIO đầu ra luôn có thể được thực hiện bằng dinh_huong_ra(), tuy nhiên, nếu biết GPIO đã ở chế độ đầu ra, dat_gia_tri_gpio() có thể hiệu quả hơn:
void dat_gia_tri_gpio(unsigned int chan_gpio, int gia_tri);
Khi GPIO đầu vào thay đổi giá trị, một số bộ điều khiển GPIO có thể tạo ra ngắt. Trong trường hợp này, mã muốn xử lý các ngắt như vậy nên trước tiên xác định số IRQ được liên kết với đường GPIO nhất định:
int gpio_sang_irq(unsigned int chan_gpio);
GPIO đã cho phải được lấy qua phan_bo_gpio() và được đặt ở chế độ đầu vào trước. Nếu có số ngắt liên kết, nó sẽ được trả về dưới dạng giá trị trả về của gpio_sang_irq(); nếu không, sẽ trả về số lỗi âm. Sau khi có được theo cách này, số ngắt có thể được truyền cho request_irq() để thiết lập xử lý ngắt.
Cuối cùng, subsystem GPIO có thể biểu diễn các đường GPIO qua cấu trúc sysfs, cho phép không gian người dùng truy vấn (và có thể sửa đổi) chúng. Mã kernel có thể khiến một GPIO cụ thể xuất hiện trong sysfs:
int xuat_gpio(unsigned int chan_gpio, bool cho_phep_thay_doi_huong);
Tham số cho_phep_thay_doi_huong kiểm soát xem có cho phép không gian người dùng thay đổi hướng GPIO hay không; trong nhiều trường hợp, việc cho phép kiểm soát này có thể dẫn đến những điều tồi tệ cho toàn hệ thống. GPIO có thể được xóa khỏi sysfs bằng huy_xuat_gpio(), hoặc có thể sử dụng tao_lien_ket_xuat_gpio() để chỉ định một tên khác.
Đây là tổng quan về giao diện GPIO cấp thấp trong kernel. Nhiều chi tiết tự nhiên bị bỏ qua; để có giải thích chi tiết hơn, hãy tham khảo Documentation/gpio.txt. Phần API phía driver cấp thấp cũng bị bỏ qua, qua đó các đường GPIO có thể được cung cấp cho subsystem GPIO; việc bao gồm API này có thể là chủ đề của các bài viết trong tương lai. Tuy nhiên, phần tiếp theo sẽ khám phá một số lỗi được tìm thấy trong API trên và cách khắc phục chúng.