2015/4/18

【樹莓派】無線網路轉送有線網路橋接

參考下圖,需求是讓RPi連接無線的網路訊號並用網路線連接到一台電腦,讓電腦能夠透過樹莓派來上網。
無線網路的設定可以參考【設定無線網路】,這篇文章著重在有線的網路封包轉傳。在Linux上要實現封包轉送只需要設定好iptable就可以了!

首先編/etc/sysctl.conf檔案,將net.ipv4.ip_forward=1這行註解拿掉
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
重新載入設定檔,讓設定生效
sysctl --system

完成上述動作RPi的iptable功能就被啟動了,接著設定RPi的eth0網卡IP設定為192.168.0.1
,修改/etc/network/interfaces
#iface eth0 inet dhcp
allow-hotplug eth0
iface eth0 inet static
  address 192.168.0.1
  network 192.168.0.0
  netmask 255.255.255.0
  broadcast 192.168.0.255
  gateway 192.168.0.1
修改後重新啟動eth0
ifconfig eth0 down
ifconfig eth0 up

最後設定iptable,在家目錄下編輯一個新檔nat.sh
#!/bin/sh
IPT=/sbin/iptables
LOCAL_IFACE=eth0
INET_IFACE=wlan0
INET_ADDRESS=`ifconfig wlan0 | grep "inet addr" | cut -d ' ' -f 12 | cut -d : -f 2`

# Flush the tables
$IPT -F INPUT
$IPT -F OUTPUT
$IPT -F FORWARD

$IPT -t nat -P PREROUTING ACCEPT
$IPT -t nat -P POSTROUTING ACCEPT
$IPT -t nat -P OUTPUT ACCEPT

# Allow forwarding packets:
$IPT -A FORWARD -p ALL -i $LOCAL_IFACE -j ACCEPT
$IPT -A FORWARD -i $INET_IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT

# Packet masquerading
$IPT -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source $INET_ADDRESS

執行nat.sh
chmod +x ~/nat.sh
~/nat.sh

到這裡一切就設定完成了,接著在電腦端設定固定IP(ex. 192.168.0.2)、路由與DNS等資訊就可以透過RPi上網了。

【樹莓派】編譯一個Hello Kernel Module(Driver)

  編譯Driver給RPi使用需要準備Toolchain與Kernel Source Tree,步驟可以參考【重編Kernel,客制化自己的核心】,以下範例目錄結構為
 /home/acos
--+ rpi
----+ linux: 存放Kernel Source
----+ tools: 存放Toolchain
----+ driver: 存放此範例檔案hello.c與Makefile

hello.c
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void)
{
 printk(KERN_ALERT "Hello, RPi!\n");

 return 0;
}

static void hello_exit(void)
{
 printk(KERN_ALERT "Goodbye, RPi\n");
}

module_init(hello_init);
module_exit(hello_exit);

Makefile
obj-m := hello.o

all:
 make -C /home/acos/rpi/linux M=$(PWD) modules

clean:
 make -C /home/acos/rpi/linux M=$(PWD) clean

進到driver目錄下執行
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
結束後會在目錄中看到hello.ko,將這檔案複製到RPi上進行載入與卸除動作就會看到對應訊息
root@raspberrypi:~# insmod hello.ko
[ 5835.187137] Hello, RPi!
root@raspberrypi:~# rmmod hello
[ 5842.134762] Goodbye, RPi

2015/4/17

【樹莓派】開機自動登入

要讓RPi自動登入並執行預設程式很簡單,只需要修改/etc/inittab檔案與登入帳號家目錄下的.profile檔案即可。

首先設定自動登入,編輯/etc/inittab檔案:
sudo vi /etc/inittab
把最後一行敘述T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100註解起來,並加入T0:23:respawn:/bin/login -f pi ttyAMA0 </dev/ttyAMA0 >/dev/ttyAMA0 2>&1
#Spawn a getty on Raspberry Pi serial line
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
T0:23:respawn:/bin/login -f pi ttyAMA0 </dev/ttyAMA0 >/dev/ttyAMA0 2>&1
存檔重開機,就會自動使用pi帳號完成登入,若想要以root身分自動登入,則將上面敘述的pi改為root即可。

自動登入後若想自動執行程式,可以從~/.profile帶起。

2015/4/15

【樹莓派】重編Kernel,客制化自己的核心

編譯Linux Kernel,準備好Toolchain(即Compiler, Linker等工具)與Kernel Source就可以開始了!此範例採用Cross-Compile,也就是在一般X86架構的PC上為樹莓派編譯核心,編譯完成在將相關檔案複製到SD Card上讓樹莓派使用。

過程中會使用到git抓取toolchain與kernel source,因此須先安裝git套件:
sudo apt-get install git-core

接著在家目錄建立rpi目錄並使用git下載toolchain與kernel source
cd ~
mkdir rpi
cd rpi
git clone https://github.com/raspberrypi/tools
git clone --depth=1 https://github.com/raspberrypi/linux
完成上述動作後可在rpi目錄中看到tools與linux兩個子目錄

為了方便後續操作,將tools套件所在目錄加到$PATH變數
vi ~/.bashrc
在檔案尾端加入敘述
PATH=$PATH:/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin
如果使用的作業系統平台是64位元的話,需換成下面這敘述
PATH=$PATH:/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
修改完成後重新關聯~/.bashrc讓設定生效
source ~/.bashrc

完成工具與環境設定後,就可以開始進行核心編譯了
進入kernel source目錄,設定預設值,進行編譯!
cd ~/rpi/linux
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
如果使用的是多核心CPU可以在make指令中使用-j <n>參數讓編譯動作分散在各核心中加快整體速度,其中<n>是核心數量,過一段時間完成後若沒出現錯誤就已經完成核心編譯了。

最後將SD卡插入電腦,把剛編譯好的模組檔案與核心檔案取代原先檔案後即完成所有步驟
mkdir /mnt/fat32
mkdir /mnt/ext4
sudo mount /dev/sdb1 /mnt/fat32
sudo mount /dev/sdb2 /mnt/ext4
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=/mnt/ext4 modules
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=/mnt/ext4 modules_install
sudo cp /mnt/fat32/kernel.img /mnt/fat32/kernel-backup.img
sudo cp arch/arm/boot/Image /mnt/fat32/kernel.img
sudo umount /mnt/fat32
sudo umount /mnt/ext4

將SD卡插入樹莓派,開機登入後查看歡迎訊息顯示的核心資訊,可以驗證一下核心產生的時間是不是正確的!

2015/4/9

【樹莓派】查看版本、規格與製造商

在第一代不同的Model在GPIO腳位的設計上有些許的不同,板子上的記憶體大小也不一樣,要知道自己手上的RPi是屬於哪個版本、製造商是誰可以透過查看CPU資訊來得知
cat /proc/cpuinfo
顯示結果會有像下面的訊息
Hardware        : BCM2708
Revision        : 000e
Serial          : 00000000bf257857
依據Revision再去查表即可知道詳細的相關資訊
像手上這塊板子是000e,則可以知道是Model B 2.0、記憶體是512MB,由Sony製造。
表格資訊會隨時間持續增加項目,最新資料可到elinux.org查詢。

2015/3/30

【樹莓派】編譯一個Hello World程式在RPi上執行

要在PC上編譯一個可以在Raspberry Pi上執行的程式必須透過Cross-Compile才能達成。Cross-Compile的意思就是在A架構電腦(比如你用的一般電腦)上編譯B架構電腦(比如樹莓派)能執行的二進位程式,為了讓電腦能夠Cross-Compile出樹莓派能接受的執行檔,須要先在電腦上安裝Cross-Compiler:
1
sudo apt-get install gcc-arm-linux-gnueabi
這裡寫了一個簡單的Hello World程式做為示範
1
2
3
4
5
6
#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello Raspberry Pi!\n");
}
透過剛安裝的Cross-Compiler進行編譯:
1
arm-linux-gnueabi-gcc -o hello hello.c
產生的執行檔可以使用file指令查看執行檔格式是否為ARM架構
若正確則可將檔案放到樹莓派上執行,應該可以得到下列結果:

2015/3/18

解決呼叫某些系統函數發生'無法解析的外部符號'問題的兩種方法

Windows有些系統函數被存放在像是Shlwapi.lib函數庫中而非常用到的kernel32.lib,在Visual Studio編譯環境中,Linker預設是不會去找Shlwapi.lib等較不常用的Library進行鏈結,所以當呼叫到如PathFileExists等系統函數,編譯過程中就會收到類似錯誤:
1>Source.obj : error LNK2001: 無法解析的外部符號 __imp__PathFileExistsA@4
1>E:\Tmp\ConsoleApplication13\Release\ConsoleApplication13.exe : fatal error LNK1120: 1 個無法解析的外部符號
1>
1>建置失敗。

解決方法有兩種:
其一是透過設定專案屬性→連結器→輸入→其他相依性,加入*.lib(如Shlwapi.lib)
其二是透過假指令#pragma告知編譯環境將調用到*.lib
#pragma comment(lib, "Shlwapi.lib")