Physical computing ︰《三》 GPIO 溯源《中》

小王子‧IX

我想小王子大概是利用一群候鳥遷徙的機會跑出来的。在他出發的那天早上, 他把他的星球收拾得整整齊齊,把它上頭的活火山打掃得乾乾淨淨。── 他有两個活火山,早上熱早點很方便。他還有一座死火山,他也把它打掃乾淨。他想, 說不定它還會活動!打掃乾淨了,它們就可以慢慢地有規律的燃燒,而不會突 然爆發。火山爆發就像煙囪裡的火焰一樣。當然,在我們地球上我們人太小,不 能打掃火山,所以火山给我們帶來很多很多麻煩。

xwz23

小王子還把剩下的最後幾棵猴面包樹苗全拔了。他有點憂傷。他以為他再也 不會回来了。這天,這些家常活使他感到特别親切。當他最后一次澆花時,準備 把她好好珍藏起来。他發覺自己要哭出來。

“再見了。”他對花ㄦ說道。

可是花ㄦ没有回答他。

“再見了。”他又說了一遍。

花ㄦ咳嗽了一陣。但並不是由於感冒。

她终於對他說道:“我方才真蠢。請你原諒我。希望你能幸福。” 花ㄦ對他毫不抱怨,他感到很驚訝。他舉著罩子,不知所措地佇立在那裡。 他不明白她為什麼會這樣温柔恬静。“的確,我愛你。”花ㄦ對他說

xwz24

道:“但由於我的過錯,你一點也没有理會。 這絲毫不重要。不過,你也和我一樣的蠢。希望你今後能幸福。把罩子放在一邊 吧,我用不著它了。”

“要是風來了怎麽辦?”

“我的感冒並不那麽重……夜晚的凉風對我倒有好處。我是一朵花。”

“要是有蟲子野獸呢?……”

“我要是想認識蝴蝶,經不起两三隻尺蠖是不行的。據說這是很美的。不然 還有誰來看我呢?你就要到遠處去了。至於說大動物,我並不怕,我有爪子。”

於是,她天真地顯露出她那四根刺,隨後又說道:
“别這麼磨蹭了。真煩人!你既然决定離開這兒,那麽,快走吧!”

她是怕小王子看見她在哭。她是一朵非常驕傲的花……

 

─── 先生接著說︰【 其他 BCM-GPIO 】先在此忽略。

學生剛想開口問︰先生,五十四和十七差很多……,一陣風吹來,只見︰ X

附近的宇宙中,還有 325、326、327、328、329、330 等幾顆小行星。他就開始訪問這幾顆星球,想在那裡找點事幹,並且學習學習。……

祇聞那學生咳嗽了幾聲………

,怎知先生早已瞧見,講︰為什麼是五十四呢?既然從 0 到 54 不是五十五嗎??

學生︰★★★………

連『五四刪』都不知道,還敢一心以為鴻鵠將至的哩!!! ───

 

GPIO Sysfs Interface for Userspace
==================================

Platforms which use the “gpiolib” implementors framework may choose to configure a sysfs user interface to GPIOs. This is different from the debugfs interface, since it provides control over GPIO direction and value instead of just showing a gpio state summary. Plus, it could be present on production systems without debugging support. 【樹莓派上使用 sysfs

Given appropriate hardware documentation for the system, userspace could know for example that GPIO #23 controls the write protect line used to protect boot loader segments in flash memory. System upgrade procedures may need to temporarily remove that protection, first importing a GPIO, then changing its output state, then updating the code before re-enabling the write protection. In normal use, GPIO #23 would never be touched, and the kernel would have no need to know about it. 一般性與特殊性分開

Again depending on appropriate hardware documentation, on some systems userspace GPIO can be used to determine system configuration data that standard kernels won’t know about. And for some tasks, simple userspace GPIO drivers could be all that the system really needs. 【標準化和客製化別立

Note that standard kernel drivers exist for commonLEDs and Buttons” GPIO tasks: “leds-gpio” and “gpio_keys“, respectively. Use those instead of talking directly to the GPIOs; they integrate with kernel frameworks better than your userspace code could.通用性為上

Paths in Sysfs
————–
There are three kinds of entry入口】in /sys/class/gpio:

Control interfaces控制界面】used to get userspace control over GPIOs;

GPIOs晶片上的接腳】themselves; and

GPIO controllersGPIO 控制器】(“gpio_chip” instances).

That’s in addition to standard files including the “device” symlink.

The control interfacesGPIO 控制器】are write-only 【只寫】:

/sys/class/gpio/

export” 【導出】 … Userspace may ask the kernel to export control of a GPIO to userspace by writing its number to this file. 【在使用者空間建立晶片編號 GPIO□□ 接腳的控制特殊檔界面

Example: “echo 19 > export” will create a “gpio19” node for GPIO #19, if that’s not requested by kernel code. 不是核心已使用的

unexport” 【結束導出】… Reverses the effect of exporting to userspace. 【關閉在使用者空間已經開啟之晶片編號 GPIO□□ 接腳的控制特殊檔界面

Example: “echo 19 > unexport” will remove a “gpio19” node exported using the “export” file.

GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
and have the following read/write attributes讀寫屬性】:

/sys/class/gpio/gpioN/

direction” 【輸入或輸出】… reads as either “in” or “out“. This value may normally be written. Writing as “out” defaults to initializing the value as low. To ensure glitch free operation, values “low” and “high” may be written to configure the GPIO as an output with that initial value. Note that this attribute *will not exist* if the kernel doesn’t support changing the direction of a GPIO, or it was exported by kernel code that didn’t explicitly allow userspace to reconfigure this GPIO’s direction.

value” 【數位 0 與 1 之值】… reads as either 0 (low) or 1 (high). If the GPIO is configured as an output, this value may be written;
any nonzero value is treated as high.

If the pin can be configured as interrupt-generating interrupt
and if it has been configured to generate interrupts (see the description of “edge”), you can poll(2) on that file and poll(2) will return whenever the interrupt was triggered. If you use poll(2), set the events POLLPRI and POLLERR. If you use select(2), set the file descriptor in exceptfds. After poll(2) returns, either lseek(2) to the beginning of the sysfs file and read the new value or close the file and re-open it to read the value.

edge” 【上升或下降邊緣】… reads as either “none“, “rising“, “falling“, or “both“. Write these strings to select the signal edge(s)
that will make poll(2) on the “value” file return. This file exists only if the pin can be configured as an interrupt generating input pin.

active_low” 【負邏輯】… reads as either 0 (false) or 1 (true). Write
any nonzero value to invert the value attribute both for reading and writing. Existing and subsequent poll(2) support configuration via the edge attribute for “rising” and “falling” edges will follow this setting.

GPIO controllers have paths like /sys/class/gpio/gpiochip42/ (for the controller implementing GPIOs starting at #42) and have the following read-only attributes唯讀屬性】:

/sys/class/gpio/gpiochipN/

base” 【接腳基底】… same as N, the first GPIO managed by this chip

label“【晶片標籤】 … provided for diagnostics (not always unique)

ngpio” 【 GPIO 個數】… how many GPIOs this manges (N to N + ngpio – 1) Board documentation should in most cases cover what GPIOs are used for what purposes. However, those numbers are not always stable; GPIOs on a daughtercard might be different depending on the base board being used, or other cards in the stack. In such cases, you may need to use the gpiochip nodes (possibly in conjunction with schematics) to determine the correct GPIO number to use for a given signal.

Exporting from Kernel code
————————–
Kernel code can explicitly manage exports of GPIOs which have already been requested using gpio_request():

/* export the GPIO to userspace */
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);

/* reverse gpio_export() */
void gpiod_unexport(struct gpio_desc *desc);

/* create a sysfs link to an exported GPIO node */
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);

/* change the polarity of a GPIO node in sysfs */
int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);

After a kernel driver requests a GPIO, it may only be made available in the sysfs interface by gpiod_export(). The driver can control whether the signal direction may change. This helps drivers prevent userspace code from accidentally clobbering important system state.

This explicit exporting can help with debugging (by making some kinds of experiments easier), or can provide an always-there interface that’s suitable for documenting as part of a board support package.

After the GPIO has been exported, gpiod_export_link() allows creating symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can use this to provide the interface under their own device in sysfs with a descriptive name.

Drivers can use gpiod_sysfs_set_active_low() to hide GPIO line polarity differences between boards from user space. Polarity change can be done both before and after gpiod_export(), and previously enabled poll(2) support for either rising or falling edge will be reconfigured to follow this setting.

 

讓我們在此舉個簡單的例子,如何控制『樹莓派 B+』上的『電源 LED 』 PWR LED ── BCM-GPIO35 ──的呢?

pi@raspberrypi ~ $ sudo -s

root@raspberrypi:/home/pi# cd /sys/class/gpio/
root@raspberrypi:/sys/class/gpio# ls
export	gpiochip0  gpiochip250	unexport

# 控制 B+ PWR LED
root@raspberrypi:/sys/class/gpio# echo "35" > export 
root@raspberrypi:/sys/class/gpio# ls
export	gpio35	gpiochip0  gpiochip250	unexport

# 進入 export 的 gpio35 子目錄
root@raspberrypi:/sys/class/gpio# cd gpio35
root@raspberrypi:/sys/class/gpio/gpio35# ls
active_low  direction  edge  power  subsystem  uevent  value

# 設定為輸出 out
root@raspberrypi:/sys/class/gpio/gpio35# echo "out" > direction 

# PWR LED On
root@raspberrypi:/sys/class/gpio/gpio35# echo "1" > value 
# PWR LED Off
root@raspberrypi:/sys/class/gpio/gpio35# echo "0" > value 

# 離開  gpio35 子目錄,準備 unexport
root@raspberrypi:/sys/class/gpio/gpio35# cd ..
root@raspberrypi:/sys/class/gpio# echo "35" > unexport 
root@raspberrypi:/sys/class/gpio# ls
export	gpiochip0  gpiochip250	unexport
root@raspberrypi:/sys/class/gpio# exit
pi@raspberrypi ~ $

 

假使你知道『樹莓派 B+』上的『 ACT LED 』── SD 卡讀/寫燈號 ── 是用【 BCM-GPIO47 】.使用同樣的方式可以控制它嗎??