2015年7月13日 星期一

Raspberry Pi2 (ARM Cortex-A7) 上編譯 Raspbain Kernel (4.0.x) with device tree


=====
前言
=====

為了在Raspberry Pi 2板子上面學習開發 Driver,最近吃飽沒事都在編譯 Kernel。之前更發了一篇文章:

Raspberry Pi2 (ARM Cortex-A7) 上編譯Raspbain Kernel

來記錄編譯核心的過程。但是依照文章裡面所說的方式開發 Driver 還是發生了一些問題。有時候會有 gcc compiler 版本的問題,有時候會出現 "your compiler is too buggy" 之類的訊息,這個是因為編譯核心的compiler 和在Pi2上面編譯 driver 的版本不太一致的關係。還有python 的 GPIO library 失效了....,後來才知道這是因為編譯出來的 kernel 不支援 device tree 的關係。

而這次參考官方網站: 


編譯出來的 kernel 總算是ok了,python GPIO也沒問題了..."compiler too buggy" 的訊息也看不到了~~~~~~

這次編譯的方式依然是跨平台編譯,使用的是vmware 裡面的 32 bit ubuntu 系統。


===================
安裝編譯器 (on ubuntu)
===================

登入 ubuntu 系統之後,會進入家目錄底下,首先去 github 下載跨平台編譯器:

$ git clone https://github.com/raspberrypi/tools.git

然後修改 ~/.bashrc 設定檔,最後一行加入:

export PATH=$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin

如果使用的Debian作業系統是64bit,則在~/.bashrc的在最後一行加入:

export PATH=$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin


重新登入一次,使剛剛修改好的.bashrc設定值生效。成功 的話可以輸入arm之後連按兩下tab鍵看看有沒有顯示一堆 arm-linux-gnueabihf- 開頭的執行檔,有的話表示設定生效了。


===================
Download kernle 4.0.y
===================

在家目錄底下用去github download 新版的kernel ,寫這篇文章的時候是 4.0.y

$ git clone https://github.com/raspberrypi/linux.git


================
準備 .config設定檔
================

$ cd ~/linux
$ KERNLE=kernel7
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig

這樣就會直接產生一個預設的.config。如果沒有其他的 kernel 設定上的需求的話就可以開始進行下一步開始編譯核心了。但是如果有一些要自行更改的kernle 選項的話,記得安裝 libncruses-dev 套件,然後:

$ cd ~/linux
$ KERNEL=kernel7
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

========
編譯核心
========

下面的指令會開始進行核心的編譯、模組的編譯、Device Tree 的設定檔的編譯:

$ cd ~/linux

$ KERNEL=kernel7
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs

這個步驟會花很久的時候,如果 ubuntu 系統是多核心的話,可以在make 後面用 -j 參數指定要使用多少顆CPU核心來進行編譯的工作。使用多核心的話可以省很多時間。下面是使用兩顆CPU核心來進行編譯:

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs - j 2

等到編譯完成之後就可以進行下一步。



========================
製作 kernel 核心檔 & module
========================

4.0.y 版的 linux source 裡面有多了一個 script 檔 mkknlimg ,用來產生 kernel image,而不能像之前的做法,直接把產生的 zImage 拿來用:

$ cd ~/linux
$ ./scripts/mkknlimg ./arch/arm/boot/zImage ../kernel7.img

然後先把 module 安裝到上一層目錄裡:

$ cd ~/linux
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=../modules modules_install

進行到目前為止,我們已經得到了編譯好的 kernel source tree 一份、moudle一份、kernel image 一份 (kernel7.img)

先在要想辦法把這三個東西 copy 到一個已有安裝 raspberry pi 系統的家目錄上。

這邊是用透過網路的方式用 scp 把東西copy 到raspberry pi 系統(假設IP為192.168.1.2)上面去:

$ cd ~/
$ scp -r ./linux/ pi@192.168.1.2:~/
$ scp -r ./modules pi@192.168.1.2:~/
$ scp ./kernel7.img pi@192.168.1.2:~/


======================================
接下來的事情都是在 Raspberry Pi 2 系統上面進行:
======================================


=========
安裝kernel
=========

Raspberry Pi2 開機登入之後,先備份舊的 kernel image 檔:

$ sudo mv /media/boot/kernel7.img /media/boot/kernel7.img.backup

之後安裝新的kernel7.img:

$ sudo mv ~/kernel7.img /boot/

====================
安裝 device tree 設定檔
====================

$ cd ~/linux
$ sudo cp ./arch/arm/boot/dts/*.dtb /boot/ 

$ sudo cp ./arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/ 
$ sudo cp ./arch/arm/boot/dts/overlays/README /boot/overlays/


===========
安裝module:
===========
$ sudo cp -Rf ~/moudles/lib/modules /lib/ 
$ sudo cp -Rf ~/moudles/lib/firmware /lib/

$ sudo rm /lib/modules/4.0.7-v7/build
$ sudo rm /lib/modules/4.0.7-v7/source
$ sudo ln -s /home/pi/linux/ /lib/module/4.0.7-v7/build 
$ sudo ln -s /home/pi/linux/ /lib/module/4.0.7-v7/source



===============
安裝 gcc-4.8
===============

增加檔案 /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 gcc-4.8

設定 gcc4.8 為預設的 gcc

$ 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

===================
make module prepare
===================
This will make sure the kernel contains the information required.to build external module

$ cd ~/linux
$ make modules_prepare




========= 其他 ================
使用這個gcc-4.8可以進行kernel driver的編譯,但是在安裝python module 需要使用到gcc的時候會出問題,這個時候會需要安裝 gcc-4.9 並且用下面的指令改變設設gcc為4.9版:

$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 10
$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 20
$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 50

$ sudo rm /usr/bin/arm-linux-gnueabihf-gcc
$ sudo ln -s /usr/bin/gcc-4.9 /usr/bin/arm-linux-gnueabihf-gcc





4 則留言 :

  1. 如果使用的是ubuntu14.04 64位元的系統
    是要用
    export PATH=$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin
    還是用
    export PATH=$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
    如果把git 下來的檔案放在home底下的新建的目錄需要修改哪些地方呢?

    回覆刪除
    回覆
    1. 我重複嘗試之後
      是用
      export PATH=$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
      因為我自建了資料夾在home/MYACOUNT/rp2tool所以修改成
      export PATH=$PATH:~/rp2tool/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueab ihf-raspbian-x64/bin

      刪除
  2. 作者已經移除這則留言。

    回覆刪除
  3. 請問為什麼在執行 scp -r ./linux/ pi@192.168.1.2:~/ 時,會造成raspberry pi SD卡容量不足呢?發現是linux Folder 檔案似乎過大了.而造成SD卡容量不足.

    回覆刪除