教學

[常見問與答] 解決從序列埠登入到 Pi 3 的亂碼問題

2016-03-18 02:54:03 service

購買產品:PL2303HX USB轉TTL傳輸線PL2303HXD USB轉TTL傳輸線

raspberry-pi-3-login-via-uart-baud-rates-broken

剛拿到 Pi 3 如果安裝 2016-02-26-raspbian-jessie 的映像檔後想使用序列埠連線,會發現出現亂碼,該怎麼辦?

這是因為原本 Pi 3 內建的硬體 UART 被 BCM2837 SoC 拿去給 Bluetooth 晶片組使用,而原本的 UART 輸出腳位(GPIOs 14 & 15)改成用 mini-uart port。意思是原本硬體 UART 有獨立的 clock divisor,因此 baud rate 可以維持在 115200,可是 mini-uart 使用系統核心時脈,實際只能跑到 72000 左右的 baud rate,因此當使用 115200 的 baud rate 連線就會出現亂碼。

解決的方法為:
步驟一,增加一個 pi3-disable-bt-overlaydevice tree overlay。這個 overlay 會停用藍牙,並且將 UART0/ttyAMA0 再設定給 GPIOs 14 & 15。
建議將 image 寫入 SD 卡後就直接修改 /boot/config.txt,在檔案最後增加兩行。

force_turbo=1
dtoverlay=pi3-disable-bt

add-pi3-disable-bt-overlay-at-config-file

其中,force_turbo=1 是強制 CPU 的時脈維持 1.2GHz 的時脈。預設值為 0 時表示時脈為 ondemand,會隨著負載而調整。
dtoverlay=pi3-disable-bt 表示載入 pi3-disable-bt 這個 device tree overlay,將會停用藍牙並將 UART0/ttyAMA0 設定到 GPIOs 14 & 15 腳位。

其實做完步驟一以後就可以用 115200 的 baud rate 透過序列埠連線進 Pi 了。可是雖然載入 pi3-disable-bt-overlay,但藍牙的服務依然是開啟的,因此還是要進入系統將藍牙服務停掉。

$ sudo systemctl disable hciuart

最後,因為使用 force_turbo=1 這個設定,整個 SoC 溫度會很高,因此再更新系統(包括 firmware 和 dtb)後就可以把這個設定註解掉,重開機生效。

$ sudo apt-get update
$ sudo apt-get upgrade

connect-to-raspberry-pi-3-via-serial

更多資訊:

1. 要如何看 CPU 時脈?
可以用 cat 指令查看以下三個檔案如下,分別為最高時脈、目前時脈、最低時脈。

$ cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
$ cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq

2. 如何看目前的 Device Tree?
首先要安裝 device tree compiler

$ sudo apt-get install device-tree-compiler

再用 dtc 指令查看。

$ dtc -I fs /proc/device-tree

結果會像

/dts-v1/;

/ {
    model = "Raspberry Pi 3 Model B Rev 1.2";
    compatible = "brcm,bcm2710", "brcm,bcm2709";
    memreserve = <0x3b000000 0x4000000>;
    #address-cells = <0x1>;
    #size-cells = <0x1>;
    interrupt-parent = <0x1>;
...
    soc {
        compatible = "simple-bus";
        ranges = <0x7e000000 0x3f000000 0x1000000>;
        #address-cells = <0x1>;
        phandle = <0x27>;
        #size-cells = <0x1>;
        linux,phandle = <0x27>;
...
            uart0_pins {
                phandle = <0x34>;
                brcm,function = <0x4>;
                brcm,pins = <0xe 0xf>;
                brcm,pull = <0x0 0x2>;
                linux,phandle = <0x34>;
            };
            uart1_pins {
                phandle = <0xf>;
                brcm,function = <0x2>;
                brcm,pins = <0xe 0xf>;
                brcm,pull = <0x0 0x2>;
                linux,phandle = <0xf>;
            };
...

參考資料:
* CONFIG.TXT
* DEVICE TREES, OVERLAYS AND PARAMETERS
* Raspberry Pi Device Tree Overlays
* Raspberry Pi 3 UART Overlay Workaround
* Raspberry Pi 3 compatibility (BT disable & serial port remap fix)
* RPi Serial Connection
* Raspberry Pi Serial Communication: What, Why, and a Touch of How
* More on Raspberry Pi serial ports

Tagged in: Bluetoothconfig.txtcpu frequencydevice treedevice tree compilerdevice tree overlaydtcmini-uartpi3-disable-bt-overlayRaspberry Pi 3serialUART Read more...

[常見問與答] 如何看 Raspbian 的版本資訊?

2016-02-12 00:06:16 service

自從 Raspbian 從 Wheezy 升級到 Jessie 以後,許多系統性的設計都有所不同。那要如何看 Raspbian 的版本資訊呢?

1. uname -a 查詢 kernel 版本。

# 2015-05-05-raspbian-wheezy 
pi@raspberrypi ~ $ uname -a
Linux raspberrypi 3.18.11-v7+ #781 SMP PREEMPT Tue Apr 21 18:07:59 BST 2015 armv7l GNU/Linux
# 2016-02-03-raspbian-jessie
pi@raspberrypi:~ $ uname -a
Linux raspberrypi 4.1.17-v7+ #834 SMP Mon Feb 1 15:17:54 GMT 2016 armv7l GNU/Linux

 

2. /opt/vc/bin/vcgencmd version 查詢 firmware 版本。

# 2015-05-05-raspbian-wheezy 
pi@raspberrypi ~ $ /opt/vc/bin/vcgencmd version
Apr 21 2015 14:42:19 
Copyright (c) 2012 Broadcom
version 2d5ad04b63af4233440c3f7c8587108223201102 (clean) (release)
# 2016-02-03-raspbian-jessie
pi@raspberrypi:~ $ /opt/vc/bin/vcgencmd version
Feb  1 2016 17:51:17 
Copyright (c) 2012 Broadcom
version b3dc56931507f355d503ea69397778643f7a3dc3 (clean) (release)

 

3. strings /boot/start.elf | grep VC_BUILD_ID 查詢 firmware 版本。

# 2015-05-05-raspbian-wheezy 
pi@raspberrypi ~ $ strings /boot/start.elf | grep VC_BUILD_ID
VC_BUILD_ID_USER: dc4
VC_BUILD_ID_TIME: 14:42:19
VC_BUILD_ID_BRANCH: master
VC_BUILD_ID_TIME: Apr 21 2015
VC_BUILD_ID_HOSTNAME: dc4-XPS13-9333
VC_BUILD_ID_PLATFORM: raspberrypi_linux
VC_BUILD_ID_VERSION: 2d5ad04b63af4233440c3f7c8587108223201102 (clean)
# 2016-02-03-raspbian-jessie
pi@raspberrypi:~ $ strings /boot/start.elf | grep VC_BUILD_ID
VC_BUILD_ID_USER: dc4
VC_BUILD_ID_TIME: 17:51:17
VC_BUILD_ID_BRANCH: master
VC_BUILD_ID_TIME: Feb  1 2016
VC_BUILD_ID_HOSTNAME: dc4-XPS13-9333
VC_BUILD_ID_PLATFORM: raspberrypi_linux
VC_BUILD_ID_VERSION: b3dc56931507f355d503ea69397778643f7a3dc3 (clean)

 

4. cat /proc/version 查詢更完整的 kernel 資料。

# 2015-05-05-raspbian-wheezy 
pi@raspberrypi ~ $ cat /proc/version
Linux version 3.18.11-v7+ (dc4@dc4-XPS13-9333) (gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 - Linaro GCC 2014.03) ) #781 SMP PREEMPT Tue Apr 21 18:07:59 BST 2015
# 2016-02-03-raspbian-jessie
pi@raspberrypi:~ $ cat /proc/version
Linux version 4.1.17-v7+ (dc4@dc4-XPS13-9333) (gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 - Linaro GCC 2014.03) ) #834 SMP Mon Feb 1 15:17:54 GMT 2016

 

5. cat /etc/os-release 查詢 OS 版本資訊。

# 2015-05-05-raspbian-wheezy 
pi@raspberrypi ~ $ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 7 (wheezy)"
NAME="Raspbian GNU/Linux"
VERSION_ID="7"
VERSION="7 (wheezy)"
ID=raspbian
ID_LIKE=debian
ANSI_COLOR="1;31"
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
# 2016-02-03-raspbian-jessie
pi@raspberrypi:~ $ cat /etc/os-release 
PRETTY_NAME="Raspbian GNU/Linux 8 (jessie)"
NAME="Raspbian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"

 

6. cat /etc/issue 查詢 Linux distro 版本。

# 2015-05-05-raspbian-wheezy 
pi@raspberrypi ~ $ cat /etc/issue
Raspbian GNU/Linux 7 \n \l

# 2016-02-03-raspbian-jessie
pi@raspberrypi:~ $ cat /etc/issue
Raspbian GNU/Linux 8 \n \l

 

7. cat /etc/debian_version 查詢 Debian 版本編號。

# 2015-05-05-raspbian-wheezy 
pi@raspberrypi ~ $ cat /etc/debian_version
7.8
# 2016-02-03-raspbian-jessie
pi@raspberrypi:~ $ cat /etc/debian_version
8.0
Tagged in: firmwarekernelraspbianstart.elfversion版本 Read more...

[常見問與答] Raspbian Jessie版本差異?

2016-02-09 21:42:26 service

Raspbian 是最多人在 Raspberry Pi 上安裝的作業系統,也是 Raspberry Pi 基金會持續維護的版本。在 Raspberry Pi 官方網站的下載JessieJessie Lite 兩種選擇,這兩者有什麼差別呢?
Download-Raspbian-Jessie-and-Raspbian-Jessie-Lite

其實這兩者主要分別在於 Jessie Lite 沒有預設安裝 X-server 與相關的套件,因此無法用 startx 啟動視窗管理員。因為也沒有安裝 QtGTK+ 的函式庫,因此也無法執行相關的視窗程式。

比較 Jessie 和 Jessie Lite 這兩個映像檔的大小(2016-02-03),分別是 3.9G(Jessie) 和 1.4G(Jessie Lite)。
jessie-vs-jessie-lite-file-size

我們可以用 ncdu / 從根目錄開始比較目錄與檔案在磁碟的使用量。下圖左邊是 Jessie 右邊是 Jessie Lite。 /usr 目錄下主要放的是 shared library,例如 Jessie 有 libreoffice 和 libQtWebKit 等視窗應用程式函式庫。
jessie-vs-jessie-ncdu-root

也可以用 dpkg -l 列出已經安裝的套件列表,並用 dpkg -l|wc 統計安裝套件數目。左邊是 Jessie 約 1150 個,右邊是 Jessie Lite 約 411 個。
jessie-vs-jessie-lite-dpkg-list

再比較這兩個映像檔預設安裝套件,可以看到 Jessie Lite 少了 x11 和 xserver 相關套件。
meld-jessie-dpkg-list-vs-jessie-lite-dpkg-list

因為少了 X 與相關套件,因此 Jessie Lite 可以有更小的磁碟空間使用與更低的記憶體使用量。一般來說 Jessie 是適合個人桌面環境使用,而 Jessie Lite 適合安裝在伺服器上。

那要如何在 Jessie Lite 上安裝視窗環境呢? 只要用 sudo apt-get updatesudo apt-get install lxde 就可以將 LXDE 和相依的套件裝起來,大約會新裝 602 個套件共計 842MB。之後就可以用 startx 開始使用 GUI。
jessie-lite-install-lxde

另外,除了 Jessie Lite,還有一套針對單板電腦(Single-Board Computer)所優化過的系統 DietPi。DietPi 也做了一個比較表,列出與 Jessie Lite 不同的地方,是打造輕量級產品的另一個選擇。
DietPi-Jessie-vs-Raspbian-Jessie-Lite
圖片來源:Raspbian Jessie Lite now available

參考資料:
* Raspbian Jessie Lite now available
* 鳥哥的私房菜第二十三章、X Window 設定介紹
* Lightweight Debian: LXDE Desktop From Scratch

Tagged in: DietPijessieJessie Litelxderaspbianstartx Read more...

[常見問與答] Raspberry Pi Zero 網路解決方案

2015-12-12 07:36:52 service

由於 Raspberry Pi Zero 沒有內建乙太網路插槽,因此如何讓 Zero 可以上網需要額外安裝其他週邊,以下我們介紹幾種可能的方式。

1. (Ethernet)OTG + USB to RJ45 Converter

圖片來源:How to give an internet access to Raspberry Pi Zero

需要搭配的硬體如下:
- OTG Cable(支援 Micro USB)
- RJ45 to USB Converter(H1102NL 晶片)
- 網路線與數據機(或是路由器)

2. (Ethernet)OTG + USB to RJ45 Converter

圖片來源:How to give an internet access to Raspberry Pi Zero

需要搭配的硬體如下:
- OTG Cable(支援 Micro USB)
- RJ45 to USB Converter(SR9800 晶片)
- 網路線與數據機(或是路由器)

3. (Ethernet)Ethernet Module
zero-enc28j60
需要搭配的硬體如下:
- Ethernet Module(ENC28J60)
- 杜邦線母對母 x6
- 網路線與數據機(或是路由器)

4. (Tethering)OTG + Sharing Internet connections via USB

圖片來源:How to give an internet access to Raspberry Pi Zero

需要搭配的硬體如下:
- OTG Cable(支援 Micro USB)
- 智慧型手機資料傳輸線
- 可上網的智慧型手機

5. (WiFi)OTG + WiFi Dongle

圖片來源:How to give an internet access to Raspberry Pi Zero

- OTG Cable(支援 Micro USB)
- EDIMAX EW-7811Un 無線網卡(RTL8188CUS 晶片)

6. (WiFi)Hack WiFi Dongle
zero-hack-wifi-dongle
- EDIMAX EW-7811Un 無線網卡(RTL8188CUS 晶片)
- 單芯線 x4
* 注意:從 Micro USB 腳位直接接線到無線網卡將導致原本的 Micro USB 插槽無法同時讀取其他裝置

《速度測試》
我們使用 speedtest-cli,測速單位為 Mbit/s

Type Download Upload
OTG + USB to RJ45 Converter(H1102NL) Ethernet 19.37 2.16
OTG + USB to RJ45 Converter(SR9800) Ethernet 7.65 4.1
Ethernet Module(ENC28J60) Ethernet 3.67 3.1
OTG + WiFi Dongle(RTL8188CUS) WiFi 18.3 4.96
Hack WiFi Dongle(RTL8188CUS) WiFi 16.5 3.92

結論:
1. 想使用 Ethernet 上網,選擇 OTG + USB to RJ45 Converter(H1102NL) 方案。
2. 想使用 WiFi 上網,選擇 OTG + WiFi Dongle 方案。
3. 最好外接 USB Hub,一方面可提供穩定的電力,另一方面也能有更多的 USB 插槽可以使用。

參考資料:
* How to give an internet access to Raspberry Pi Zero
* Ethernet On Pi Zero – How To Put An Ethernet Port On Your Pi
* FIRST RASPBERRY PI ZERO HACK – PIGGY-BACK WIFI.

Tagged in: 7811UnENC28J60EthernetH1102NLOTGraspberry pi zeroRTL8188CUSspeedtest-cliSR9800TetheringUSB to RJ45 ConverterWiFi網路解決方案 Read more...

[常見問與答] Raspberry Pi 的工作溫度範圍?

2015-07-06 23:42:08 service

以下內容翻自於 geektopiaRPi FAQ

使用 BCM2835Raspberry Pi Model B,熱的來源主要從以下三個元件而來:
1. 電源輸入的穩壓器(voltage regulator)。
2. SoC BCM2835,包含了 ARM11 CPU、GPU 和 RAM。
3. LAN9512,是 USB 和 Ethernet 的控制器。

我們可以比較幾個情境。
* 閒置狀態(僅通電開機,沒有連接 Ethernet)
thermal raspberrypi idle
圖片來源:geektopia
BCM2835 平均溫度在 48.7°C。Voltage regulator 平均溫度在 49.9°C。LAN9512 溫度是三者最高的,平均溫度在 53.0°C。

* 網路傳輸狀態(Ethernet 以平均 40MBits/s 速度傳輸 20 分鐘後)
thermal raspberrypi samba
圖片來源:geektopia
LAN9512 溫度仍然是三者最高的,平均溫度在 59.2°C。

* 忙碌狀態(以 stress 程式對 CPU 進行壓力測試,使用率達 100%)
thermal raspberrypi stress.png
圖片來源:geektopia
LAN9512 溫度仍然是三者最高的,平均溫度在 60.6°C。

* 影片播放狀態(從隨身碟播放以 x264 視訊格式和 AC3 音訊格的 1080p 影片為例)
thermal raspberrypi video playback
圖片來源:geektopia
LAN9512 溫度仍然是三者最高的,平均溫度在 58.5°C。

結論:
1. LAN9512 溫度會比 voltage regulator 和 SoC 來的高。

2. 從以上幾張圖片的條件,我們可以知道 CPU 滿載或是檔案傳輸最容易讓溫度升高。並且在正常使用情況下(未超頻),各元件的最高溫度會是在 65°C 以下。

3. 而根據 RPi FAQ,LAN9512 的工作溫度範圍在 0°C 到 70°C,BCM2835 的工作溫度範圍在 -40°C 到 85°C。

The Raspberry Pi is built from commercial chips which are qualified to different temperature ranges; the LAN9512 is specified by the manufacturers being qualified from 0°C to 70°C, while the AP is qualified from -40°C to 85°C. You may well find that the board will work outside those temperatures, but we’re not qualifying the board itself to these extremes.

4. 根據實測,在 -78°C 的低溫下,Raspberry Pi 會停止反應。

圖片來源:geek

5. 除了使用紅外線測溫外,我們還可以使用 /opt/vc/bin/vcgencmd measure_temp 指令來查看 CPU 的溫度。
raspberry_pi_measure_cpu_temp

參考資料:
* Does the computer Raspberry Pi is heated? Study their operating temperatures
* RPi FAQ
* Raspberry Pi proven to be stable when submerged in liquid nitrogen
* Raspberry Pi model B Thermal Tests

Tagged in: BCM2835LAN9512Raspberry Pi Model Bstresstemperaturevoltage regulator Read more...

[常見問與答] Raspbian (2015-01-31) 在 Pi 2 的 RPi.GPIO 問題

2015-02-17 23:50:08 service

問題:
2015-01-31 釋出的 RaspbianPi 2 呼叫 RPi.GPIO 模組會出現 RuntimeError: This module can only be run on a Raspberry Pi! 錯誤訊息。

情境:
假設我們寫一個可以控制 LED 一明一滅的 python 程式。範例來自 用 Raspberry Pi 學 GPIO – 自己做遊戲機

線路圖如下:
led_blink_schematic

程式碼範如 led_blink.py

import RPi.GPIO as GPIO 
import time

LED_PIN = 12    
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN, GPIO.OUT)

try:
    while True:
        print("LED is on")
        GPIO.output(LED_PIN, GPIO.HIGH)
        time.sleep(1)
        print("LED is off")
        GPIO.output(LED_PIN, GPIO.LOW)
        time.sleep(1)

except KeyboardInterrupt:
    print "Exception: KeyboardInterrupt"

finally:
    GPIO.cleanup()    

如果在 Raspberry Pi 2 (2015-01-31 版本)執行這段程式碼會出現以下訊息:

pi@raspberrypi ~ $ sudo python led_blink.py
Traceback (most recent call last):
  File "led_blink.py", line 1, in 
    import RPi.GPIO as GPIO    
RuntimeError: This module can only be run on a Raspberry Pi!

看起來是沒有 RPi.GPIO 的模組。所以我們用 sudo pip install RPi.GPIO 指令安裝 RPi.GPIO 模組看看。

pi@raspberrypi ~ $  sudo pip install RPi.GPIO
Requirement already satisfied (use --upgrade to upgrade): RPi.GPIO in /usr/lib/python2.7/dist-packages
Cleaning up...

解答:
原來是要升級模組才行。我們要使用 sudo pip install --upgrade RPi.GPIO 指令。

pi@raspberrypi ~ $ sudo pip install --upgrade RPi.GPIO
Downloading/unpacking RPi.GPIO from https://pypi.python.org/packages/source/R/RPi.GPIO/RPi.GPIO-0.5.11.tar.gz#md5=9dc3dab6ce2b7ccb833a866efb392821
  Downloading RPi.GPIO-0.5.11.tar.gz
  Running setup.py egg_info for package RPi.GPIO
    
Installing collected packages: RPi.GPIO
  Found existing installation: RPi.GPIO 0.5.9
    Uninstalling RPi.GPIO:
      Successfully uninstalled RPi.GPIO
  Running setup.py install for RPi.GPIO
    building 'RPi.GPIO' extension
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/py_gpio.c -o build/temp.linux-armv7l-2.7/source/py_gpio.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/c_gpio.c -o build/temp.linux-armv7l-2.7/source/c_gpio.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/cpuinfo.c -o build/temp.linux-armv7l-2.7/source/cpuinfo.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/event_gpio.c -o build/temp.linux-armv7l-2.7/source/event_gpio.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/soft_pwm.c -o build/temp.linux-armv7l-2.7/source/soft_pwm.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/py_pwm.c -o build/temp.linux-armv7l-2.7/source/py_pwm.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/common.c -o build/temp.linux-armv7l-2.7/source/common.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/constants.c -o build/temp.linux-armv7l-2.7/source/constants.o
    gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro build/temp.linux-armv7l-2.7/source/py_gpio.o build/temp.linux-armv7l-2.7/source/c_gpio.o build/temp.linux-armv7l-2.7/source/cpuinfo.o build/temp.linux-armv7l-2.7/source/event_gpio.o build/temp.linux-armv7l-2.7/source/soft_pwm.o build/temp.linux-armv7l-2.7/source/py_pwm.o build/temp.linux-armv7l-2.7/source/common.o build/temp.linux-armv7l-2.7/source/constants.o -o build/lib.linux-armv7l-2.7/RPi/GPIO.so
    
Successfully installed RPi.GPIO
Cleaning up...

再次執行,沒問題了。

Read more...

[基礎] Raspberry Pi 用 3G 網卡(3G USB dongle)上網

2015-01-09 01:43:33 service

e1820_with_raspberry_pi_model_b_plus

本文章使用 Raspberry Pi Model B+,映像檔為 2014-12-24-wheezy-raspbian.img。使用的 3G 網卡為 Huawei E1820 3G 網卡。

現在的 3G/4G 網卡(或稱為 USB 數據機)大多同時有儲存設備和 USB 數據機的功能,其中儲存設備功能存放 MS Windows 的驅動程式,USB 數據機就是可撥號連線接取上網際網路。

如果是第一次將 3G 網卡插在安裝了 Windows 系統的電腦上,網卡將會以虛擬光碟機的模式掛載成儲存設備,並且自動安裝驅動程式。當完成安裝後就可用虛擬光碟機轉換工具(Virtual CD-ROM switching utility)或稱為模式轉換工具,正確轉換網卡為 USB 數據機。

如果要在 Raspberry Pi 上使用 3G/4G 網卡上網,要做的事就是安裝設定模式轉換工具與安裝設定撥號連線程式。步驟如下:
 
1. 確認硬體資訊。
當插上 E1820 時,可以看到系統可辨認成 HSPA modem。

pi@raspberrypi ~ $ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. 
... skip ...
Bus 001 Device 008: ID 12d1:1446 Huawei Technologies Co., Ltd. E1552/E1800/E173 (HSPA modem)
... skip ...

dmesg 查看時,可看到系統將網卡的儲存功能辨認成 scsi 介面的 CD-ROM(sr0)。

pi@raspberrypi ~ $ dmesg
... skip ...
[    7.062455] usb 1-1.4: new high-speed USB device number 6 using dwc_otg
[    7.195063] usb 1-1.4: New USB device found, idVendor=12d1, idProduct=1446
[    7.219562] usb 1-1.4: New USB device strings: Mfr=3, Product=2, SerialNumber=0
[    7.242348] usb 1-1.4: Product: HUAWEI Mobile
[    7.251156] usb 1-1.4: Manufacturer: Huawei Technologies
[    7.282719] usb-storage 1-1.4:1.0: USB Mass Storage device detected
[    7.309727] scsi0 : usb-storage 1-1.4:1.0
[    7.323198] usb-storage 1-1.4:1.1: USB Mass Storage device detected
[    7.351048] scsi1 : usb-storage 1-1.4:1.1
[    8.322907] scsi 0:0:0:0: CD-ROM            HUAWEI   Mass Storage     2.31 PQ: 0 ANSI: 2
[    8.363958] scsi 1:0:0:0: Direct-Access     HUAWEI   TF CARD Storage       PQ: 0 ANSI: 2
[    8.417357] sd 1:0:0:0: [sda] Attached SCSI removable disk
[    8.583801] sr0: scsi-1 drive
[    8.591172] cdrom: Uniform CD-ROM driver Revision: 3.20
[    8.681129] sr 0:0:0:0: Attached scsi generic sg0 type 5
[    8.698176] sr 0:0:0:0: Attached scsi CD-ROM sr0

e1820_dmesg_before_mode_switch
如果我們將 sr0 掛載起來,就可清楚的看到裡面所存放的檔案是 Windows 驅動程式。

pi@raspberrypi ~ $ ls -al /dev/disk/by-id/
total 0
drwxr-xr-x 2 root root 140 Dec 24 12:31 .
drwxr-xr-x 6 root root 120 Jan  1  1970 ..
lrwxrwxrwx 1 root root  13 Jan  1  1970 memstick-SU16G_0x27885644 -> ../../mmcblk0
lrwxrwxrwx 1 root root  15 Dec 24 12:28 memstick-SU16G_0x27885644-part1 -> ../../mmcblk0p1
lrwxrwxrwx 1 root root  15 Dec 24 12:28 memstick-SU16G_0x27885644-part2 -> ../../mmcblk0p2
lrwxrwxrwx 1 root root   9 Dec 24 12:38 usb-HUAWEI_Mass_Storage-0:0 -> ../../sr0
lrwxrwxrwx 1 root root   9 Dec 24 12:31 usb-HUAWEI_TF_CARD_Storage-0:0 -> ../../sda
pi@raspberrypi ~ $ sudo mount /dev/sr0 /mnt
mount: block device /dev/sr0 is write-protected, mounting read-only
pi@raspberrypi ~ $ ls -al /mnt/
total 586
dr-xr-xr-x  1 root root   2048 Nov 27  2012 .
drwxr-xr-x 22 root root   4096 Dec 21 11:09 ..
-r-xr-xr-x  1 root root 148320 Mar 14  2011 AutoRun.exe
-r-xr-xr-x  1 root root     45 Oct  1  2008 AUTORUN.INF
dr-xr-xr-x  1 root root   2048 Nov 27  2012 Mobile Partner
-r-xr-xr-x  1 root root 439926 Nov 15  2009 Startup.ico
-r-xr-xr-x  1 root root   1742 Nov 23  2012 SysConfig.dat

e1820_mount_device

 
2. 安裝與設定模式轉換工具。
安裝 usb-modeswitch 會將有相依性的 usb-modeswitch-data 一併安裝起來。

pi@raspberrypi ~ $ sudo apt-get install -y usb-modeswitch

e1820_install_usb_modeswitch

我們可以比較模式轉換前後的分別,這可幫助我們確認是否有成功轉換 3G 網卡成 USB 數據機。檢查方式是執行 ls /dev/tty*,在模式還沒有轉換前,可以看到最後兩項是 /dev/ttyAMA0/dev/ttyprintk
e1820_ls_tty_before_mode_switch

安裝完成後就要進行模式的設定,usb-modeswitch 需要和 udev 搭配。

udev 包含 user space daemon(udevd)和工具程式 udevinfo(或 udevadm),並可以讓使用者自訂規則存放於 /etc/udev/rules.d/ 下。有關 udev 可以看 wiki 的介紹。

udev 是 Linux kernel 2.6 系列的設備管理器。它主要的功能是管理 /dev 目錄底下的設備節點。它同時也是用來接替 devfs 及 hotplug 的功能,這意味著它要在添加/刪除硬件時處理 /dev 目錄以及所有用戶空間的行為,包括加載 firmware 時。

實際上 usb-modeswitchudev 的運作順序如下:

* /lib/udev/rules.d/40-usb_modeswitch.rules:udev 的規則文件,如果設備被識別(包括 Vendor ID 和 Product ID)就會啟動 usb_modeswitch。
* /lib/udev/usb_modeswitch: 執行 usb_modeswitch_dispatcher 的 script。
* /usr/sbin/usb_modeswitch_dispatcher:usb_modeswitch 的 wrapper,用 tcl 寫的,會根據所選擇的設備與設定實際執行 /usr/sbin/usb_modeswitch。
* /etc/usb_modeswitch.conf:全域的設定檔案,也可用於單一的設備設定資訊。
* /etc/usb_modeswitch.d:該文件夾包含了各別設備的獨立設定資訊,各別裝置的設定檔案是用設備的 ID 來命名。
* /usr/sbin/usb_modeswitch:實際轉換裝置模式的二進位程式。

因此我們要新增網卡設備的規則到 /lib/udev/rules.d/40-usb_modeswitch.rules

pi@raspberrypi ~ $ sudo vi /lib/udev/rules.d/40-usb_modeswitch.rules

在檔案最後加上兩行。

# E1820
ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1446", RUN+="usb_modeswitch '%b/%k'"

e1820_udev_config

其中 idVendor="12d1" 和 idProduct="1446" 這些資訊是由 lsusb 得到的。
e1820_lsusb_before_mode_switch

接著再將網卡要轉換的資訊加到 /etc/usb_modeswitch.conf 下。

pi@raspberrypi ~ $ sudo vi /etc/usb_modeswitch.conf

在檔案最後加上幾行。

DefaultVendor=0x12d1
DefaultProduct=0x1446

TargetVendor=0x12d1
TargetProduct=0x14ac

MessageContent="5553424312345678000000000000061e000000000000000000000000000000"

e1820_usb_modeswitch_config

DefaultVendor 和 DefaultProduct 也是剛剛 lsusb 的結果。但 TargetVendor 和 TargetProduct 就需要上網爬文,例如這裡有提供。

而將 EnableLogging=0 改為 EnableLogging=1 可在 /var/log 下查看 usb_modeswitch_** 的 log 方便除錯。

如果設定沒問題,重開機用 dmesg 就可以看到已經成功的將 USB 數據機(usb 1-1.4) 掛載到 ttyUSB0、ttyUSB1 和 ttyUSB2。

... skip ...
[    7.062368] usb 1-1.4: new high-speed USB device number 6 using dwc_otg
[    7.185037] usb 1-1.4: New USB device found, idVendor=12d1, idProduct=1446
[    7.208299] usb 1-1.4: New USB device strings: Mfr=3, Product=2, SerialNumber=0
[    7.230322] usb 1-1.4: Product: HUAWEI Mobile
[    7.250718] usb 1-1.4: Manufacturer: Huawei Technologies
[    7.273445] usb-storage 1-1.4:1.0: USB Mass Storage device detected
[    7.297764] scsi0 : usb-storage 1-1.4:1.0
[    7.313332] usb-storage 1-1.4:1.1: USB Mass Storage device detected
[    7.342617] scsi1 : usb-storage 1-1.4:1.1
[    8.315111] scsi 0:0:0:0: CD-ROM            HUAWEI   Mass Storage     2.31 PQ: 0 ANSI: 2
[    8.345229] scsi 1:0:0:0: Direct-Access     HUAWEI   TF CARD Storage       PQ: 0 ANSI: 2
[    8.373824] sd 1:0:0:0: [sda] Attached SCSI removable disk
[    9.630014] scsi 0:0:0:0: Attached scsi generic sg0 type 5
[    9.773321] sd 1:0:0:0: Attached scsi generic sg1 type 0
[    9.819475] sr0: scsi-1 drive
[    9.942382] cdrom: Uniform CD-ROM driver Revision: 3.20
[   10.122331] sr 0:0:0:0: Attached scsi CD-ROM sr0
[   11.142844] usb-storage 1-1.4:1.0: USB Mass Storage device detected
[   11.153861] usb 1-1.4: USB disconnect, device number 6
[   11.176368] scsi2 : usb-storage 1-1.4:1.0
[   11.208558] scsi 1:0:0:0: rejecting I/O to offline device
[   11.218302] scsi 1:0:0:0: killing request
[   15.762375] usb 1-1.4: new high-speed USB device number 7 using dwc_otg
[   15.885281] usb 1-1.4: New USB device found, idVendor=12d1, idProduct=14ac
[   15.906715] usb 1-1.4: New USB device strings: Mfr=4, Product=3, SerialNumber=0
[   15.929998] usb 1-1.4: Product: HUAWEI Mobile
[   15.959491] usb 1-1.4: Manufacturer: Huawei Technologies
[   15.999001] usb-storage 1-1.4:1.5: USB Mass Storage device detected
[   16.040642] scsi3 : usb-storage 1-1.4:1.5
[   16.057131] usb-storage 1-1.4:1.6: USB Mass Storage device detected
[   16.099706] scsi4 : usb-storage 1-1.4:1.6
[   16.366181] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
[   16.445601] usbcore: registered new interface driver cdc_ether
[   16.491873] usbcore: registered new interface driver usbserial
[   16.586318] usbcore: registered new interface driver usbserial_generic
[   16.617253] usbcore: registered new interface driver cdc_wdm
[   16.679164] usbserial: USB Serial support registered for generic
[   16.721907] qmi_wwan 1-1.4:1.1: cdc-wdm0: USB WDM device
[   16.751517] qmi_wwan 1-1.4:1.1 wwan0: register 'qmi_wwan' at usb-bcm2708_usb-1.4, WWAN/QMI device, a6:37:fd:d4:42:14
[   16.800868] usbcore: registered new interface driver qmi_wwan
[   16.830143] usbcore: registered new interface driver option
[   16.866417] usbserial: USB Serial support registered for GSM modem (1-port)
[   16.953166] option 1-1.4:1.0: GSM modem (1-port) converter detected
[   17.008423] usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB0
[   17.054788] scsi 3:0:0:0: CD-ROM            HUAWEI   Mass Storage     2.31 PQ: 0 ANSI: 2
[   17.095286] sr0: scsi-1 drive
[   17.113002] sr 3:0:0:0: Attached scsi CD-ROM sr0
[   17.113502] sr 3:0:0:0: Attached scsi generic sg0 type 5
[   17.134929] option 1-1.4:1.3: GSM modem (1-port) converter detected
[   17.155709] scsi 4:0:0:0: Direct-Access     HUAWEI   TF CARD Storage       PQ: 0 ANSI: 2
[   17.193722] sd 4:0:0:0: [sda] Attached SCSI removable disk
[   17.204968] sd 4:0:0:0: Attached scsi generic sg1 type 0
[   17.326895] usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB1
[   17.473045] option 1-1.4:1.4: GSM modem (1-port) converter detected
[   17.612898] usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB2
... skip ...

e1820_dmesg_after_mode_switch
 
ls /dev/tty* 也可看到最後長出了 /dev/ttyUSB0、/dev/ttyUSB1 和 /dev/ttyUSB2。

pi@raspberrypi ~ $ ls /dev/tty*

e1820_ls_tty_after_mode_switch

這時候我們用 lsusb 也可以發現讀到的硬體資訊改變了,包括 idProduct 和名稱都有變化。

pi@raspberrypi ~ $ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. 
... skip ...
Bus 001 Device 007: ID 12d1:14ac Huawei Technologies Co., Ltd. 
... skip ...

e1820_lsusb_after_mode_switch

 
3. 安裝與設定撥號程式。
安裝撥號程式 wvdial 會一同安裝 ppp

pi@raspberrypi ~ $ sudo apt-get install -y wvdial

e1820_install_wvdial
 
再來設定 wvdial.conf

pi@raspberrypi ~ $ sudo vi /etc/wvdial.conf

加上一個撥號的 profile。

[Dialer E1820]
Phone = *99#
APN = internet
Username = username
Password = password
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+CGDCONT=1, "IP","Internet"
Modem = /dev/ttyUSB0
Baud = 460800
Stupid Mode = 1

e1820_wvdial_config
其中
* [Dialer xxx]:profile 名稱,之後撥號就會以 xxx 為名,可設定多組 profile。
* Modem:wvdial 所用的數據機設備位置,預設為 /dev/modem。
* Baud:wvdial 和數據機所溝通的 baud rate。
* Stupid Mode:如果啟用 stupid mode,數據機在和終端伺服器(terminal server)溝通時將不會出現提示,並且當數據機連上後會立即啟動 pppd。

使用 wvdial 進行撥號連線,選擇 E1820 的 profile。

pi@raspberrypi ~ $ sudo wvdial E1820

在進行 pppd 連線過程中,會看到像是亂碼的符號,但如果連線成功會得到 IP 和 DNS 的位址。
e1820_wvdial
 
再用 ifconfig 查看網路介面資訊,可以發現多了一個 ppp0 的連線。
e1820_wvdial_ifconfig
 
開啟瀏覽器,確認可以連上網際網路。
browser_show_raspberry_pi_taiwan
 

常見問與答:

1. 如何測連線速度?
有關測網路的連線速度方法有很多,我們使用 speedtest-cli 這個用 python 寫的命令列測速套件,原始碼在 github。實際執行時,這個工具會連線到 speedtest.net 並測試上傳和下載的速度。

使用前需要先安裝相關的套件如下。

pi@raspberrypi ~ $ sudo apt-get install python-dev python-pip
pi@raspberrypi ~ $ sudo pip install speedtest-cli

執行 speedtest-cli

pi@raspberrypi ~ $ speedtest-cli
Retrieving speedtest.net configuration...
Retrieving speedtest.net server list...
Testing from Chunghwa Telecom Co., Ltd. (223.136.198.66)...
Hosted by Taiwan Fixed Network (New Taipei) [7.30 km]: 91.097 ms
Testing download speed........................................
Download: 2.48 Mbits/s
Testing upload speed..................................................
Upload: 1.41 Mbits/s

speedtest-cli 會根據使用者所在的位置,連線到最近的伺服器做測速。我們可以加上 --list 列出在台灣的伺服器列表。

pi@raspberrypi ~ $ speedtest-cli --list | grep Taiwan
2133) Taiwan Fixed Network (Taipei, Taiwan) [0.47 km]
2327) Far Eastone Telecommunications Co., Ltd. (Taipei, Taiwan) [0.47 km]
5008) Asia Pacific Telecom (Taipei, Taiwan) [0.47 km]
5661) NCIC Telcom (Taipei, Taiwan) [0.47 km]
2188) TFN Media Co., Ltd. (Taipei, Taiwan) [0.47 km]
3967) Chief Telecom (Taipei, Taiwan) [0.47 km]
5056) Taipei Fiber (Taipei, Taiwan) [0.47 km]
5660) NCIC Telcom (New Taipei, Taiwan) [9.09 km]
4505) Chief Telecom (New Taipei, Taiwan) [9.09 km]
5219) Taiwan Fixed Network (New Taipei, Taiwan) [9.09 km]
5067) Far Eastone Telecommunications Co., Ltd. (New Taipei, Taiwan) [9.09 km]
3921) Taiwan Fixed Network (Taoyuan, Taiwan) [31.66 km]
2589) Far EasTone Telecommunications Co., Ltd (Taoyuan, Taiwan) [31.66 km]
... skip ...

我們也可以指定伺服器做測試。只要在 speedtest-cli 後面加上伺服器的編號例如 --server 2133 就可以了。但我們實際測試時是沒有加上這個選項,而讓它自己選擇最近的伺服器。

2. 有其他網卡的設定可參考嗎?
以下是我們測過的幾張網卡的設定檔。

Huawei E220/Huawei E230
修改 /lib/udev/rules.d/40-usb_modeswitch.rules

ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1003", RUN+="usb_modeswitch '%b/%k'"

修改 /etc/usb_modeswitch.conf

DefaultVendor=0x12d1
DefaultProduct=0x1003
TargetVendor=0x12d1
TargetProductList="1001,1003,1406,140c,14ac"
MessageContent="55534243123456780000000000000011060000000000000000000000000000"

使用 speedtest-cli 的參考結果。
E230_speedtest_cli
 

Huawei E372
修改 /lib/udev/rules.d/40-usb_modeswitch.rules

ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1505", RUN+="usb_modeswitch '%b/%k'"

修改 /etc/usb_modeswitch.conf

DefaultVendor=  0x12d1
DefaultProduct= 0x1505
TargetVendor=   0x12d1
TargetProduct=  0x140c
TargetProductList="1001,1406,140b,140c,1412,141b,1433,14ac,1506,150f"
MessageContent="5553424312345678000000000000061e000000000000000000000000000000"

使用 speedtest-cli 的參考結果。
E372_speedtest_cli
 

Huawei E398u-1
修改 /lib/udev/rules.d/40-usb_modeswitch.rules

ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1505", RUN+="usb_modeswitch '%b/%k'"

修改 /etc/usb_modeswitch.conf

DefaultVendor=0x12d1
DefaultProduct=0x1505
TargetVendor=0x12d1
TargetProduct=0x1506
MessageContent="5553424312345678000000000000061e000000000000000000000000000000"

使用 speedtest-cli 的參考結果。
E398_speedtest_cli
E372 和 E398 的 idProduct 相同,只是因為 Huawei 沒有給每一個裝置都使用唯一的 idProduct。
 

3. 這錯誤訊息是什麼意思?

--> WvDial: Internet dialer version 1.61
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
OK
--> Sending: AT+CGDCONT=1, "IP","Internet"
AT+CGDCONT=1, "IP","Internet"
ERROR
--> Bad init string.
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
OK
--> Sending: AT+CGDCONT=1, "IP","Internet"
AT+CGDCONT=1, "IP","Internet"
ERROR
--> Bad init string.
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
OK
--> Sending: AT+CGDCONT=1, "IP","Internet"
AT+CGDCONT=1, "IP","Internet"
ERROR                                             
--> Bad init string.

會發生這樣錯誤訊息的可能性有很多種,比如說網卡和 /etc/usb_modeswitch.conf 不匹配,或是 wvdial.conf 連線設定有誤,有可能是 SIM 卡沒安裝或沒插好,也有可能是網卡壞掉,甚至有時候從 Model B 換到 Model B+ 就解決了。
 

4. 如果發現連線到一半容易斷線該怎麼辦?
這通常是供電不足造成的結果。如果使用好的電源還是會容易斷線的話,解決方法第一個可以先修改 /boot/config.txt 如下,讓 USB 的電流可以從 600mA 提升到 1200 mA。

max_usb_current=1

解決方法第二是接一個有獨立供電的 USB Hub,問題就會解決了。
 

參考資料:
* Huawei E220
* How to setup a USB 3G Modem on Raspberry PI using usb_modeswitch and wvdial
* Use 3g/UMTS USB Dongle for WAN connection
* USB_ModeSwitch – Handling Mode-Switching USB Devices on Linux
* usb_modeswitch_dispatcher
* usb_modeswitch(1) – Linux man page
* udev
* Device Reference
* Linux / Unix Command: wvdial.conf
* Huawei E372 mobile broadband
* TROUBLESHOOT HUAWEI E398 ON MANJARO LINUX
* How to check Internet Speed via Terminal?
* How to Test Internet Connection Speed using Speedtest-Cli on Ubuntu Server

Tagged in: 3G dongleE1820E220E230E398E398u-1Huaweispeedtest-cliudevusb_modeswitchwvdial Read more...

[基礎] 命令列設置無線網路

2014-09-21 13:41:18 service

本文章使用的映像檔為 2014-09-09-wheezy-raspbian.img
setting-up-wifi-with-the-command-line

一般設置 Raspberry Pi 的無線網路大多是透過 WiFi Config 這個應用程式做設定。
wifi-config-gui

但在某些情況,例如 從序列埠登入到 Raspberry Pi,就只能靠命列列設置無線網路。但是記得,做任何修改前要先備份原始設定,以免出錯了無法回復原始狀態。

用命令列設置無線網路的步驟如下:

1. 確認硬體資訊,我們使用 EDIMAX 7811Un 這張無線網卡做設定。建議使用的網卡有在清單中,才可隨插即用。

pi@raspberrypi ~ $ lsusb
Bus 001 Device 005: ID 7392:7811 Edimax Technology Co., Ltd EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS]

2. 查看目前無線網路設定,一開始還沒連接上無線網路,所以狀態會是 “unassociated”。

pi@raspberrypi ~ $  iwconfig wlan0
wlan0     unassociated  Nickname:""
          Mode:Managed  Frequency=2.412 GHz  Access Point: Not-Associated   
          Sensitivity:0/0  
          Retry:off   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality:0  Signal level:0  Noise level:0
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

3. 掃描無線網路,我們會根據掃描結果來設定無線網路。假設本例的 SSID 為 foo,加密方式為 WPA2,使用的 pre-shared key 為 1234567890123。

pi@raspberrypi ~ $ sudo iwlist wlan0 scan
wlan0     Scan completed :
          Cell 03 - Address: 40:4A:03:92:BA:4B
                    ESSID:"foo"
                    Protocol:IEEE 802.11bgn
                    Mode:Master
                    Frequency:2.462 GHz (Channel 11)
                    Encryption key:on
                    Bit Rates:144 Mb/s
                    Extra:rsn_ie=30140100000fac040100000fac040100000fac020c00
                    IE: IEEE 802.11i/WPA2 Version 1
                        Group Cipher : CCMP
                        Pairwise Ciphers (1) : CCMP
                        Authentication Suites (1) : PSK
                    Quality=88/100  Signal level=42/100  

4. 修改 /etc/wpa_supplicant/wpa_supplicant.conf

pi@raspberrypi:~$ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

所對應的設定檔如下。

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
        ssid="foo"
        psk="1234567890123"
        proto=RSN
        key_mgmt=WPA-PSK
        pairwise=CCMP
        auth_alg=OPEN
}

掃描結果與設定檔對應的欄位說明如下。

IE: IEEE 802.11i/WPA2 Version 1

表示加密方式為 WPA2,所對應的欄位 proto。
RSN:WPA(2)
WPA:WPA(1)

Group Cipher : CCMP 
Pairwise Ciphers (1) : CCMP

表示 WPA2 使用 AES 加密方式,所對應的欄位 pairwise。
CCMP:AES cipher,WPA(2)
TKIP:TKIP cipher,WPA(1)

Authentication Suites (1) : PSK

表示使用 pre-shared key 做鑑別,所對應的欄位為 key_mgmt。
WPA-PSK:Authentication via pre-shared key
WPA-EAP:Authentication via enterprise authentication server。

再例如使用 SSID 為 bar,加密的方式為 WEP,使用的 WEP key 為 1234567890123。

pi@raspberrypi ~ $  iwlist wlan0 scan
wlan0     Scan completed :
          Cell 03 - Address: 40:4A:03:92:BA:4B
                    ESSID:"bar"
                    Protocol:IEEE 802.11bg
                    Mode:Master
                    Frequency:2.437 GHz (Channel 6)
                    Encryption key:on
                    Bit Rates:54 Mb/s
                    Quality=72/100  Signal level=43/100  

所對應的設定檔如下。

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
        ssid="bar"
        key_mgmt=NONE
        auth_alg=OPEN
        wep_key0="1234567890123"
}

更多 wpa_supplicant.conf 的範例可參考這裡

5. 停用 wlan0 網卡。

pi@raspberrypi ~ $ sudo ifdown wlan0

6. 啟用 wlan0 網卡。

pi@raspberrypi ~ $ sudo ifup wlan0

可能會回傳以下訊息,我們忽略掉。

ioctl[SIOCSIWAP]: Operation not permitted
ioctl[SIOCSIWENCODEEXT]: Invalid argument
ioctl[SIOCSIWENCODEEXT]: Invalid argument

7. 將原來讀取 wpa_supplicant.conf 的程序 wpa_supplicant 殺掉。

pi@raspberrypi ~ $ sudo kill -9 $(ps -ef | grep wpa | awk '{print $2}')

8. 重新執行 wpa_supplicant,並讀取 wpa_supplicant.conf 設定。

pi@raspberrypi ~ $ sudo wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf

-B 表示以 daemon 方式在背景執行。
-i 表示指定介面(interface)名稱。
-c 表示設定檔路徑。

若回傳以下訊息,我們忽略掉。

rfkill: Cannot open RFKILL control device
ioctl[SIOCSIWAP]: Operation not permitted
ioctl[SIOCSIWENCODEEXT]: Invalid argument
ioctl[SIOCSIWENCODEEXT]: Invalid argument

9. 執行 DHCP 用戶端,取得 IP。

pi@raspberrypi ~ $ sudo dhclient

若回傳以下訊息,我們忽略掉。

RTNETLINK answers: File exists

10. 查尋 IP 位址,成功取得 192.168.1.117

pi@raspberrypi ~ $ ifconfig wlan0
wlan0     Link encap:Ethernet  HWaddr 74:da:38:05:68:4c  
          inet addr:192.168.1.117  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1158 errors:0 dropped:79 overruns:0 frame:0
          TX packets:53 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:109024 (106.4 KiB)  TX bytes:6214 (6.0 KiB)

 

常見問與答:

1. WiFi連不上怎麼辦?
接螢幕用 GUI 設定吧,可避免錯誤的設定。
wifi-config-gui-setting

2. WiFi Config的Adapter不見了怎麼辦?
wifi-config-gui-no-adapter
/etc/network/interfaces/etc/wpa_supplicant/wpa_supplicant.conf 回復成預設值吧。

##### Default configuration of /etc/network/interfaces #####
auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
##### Default configuration of /etc/wpa_supplicant/wpa_supplicant.conf #####
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
Tagged in: command lineWiFi Read more...

[基礎] 從序列埠登入到 Raspberry Pi

2014-09-16 15:56:08 service

購買產品:PL2303HX USB轉TTL傳輸線PL2303HXD USB轉TTL傳輸線

Raspberry Pi 有提供原生的序列(Serial)傳輸介面,因此只要透過 USB 轉 TTL 序列傳輸線,就可以在不需要螢幕和鍵盤滑鼠的情況下登入 Raspberry Pi (預設帳號密碼是 pi/raspberry),連上的虛擬終端機為 ttyAMA0。
序列傳輸介面至少需要有三條線,包括接地(GND)、接收(RX)和傳送(TX),參考接線圖如下。
connect-serial-to-raspberry-pi-model-b
connect-serial-to-raspberry-pi-model-b-plus本 Raspberry Pi B+ GPIO 腳位圖獲得授權使用

比較好的產品會有較多的連接線,例如做流量控制的 RTS/CTS 等。在不同作業系統使用的方式大同小異,詳細步驟如下。

注意:
1. 目前 PL2303HX 僅支援 Windows XP/Vista/7 和 Linux 使用,如果是 Windows 8 和 Mac 作業系統,需使用 PL2303HXD 才能正常使用。
2. 安裝 USB 轉 TTL 傳輸線設定時,Raspberry Pi 不需要開機。但是完成安裝後,記得要將 Raspberry Pi 開機,才能透過該序列傳輸線連接。

Windows XP
1. 沒有接上 USB 轉 TTL 序列傳輸線時的裝置管理員。
not-connect-to-serial

2. 接上 USB 轉 TTL 序列傳輸線時的裝置管理員,一開始會跳出”歡迎使用尋找新增硬體精靈”。我們先暫時忽略這訊息並下載驅動程式吧。
ask-for-insert-new-hardware

3. PL2303HXPL2303HXD 都是使用旺玖科技的晶片,官方網站驅動程式下載連結為:
http://www.prolific.com.tw/TW/ShowProduct.aspx?p_id=226&pcid=79
prolific-driver-download-url-windows

4. 下載後解壓縮執行 PL2303_Prolific_DriverInstaller_v1.8.0.exe,按照指示完成後重開機。再次開啟裝置管理員,可以發現多了一個連接埠 COM3。
connect-to-serial

5. 下載並開啟 putty。
putty-windows

6. 在 Connection type 先選擇 Serial,再根據剛剛的連接埠依序填入 Serial line、Speed的值。由於剛剛裝置管理員是看到 COM3,因此在 Serial line 也填入 COM3,Speed 填入 115200。
putty-serial-setting-windows

7. 相關的參數填完後,按 “Open” 就能連上 Raspberry Pi 如下圖。如果等了幾秒還是沒有畫面,可將 Raspberry Pi 重開(電源重插拔),應該就可以順利看到登入訊息。
successful-to-connect-to-raspberry-pi-via-serial-on-windows

Ubuntu Linux
1. 接上 USB 轉 TTL 序列傳輸線,打 ls /dev/ttyUSB*,在我們的環境是長在 ttyUSB0。
tty-usb0

2. 開啟 putty,如果還沒安裝請執行sudo apt-get install putty安裝。
putty-linux

3. 在 Connection type 先選擇 Serial,再根據剛剛的連接埠依序填入 Serial line、Speed的值。由於該節點是長在 ttyUSB0,因此在 Serial line 也填入 ttyUSB0,Speed 填入 115200。
putty-serial-setting-linux

4. 如果出現 Unable to open serial port 如下圖,改用 sudo 權限執行 putty。
putt_unable_to_open_serial_port

5. 相關的參數填完後,按 “Open” 將能連上 Raspberry Pi 如下圖。如果等了幾秒還是沒有畫面,可將 Raspberry Pi 重開(電源重插拔),應該就可以順利看到登入訊息。
successful-to-connect-to-raspberry-pi-via-serial-on-linux

Mac
1. 下載並安裝 PL2303HXD Driver,安裝後會重新開機。官方網站驅動程式下載連結為:
http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=229&pcid=41
prolific-driver-download-url-mac

2. 重開機生效。

3. 檢查是否出現裝置節點,打 ls /dev/cu*,如果出現 /dev/cu.usbserial,可以直接使用指令 screen /dev/cu.usbserial 115200 連線進去。

4. 如果沒出現 /dev/cu.usbserial,試著重插拔 USB 轉 TTL 傳輸線和重新插拔電源。

5. 如果使用 screen 後沒畫面出現,重新插拔電源試試看(USB 轉 TTL 傳輸線不要拔掉)。

常見問與答:

1. 我需要接紅色的線嗎?
如果將 USB 轉 TTL 傳輸線的紅色線接到 Pin 2,將會從傳輸線供電給 Pi 而讓 Pi 開機。由於我們已經有供給穩定的電源給 Pi,因此這邊我們不會將紅色線接到 Pin 2。

2. 我可以將序列埠的功能關掉嗎?
我們可以透過修改/boot/cmdline.txt,將

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

改為

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

還要再修改/etc/inittab,將

#Spawn a getty on Raspberry Pi serial line
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

改為

#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

再重開機即可。

Tagged in: pl2303hxpl2303hxdserialusb to serialUSB to TTL Read more...

[常見問與答] 如何在Raspberry Pi上擷取畫面?

2014-05-16 00:16:53 service

如果是在 X Window 下,最簡單的方式是安裝 shutter,但這有兩個缺點,就是 shutter 相依的套件太多,所以光是截圖這個小功能就需要安裝將近 90MB 的套件,並且執行起來很慢,但使用最容易。

步驟如下:
1. 先安裝必要套件

pi@raspberrypi:~$ sudo apt-get install shutter

2. 從主要功能選單(main-menu)叫起來
shutter_shortcut
3. 執行區域性的截圖、或是全螢幕的截圖等功能
shutter_capture_window

如果覺的 shutter 不適合,還可以用 scrot + openbox,之後就可以按 PrtSc 直接做 snapshot。有關 scrot 的使用方式可以參考這篇

步驟如下:
1. 先安裝必要套件

pi@raspberrypi:~$ sudo apt-get install scrot

2. 增加按鍵的繫結(key binding),將 keybind 的定義放在 <keyboard> 和 </keyboard> 之間

pi@raspberrypi:~$ vi ~/.config/openbox/lxde-rc.xml
  <keybind key="Print">
      <action name="Execute">
          <command>scrot</command>
      </action>
  </keybind>

3. 進到桌面環境下,按 PrtSc 做 snapshot,擷取畫面的預設路徑是放在家目錄 (/home/pi) 下。
xwindow

 

如果是在 console 底下 可以透過 cat /dev/fb0 > snapshot.rawframebuffer 的資料轉存為 RGB565 的 raw 檔。但如果要用 Eye 等看圖軟體讀取,就需要將 raw 檔透過 FFmpeg 等軟體先轉為 PNG 或是 BMP 等格式。

幸運的是,我們也可以透過 vc_dispmanx_snapshot 這個函式取得目前螢幕的狀態。
Andrew Duncan 已經寫成成執行檔,下載後編譯就可以在 console 底下隨時擷取螢幕畫面。

步驟如下:
1. 先安裝必要套件

pi@raspberrypi:~$ sudo apt-get install libpng12-dev

2. 下載原始碼

pi@raspberrypi:~$ git clone https://github.com/AndrewFromMelbourne/raspi2png.git

3. 編譯

pi@raspberrypi:~$ cd raspi2png
pi@raspberrypi:~$ make

4. 使用,不加任何參數時預設是存成 png 格式的檔案

pi@raspberrypi:~$ ./raspi2png

console

可用的參數有以下幾種,當然這指令也可以在X Window下執行。

--pngname - 抓圖後的存檔名稱(預設是 snapshot.png )
--verbose - 顯示完整資訊
--height - 圖片高度(預設是螢幕的高度)
--width - 圖片寬度(預設是螢幕的寬度)
--type - 圖片的色彩格式,可用的格式為 RGB565 RGB888 RGBA16 RGBA32
--delay - 多久後擷取(預設是0,立刻執行)

最後,我們最喜歡用的其實是同一個作者的 fb2png。這程式可以讀取 framebuffer 並直接儲存成 png 格式的檔案。

步驟如下:
1. 先安裝必要套件

pi@raspberrypi:~$ sudo apt-get install libpng12-dev

2. 下載原始碼

pi@raspberrypi:~$ git clone https://github.com/AndrewFromMelbourne/fb2png.git

3. 編譯

pi@raspberrypi:~$ cd fb2png
pi@raspberrypi:~$ make

4. 使用

pi@raspberrypi:~$ ./fb2png

最後比較一下 raspi2png 和 fb2png,底下是相同時間的擷取結果,可以發現 raspi2png 是根據 VideoCore API 的 vc_dispmanx_display_get_info 傳回螢幕解析度,因此雖我們已經將 framebuffer 的解析度調整成 800×600,但是因為我們用的螢幕解析度是 1280×800,因此最後還是抓下 1280×800 的截圖。
snapshot

而 fb2png 則是開啟 /dev/fb0 的裝置檔,並根據 fb_var_screeninfo 回傳 framebuffer 的 xres 和 yres,因此最後截圖結果會是 800×600 的解析度,比較符合我們想要的結果。
fb

Tagged in: consolefb2pngraspi2pngscreenshotshuttersnapshotx window Read more...

[基礎] 以 VNC 和 Raspberry Pi 連線

2014-04-21 00:33:28 service

VNC 是一種使用 RFB 協定的螢幕畫面分享及遠端操作軟體。由於 VNC 與作業系統無關,因此可跨平台使用。如果我們需要和 Pi 做有圖形介面的連線,VNC 是首選。

這裡簡介如何在 Pi 上安裝設定 VNC 伺服器,並透過個人電腦以 VNC 用戶端連線到 Pi。

1. 在 Pi 上安裝 VNC 伺服器。

pi@raspberrypi:~$ sudo apt-get install tightvncserver

2. 在個人電腦安裝 VNC 用戶端。

sosorry@ubuntu:~$ sudo apt-get install vncviewer gtkvncviewer

3. 在 Pi 上啟動 vncserver。

pi@raspberrypi:~$ vncserver

如果是第一次執行 vncserver 時會問幾個問題,包括登入的密碼和可供其他人流覽的 read-only 密碼,而 read-only 密碼可以不設定。登入的密碼會加密後存在 ~/.vnc/passwd 檔案裡。

You will require a password to access your desktops.

Password: 
Verify:   
Would you like to enter a view-only password (y/n)? n

之後我們就可以透過 vncviewer 或是 gtkvncviewer 之類的軟體和 Pi 連線了。假設 Pi 的 IP 為 192.168.1.2。

sosorry@ubuntu:~$ vncviewer 192.168.1.2:5901

tightvnc

如果要對 VNC 伺服器做更多設定,常用的參數有:
- 連線埠 (:$NUM):例如設定 :1 開啟的 port 為5901,:2 開啟的 port 為5902,依此類推,預設為 :1。
- 解析度(geometry):例如 640×480, 800×600, 1024×768 等,預設為 1024×768。
- 像素深度(depth):例如 8, 16, 24 等,這是指每個像素可顯示的位元數,預設為 16。

例如我們想設定 VNC 伺服器監聽 5902 這個埠號,當有用戶連線到 5902 後可開啟一個 640×480 BGR233的畫面。

pi@raspberrypi:~$ vncserver :2 -geometry 640x480 -depth 8

如果使用 gtkvncviewer 連線,需要輸入 IP、port 和密碼,使用者名稱可任意輸入。

sosorry@ubuntu:~$ gtkvncviewer

gtkvncviewer_setup

連線成功的畫面。
gtkvncviewer

 

常見問與答:

1. 如何修改 VNC 伺服器的連線密碼?
我們可以用 vncpasswd 這個指令改 VNC 的連線密碼。

Using password file /home/pi/.vnc/passwd
Password: 
Verify:   
Would you like to enter a view-only password (y/n)? n

 

2. 我忘了設定 VNC 伺服器聽哪一個 port 了?
我們可以用 netstat 這個指令來查看目前系統開啟的 port。

pi@raspberrypi:~$ netstat -nutlp

-n :列出數字形式的連線地址
-u :列出 UDP 的連線
-t :列出 TCP 的連線
-l :正在進行 Listen (監聽)的服務之網路狀態
-p :列出 PID 與 Program 的檔名

pi@raspberrypi:~$ netstat -nutlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:6002            0.0.0.0:*               LISTEN      2124/Xtightvnc  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               
tcp        0      0 0.0.0.0:5902            0.0.0.0:*               LISTEN      2124/Xtightvnc  
udp        0      0 0.0.0.0:22316           0.0.0.0:*                           -               
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -               
udp        0      0 192.168.1.2:123         0.0.0.0:*                           -               
udp        0      0 127.0.0.1:123           0.0.0.0:*                           -               
udp        0      0 0.0.0.0:123             0.0.0.0:*                           -

我們也可以用 ps 這個指令查看目前系統執行的程序中。

pi@raspberrypi:~$ ps aux | grep vnc

- a :不和終端機 (terminal) 有關的所有程序
- u :所有有效使用者 (effective user) 的程序
- x :與 a 這個參數一起使用可列出完整資訊
- | grep vnc 表示只列出有包含 vnc 關鍵字的程序

pi@raspberrypi:~$ ps aux | grep vnc
pi        2124  0.0  0.9   6532  3460 ?        S    14:36   0:03 Xtightvnc :2 -desktop X -auth /home/pi/.Xauthority -geometry 640x480 -depth 8 -rfbwait 120000 -rfbauth /home/pi/.vnc/passwd -rfbport 5902 -fp /usr/share/fonts/X11/misc/,/usr/share/fonts/X11/Type1/,/usr/share/fonts/X11/75dpi/,/usr/share/fonts/X11/100dpi/ -co /etc/X11/rgb
pi        2128  0.0  0.1   1760   508 ?        S    14:36   0:00 /bin/sh /home/pi/.vnc/xstartup
pi        2426  0.0  0.2   3548   800 pts/0    S+   15:44   0:00 grep --color=auto vnc

 

3. 如何在開機時就啟動 VNC 伺服器?
在 /etc/init.d/ 下建立一個控制的腳本 (script),例如取名為 tightvncserver

pi@raspberrypi:~$ sudo vim /etc/init.d/tightvncserver

內容如下,重要的是在 start) 部份設定啟動的參數。

#!/bin/bash
### BEGIN INIT INFO
# Provides:          tightvncserver
# Required-Start:    $syslog
# Required-Stop:     $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: vnc server
# Description:
### END INIT INFO

export USER='pi'

eval cd ~$USER

# Check the state of the command - this'll either be start or stop 
case "$1" in
  start)
    # if it's start, then start vncserver using the details below
    su $USER -c '/usr/bin/vncserver :1 -geometry 800x600 -depth 16 -pixelformat rgb565'
    echo "Starting vncserver for $USER "
    ;;
  stop)
    # if it's stop, then just kill the process
    pkill Xtightvnc
    echo "vncserver stopped"
    ;;
  *)
    echo "Usage: /etc/init.d/tightvncserver {start|stop}"
    exit 1
    ;;
esac
exit 0

修改腳本權限。

pi@raspberrypi ~ $ sudo chmod 755 /etc/init.d/tightvncserver

將該腳本加入預設的啟動程序。

pi@raspberrypi ~ $ sudo update-rc.d tightvncserver defaults

執行結果如下。

update-rc.d: using dependency based boot sequencing
insserv: warning: script 'mathkernel' missing LSB tags and overrides

如果不喜歡這 warning,就順便修改一下 mathkernel 的腳本吧。

pi@raspberrypi ~ $ sudo vim /etc/init.d/mathkernel

根據 LSB 的規則將啟動資訊加到最前面。

### BEGIN INIT INFO
# Provides:          mathkernel
# Required-Start:    $local_fs 
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5 
# Default-Stop:      0 1 6 
# Short-Description: mathkernel
### END INIT INFO

重新啟動 Pi,再執行 netstat -nutlp 或是 ps aux | grep vnc,可以看到 VNC 伺服器已經跑起來了。

Tagged in: accessvnc Read more...

[常見問與答] sudo: effective uid is not 0, is sudo installed setuid root?

2014-04-19 02:54:56 service

在某些情況下,sudo 會突然失靈,回傳錯誤訊息如: sudo: effective uid is not 0, is sudo installed setuid root?

解決方法如下:

1. 將 SD 卡接到其他電腦,在 /boot/cmdline.txt 最後面加上 single

2. 將 SD 卡插回 Raspberry Pi,重新啟動後將會進入 single user mode。

3. 將 /usr 的擁有者和群組改成 root,並修改全部權限為 rX 。

chown -R root:root /usr
chmod -R a+rX /usr

4. 更改 sudo 相關檔案的使用者和權限。

chown root:root /usr/lib/sudo/sudoers.so
chown -R root:root /etc/sudoers*
chmod 4755 /usr/bin/sudo

5. 測試。

su - pi
sudo
usage: sudo [-D level] -h | -K | -k | -V
usage: sudo -v [-AknS] [-D level] [-g groupname|#gid] [-p prompt] [-u user name|#uid]
usage: sudo -l[l] [-AknS] [-D level] [-g groupname|#gid] [-p prompt] [-U user name] [-u user name|#uid] [-g groupname|#gid] [command]
usage: sudo [-AbEHknPS] [-r role] [-t type] [-C fd] [-D level] [-g groupname|#gid] [-p prompt] [-u user name|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] []
usage: sudo -e [-AknS] [-r role] [-t type] [-C fd] [-D level] [-g groupname|#gid] [-p prompt] [-u user name|#uid] file ...

6. 將 single user mode 取消後重開機就大功告成了。

Tagged in: not workingsudo Read more...

[進階] 編譯 Raspberry Pi 的核心

2014-04-16 03:33:07 service

本文前言來自鳥哥的私房菜中的第二十六章、Linux 核心編譯與管理

核心是什麼?

其實核心就是系統上面的一個檔案而已,這個檔案包含了驅動主機各項硬體的偵測程式與驅動模組。

為什麼要編譯核心?

新功能的需求、原本核心太過臃腫、與硬體搭配的穩定性、其他需求(如嵌入式系統)。

 

這裡簡介編譯安裝 Raspberry Pi 的流程,未來我們還會常常回來看這篇。

1. 在個人電腦建構交叉編譯的環境,步驟可參考這裡

2. 查詢目前 Pi 的核心版本(以安裝2014-01-07-wheezy-raspbian.img 的映像檔為例,使用的核心版本為 3.10.25)。

pi@raspberrypi:~$ uname -a
Linux raspberrypi 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l GNU/Linux

3. 取得 Pi 的核心設定。

pi@raspberrypi:~$ zcat /proc/config.gz > .config

4. 在個人電腦下載核心原始碼。

sosorry@ubuntu:~$ cd rpi
sosorry@ubuntu:~/rpi$ git clone https://github.com/raspberrypi/linux.git
Initialized empty Git repository in /home/sosorry/linux/.git/
remote: Counting objects: 3512060, done.
remote: Compressing objects: 100% (586452/586452), done.
Receiving objects: 100% (3512060/3512060), 957.40 MiB | 3.18 MiB/s, done.
remote: Total 3512060 (delta 2897634), reused 3510306 (delta 2896207)
Resolving deltas: 100% (2897634/2897634), done.
Checking out files: 100% (43371/43371), done.

5. 切到目標分支。

sosorry@ubuntu:~/rpi$ cd linux
sosorry@ubuntu:~/rpi/linux$ git checkout rpi-3.10.y

6. 讀取目前 Pi 的核心設定,假設 Pi 的 IP 為 192.168.1.2。

sosorry@ubuntu:~/rpi/linux$ make mrproper
  CLEAN   scripts/basic
  CLEAN   scripts/kconfig
  CLEAN   include/config include/generated

sosorry@ubuntu:~/rpi/linux$ scp pi@192.168.1.2:/home/pi/.config .

sosorry@ubuntu:~/rpi/linux$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- oldconfig
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/zconf.lex.c
  SHIPPED scripts/kconfig/zconf.hash.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf --oldconfig Kconfig
*
* Restart config...
*
*
* ALSA for SoC audio support
*
ALSA for SoC audio support (SND_SOC) [M/n/?] m
  SoC Audio for the Atmel System-on-Chip (SND_ATMEL_SOC) [N/m/?] n
  SoC Audio support for the Broadcom BCM2708 I2S module (SND_BCM2708_SOC_I2S) [M/n/?] m
    Support for HifiBerry DAC (SND_BCM2708_SOC_HIFIBERRY_DAC) [M/n/?] m
    Support for HifiBerry Digi (SND_BCM2708_SOC_HIFIBERRY_DIGI) [N/m/?] (NEW) 
    Support for RPi-DAC (SND_BCM2708_SOC_RPI_DAC) [M/n/?] m
    Support for IQaudIO-DAC (SND_BCM2708_SOC_IQAUDIO_DAC) [N/m/?] (NEW) 
  Synopsys I2S Device Driver (SND_DESIGNWARE_I2S) [N/m/?] n
  Build all ASoC CODEC drivers (SND_SOC_ALL_CODECS) [N/m/?] n
  ASoC Simple sound card support (SND_SIMPLE_CARD) [N/m/?] n
#
# configuration written to .config
#

7. 以選單方式選取所需要的功能。

sosorry@ubuntu:~/rpi/linux$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

raspberry_pi_kernel_configuration

8. 編譯核心(k, –keep-going)。

sosorry@ubuntu:~/rpi/linux$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -k V=1

9. 安裝核心模組。

sosorry@ubuntu:~/rpi/linux$ mkdir ../modules
sosorry@ubuntu:~/rpi/linux$ make modules_install ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=../modules/

10. 使用內建的工具產生出 Raspberry Pi 的核心(kernel.img)。

sosorry@ubuntu:~/rip/linux$ cd ~/tools/mkimage
sosorry@ubuntu:~/rpi/tools/mkimage$ ./imagetool-uncompressed.py ~/rpi/linux/arch/arm/boot/zImage"

11. 將 kernel、firmware、lib 安裝到 Pi 上(假設 SD 卡已經 mount 在 ~/sdb1 和 ~/sdb2)。

sosorry@ubuntu:~/rpi/tools/mkimage$ sudo cp -Rf ~/rpi/modules/lib/firmware/ ~/sdb2/lib/
sosorry@ubuntu:~/rpi/tools/mkimage$ sudo cp -Rf ~/rpi/modules/lib/modules/ ~/sdb2/lib/

12. 移除 SD 卡,重新啟動 Pi,查詢核心版本,可以看到我們從 3.10.25 升級到 3.10.37。

pi@raspberrypi:~$ uname -a
Linux raspberrypi 3.10.37+ #1 PREEMPT Wed Apr 16 03:12:08 CST 2014 armv6l GNU/Linux

常見問與答:

1. 如果沒有 /proc/config.gz 怎麼辦?
請先執行 pi@raspberrypi:~$ sudo modprobe configs 就可以了
(感謝 Jimmy Chen 的貢獻)

RASPBERRY.ORG參考資料:
* KERNEL BUILDING
* CONFIGURING THE KERNEL
* PATCHING THE KERNEL

Tagged in: cross compilekernel Read more...

[進階] 安裝 Raspberry Pi 的 Toolchain

2014-04-16 01:05:10 service

Toolchain 是一套能讓你編譯、連結、除錯程式的軟體,例如 GCCLDGDBAS glibc 等。

假設我們寫了一個 hello.c 的程式要在個人電腦上執行,我們只要打 gcc hello.c 就可以將 hello.c 編譯成 x86 架構的可執行檔。

由於 Raspberry Pi 上的處理器是 ARM 架構的,因此要將同樣的 hello.c 在 Raspberry Pi 執行,必須將程式編譯成 ARM 架構的可執行檔。

我們有兩個選擇,第一是直接在 Raspberry Pi 上編譯。第二是先在我們的個人電腦用 Raspberry Pi 的 toolchain 編譯完成後,再上傳到 Pi。

這裡簡介如何在個人電腦安裝 Raspberry Pi 的 toolchain,以在 ubuntu 上安裝 gcc-linaro-arm-linux-gnueabihf-raspbian 為例。

1. 在個人電腦安裝必要的套件。

sosorry@ubuntu:~$ sudo apt-get install make git-core ncurses-dev

2. 下載最新版的 toolchain。

sosorry@ubuntu:~$ mkdir rpi
sosorry$ubuntu:~$ cd rpi
sosorry@ubuntu:~/rpi$ git clone https://github.com/raspberrypi/tools.git
remote: Reusing existing pack: 17273, done.
remote: Total 17273 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (17273/17273), 311.52 MiB | 343 KiB/s, done.
Resolving deltas: 100% (11698/11698), done.
Checking out files: 100% (15860/15860), done.

3. 安裝 toolchain。安裝方法是將 gcc-linaro-arm-linux-gnueabihf-raspbian 加到環境變數裡。

sosorry@ubuntu:~/rpi$ vi ~/.bashrc
export PATH=$PATH:/home/sosorry/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin   # add this line at the end of file

4. 測試。先開啟一個新的終端機,輸入 arm 後連續按兩次 tab 鍵,如果跑出來一堆像下面的提示表示安裝成功。

arm-linux-gnueabihf-addr2line        arm-linux-gnueabihf-gcc              arm-linux-gnueabihf-gfortran         arm-linux-gnueabihf-objdump
arm-linux-gnueabihf-ar               arm-linux-gnueabihf-gcc-4.7.2        arm-linux-gnueabihf-gprof            arm-linux-gnueabihf-pkg-config
arm-linux-gnueabihf-as               arm-linux-gnueabihf-gcc-ar           arm-linux-gnueabihf-ld               arm-linux-gnueabihf-pkg-config-real
arm-linux-gnueabihf-c++              arm-linux-gnueabihf-gcc-nm           arm-linux-gnueabihf-ld.bfd           arm-linux-gnueabihf-ranlib
arm-linux-gnueabihf-c++filt          arm-linux-gnueabihf-gcc-ranlib       arm-linux-gnueabihf-ldd              arm-linux-gnueabihf-readelf
arm-linux-gnueabihf-cpp              arm-linux-gnueabihf-gcov             arm-linux-gnueabihf-ld.gold          arm-linux-gnueabihf-size
arm-linux-gnueabihf-elfedit          arm-linux-gnueabihf-gdb              arm-linux-gnueabihf-nm               arm-linux-gnueabihf-strings
arm-linux-gnueabihf-g++              arm-linux-gnueabihf-gdbtui           arm-linux-gnueabihf-objcopy          arm-linux-gnueabihf-strip

讓我們實際寫一個 hello.c 並編譯它吧。

sosorry@ubuntu:~/rpi$ vi hello.c
#include <stdio.h>
int main()
{
	printf("hello, world\n");
        return 0;
}

用 Raspberry Pi 的 toolchain 編譯 hello.c。這一步驟稱為交叉編譯(cross-compiling)。

sosorry@ubuntu:~/rpi$ arm-linux-gnueabihf-gcc hello.c -o hello-arm

讓我們看看檔案的資訊,可以看到該檔案是 ARM 的格式。

sosorry@ubuntu:~/rpi$ file hello-arm
hello-arm: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, not stripped

如果我們在 x86 環境下試著執行會發現無法成功。

sosorry@ubuntu:~/rpi$ ./hello-arm 
bash: ./hello-arm: cannot execute binary file

我們把 hello-arm 上傳到我們的 Pi,假設 IP 為 192.168.1.2。

sosorry@ubuntu:~/rpi$ scp hello-arm pi@192.168.1.2:/home/pi
pi@192.168.1.2's password: 
hello-arm                                                                                                                             100% 5447     5.3KB/s   00:00

在我們的 Pi 上執行,看看結果吧。

pi@raspberrypi:~$ ./hello-arm
hello, world

 

常見問與答:

1. 為什麼要在個人電腦上安裝 toolchain?
因為個人電腦的處理速度通常高於 Raspberry Pi ,因此如果要開發比較大的專案(例如編譯核心),建議在個人電腦上處理,才不會等等等等。實務上在嵌入式系統的開發過程中,目標機器通常不會有 toolchain,因此常常會需要先在開發環境上將專案交叉編譯後再燒到目標機器。

2. 為什麼要安裝 gcc-linaro-arm-linux-gnueabihf-raspbian?
因為在 userland README.md 告訴我們的。

This repository contains the source code for the ARM side libraries used on Raspberry Pi. These typically are installed in /opt/vc/lib and includes source for the ARM side code to interface to: EGL, mmal, GLESv2, vcos, openmaxil, vchiq_arm, bcm_host, WFC, OpenVG.

Use buildme to build. It requires cmake to be installed and an arm cross compiler. It is set up to use this one: https://github.com/raspberrypi/tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian

3. 如果個人電腦(主機端)是 64 位元的要裝那個版本的 toolchain?
要使用 tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin 目錄下的執行檔,也就是將該路徑加入環境變數即可。

Tagged in: cross compilergcc-linaro-arm-linux-gnueabihf-raspbianraspberry pitoolchainubuntu Read more...

Leave a Reply

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


two + 9 =


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>