勇闖新世界︰ 《 Kernel 4.X 》之整裝蓄勢‧事件驅動 →→ 設備管理及應用

裝置驅動程式一向被認為是高深莫測的領域。或許是因為寫作的人需要了解作業系統、裝置硬體、界面規範、資料結構 …… 編譯環境建立以及編譯工具等等。洋洋灑灑五花八門,以至於繁雜生煩難,就難以掌握的了!讀者如果試著閱讀 notro 先生寫的

Examples on how to build various modules 

【Hello World example】

Classic Hello World example for a loadable kernel module (LKM).

# 建立來源檔目錄且進入該目錄

mkdir hello && cd hello

# 建立 Makefile 編譯描述檔,內容為

obj-m := hello.o

# 寫作 hello.c 裝置原始碼,內容是

#include <linux/module.h>
#include <linux/kernel.h>

int hello_init(void)
{
pr_alert(“Hello World :)\n”);
return 0;
}
void hello_exit(void)
{
pr_alert(“Goodbye World!\n”);
}
module_init(hello_init);
module_exit(hello_exit);

# 執行編譯

make -C /lib/modules/$(uname -r)/build  M=$(pwd) modules

# 將模組加入
sudo insmod hello.ko

# 檢查核心輸出訊息
dmesg | tail -1
[58728.008906] Hello World 🙂

# 把模組移除
sudo rmmod hello

# 檢查核心輸出訊息
dmesg | tail -1
[58732.440677] Goodbye World!

也許會覺得還好嘛!事實上程式就是程式,雖有領域與繁難之分,真的能有什麼其它不同的嗎!?比方說,

Adafruit 編譯的 PiTFT 核心版本上有一個『rpi_power_switch』︰

Extras!

Tactile switch as power button

Its a good idea to safely turn off your Pi with a good sudo shutdown -h now but that often means pulling out a keyboard or connecting to the console. With our kernel we added a cool module that will let you turn any GPIO into a power button. Since there’s a couple of tactile switches right there on the front, lets turn one into a power button. Press once to properly turn off the pi, press again to start it up. Isn’t that nice?

We’ll be using GPIO #23, the left-most button on a PiTFT 2.8″, on the 2.4″ HAT, #16 is a good choice since its on a tactile button. But, you can use any GPIO  you want, really!

You will have to grab a pack of slim tactile switches or otherwise solder in a button

Add rpi_power_switch to /etc/modules and save

Now create a new conf file or edit our existing one with

sudo nano /etc/modprobe.d/adafruit.conf

and enter in the line

options rpi_power_switch gpio_pin=23 mode=0

Of course, change the gpio_pin setting to some other # if you wish. mode=0 means its a pushbutton not a switch. If you happen to install an on/off switch, use mode=1

 

這個模組在樹莓派基金會官方版 raspbian 上面沒有,雖然講 notro 先生的範例上也有,但是編譯後恐安裝不起來。作者隨興瀏覽網路文章時,曾聞有些人滿鍾情於這個模組,何不略為說說,也算對『驅動程式實務』有點交代的吧!假使能夠激發讀者的興趣,將來為自己打開一扇門,誠所願矣!!

其實當用『rpi-source』取得原始碼時,模組的『編譯環境』就已經建立完成。所欠的只是『適當版本』 gcc/g++ 而已。目前『jessie』repo 上的 gcc 版本是 4.8.4 ,依據作者實測,沒有什麼問題。茲將 notro 先生安裝與設定方法移譯如下︰

※ 註︰ gcc/g++ 更新至 4.9

【建立 jessie 程式庫來源】

建立 apt-get 『jessie.list』之來源檔

sudo nano /etc/apt/sources.list.d/jessie.list

內容為一行
deb http://mirrordirector.raspbian.org/raspbian/ jessie main contrib non-free rpi

 

【安裝】

# 更新資料庫快取
sudo apt-get update

# 安裝
sudo apt-get install -y gcc-4.8 g++-4.8

# 當執行安裝設定,問到『重啟服務』時,回答『Yes』。

# Package configuration
# Configuring libc6:armhf
# Restart services during package upgrades without asking?
# <Yes>

※ 需補裝 ncurses-devel

sudo apt-get install libncurses5-dev

 

【gcc/g++ 多重選擇環境設定】

可用

sudo update-alternatives –config gcc

選擇所要的 gcc/g++ 編譯環境。

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 20
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.6 20
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50

 

如是就將『編輯工具』建制完成了。

pi@raspberrypi ~ gcc --version gcc (Raspbian 4.8.4-1) 4.8.4 Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  pi@raspberrypi ~ sudo update-alternatives --config gcc
替代項目 gcc(提供 /usr/bin/gcc)有 2 個選擇。

  選項       路徑            優先權  狀態
------------------------------------------------------------
* 0            /usr/bin/gcc-4.8   50        自動模式
  1            /usr/bin/gcc-4.6   20        手動模式
  2            /usr/bin/gcc-4.8   50        手動模式

按 [enter] 保留目前選項 [*],或輸入選項編號:
pi@raspberrypi ~ </pre>    <span style="color: #808000;">接著按照 notro 先生範例所言︰</span>  rpi_power_switch  Use an active low push button to turn the Raspberry Pi off and on. It does not actually turn the power off, but it halts Linux and restarts again. <pre class="lang:sh decode:true"> cd
git clone https://github.com/notro/fbtft_tools.git cd fbtft_tools/rpi_power_switch/

make make -C /lib/modules/3.12.18+/build M=/home/pi/fbtft_tools/rpi_power_switch modules make[1]: Entering directory `/home/pi/linux-b09a27249d61475e4423607f7632a5aa6e7b3a53'   CC [M]  /home/pi/fbtft_tools/rpi_power_switch/rpi_power_switch.o   Building modules, stage 2.   MODPOST 1 modules   CC      /home/pi/fbtft_tools/rpi_power_switch/rpi_power_switch.mod.o   LD [M]  /home/pi/fbtft_tools/rpi_power_switch/rpi_power_switch.ko make[1]: Leaving directory `/home/pi/linux-b09a27249d61475e4423607f7632a5aa6e7b3a53'  # 安裝位置有問題 sudo make install
make -C /lib/modules/3.12.18+/build M=/home/pi/fbtft_tools/rpi_power_switch modules_install
make[1]: Entering directory `/home/pi/linux-b09a27249d61475e4423607f7632a5aa6e7b3a53'
  INSTALL /home/pi/fbtft_tools/rpi_power_switch/rpi_power_switch.ko
  DEPMOD  3.12.18+
make[1]: Leaving directory `/home/pi/linux-b09a27249d61475e4423607f7632a5aa6e7b3a53'

 

先將 rpi_power_switch 模組編譯好。然後手動安裝

sudo cp rpi_power_switch.ko /lib/modules/4.1.4-v7+/kernel/drivers/power/

sudo depmod

 

這樣你就可以如前面 Adafruit PiTFT 文件所說的,將按鍵當成電源開關來使用。

sudo modprobe rpi_power_switch gpio_pin=17 mode=0

 

最後就讓我們再次回到『DS18B20』數位環境溫度感測器,當我們已經設定了『w1-gpio』的 dtoverlay ,也安裝了感測器,我們怎麼知道裝置正確工作了呢?也許可以用

pi@raspberrypi ~ dmesg | grep w1-gpio [    4.955057] w1-gpio onewire@0: gpio pin 4, external pullup pin -1, parasitic power 0 [    4.955143] w1_add_master_device: set_pullup requires write_byte or touch_bit, disabling</pre>    <span style="color: #808000;">來作初步確認。再用下面辦法『讀取溫度』作驗證</span> <pre class="lang:sh decode:true "># w1-gpio 裝置的『基底』 base 目錄 pi@raspberrypi ~ cd /sys/bus/w1/devices/

# 28-021463ab43ff 某個『DS18B20』數位環境溫度感測器
pi@raspberrypi /sys/bus/w1/devices ls 28-021463ab43ff  w1_bus_master1  # 裝置目錄 pi@raspberrypi /sys/bus/w1/devices cd 28-021463ab43ff
pi@raspberrypi /sys/bus/w1/devices/28-021463ab43ff ls driver  id  name  subsystem  uevent  w1_slave  # 讀取裝置名稱 pi@raspberrypi /sys/bus/w1/devices/28-021463ab43ff cat name
28-021463ab43ff

# 第一行的 YES 代表第二行溫度取得正確,若是 NO 代表溫度取得錯誤。
# 讀取溫度, t=35937 意味 35937/1000 = 35.937 °C
pi@raspberrypi /sys/bus/w1/devices/28-021463ab43ff $ cat w1_slave 
3f 02 55 00 7f ff 0c 10 89 : crc=89 YES
3f 02 55 00 7f ff 0c 10 89 t=35937

 

這個古怪的『類檔案裝置界面』顯然不怎麼對『使用者友善』 user friendly ,要是想一想所謂的『API』,指應用程式界面,原本就是設計給『程式』用的,自然就可以釋懷的了。即使是『程式』應用 ,『界面』也有使用上方便與否的問題,所以為『界面』再寫個易使用的『程式庫』,包裹成易記易讀的『新界面』也是常有的事。《 M♪o 之學習筆記本《巳》文章︰【䷡】藩決不羸》文本裡的 《W1ThermSensor》 就是這一類的『程式庫』。建議讀者閱讀它的『原始碼』《core.py》,思索設備『應用』以及『管理』方法,或將能夠對『程式實務』有更深的認識耶!