2013-04-27

Learning ARM Assembly in Raspberry Pi - 2

經過了第一次的試煉Learn ARM Assembly in Raspberry Pi,發現組合語言其實沒想像中的難,反倒是花了不少時間才弄懂GPIO的spec,尤其是Function Select及Pin Output Set/Clear那部份。第一次的練習讓ACT燈恆亮,接下來加點花俏的功能,讓它閃爍。

修改main.s的內容如下:

.section .init
.globl _start
_start:

ldr r0,=0x20200000

mov r1,#1
lsl r1,#18
str r1,[r0,#4]

/* <#1> */
loop$:
mov r1,#1
lsl r1,#16
str r1,[r0,#40]

/* <#2> */

mov r2,#0x3f0000
wait$:
sub r2,#1
cmp r2,#0
bne wait

/* <#3> */
mov r1,#1
lsl r1,#16
str r1,[r0,#28]


/* <#4> */
mov r2,#0x3f0000
wait2$:
sub r2,#1
cmp r2,#0
bne wait2

b loop$



說明:

<#1>
在這段之前的程式碼不變,而這一段落也只加了loop$,這個區段的tag。

<#2>
打開16th pin的開關後,維持一小段時間,再把16th pin的開關關掉,再等待一段時間再打開,如此反覆即可達到閃爍的效果。這一段程式碼的目的就是等待,但是目前還沒用到計數器,只是很單純的暴力解法,設定一個值,然後一直減1減1直到變成0等待結束,這樣的寫法非常直觀,但是不能保證每次的時間間隔是固定的。

使用mov在r2中填入0x3f0000的值,接著設定一個wait$的tag,用sub將r2的值減去1,然後用cmp比較目前r2的值跟0之間的大小,最後用bne反覆執行wait$的內容。bne是指令b的變形,b可以想成是執行,而bne則是有條件的執行,代表當上一次比較結果不一致時則執行,b + not equal = bne。所以在r2的值不為0的時候會一直反覆減1,直到r2 = 0為止才會跳脫wait$這個區段。

<#3>
這個區段的程式碼跟<#1>相似,差別只在於最後將直寫入的記憶體位址不同,這裡是寫到r0 + 28 bytes的地方,而不是r0 + 40 bytes。目的是要將16th pin的Output Set值設定為1,藉此將ACT燈關掉。

<#4>
這個區段跟<#2>意義相同,差別只在於tag不同,因為tag的名稱不能重複,如此而已。這種寫法看起來很蠢,程式碼重複但不能重用,在此先牛刀小試一番,之後再改成聰明的寫法。最後再回到loop$的開頭重新執行,這樣就能使ACT燈一明一滅,非常有趣,當然也可以讓明滅等待的時間不同。

同樣回到Template目錄,執行make編譯,將編譯產生的kernel.img複製到SD卡上取代原本的kernel.img。

Learn ARM Assembly in Raspberry Pi

拿到Raspberry Pi之後到處找一些有趣的教學想試試看,無意間找到一個利用Raspberry Pi來學習寫一個作業系統的課程,是用組合語言來實作,以前沒學過組語,趁這個機會學一點組語的皮毛。Baking Pi – Operating Systems Development

在開始之前要先在Mac上建立編譯組合語言的環境,參考這篇Setting Up an ARM EABI Toolchain on Mac OS X,接著到OS Template下載編譯教學課程檔案用的Script Template。

一開始的概念很簡單,利用Raspberry Pi上的GPIO控制器送訊號到LED燈,藉此控制燈的明暗,這個教學中要控制的是ACT燈號,屬於16th GPIO pin。

在template/source中新增一個main.s檔,檔案內容如下:

/* <#1> */
.section .init
.globl _start
_start:

/* <#2> */
ldr r0,=0x20200000

/* <#3> */
mov r1,#1
lsl r1,#18
str r1,[r0,#4]

/* <#4> */
mov r1,#1
lsl r1,#16
str r1,[r0,#40]

/* <#5> */
loop$:
b loop$


以下為程式碼的說明:
<#1>
檔案一開始要指定程式的進入點,在Template的設定中以.init為進入點,而_start為第一個執行的程式區段,利用.globl宣告為global function。

<#2>
用指令ldr將記憶體位址0x20200000寫入暫存器r0中,0x20200000是GPIO控制器的記憶體位址,透過改變這個位址的值送訊號給GPIO,所以目前暫存器r0中的值代表GPIO的位址。

<#3>
用指令mov設定暫存器r1的值為1,在這裡ldr與mov看起來像是類似功能的指令,但是mov只能設定8bit的值,而ldr能設定32bit的值,因此要用ldr才能指定記憶體位址,而處理小數字用mov就夠了。接著用指令lsl將r1的值,向左移位18 bits,也就是說從0b1變成0b1000000000000000000。
Why?

跟據SoC-Peripherals.pdf第六章,Raspberry Pi的GPIO控制器記憶體位址規劃如下:
0~24 bytes: Function Select
28~36 bytes: Pin Output Set
40~48 bytes: Pin Output Clear


前24 bytes設定為每4 bytes選擇10 pins,GPIO總共控制54 pins,所以會用到24 bytes。而4 bytes共有32 btis,因此每3 bits可設定一個pin的控制方式,排列如xx999888777666555444333222111000,假設這是第一組4 bytes,最高2 bits不用,接下來3 bits控制9th pin,再來是8th pin,一直到0th pin。第二組4 bytes的話,依序為19th pin、18th pin、17th pin、16th pin直到10th pin。而ACT燈號為16th pin,所以是第二組4 bytes的xx999888777666555444333222111000,由右向左數為19~21st bits,在此將16th pin這3 bits設定為001,代表要將16th pin當作output,即r1為0b1000000000000000000。

最後用指令 str把r1的值寫入[r0,#4]的位址中,前面提到r0為GPIO控制器的起點,[r0,#4]代表r0的記憶體位址加4 bytes的位址,也就是第二組4 bytes的起點,如此一來即可將GPIO16th pin設定為output。

<#4>
設定好16th pin為output後,接下來要點亮ACT燈,方法為利用Pin Output Clear給予訊號。(注意要讓pin通電是使用Pin Output Clear而不是Pin Output Set)

Pin Output Set/Clear的控制範圍為前4 bytes對應0~31st pins,1 bit對應1 pin,後4 bytes對應32~54th pins,後4 bytes只使用低位的22 bits,剩餘的不使用。將該位置的bit值設定為1即可指定對應位置的pin為Set/Clear。

因此將r1的值設定為1,用lrl將r1的值向左位移16 bits,最後用str將r1的值寫入r0加40 bytes的位址,即設定GPIO 16th pin為Output Clear。

<#5>
最後為了不讓程式結束跳離,使用空的無限迴圈,指定一段程式區間 loop$,再用指令b執行loop$這個沒有任何指令區間。

回到Template目錄,執行make,即可編譯,將編譯產生的kernel.img複製到SD卡上取代原本Linux的kernel.img。插入SD卡開機後,發現ACT燈號恆亮,代表成功!

2013-04-20

Raspberry Pi

付款後一直在等待Raspberry Pi從英國寄到台灣,大約等了兩星期左右終於到了。
只訂了機板跟一個透明的殼,台灣雖然以有在賣,但是貴好多,從英國買含運大約30.5英磅,折合台幣1400內,台灣光機板就賣1800實在太誇張。Raspberry Pi真的很小,大概比悠遊卡大一點而已。
接下來要準備開機用的SD卡,有很多在Windows及Linux下的教學,但是Mac的教學不多,這裡列出Mac下使用Terminal設定的方法。

  1. 先從官網下載作業系統 http://downloads.raspberrypi.org/images/raspbian/2013-02-09-wheezy-raspbian/2013-02-09-wheezy-raspbian.zip
  2. 下載完後檢查SHA-1值是否正確
    shasum 2013-02-09-wheezy-raspbian.zip
  3. 接著解壓縮檔案
    unzip 2013-02-09-wheezy-raspbian.zip
  4. 接上SD卡之前先檢查目前磁碟的列表,插入SD卡後再看一次,找出SD卡的磁碟路徑
    df -h (兩次)
  5. 我的路徑是 /dev/disk1s1
  6. 卸載SD卡
    sudo diskutil unmount /dev/disk1s1
  7. 接下來要把解壓出的映像檔複製到SD卡上,但是不是直接寫入/dev/disk 1s1,找到的教學是說把/dev/disk1s1改成/dev/rdisk1,去掉最後面的s1並在最前面補上r。但是我照這樣作會寫入失敗,但是改成/dev/disk1,僅去掉最後面的s1就成功了
    sudo dd bs=1m if=2013-02-09-wheezy-raspbian.img of=/dev/disk1
  8. 寫入的時間有點久,完成後退出SD卡
    sudo diskutil eject /dev/disk1
將SD卡插入Raspberry Pi後開機,登登登登

2013-04-14

定義?定理?

最近在看有關微分幾合的論文,出現很多Definition, Theorem, Lemma, Corollary等的輔助說明,回想以前學過的數學,比較常聽到的就是定義及定理,但是精確來說,實在分不出這幾個的不同。後來在網路上找到一篇還算簡單的說明:http://divisbyzero.com/2008/09/22/what-is-the-difference-between-a-theorem-a-lemma-and-a-corollary/

Definition (定義)
精確而清楚地描述數學式的意義,其描述的特性必然成立

Theorem (定理)
經過嚴格的數學推理證明後得出的數學陳述可視為定理

Lemma (引論)
在證明定理時所需較次要的結果,引論通常為證明定理的墊腳石

Corollary (推論)
定理所得的結果稱為推論

網頁廣告新手法

最近讀到一篇國外的文章提到網頁置入廣告的新手法,一種會讓賈伯斯瘋掉的方法。

這次的受害者是ISP的用戶,而置入的人竟然是ISP業者。ISP業者為了加速其用戶使用網路的順暢,多會使用代理伺服器,而代理伺服器成為廣告置入的管道。ISP用戶連線到著名的網頁,如Apple官網時,ISP在代理伺服器回傳網頁給用戶時,不是回傳原本Apple的官網,而是先將廣告頁面與原本Apple官網頁面結合,產生一個新的網頁,再將這個修改過的官網回傳給ISP用戶,藉此達到廣告置入的目的。

其實台灣第四台業者目前也是這樣搞,插了一堆跑馬燈在各節目頻道,只是不知道什麼時候會開始用同樣的模式,插入廣告 在第四台業者的ISP服務中。(還是其實已經有這樣的行為了?!)

2013-04-11

Android emulator

用emulator的環境來執行Firefox OS會有畫面上下顛倒的問題,不知道如果是Android會不會也這樣,於是照著AOSP的步驟設定環境、並且編譯Android,在emulator上執行Android並不會像Firefox OS一樣上下顛倒,這就有趣了,看來Firefox OS遇到的問題應該有機會修~


2013-04-09

Firefox OS - 5 (building B2G)

emulator-x86的設定環境完成後,即可開使編譯,在B2G的目錄下,輸入

./build.sh

接下來又是另一段漫長的等待。不過編譯的過程一向都沒這麼順利,這次遇到的問題是redefinition of typedef,在B2G/external/qemu/telephony/sim_card.c的第6 0行有這個定義

typedef union SimFileRec_ SimFileRec, *SimFile;

後面真正定義SimFileRec時

typedef union SimFileRec_ {
SimFileAnyRec any;
SimFileEFDedicatedRec dedicated;
SimFileEFLinearRec linear;
SimFileEFCyclicRec cyclic;
} SimFileRec, *SimFile;

於是我就遇到redefinition of typedef的問題了,拿掉後面的重複定義後,就可以順利編譯完成。啟動emulator的方法為

./run-emulator.sh

可是啟動畫面不正常,算是根本沒有啟動畫面。後來重新設定成emulator而不是用emulator-x86重新編譯,居然就可以了!啟動畫面長這樣



美中不足的是畫面呈現上下鏡射的狀態,在網路上搜尋到的結果可能是emulator使用GPU加速的bug,但是不用GPU根本沒辦法啟動。到目前為止算是踏出Firefox OS的第一步了。

參考:http://goo.gl/5lUF0

2013-04-06

Kindle新用法

最近發現Kindle的新用法!

Kindle真是不錯的電子書閱讀器,可惜Amazon以原文書為主沒有中文書,有些中文書有PDF檔,可是轉成MOBI後排版常常是亂的,漸漸的就很少拿Kindle來看書。最近有了大轉變!

首先是Google Reader宣布要關閉服務,準備轉移陣地到其他服務,這時候,Feedly跟Flipboard跳出來了,前者是專門為RSS開發的閱讀器,用起來還不錯;後者拿來閱讀RSS的資訊作的沒有前者好,尤其是RSS資訊的分類安排。但是Flipboard的功能可不只如此,根本就是社群資訊的集中管理器,拿來看Facebook,Twitter,Instagram都不錯,而且還有一些出版者自己的專欄,例如Wired,Harvard Business Review,甚至Flipboard還提供個種分類的資訊來源,例如Technology會從The Verge,TechCrunch蒐集資訊,每天都有好多好多文章可以看。(iPad上的Flipboard使用者介面比iPhone上的好)

問題來了,這麼多資訊,用iPhone看實在是太吃力了,螢幕小又亮,非常不適合長時間閱讀。而且 很 多 文 章 實 在 是 超 級 長 , 像 是 H a r v a r d B u s i n e s s R e v i e w , 坐在馬桶上看一篇半小時就過了,都不用工作了。Feedly還可以在電腦上看,Flipboard就真的只能用手機看了。還好這兩種服務都有提供Read it later的功能,原本的目的是要讓讀者遇到長文章時先存起來,有時間再慢慢看,但是我的問題並沒有完全解決!Read it later其實有其他專門的服務,例如Pocket,Readability及Instapaper,Pocket對多媒體類資訊的整合做的不錯,Readability及Instapaper以文字資訊為主,前者還整合Longform的文章來源,有更豐富的閱讀資料;後者則是一人硬幹的服務,相對功能較陽春。Readability跟Instapaper有個特點非常吸引我,就是透過這些服務儲存的文章,可以轉送到Kindle!可以設定每天凌晨傳送,早上打開Kindle就有前一天儲存的文章可以看,這真是太棒了!!!

整合了這些服務,我的閱讀習慣變成了:iPhone => (Feedly, Flipboard) => (Readability, Instapaper) => Kindle。用Kindle看文章真的舒服很多,非常適合吃早餐及睡前看。但是最近遇到另一個問題,有時候不小心儲存太多想看的文章,每天都看不完~我到今天還在看4/3的文章,人生就是不斷地解決問題阿!

Firefox OS - 4 (preparing for B2G build)

設定完編譯環境後,可以開始用git下載B2G,在git上的B2G還不是所有Firefox OS的程式,只是B2G的編譯系統,B2G本身的程式是透過Mercurial管理的。

git clone git://github.com/mozilla-b2g/B2G.git

進到B2G的目錄後執行

./config.sh

列出支援的硬體,手邊沒有跑Android的機器,所以選擇emulator-x86

./config.sh emulator-x86

接下來就是漫長的等待…

參考:http://goo.gl/HJcoA

2013-04-05

Firefox OS - 3 (build prerequisites)

在MacBook上開發Firefox OS需要用到Command Line Tools,現在新的機器上都可以直接在Apple Developer下載,我的老MacBook還在用Snow Leopard,最新只能用到Xcode 3.2.6(包含Command Line Tools),沒辦法,只能裝整包Xcode。接下來很簡單,輸入以下指令

curl -fsSL https://raw.github.com/mozilla-b2g/B2G/master/scripts/bootstrap-mac.sh | bash

讓bootstrap-mac.sh完成剩下的檢查。除此之外安裝Android SDK也是必需的,之前是透過Command Line安裝

wget http://dl.google.com/android/android-sdk_r20.0.3-linux.tgz
tar -xzf android-sdk_r20.0.3-linux.tgz
./$SDK_HOME/tools/android update sdk --no-ui
./$SDK_HOME/tools/android update adb

而且記得要把PATH=$SDK_HOME/platform-tools:$PATH加到~/.profile,還要調整ccache的大小

ccache --max-size 3GB

參考:http://goo.gl/ZfNdA

Firefox OS - 2

在設定編譯環境時遇到一個難題,Firefox OS預設使用Homebrew檢查編譯所需的工具及函式庫,但是我平常都用Macports,而這兩種套件管理系統並不相容,又覺得兩種並存的話很容易搞亂整個環境。後來看到http://goo.gl/r6hYu這篇文章提到的比較,決定把Macports移除,改用Homebrew管理套件。

Firefox OS

訂了一台Raspberry Pi,想要裝Firefox OS,但是不知道什麼時候才會到,在這之前先來研究怎麼編譯Firefox OS。編譯的機器一定要用64bit的Linux或是MacOS,可惜IBM R60只能裝32bit的Linux,所以得用MacBook來跑,在Mac設定編譯的環境不像在Ubuntu上熟悉,第一項任務就是先搞定我的編譯環境!