Pin Control trong Linux

1. Tổng quan

Trong các thiết bị Linux, có rất nhiều ngoại vi sử dụng các chân Pin để có thể hoạt động được. Với mỗi ngoại vi khác nhau lại yêu cầu cấu hình chân pin với các chức năng (mode) tương ứng khác khau.

Một chân pin có thể hoạt động ở các chức năng khác nhau: GPIO, I2C, SPI,…Tuy nhiên, tại mỗi thời điểm thì chỉ có mộtchức năng  được phép hoạt động.

Ví dụ: trên BeagleBone Black, mỗi chức năng của chân pin tương ứng với một mode hoạt động tương ứng

Kỹ thuật lập trình nhóm các chân của một vi điều kiển để đáp ứng các chức năng như trên được gọi là pin muxing

Ví dụ khi cần cấu hình một chân pin với chế độ GPIO, ta cần thực hiện các công việc như: request, map các thanh ghi, set các giá trị phù hợp cho thanh ghi,… Nhưng trong trường hợp chúng ta phải thiết lập 5 hay 10 chân với các chức năng khác nhau sẽ tiêu tốn rất nhiều thời gian

Chính vì vậy, Linux đã hỗ trợ giải quyết khó khăn trên thông qua hệ thống Subsystem là Pinctrl (Pin Control)

2.  Kiến trúc của Pin Control trong Linux

Hình ảnh trên mô tả chi tiết ngoại vi SPI sử dụng bus 0

  • SPI0 Driver: Điều khiển trực tiếp ngoại vi trên SoC, có thể cấu hình pins theo mong muốn
  • Pinctrl Core: là core của framework được cung cấp bởi Linux và cung cấp các APIs cho Driver sử dụng
  • Pinctrl Base: lấy cấu hình từ Device Tree để đăng kí chân pin với Pinctrl Core
  • Pinctrl BeagleBone: điều khiển Pin Control trong các thiết bị beagleBone, đăng kí các hàm callback đến Pinctrl để truy cập hardware
  • Debugfs: cung cấp interface để debug đến cho user space

Ưu điểm của kiến trúc:

  • Phần điều khiển ngoại vi tách biệt với việc tương tác với thanh ghi của ngoại vi nên có thể sử dụng ở các SoC khác nhau
  • Có các quy luật để tránh xung đột trong hệ thống: không cho phép nhiều driver điều khiển các chân pin giống nhau
  • Dễ dàng debug khi xảy ra lỗi

3. Pin Control Subsystem và Device Tree

Để có thể cấu hình các chức năng và sử dụng chức năng đó cho pin tương ứng, ta cần phải khai báo 2 node trong Device Tree:

  • Node khai báo cấu hình
  • Node khai báo chức năng

Khai báo cấu hình

Node khai báo cấu hình là node con của node pin control quản lý nó. Ví dụ đối với kiến trúc am335 trên beaglebone black, node pincontrol có tên là “am33xx_pinmux”

Nó được gán một label để định danh

Với mỗi Soc khác nhau thì việc khai báo cấu hình sẽ khác nhau. Để biết thêm chi tiết cấu hình với từng SoC cụ thể, ta có thể tham khảo: pinctrl – Documentation/devicetree/bindings/pinctrl – Linux source code (v6.6.3) – Bootlin

Ví dụ: cấu hình chức năng uart trên bus 0 trên beaglebone black

Trong source code của kernel cung cấp macro trong file header để có thể ghi các giá trị vào các thanh ghi cụ thể để cấu hình chức năng mong muốn

Với pa là offset thanh ghi cần ghi giá trị, cof là cấu hình thuộc tính của chân pin, mux là số thự tự mode của chân pin với chức năng tương ứng (tra trong bảng Header của SoC do nhà sản xuất cung cấp)

Thông thường các driver cũng sẽ define các macro đại diện cho địa chỉ của chân Pin

Khai báo chức năng

Sử dụng 2 thuộc tính pinctrl-names và pinctrl-<id>:

  • pinctrl-names đại diện cho các state
  • pinctrl-<id> trỏ đến node cấu hình state tương ứng

Mỗi state sẽ tương ứng với một ID với số nguyên bắt đầu từ 0 và tăng dần (tương tự như với chỉ số của mảng trong C, ta coi pinctrl-names chứa danh sách các phần tử tương ứng 1 chuỗi kí tự)

Xét ví dụ sau:

pinctrl-0 sẽ tương ứng với state đầu tiên trong pinctrl-names “default”, sau dấu phẩy sẽ là state thứ hai “sleep” tương ứng với pinctrl kế tiếp ( ở đây là pinctrl-1). Ta có thể liên tưởng tới các index của mảng trong C.

Khi SoC boot thành công, state được áp dụng tự động cho chân pin là “default”. Với vị dụ trên thì cấu hình được nằm trong node “cpsw_default”. Còn khi hệ thống muốn tiết kiệm năng lượng, cấu hình tương ứng với state “sleep” sẽ được áp dụng với chân pin.

Ngoài ra, mỗi chân pin có thể cấu hình được nhiều chức năng khác nhau ngoài default và sleep. Chúng ta có thể chuyển đổi giữa các mode đó thông qua driver

4. Cấu hình GPIO sử dụng Pin Control trên BeagleBone Black

Với beaglebone black, khi hệ thống được boot lên thành công, các chân pin sẽ sử dụng các chức năng mặc định do nhà sản xuất cung cấp:

Chúng ta cùng nhau cấu hình chân P9_17 thành chân GPIO để bật tắt LED

Tra trong bảng P9 Header của beaglebone black, ta thấy mode tương ứng với chức năng GPIO là mode 7 và địa chỉ tương ứng là 0x95c

Để cấu hình chức năng GPIO cho pin P9_17 ta cần khai báo trong devie tree các node sau:

  • Node khai báo cấu hình

Với macro AM335X_PIN_SPI0_CS0 tương ứng với địa chỉ 0x95c

  • Node khai báo chức năng

Sau đó, ta thực hiện reboot lại hệ thống, nếu thành công, chân P9_17 sẽ sử dụng cấu hình mặc định “default” là GPIO. Từ đó, ta có thể thực hiện việc bật tắt LED bằng cách sử dụng sysfs

Đầu tiên, ta thực hiện export GPIO pin 5 với hệ thống bằng cmd:

Tiếp đó, set output cho GPIO 5:

Cuối cùng, ta có thể tùy ý set mức logic cho GPIO5 để bật tắt LED

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top