2007年12月11日 星期二

WebKit/QT & WebKit/GTK+ on Ubuntu Linux初體驗

前兩篇「WebKitGtk+支援」與「OWB:以WebKit為基礎的嵌入式網路瀏覽器」介紹了些 WebKit的開發現況後,這邊大概講一下在Ubuntu Linux底下如何無痛進行初體驗。依據官方首頁的訊息,WebKit 簡介如下:

WebKit是一種開放原始碼瀏覽器引擎,同時也是 Mac OS X 底下的Safari 、 Dashboard、Mail、與其他Apple Mac OS X所使用的系統框架版本。WebKit所使用的KDE函式庫KHTMLKJS是屬於HTML與JavaScript實做的分支。
先來體驗一下原生於QtWebKit瀏覽器,動手打造個「仿Safari」。以Ubuntu Linux 7.10為例,操作程序如下:
1. 先安裝編譯時所需的軟體與套件庫
sudo apt-get install libqt4-dev libxslt-dev gperf bison libsqlite3-dev flex build-essential subversion
2.取得Subversion中的原始碼 (筆者花了近20分鐘才下載完畢,所以請保持耐心)
svn checkout http://svn.webkit.org/repository/webkit/trunk WebKit
3.建立一個Qt for WebKit的瀏覽器
(安裝的機器 Intel CoreDue L2300@1.5GHZ 跑了近45 min )
QTDIR=/usr/share/qt4/ WebKit/WebKitTools/Scripts/build-webkit
4.安裝完後,打以下指令開啟剛剛建立的瀏覽器。
WebKit/WebKitBuild/Release/bin/QtLauncher
有圖有真相!!


接著,嘗試原生於Gtk+WebKit,不過這次就直接介紹個剛成立的一個新軟體專案 Midori來體驗一下 WebKit/Gtk+Midori 是一個輕量化的瀏覽器,有以下特點:
  • 完全採用Gtk+ 2.x打造
  • WebKit 進行快速網頁繪製
  • 分頁、視窗與任務對話管理
  • 書籤的儲存採用XBEL
  • 搜尋框則基於OpenSearch
  • 可自訂前後選單動作
  • 支援使用者腳本與樣式自訂
  • 可透過 Lua scripts 擴充
然而,這個專案目前還是屬於alpha測試版的狀態,所以可能會比較不穩定些,而且有些功能還沒實做出來。

Midori目前則可透過apt的方式去安裝預先編譯的套件,但得先編輯設定:
sudo gedit /etc/apt/sources.list
然後加入以下兩行:
deb http://ppa.launchpad.net/stemp/ubuntu gutsy main
deb-src http://ppa.launchpad.net/stemp/ubuntu gutsy main

儲存後離開,並進行更新:
sudo apt-get update
然後就可安裝Midori
sudo apt-get install midori
跑完後,就可以直接從「應用程式」裡的「網際網路」選單開啟Midori ,其執行時期的快照如下:


本文改寫於以下兩篇文章:

2007年11月20日 星期二

svn http, user-password and access control

使用http protocol作為Subversion的URL,可利用apache的dav_svn module達成。

dav是distribution authorization and versioning,為http協定的一個擴充
AuthUserFile  /etc/apache2/dav_svn.passwd
AuthzSVNAccessFile /etc/apache2/dav_svn.authz
所以:
  1. 要先準備好這兩個擋案,並依據.conf 的內容,擺在對應的路徑中
  2. user-passwd file的內容是用 htpasswd 操作的,add user、change password都要用htpasswd來作
  3. svn下各個目錄的存取權限就由dav_svn.authz設定,該檔案為純文字檔
Add User :
htpasswd  'target .passwd file' user-name
這裡'target.passwd file'就是/etc/apache2/dav_svn.passwd.

權限設定方式 :
[/]
* =
guest = r
svntest = rw
charles-chang = rw
意思是對 [/] 目錄的權限設定:
* - 所有人 - 無法access
guest - 僅能讀取,無法修改
svntest, charles-chang 都是一般user,可以讀取、修改。
當然,要用htpasswd把 guest, svntest, charles-chang都加到 user-passwd file 中
僅能讀取的user一樣可作check-out、add file等操作,但在commit時會出現error,svn log上也不會有該user的更動紀錄。

使用hg內建的web server

hg( Mercurial)內建 web server。

一般使用方式如下:

到已開啟好(hg init完畢)的repository (例如 c:\writeMLC)目錄下,執行以下指令:

hg serve -p 8002
然後開啟web browser,開啟以下網址:
http://127.0.0.1:8002/
即可看到該repository的資訊:

此功能一方面可以作為command line模式的"friendly front end" ,另一方面,可以跟合作夥伴共享程式碼。

若有多個repository ,就要用webdir-conf 這個選項。使用方式先編輯一個設定檔,指定web server path和repository的關聯性:
編輯 一個檔案 (假設為webdirconf)
[paths]
writeMLC = C:\Whimery\DownloadWriteMLC
UseYagarto = C:\Yagarto\UseYagarto
BootRun = C:\BootRun\BootRun_Robert
在啟動hg server時,加上以下參數:
hg serve -p 8002 --webdir-conf webdirconf
然後在web browser上的顯示會像是以下:


每個 repository 可以自行設定一些特徵,諸如:web style、authorization、zip download support,指定方式即利用每個 repository 下.hg目錄裡的hgrc 檔 (要自行建立與編輯)。

以下就是為了方便所寫的hgrc內容:
[web]
style = gitweb
allow_archive = bz2 gz zip
push_ssl = false
allow_push = *
說明:
  • 改用git style 的wen interface (較詳細)
  • 增加 bz2、gz、zip的source snapshoot下載
  • 不使用ssl (因為不知道在windows command 下怎麼用 :P)
  • 允許經由http作push的動作 (允許他人check-in)

2007年11月13日 星期二

OWB:以WebKit為基礎的嵌入式網路瀏覽器

幾個月前介紹了「WebKit的Gtk+支援」新進展,現在openmoko已正式採納為web engine,提供為網頁瀏覽與RSS reader使用。Origyn Web Browser (OWB)則是另一個以WebKit為基礎的開放原始碼網路瀏覽器 (BSD license + LGPL + misc),針對嵌入式環境做了許多微調與修正,引入一層簡化描繪與底層操作的軟體層,稱為OWB Abstraction Layer (OwBal),得以銜接WebKit與消費性電子產品需求。具體來說,原本的WebKit需要heavyweight UI toolkit去作widget/font描繪,但OWBOwBAL巧妙地補齊介面部份,並允許lightweight UI呈現,也就是 "render itself by its own toolkit"。詳細的技術介紹可參考「Introducing OWB, an open-source browser for consumer devices」一文。

建構方式如下:

  • 取得開發中的程式碼:
svn checkout http://www.sand-labs.org/svn/trunk owb
  • CMake調整組態設定:
cd owb && ccmake .
具體情況如下圖: 按下[c]則可進行組態設定,過程中會提示缺乏的開發套件。
最後按下[g]即可產生必要的Makefile
  • 開始建構,當然是執行make
目錄下應該會有名為"owb"的執行檔。注意,建議安裝CJKUnifonts以支援中日韓文顯示支援,並且需作以下修正:
Index: BAL/Implementations/Fonts/freetype/BTFont.cpp
===================================================================
--- BAL/Implementations/Fonts/freetype/BTFont.cpp (revision 147)
+++ BAL/Implementations/Fonts/freetype/BTFont.cpp (working copy)
@@ -114,7 +114,7 @@
int size = static_cast<int>(m_fontDescription.specifiedSize());

if (m_fontMap[size] == 0)
- m_fontMap[size] = d->open("/usr/share/fonts/owb.ttf", size, 0);
+ m_fontMap[size] = d->open("/usr/share/fonts/truetype/arphic/ukai.ttf", size, 0);
d->m_ttfFont = m_fontMap[size];
if (d->m_ttfFont == NULL)
logml(MODULE_FONTS, LEVEL_EMERGENCY, make_message("open : \n"));
以「Jserv's blog」為例,OWB的呈現效果如下:

在組態設定時,指定了以FreeType作為字型描繪引擎 (即 "WEBKIT_USE_FONTS_FREETYPE" 選項),以取得更加的顯示效果。可發現網頁周圍沒有視覺捲軸 (但可使用方向鍵或PageUp/Down),而且HTML按鈕則是OWB自行描繪的,輸入框亦然。

OWB現在的空間使用量與網頁呈現正確度相當不錯,除了使用curl的方式還需要效能調整外,整體已相當穩定,目前的參考圖形引擎實做為SDL,官方網頁提供相當好的移植文件「OWBAL Porting Guide to Embedded Systems」。依據發展方向,OWB適合應用於Set-Top Box、數位電視、Kiosk等環境,並且對DirectFB的支援也開始進行。

2007年10月21日 星期日

EGLIBC於S3C2410 ARM SoC的體驗

稍早於「EGLIBC初探」提過CodeSourcery與諸多系統廠商合作,針對glibc的改進計畫 (自2.5版開始),實做出更適合Embedded環境的C Library實做 ── EGLIBC,前文也提及快速建構的script,而OpenEmbedded也正式納入對EGLIBC的支援。所以現在要建構與測試都可以相當快速,以下是參考的option groups組態:

jserv@venux:/home/moko/build$ cat ../org.openembedded.dev/packages/glibc/eglibc-svn/option-groups.config
# This file sets default values for all option group variables
# mentioned in option-groups.def; see that file for a description of
# each option group.

OPTION_EGLIBC_ADVANCED_INET6 = n
OPTION_EGLIBC_BSD = n
OPTION_EGLIBC_CATGETS = n
OPTION_EGLIBC_CHARSETS = n
OPTION_EGLIBC_DB_ALIASES = n
OPTION_EGLIBC_ENVZ = n
OPTION_EGLIBC_FSTAB = n
OPTION_EGLIBC_GETLOGIN = n
OPTION_EGLIBC_INET = y
OPTION_EGLIBC_LIBM = y
OPTION_EGLIBC_LOCALES = n
OPTION_EGLIBC_LOCALE_CODE = n
OPTION_EGLIBC_NIS = n
OPTION_EGLIBC_NSSWITCH = y
OPTION_EGLIBC_RCMD = n
OPTION_EGLIBC_SPAWN = n
OPTION_EGLIBC_SUNRPC = n
OPTION_EGLIBC_UTMP = y
OPTION_EGLIBC_UTMPX = n
OPTION_EGLIBC_WORDEXP = n
OPTION_POSIX_REGEXP = y
具體的細節可參考Jim Blandy發表於mailing-list的文章「EGLIBC size measurements for option groups」,EGLIBC透過option groups可讓C runtime的建構更加模組化,可輕易挑選Embedded環境所需的特徵,大幅降低code size與memory footprint,以常見組態來說,後者相較於glibc縮減為85%。筆者實際在openmoko GTA01bv4硬體 (based on S3C2410 ARM SoC)測試,在Smartphone的使用情境中,free memory從原本58444 bytes (glibc) 增加到67404 bytes (eglibc),幅度達13%,功能卻沒有因此打折,這與uClibc或其他小型的C Runtime來說,是很大的優勢。

取得筆者建構的EGLIBC-based openmoko 2007.2 image:http://people.openmoko.org/jserv/images/

2007年8月27日 星期一

教學:透過screen + irssi使用IRC

最近身旁許多在上 IRC (Internet Relay Chat)的朋友都問我哪個IRC client 比較好用?其實,只要問過我的,而且又是UNIX-like的系統使用者時,基本上都會被我推薦irssi這個command mode的純文字IRC程式。若有server可用的朋友們,更是會被我力推screen + irssi的組合。好處是,可以遠端持續掛著IRC,到哪邊都可以ssh進去繼續看IRC log,這樣真的很方便,也不用擔心因為沒開自己的電腦,就看不到別人的對話或別人要留給自己的訊息。

以下是針對irssi這軟體所寫的簡易基本介紹與使用和一些需要使用到IRC與GNU screen的基本指令,如需IRC或screen的其他更詳細指令與資料,文末會補上相關連結,如有不足,歡迎補充。

irssi的程式安裝不贅述,可由apt-get或yum等工具自套件庫裡面找尋並安裝。

先在這邊建立第一次使用screen + irssi操作IRC的朋友們觀念,確定遇到的問題跟操作,該是由screen還是由irssi的程式部份來處理,或者本身只是IRC上的指令操作罷了。screen只是方便讓使用者可以利用server不關機的優勢,讓irssi可以連續開著不中斷,使得下次再透過screen來接軌回到上次開啟還未被關閉的irssi來繼續IRC這樣子。所以,這樣看下面的簡介操作後比較不會搞混狀況,如果請教朋友也比較能問到問題處。

以下例子皆以irssi 0.8.10或以上版本,經實驗都可順利執行,且都以在FreeNode上的#orzlab IRC channel 為例。

(如果不掛 screen 者,這一段請直接跳過) 首先ssh login到server後,請輸入:

screen -RD
-R Reattach if possible, otherwise start a new session.
-D (-r) Detach and logout remote (and reattach here).
然後會進入到新開啟的screen,並且screen會自動開啟一個新的window讓我們使用,接下來直接輸入:
irssi
就會在screen底下的第一個視窗執行irssi這隻程式。

如果沒有要掛著screen執行irssi的朋友,那直接輸入
irssi
就可以直接執行 irssi 這隻程式。

進入irssi後,直接在提示輸入字元處輸入
/connect irc_server
就會直接連到該個IRC server,例如:
/connect irc.freenode.net
這樣就會直接連接到freenode的IRC server上,此時,可以先在這邊修改自己要在該IRC server 上的暱稱,如果要修改,則輸入以下格式:
/nick you_want_nickname
例如當我輸入
/nick lzy
時,那我顯示出來的暱稱將會是「lzy」的字樣( irssi 預設的暱稱會是 login 的使用者名稱)。
搞定暱稱後,接著我們就可以加入其他頻道了。
只要輸入
/j #channel_name
就可以直接加入了,例如:
/j #orzlab
這樣就完成加入#orzlab這個IRC channel(即OrzLab的主要IRC channel),如果該IRC channel需要key/password的話,則輸入:
/j #channel_name password
如果要離開單一IRC channel ,則直接輸入
/wc
就可以離開這個IRC頻道。
若是要離開一個IRC server的連線,則輸入
/disconnect irc_server_name

剛剛是教如何連線,現在則是教一些常用的熱鍵與功能。
先來看圖說故事一下:


上面的這張圖,我們在
[Act: 1,2,4,6,9,10]
這邊發現了幾個不一樣的標示數字,Act這一欄位會提示你在第幾編號的channel上對話狀況,而你還沒切換到該IRC channel 上觀看。顏色對應的意思如下:
  • 灰色一般體的是代表有人登入或登出此 irc channel (如 1,9,10)
  • 白色粗體的是代表有人正在此 irc channel 上談話(如 4,6)
  • 灰色粗體的則是有人在對話中提起你的名字或者呼叫你,總之就是有出現你的名字(如 2)
這是基本識別,再來是知道哪個channel有什麼狀況後,就是切換到該IRC channel上查看:
Alt + 1~0 對應 1~10 的 irc channel 編號;
Alt + q~p 對應 11~20 的 irc channel 編號;
Ctrl + n/p 可切換 上/下 一個 irc channel;
按鍵盤上的 PageUP/PageDn 可以直接切換 上/下 頁訊息。
如發現有編碼上的問題,需要轉編碼的話,則可輸入
/recode add #channel_name code_type
例如要把#orzlab的UTF-8格式加入,則輸入
/recode add #orzlab utf8
即可加入此頻道的編碼格式。
然後輸入
/recode
就可以看到加入的編碼列表。
(註:因 /recode add會寫入到設定檔裡,所以僅需要寫入一次即可)


Q&A TIME:

Q:如何同時有連接多個IRC server呢?又該怎樣切換不同IRC server來加入該server的IRC channel呢?
A:
請直接再下一次 /connect irc_server 就可以再連接一個新的 irc server ,然後按Alt + 1切換到第一個的特殊頻道上,再按 Ctrl + x來切換目前要下達指令的 IRC server名稱。

Q:如何查看該頻道的所有人呢?
A:
請下達/who的IRC指令即可,然後也是一樣按Alt + 1切換到第一個伺服器狀態頻道上觀看

Q:如何查看單一網友的基本連線資料呢?
A:
請下達/whois nickname的IRC指令即可,然後也是一樣按Alt + 1切換到第一個伺服器狀態頻道上觀看

Q:如何傳送私人訊息到指定的朋友暱稱呢?
A:
請下達/msg nickname即可開啟一個名為指定暱稱的訊息頻道,一樣用alt + 1~0/q~p 來選擇(注意:某些IRC server 會限制此功能,傳訊前請先確認是否有權限,如FreeNode)。
Q:已使用上面所講的方式操作screen + irssi ,那我離開時,是否得下達任何參數或指令?又下次ssh login 後,需要打什麼指令呢?
A:
為了簡化登入與記憶上的方面,採用-RD的參數,所以每次要離開irssi時,直接關閉該視窗就好,不需下達任何參數或指令。然後下一次ssh login後,只要打screen -RD 這樣就可以接軌回上次開啟的irssi了。

Q:如果遠端連線到編碼為Big5 的主機掛screen + irssi,且client端是採用UTF-8編碼時,編碼的亂碼問題如何處理?
A:
首先,先處理screen的編碼問題,從utf8端要檢視big5 server時,先Ctrl + a,然後輸入 :encoding big5 utf8 ,把從server將送出的Big5編碼先轉成UTF-8後再送出,然後輸入 "/recode" 觀看頻道編碼是否指定正確,照上述設定,理應能順利顯示。

Q:如果不小心按到Ctrl + z或鍵盤上的Pause時, irssi被suspend了,該如何恢復?
A:
請直接輸入fg後按Enter ,就可以把剛剛被suspend的irssi給喚醒。

Q:如果我要關閉一個irssi,該如何下達指令?
A:
請直接關閉開啟irssi的screen ,請按Ctrl + k來關閉screen window,然後可以再重新開啟一個全新的 rssi出來。

Q:要如何自動儲存IRC log ?
A:
在需要auto irc log的IRC channel上輸入/SET autolog ON,即可打開autolog功能。

Q:要如何指定當開啟irssi後,自動連接IRC server與自動連接IRC channel ?
A:
直接看例子會比較快,先假設我要讓他自動用 lzy 的暱稱連接到Freenode的IRC server 上的#orzlab:
/network add -nick lzy Freenode
/server add -auto -network Freenode irc.freenode.net 7000
/channel add -auto #orzlab Freenode

如果是需要key/password的IRC channel的話,則把最後一行改為
/channel add -auto #irc_channel_name irc_server_name password
也就是直接把密碼接在後面就可以了
如果需要自動對註冊的暱稱進行認證登入的話 (設口令為abcde):
/network add -autosendcmd "/^msg nickserv ident abcde;wait 2000" Freenode

Q:如何讓irssi發出有人提起自己暱稱時的訊息警告(或響鈴)?
A:
在irssi裡輸入以下指令,讓irssi適時發出聲音訊號:
/set beep_when_window_active ON
/set beep_when_away ON
/set beep_msg_level MSGS NOTICES DCC DCCMSGS HILIGHT
/set bell_beeps ON

在screen中按下Ctrl +a , Ctrl + g的按鍵,讓screen把irssi發出來的聲音訊號傳出來
或參考Jedi的blog一文「會響的 PuTTY + screen + irssi
Q:如何更換irssi的theme ?
A:
把抓好的 theme(可從官網選擇偏好的),然後複製該theme的檔案到~/.irssi/路徑,並下達/SET theme theme_name來更改該 theme 。

Q:如何自訂irssi的IRC訊息熱鍵?
A:
因為設定比較繁雜,故只提供官網網址,讓有興趣的朋友可以自己去翻閱。

提供幾個額外補充的網站,沒標示語言者,皆為中文
※本文另有較鄉民版本:「用 screen + irssi 上 irc 之鄉民版教學 (含Q&A)

2007年7月31日 星期二

SLC ECC Correction in S3C2440

S3C24xx都內建有NAND Flash Controller,而且都支援NAND Flash Boot。NAND Flash 和NOR Flash 相比,除了不能用linear addressing的方式來access外,就是NAND Flash有「允許bit error」的特性,所以在實際的使用上,就要配合ECC 來correct。

NAND Flash Controller中NFECCSAT0就NFESTAT0 (0x4E000024) ,用來表示以下:

  • Main Area
  • Spare Area
兩個區域的「哪個byte中的哪個bit是錯的」,這就是NAND flash Controller提供的hardware ECC 功能。

S3C2440只支援SLC,因為只有內建1 bite ECC,也就是說只能correct 1 bit的錯誤。S3C2443則內建4 bit的ECC,最多可以correct到4 bit的錯誤,所以可以support MLC。

SLC和MLC除了1 time programming的限制外,就是容易產生的Error bit 數。
  • SLC保證 99.9999% 的chip 只會產生最多 1 bit的error。
  • MLC要到99.9999%的程度,會有 4 bit error。
(以上的% 是僅供參考)

回到NFESTAT0,要correct bit error,首先要check一下 error的狀態,以bit[1.0],[3.2] 分別代表兩個區域的error狀態:
  • 00 : No Error - Lucky
  • 01 : 1 bit error - Correct 回來
  • 10 : Multiple error - 沒救了
  • 11 : ECC area error - 沒救 (?)
所以,需要作ECC correct的,只有在 01 的時候。

然後讀出 Error bit 所在的byte位置和bit位置,分別是
  • Byte 位置 bit[17:7], bit[24:21]
  • Bit 位置 bit[6:4], bit[20:18]
所以correction 的動作
 *(ReadBuf + ByteNo) ^= ( 1 << BitNo ) 

SECCD 就是 Spare-area ECC Data
MECCD 就是 Main-area ECC Data

2007年7月30日 星期一

Baudrate set in S3C2443

S3C2442 的UART Baurdate可設定的更細微,提供兩個register :

  1. UBDIV : 整數部份
  2. UDIVSLOT : 小數部份
設定的計算為:
整數 + 小數 = SRCCLK/ (baudratex16) - 1
以115200, SRCCLK=40MHz為例
整數 + 小數 = 40000000/(115200 x 16) - 1 = 20.7
所以
整數 = 20
小數 = 0.7
因此,UBRDIV = 20

小數部份與UDIVSLOT的關係是
小數 = UDIVSLOT 中 bit是1的數量 / 16
所以
0.7 = 1's number in UDIVSLOT / 16
1's number in UDIVSOLT = 11
UDIVSLOT有很多種組合,只要讓1的個數是11即可,Samsung建議,個數為11時,UDIVSOLT用 0xDDDD。

2007年7月28日 星期六

筆記:Into Idle

在設定完chip register,進入idle mode後,還要program co-processor:
這一篇 http://nocash.emubase.de/gbatek.htm 有說明到ARM CP15 Cache Control。

Cn,Cm,Op2 Rd   Command
C7,C0,4 0 Wait For Interrupt (Halt)
另外在linux kernel code中也有:
/*
* cpu_arm926_do_idle()
*/
.align 5
ENTRY(cpu_arm926_do_idle)
#if defined(CONFIG_CPU_ARM926_CPU_IDLE)
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
#endif
mov pc, lr
ref SystemIdle Function:
MMU_WaitInterrupt(void)
mov  r0,#0x0
mcr p15,0,r0,c7,c0,4
mov pc,lr
所以,這是要cache 進入idle mode,等待interrupt 的意思 ?

S3C2412有三種Power mode:
  1. IDLE
  2. STOP
  3. SLEEP
是利用PWRMODECON 這個register來設定。

說是這樣說,但是Samsung的BSP code卻沒有這樣作,完全沒用PWRMODECON,反而是用 PWRCFG。其中的STANDBYWFI 佔2 bit,設定後,可以進入:
  • IDLE : 01b
  • STOP : 10b
  • SLEEP : 11b
這種利用寫入 PWRMODECON 的STANDBYWFIbit 的作法,在datasheet 中稱作是 "mcr p15, 0, r0, c7, c0, 4"。

datasheet 中「很好心」地為大家提供一個 "alternat method to set STANDBYWFI" :就是用剛剛的cp15 command:

mcr  p15,0,r0,c7,c0,4
但是沒有說明相當於command的哪一個信號? 01b, 10b, 11b ?

對照datasheet和BSP code:

STANDBYWFI 進入IDLE是 01b。
BSP code用 mcr cp15 command 進入時,Rd (在此用r0),卻是設定成 #0x0。

而且這是datasheet中有關"進入STOP Mode"的說明中寫的,BSP code卻是在進入idle mode 的code中使用的。

接著有一個table,說明進入三個mode的方法:
  • IDLE - STANDBYWFI
  • STOP - CMD or STANDBYWFI
  • SLEEP - CMD or STANDBYWFI
STANDBYWFI 的意思大概可瞭解,雖然有點不清楚,那麼"CMD"是什麼 ?是寫入command到PWRMODECON的MODESLEEP 嗎?

2007年7月27日 星期五

External Interrupt in S3C2440

S3C2440的EINT (Extend INT)中斷示意
s3c2440int

EINT也算是SUB INTERRUPT,但是完全沒有相似於SUBSRCPND的解說。只有register 說明,而且是安排在GPIO的部份... (好吧,該GPIO的mux function有Interrupt,所以算OK吧)

偉大的EINT的registerg的說明中,EINTMASK、EINTPEND這兩個register只有table,沒有多餘的說明。

本來以為EINTPEND是指「經過mask後的interrupt」,結果不是,是mask前。所以要處理 EINT時要這注意,要將 EINTPEND和EINTMASK「處理」後,才是真正產生中斷的中斷源。


跟trigger mode有關係,當是外部controller觸發,設定成edge trigger時,因為未回應外部controller時,trigger signal不會改變,不會再有一次edge波形發生,所以即使先ACK這個INT也沒關係。反而是未能要能正確,無漏失的catch next edge,ISR要儘快的ACK這個interrupt,免得edge 出現時,interrupt還未ACK而miss。

.. 真是麻煩呀...

這樣的連動是不是要用class包裝起來?當設定edge trigger,該isr先ACK。當設定level triiger,作post ACK?

回到上面的圖,SRCPND經過priority arbitration,Mask後,選出一個bit 到INTPND。實際產生中斷。

INTPND和SRCPND都是要「手動」清除的。
DataSheet (14. Interrupt Controller - Interrupt Pending Register) 是說..
Like the SRCPND register, this reister has to be cleaned in interrupt service routine after cleaning the SRCPND register.
所以,中斷發生後,一定要clear SRCPND和INTPND。而且順序是
  1. SRCPND
  2. INTPND
原因和上面說的一樣..如果先clear到INTPND,但是SRCPND還沒清,則同一個中斷馬上又從SRCPND浮上來,導致一樣的INTPND。

2007年7月26日 星期四

SMS PDU

ETSI (GSM 03.40 and GSM 03.38)中規範SMS的encoding可有以下幾類:

  • 7 bit encoding:最多可以包含160個characters,其中每個character只用一個或兩個byte的 7-bit data來作encoding。7 - bit encoding table 在.. http://www.dreamfabric.com/sms/default_alphabet.html 和ASCII Code比較後,除了0123456789、A-Z、a-z,和%$!*& ' ' 相同外,其他都不一樣。
  • 8 bits encoding:最多可以包含140 個字。通常用作非文字SMS,而拿來當作Data傳輸使用。
  • 16 bit encoding:最多只可以有 70 個'字',是用來傳送Unicode text messages。 可以當作文字讀取。
另外,還規範傳送的方式(Mode):
  • Text Mode
  • Pdu Mode
PDU (Protocol Description Unit)

PDU封包中,除了內文外,還包含其他的information,像是:
  • Sender
  • SMS service center
  • time stamp
傳送的data是以"hexa-decimal" or "decimal semi-octents"。

這個encoding有點麻煩,採用7 bit encoding是為了減少資料量。所以一個「字」就佔不滿一個byte,多的bit,就拿下一個「字」的bit,拿法是:
從下一個「字」中 ,從後算起,還沒被拿走的bit 拿起。
這一篇文章,有很好的示範.. http://www.dreamfabric.com/sms/hello.html

2007年6月29日 星期五

OLPC Hacking Meet-up心得

經過十天的等待,於於完成了這次「OLPC Hack Meet-Up Day」的活動。活動期間,感謝jollen、jserv、PingYeh、 Andrew、...等人提供不少對活動的經驗和建議。這段期間也感謝BV1AL、KC、olv、 FourDollars、linanne、aguai、wesley、thinker、yungyuc、gaso、yuren...等人的幫忙,才能順利將活動完成。

活動開始,先是由Mat簡單介紹一下如何用QEMU模擬OLPC和測試程式。之後則是共同開發和交流討論。21:10-22:00 則是展示時間,首先是jserv展示了QEMU用於模擬系統開發的各個應用,也現場展示了他最新的成果「親手打造Tablet / WebPad」。接著,FourDollars也跟著和大家分享影音串流程式最新的發展,分析未來的驅勢。並同時展示了一個他參考pcman的程式而改出來的影音外掛程式。可以非常方便的點選網路廣播並收聽,並發想也能整合進OLPC,提高OLPC的娛樂性。

而在PCMan on OLPC這個主題上,由國內開發LiveCD(USB)系列的BV1AL將gcinOLPC上的成果作成LiveCD的映像檔,並設定好網路等相關部分。而PCMan X開發團隊的字型好手olv ,則是解決OLPCPCMan X中文字型顯示的問題。在經過一段時間修改,順利將兩方的成果結合起來,如下:

雖然還是有許多小缺點,但這張快照也象徵了我們用行動來實踐我們的信念,也呼應了活動發起的訴求。

在活動期間,wesley、aguai、annelin... 也嘗試利用QEMU建立多個OLPC來模擬mesh network的測試環境。而Andrew、PingYeh、BV1AL、...在Tick偶然拿到OLPC實機的root console後,也著手研究了OLPC的系統更新、開機流程,相信不久之後也能見到相關的經驗分享。

最後希望能持續將這些成果整理出來,以開放的方式回饋給upstream和社群。

2007年6月28日 星期四

親手打造Tablet / WebPad

從事嵌入式系統開發,很大層面就是想體會「親手打造」的成就感。以往最大的問題就是進入的門檻較高,不僅得有開發硬體,還得要耗費大量的時間進行驗證測試,然而,這些繁瑣的過程會讓我們失焦,是的,最重要的部份,還是賦予硬體生命的軟體,這才是具備長遠價值的產物,一旦有了足夠的經驗與系統軟體,要在相容的硬體移植或加強功能設計,那就如魚得水了。

之前選定一個用以「練功」的題目「構想:Embedded Linux + Mozilla」,作法可有很多種,不過筆者嘗試以系統模擬的途徑,驗證「視覺化系統模擬與偵錯」一文中提出的概念:引入針對嵌入式裝置的基礎建設,作以system prototype、進階分析,以及快速軟體開發之用。上個月則於討論群組提出具體的想法「RFC: Tablet/WebPad 參考設計」,目前已稍有成果,在Google Code Hosting上申請了新專案「mind - MIND stands for "Mind Is Not a Device"」,可透過OpenEmbedded的迷你子集合去建構整個Embedded Linux作業系統,並調整為Tablet / WebPad的系統組態,以Xscale與x86作為參考開發的硬體平台,本階段已可使用Qemu為基礎的系統模擬進行驗證 (GNU Toolchain、Emulator,與Debugger均移植到Win32),以下是運作中的展示畫面:

這呈現了我們Embedded Linux平台的應用程式,即精簡版的Mozilla web browser,輔以XUL打造進階的使用者介面。這個系統主要是作概念性呈現,所以其他應用程式則相對單純,程式主畫面如下:
待作事項:
  • 針對ARM平台規範新的虛擬硬體組態,加入Wifi / Bluetooth裝置模擬
  • 加入網路管理程式,如Linetconf
  • 透過內建的OProfile進行深入的效能調校
  • 提供x86 LiveCD

2007年6月27日 星期三

在Ubuntu / Debian上啟動kqemu加速OLPC的執行

Mat 已經寫了一篇簡單的文件「Hello World for OLPC」,只要照著做就可以很容易的把 OLPC 利用 qemu 模擬跑起來了。不過如果可以先把kqemu的kernel module裝起來的話,那麼執行OLPC的模擬會更加的快速順暢。以下簡單介紹Debian/Ubuntu上啟動kqemu的方法:

1. 首先把相關的套件裝好

# sudo aptitude install module-assistant
2. 然後利用module-assistant編譯出kqemu的kernel module並且安裝到系統中
# sudo module-assistant auto-install kqemu-source
3. 最後載入模組並建立裝置節點
# sudo modprobe kqemu major=250
# sudo mknod /dev/kqemu c 250 0
# sudo chmod 666 /dev/kqemu
然後就可以照著Mat寫的文件跟著做即可。

另外~ 目前OLPC底層的作業系統是Fedora Core 6 (zod),所以啦,知道FC6怎麼玩的,基本上OLPC也是一樣地玩。

2007年6月25日 星期一

模擬Linux on Palm 5

Palm產品家族自第五代開始,部份採用Intel Xscale處理器,日前qemu的CVS tree也正式納入支援,於是熱血的hackers又開始鑽研是否可模擬Palm 5的硬體,並在其上運作Linux。在一番嘗試後,Alex很高興跟大家宣佈這個訊息,請見「Testing Linux4Palm on qemu」一文。他在 Hack&Dev計畫 (目標即是將Linux移植到原本運作PalmOS的硬體環境) 的程式碼加入以qemu為基礎的Palm 5的硬體模擬器,目前支援的硬體列表如下:

  • palmtc - Palm Tungsten|C (PXA255)
  • palmz72 - Palm Zire72 (PXA270)
  • palmtx - Palm TX (PXA270)
  • palmld - Palm LifeDrive (PXA270)
取得與編譯方式如下:
# svn co https://hackndev.svn.sourceforge.net/svnroot/hackndev/qemu/trunk qemu-hnd
# cd qemu-hnd
# ./configure --target-list=arm-softmmu --cc=gcc-3.4
# make -j2
預先取得必要的核心與檔案系統影像檔,假設解開壓縮檔後位於./palm/0.0.3-fnw目錄,則可透過以下方式執行: (其中一個hardware model)
$ cat RUN.sh
#!/bin/sh
BASE_DIR=`pwd`/palm/0.0.3-fnw
./arm-softmmu/qemu-system-arm \
-M palmld \
-kernel $BASE_DIR/zImage \
-sd $BASE_DIR/Angstrom-opie-image-palmld-0.0.3-alpha.rootfs.ext2 \
-append "root=/dev/mmcblk0 psplash=false"
啟動畫面如下:
過程中可透過qemu作LCD panel與終端機顯示 (serial) 的切換,也就是 Ctrl-Alt-[13]。以下是終端機操作畫面:
系統模擬越來越多元了。

2007年6月21日 星期四

Hello World for OLPC

許多朋友好奇前天的螢幕快照怎麼來的,其實過程並沒有想像中的那麼難。小弟就以作一個Hello World的程式作範例。

在開始之前,先假設你手邊已俱備下列幾個主要的工具:

  • QEMU i386 ( OLPC的平台是x86 )

操作步驟如下:

1. 首先取得OLPC的映像檔:按這裡下載

2. 啟動qemu
qemu -redir tcp:2222::22 olpc-redhat-stream-development-devel_ext3.img
其中 "-redir tcp:2222::22"的意思是將 QEMU中的OLPC的:22 Port和本機端的:2222 Port接在一起。

3. 取得終端機

進入到OLPC視窗環境後,在OLPC的模擬環境按 “
Ctrl-Alt-3”,就會進到console模式(要回到視窗模式請按 “Ctrl-Alt-1” )。接著用root登入(預設沒有密碼),就可以順利取得root console。記得順便設定一下root的密碼

4. 下一步?

根據官網上的說明,下一步應該就可以直接連線進去,但是實際上卻不行,為什麼呢?因為這時候的OLPC還沒有將網路啟動,需要先設定網路才行。

5. 設定網路

在root console下執行
ifup eth0
或是
echo ifup eth0 >> /etc/rc.local
設成下次自動啟動

6. 確定啟動sshd
/etc/init.d/sshd start
執行到這裡,我們已經有能力可以連線到QEMU中的OLPC了。

7. 連線到OLPC
ssh -X -o NoHostAuthenticationForLocalhost=yes -p 2222 root@localhost
其中 "-X" 是設定視窗轉送的參數。(可以執行xterm看看,所產生的視窗會將送到本機端來)。進行到這裡,我們已經有操控整個OLPC系統的能力,可以像使用一般Linux的方式去使用。

8. 如何作一個最簡單的Hello World?

目前OLPC並沒有內建gcc等開發工具。不過uname一下,可以發現OLPC的平台是i686。也就是說,我們可以先在本機端開發好程式,編譯好了再上傳執行即可。

而在OLPC裡的視窗程式執行環境為gtk、pygtk。我們不妨利用現在的pygtk來作為試驗。在這裡我們就直接引用pygtk給的官方範例

9. 如何上傳?

最直接的方式就是透過scp的方式上傳。
scp -o NoHostAuthenticationForLocalhost=yes -P 2222 ./helloworld.py \ root@localhost:/home/olpc/hello_world.py
10. 如何執行:

由於OLPC的XWindow是用olpc這個使用者的身份執行。所以在執行前記得切換成olpc這個使用者
su - olpc
之後用視窗轉送的方式來執行
DISPLAY=:0.0 ./helloworld.py
就可以看到簡單的Hello World的畫面了

2007年6月20日 星期三

多國語言支援的圖形化kboot

上週二 (Jun 12) 在TOSSUG聚會活動「2007 年第 7 場心得分享 - 組字的核心:字的結構」時,展示「Xorz/Embedded的動態組字實做」並提及可能的應用形式,我舉了關於boot loader的例子,作為說明動態組字技術在嵌入式系統的重要性。的確,隨著虛擬化技術與能源管理技術的突破,boot loader越來越多元,針對前者,得配合virtualization executive做出不同的啟動程序,而對後者來說,動態進階能源管理所建立的「中間資訊」(suspend to RAM / suspend to Disk),也需要作合理的處理,這都需要高度彈性的boot loader涉入。另外,我們可從DSLinux (port Linux to the Nintendo DS gaming console) 與PS3 Linux (SONY PlayStation 3的Linux移植) 等計畫發現,其移植的途徑不同以往,而是大膽採用kboot/kexec的機制來降低移植的難度,並提供多樣的應用方式,詳情可參考之前的文章「kboot初探與模擬驗證」。

早上在hack OLPC時,又想到上述議題,所以我決定作個概念性驗證的實做,驗證kboot這個「功能強大的Linux boot loader」對OLPC的影響。以往的boot loader雖然實做了圖形介面,但功能是很侷限的,頂多只能產生靜態選單與底圖,筆者的想法就是,用一個簡單的圖形系統取而代之,提供真正有彈性的使用者互動機制,而我們有Xorz/Embedded。另外一個議題是,我們應該允許不同的開機方式,比方說透過網路或USB隨身碟,而且可在任何時間切換,使用情境很直覺,可以假設一開始運作缺乏中文系統的OLPC預設Sugar UI,等有需要的時候,插入USB隨身碟,系統會彈出一個boot畫面,提示使用者是否要重新開機,因為透過kexec系統呼叫,這一切將會非常快速 (跳過BIOS與硬體初始化),而USB隨身碟上面的系統當然就可以有中文或者其他客制化的環境。

同時,筆者也想藉此彰顯在「組字技術與手持式裝置的新機會」一文表達的想法,為何我們千方百計想把CJK (中日韓) 語文整合到嵌入式系統設計呢?或許我們會犧牲美觀,但是可帶來對於多國語文最基本的顯示能力,這大可整合到boot loader或kernel中。聽起來很玄,俗語說:「一圖勝千言」,看看現在的進度:
以上呈現的想法就是動態讀取裝置列表 (透過udev與FreeDesktop HAL),讓OLPC的軟體建設得以作基本的probing處理,進而在小型的圖形環境中產生對應的動態選單與動作描述。圖片展示了讀取USB Disk,並取出其中的中文標籤,以選單方式讓使用者決定系統的啟動與否,甚至,我們可透過網路來啟動或更新整個OLPC,這一切將可相當有彈性。

附帶一提,右下角的圖示就是「OrzLab的吉祥物」:「囧囧」,正準備跳出傳統的PC,走向多種嵌入式系統裝置的新應用。

OLPC Hack Meet-Up Day

Mat稍早寫了「PCManX on OLPC」一文,提到他最近對OLPC所作的修改,並試圖移植知名的BBS連線程式PCManX到該平台上,不過礙於OLPC底層未能提供足夠的基礎建設,所以Mat發起一個活動「OLPCHackMeetUp」,邀請更多同好齊聚hacking。以下引述介紹文字:

== 活動宗旨 ==
國際知名的OLPC(One Latop Per Child,百元電腦)計劃正在進行,硬體製造的業務也由國內的廣達代工。然而國內社群對OLPC相關的知識並不多,軟體方面也參與的很少。 因此希望能藉著發起這個活動,引介自由軟體愛好者實際參與OLPC的軟體開發,同時能互相交流軟體開發的經驗和心得,並以開放的方式回饋給OLPC計劃與自由軟體社群。

== 活動目標 ==
在目標的選定上,我們希望能以一個近程目標來秀出我們的特有的特色軟體。於是我們選定開放的BBS軟體PCManX作為目標,同時也希望能在實作過程中,找出OLPC的中文支援的方法:

  • PCManX放進OLPC環境執行,並調整成符合Sugar (OLPC的外觀風格) 的應用程式風格
  • 實作glibc locale + Fontconfig data + TTF + SCIM以提供中文顯示、輸入環境

時間預定於June 28, 2007 (四),晚間19:00~22:00舉辦,歡迎參與OrzLab的討論「OLPC Hack Meet-Up Day」。至少有以下議題需要思考:

  • 輸入法的型態:傳統的GTK+ IM module或Ajax web IM
  • OLPC的軟體開發方式與模擬器的整合
  • 底層i18/L10n基礎建設

期待您的參與及指教!

2007年6月18日 星期一

PCManX on OLPC

感謝jollen前輩的幫忙,讓我有進一步接觸OLPC(傳說中的百元電腦)的機會。

去年年底時就聽了好幾次OLPC的新聞,能真的用到實品,興奮之情真是難以言喻。期待歸期待,真實世界的OLPC用起來感覺倒還不是很順暢。可能是裡頭的軟體版本還沒跟到最新版,或是還不夠成熟,沒有完全發揮硬體完全的效能的原因吧。

想要更新到最新的版本,然而手邊又沒有工具也是沒輒。幸好,拜模擬器之賜,軟體的開發不再死死侷限在硬體上。

OLPC的組織已經有提供好相關的軟體模擬環境和開發工具,讓參與者即使沒有機器也能進行軟體測試與開發的工作。其相關的聯結如下:

幸運的是,OLPC的本質就是Linux系統,只有表面的介面看起來不太一樣,其他的系統設定跟程式環境都一樣。只要拿到OLPC裡的super-user,理論上幾乎可以作到任何在Linux上的事。
「理論上?!」
我們總是需要作一些嘗試來堅定我們的信念。
BBS可說是咱在地特有的文化,適逢(Open-) PCMan於日前釋出2007的最新版本。何不移稙一個BBS軟體到OLPC上呢?經過幾天的嘗試,終於有了初步的成果如下:

2007年6月16日 星期六

kboot初探與模擬驗證

kboot本質上是個小型Linux作業系統,但功能卻是個boot loader,何解?kboot本身提供簡單的系統工具,支援檔案與網路操作,可自外界取得kernel image或其他檔案,進而kboot利用了kexec的機制,讓Linux kernel可快速重新啟動,於是具備boot loader的功能。

kexec是一組新的系統呼叫,包含在2.6 kernel中 (視支援架構而定),搭配其user-space的工具kexec-tools,則可在既有的Linux kernel (支援kexec系統呼叫) 中載入其他的kernel (不需要有kexec支援),並給予必要之參數或檔案,如kernel command line與initrd等,這方面的資訊可參考以下文章:

目前,kexec的硬體支援不限定x86,包含ARM與PPC都已有patch現身。那麼,如此的機制到底有什麼價值呢?以往的boot程序是很單純,清一色就是boot loader載入kernel,然後跳到user-mode或者是特定的工作,但現在的系統設計往往不是單一硬體、單一架構就可勝任的,諸如RAID或高負載的備援系統設計,都需要相當繁複的規劃,很顯然就非普通的boot loader可以應付,也很難修改Etherboot去圓滿符合需求,這時候,我們聯想到Linux,搭配到上述的kexec,不就是最美妙的boot loader嗎?在載入新的kernel之前,我們可作任何Linux能做的事情,像是載入firmware並進行設定、掛載NFS、掛載NTFS (透過Linux-NTFS)、... 等等,只要能提供新kernel給kexec-tools工具作載入,最後再透過kexec系統呼叫,就可完成這個「功能強大的boot loader」的終極任務。

kboot就是這樣的概念驗證實做品,使用的情境相當多元。舉例來說,kboot想進行遠端開機 (Diskless),但只有Wireless LAN或3G network可用,這時候就掛載對應的kernel module (包附在kboot中),然後透過user-space的應用程式進行設定,等待連線建立並確保檔案擷取成功,接著就在裝置上執行自遠端取得核心。另一種情境也很有趣,以往Linux distribution都得作通用性與最佳化的妥協,前者往往得將系統劃分諸多核心模組與大量的設定程式,後者往往得針對硬體作多次嘗試,那麼,透過kboot可先啟動generic kernel,然後進行硬體偵測,參考所需的硬體與最佳化組態,重新編譯核心,最後將該核心載入,而這個過程可透過一些設計得當的效能評估工具,一次又一次的重複自動微調,有別於以往的boot loader。關於kboot的應用,可參考以下簡報:後者給予我們極大的想像空間,當我們在新的硬體進行核心與週邊移植時,的確可先把能運作的最低限度核心置入kboot,然後再從不同的開發分支取得新核心並啟動,而這些過程都是透明的,而且不需要燒錄到傳統儲存裝置中,只要資源允許,可在RAM中做到繁瑣的事情。

昨天做了一個小hack,將原本的kboot (Version 11) 進行調整,更動紀錄如下:
Enhancements:
. Provided qemu specific configurations for verifying kboot
. Enable Visibility for gcc-3.4 (symbol hidden)
. Perform size optimizations against user-space packages.
Upgraded:
. kernel - 2.6.21
. binutils - 2.17.50.0.16
. uClibc - 0.9.29
我們甚至不需要單獨的x86機器,就能測試kexec與kboot,只要有能夠運作Qemu的環境即可。首先,取得OrzLab修改的版本:kboot-11-orzlab.tar.bz2,解開後直接打 "make" 就會建構整個系統,包含下載必要的套件、工具,以及編譯與安裝等。搭載於kboot的Linux kernel是精簡的版本,只提供TCP/IP stack、procfs、initrd/initramfs、ne2k NIC driver、VESA VGA framebuffer console等,但足以讓我們作許多應用。

Qemu提供DHCP與TFTP server的模擬,完全省下我們佈署的難度,所以在模擬環境中,所需的操作甚至大幅少於實體。筆者提供了簡單的script名為 "qemu-launcher.sh",直接執行即可,kboot啟動後的畫面如下:
依據Qemu的操作文件,預設透過模擬的DHCP server取得的IP是10.0.2.15,而server自己則是10.0.2.2,上面的畫面展示kboot已經載入一個小型的Linux kernel並出現提示訊息,等待命令操作,我們可打一些指令如下:
看到kernel version 2.6.21與ping連線的狀況,除此之外,還有ssh/sshd可用,所以大可連線到某台server,重新編譯核心程式碼,然後放到某個網路伺服器上。接著我們就要來驗證kexec/kboot的功能。Qemu內建的TFTP server相當好用,直接對應於host上的目錄架構,而就Debian/Ubuntu來說,host的核心會在根目錄建立symbolic link,而vmlinuz與initrd.img就指向目前運作的核心與initrd。

於是,我們在模擬的環境只要下簡單的一行指令即可載入並重新啟動: (鍵入粗體字部份)
kboot: tftp://10.0.2.2/vmlinuz
然後我們會看到 "Start Kernel" 的字樣跳過,然後我們就在Qemu的模擬環境看到啟動目前host上的核心:
因為在之前提供的qemu啟動script中省略root file system的指派,所以會停在kernel panic的畫面,不過這也達到我們的目的,驗證kexec/kboot,有了這個便利的模擬測試環境,未來也可作不同的變化。

2007年6月14日 星期四

WebKit的Gtk+支援

khtml是在KDE 2中,集合檔案檢視系統與網頁瀏覽器於一身的Konqueror內部主幹,是極為精美細膩的設計,如果說為一窺 KDE 技術最佳的進入點,那真是一點都不為過。由於khtml卓越的設計,很快就出現以khtml為基礎的網路瀏覽器專案,比方說運作於Qtopia (Core)之下的Konqueror/Embedded,而Apple Inc.也採納khtml,部分重新設計與最佳化就變成WebCore (MacOS X內建瀏覽器Safari的核心基礎建設)。而業界的應用也很廣泛,像是韓國嵌入式系統廠商Mizi Research就曾將Konqueror/Embedded經過一番調整,成為相當強悍的瀏覽器。

Apple Inc.提供了大量的修改,讓khtml的品質獲得極大的提昇,又在KDE開發者的斡旋下,Apple Inc.終於採納了社群開放發展的模式,於是KDE與Apple Inc.兩組開發人馬傾向共享WebKit的程式碼基礎 (codebase)。接著,Nokia也宣佈WebKit為基礎的S60WebKit (針對S60手機平台)與gtk+-webcore (針對Gtk+/X11環境),並依循LGPL與BSD License的方式,將修改貢獻回WebKit專案。

WebKit在這三年內蓬勃發展,提供了許多不同軟硬體平台的移植,值得一提的是新出現的GDK (Gtk+的低階圖形處理部份) 移植,這意味著WebKit可運作於GDK支援的環境,就嵌入式系統來說,我們會關注linux-fb與DirectFB兩個Gtk+/GDK所支援的backend。在近半年來的發展,WebKit的Gtk+/GDK移植已到堪用的地步,針對Nokia770/MaemoOpenMoko的硬體移植也出現成功案例。

為了降低建構WebKit/Gtk+的難度,我做了簡單的建構系統 (檔案:webkit-build-script.tar.bz2),允許從Subversion取出最新的發展版本,並作必要的設定,最後進行編譯。下載並解開後,直接執行以下script:

# ./BUILD.sh
中間會透過apt-get取得必要的開發套件。建構完畢後,大致的執行畫面如下:
(1) wiki.openmoko.org
(2) Google MapsWebKitOpenMoko GTA01也開始運作了,但還是有很多需要調整之處,這也是今年Google Summer of Code的項目之一,期待這方面的新進展。

2007年6月11日 星期一

從Chrasis談手寫辨識引擎在移動裝置的機會

Gentoo TaiwanPalatis日前公開他發展中的手寫辨識引擎與訓練程式,可參考blog文章「Chrasis 0.1.0 alpha!」,專案發展紀錄可參考Chrasis - Chinese Handwriting Recognition As-Is」,正如版本號所宣示的,現在還有很大的改進空間,不過已經初步可運作,以下是其訓練手寫辨識程式的執行畫面:
程式碼可透過Subversion存取:

# svn co svn://svn.berlios.de/chrasis/Engine/libchrasis/trunk libchrasis
# svn co svn://svn.berlios.de/chrasis/Linux/ChrasisTrainer/trunk ChrasisTrainer
libchrasis為手寫辨識引擎,其相依性有: (以Ubuntu 7.04為例)
  • libxml++2.6-dev
  • libsqlite3-dev
  • sqlite3
  • libboost-dev
ChrasisTrainer顧名思義就是訓練程式,以Gtk+打造,其相依性如下:
  • libgtkmm-2.4-dev
  • llibxml++-2.6-dev
測試了幾個簡單的中文字,都能正確辨識,算是不錯了。當然,手寫辨識的議題很複雜,以下是筆者在wiki - ChineseInformationProcessing的「手寫輸入」段落紀錄的部份資訊l:

以下為 rabit 的個人見解 (Modified by User:jserv):

  • KanjiPad 本身使用的辨識方法是很簡單的字典法,當使用者透過手寫版或滑鼠寫出字時,程式辨識出筆劃種類,並紀錄每個筆劃的順序,然後根據字典查出候選字。也因此,KanjiPad 根本不考慮寫出來的字形貌是否相似,只求筆劃順序相符。

chinput_5.gif

  • 以 Cinput (修改自 Kanji Pad) 的圖為例,「林」這個字辨識出來的候選字有「林、杯、枝、板、茂」,這幾個字右半邊的「木、不、支、反」筆劃順序都是跟「木」是相似的。這樣的演算法辨識 率是不高的,一但筆順不對,就很難辨識出來,不過話說回來,也不能太苛求 KanjiPad,因為它原本的用途就是日本人寫來學習漢字用的,可以說本來就是當作字典使用。
  • 中文手寫辨識是難度相當高的, 困難的地方有二:
    • 就技術而言,在辨識方面會用到許多數學模型,如 Baysian Decision Theory hidden Markov models、類神經網路等,而辨識中文還必須對中文字作分析,找出每個中文字的特徵 (筆形、筆順等),若要更精準,需拆解中文字成基本的部件,來作分析 (有點像漢字跡因工程),這時就要處理寫字上連筆的問題,技術上有實現的複雜度,但或許還不是最困難的。
    • 必須對每一個字的分析,建立資料庫,這是需要大量的成本 (包含時間、人力等),中文字尤其複雜,除了大量的漢字,還有異體字、罕用字等,我想這對 open source 是最困難之處,這跟 open source license 中文字型的狀況有些類似。
看似這是NP-Hard的問題,但如果我們思考Mobile 2.0對我們的衝擊,可以發現,大多數的手持裝置都需要手寫、筆跡、觸碰軌跡辨識的技術,而且也依賴原本在桌面系統的軟體元件與操作習慣,此時,危機反而就是轉機。具體來說,我們可思考「新酷音」一類智慧型輸入法如何移植到手持式裝置如PDA或SmartPhone一類的裝置,基本上,運算速度與儲存裝置都不是大問題 (早在兩年前,「新酷音」輸入法系統就證明在某隻SmartPhone上正確運作),真正的難題反而是輸入法的「輸入」本身。是的,以「新酷音」來說,支援兩種基本符號:
  • 注音符號
  • 拼音字母
這兩者背後也有學問,光是注音符號對照的鍵盤排列就可玩許多花樣,諸如許氏注音、倚天26鍵等等,拼音系統就不必多說,在台灣根本就是多頭馬車。以往,「新酷音」的開發者花了很大的心力去維護這些子系統的可用性與正確度,整合到libchewing (核心函式) 中,但如今要整合到手持式裝置,就面臨新問題:
「如何將傳統鍵盤的行為導入輸入法系統?」
我們首先會想到手寫辨識,就目前的系統來說,多半會內建OSK (On-Screen Keyboard),所以「新酷音」理所當然可架構於OSK之上,不過這與我們中文打字者的思維有很大的落差。何以此說?試想,「新酷音」的中文簡介是什麼?就是「智慧型注音輸入法」,透過統計與預測方式,大幅降低同音字詞的出現率,進而改善注音輸入的速度,使用鍵盤只是一種過度,真正使用者腦海中的思維,仍是「注音」(或拼音)本身,所以,日前筆者也跟Palatis聊到一種新途徑:
「何不直接辨識注音符號,然後導入新酷音輸入法引擎去作猜字處理?」
這種技術難度對於Chrasis一類的簡化手寫辨識引擎來說,算是綽綽有餘,如果不討論太複雜的連寫與草寫議題的話。某種角度來說,這說明了Mobile 2.0的思維方式:「過去的桌面技術有機會走入移動裝置之中」與「打破過去封閉技術的藩籬,個人也得以貢獻新的技術元素到移動裝置設計」,如今,我們有完全開放程式碼並開放手機規格與實做的openmoko、有高效率的動態組字技術,以及最寶貴的資源,也就是富有高度創意的自由軟體開發者,其整體的影響將會很有趣,手持裝置才正要作更有意義的應用,咱們拭目以待。

Xorz/Embedded的動態組字實做

之前的文章「Xorz/Embedded作為Phone UI」與「組字技術與手持式裝置的新機會」提到輕量級視窗圖形系統的實做進度,同時也思考組字技術帶來的新契機,無論是技術與實務規劃面來說,都還有很大的商議空間,但筆者認為這是必要的基礎建設。利用週末,終於在Xorz/Embedded實做出基本的中文動態組字功能,執行畫面如下:

以上展示「黃」(Unicode 0x9EC3)與其搭配不同組件 (部首) 的呈現方式。原本single.fnt (剎那單線體) 定義為:

!009EC300|黃0=0000162E0001F02E00005A1100015A5E0000A8110001A85F0000595F0001AC5F00000A5F0001F55F00003C7300013CCE00003D7B0001CA7B0001CACF00003B9E0001C99E00008066000180C1000062D6000242EB000116FA00009AD00002D0E50001DEF700003CC00001CAC0
又,考慮美觀,我從文鼎楷體轉出了stroked font,從而做了細部的調整,這方面還得與剎那搜尋工坊討論如何整合,但基本上組字的概念是可以延續的。「黈」這字在single.fnt是如此定義:
009EC800|黈0=黃0131272E1主0811078D9
相當明顯就是「黃」與「主」兩部件的左右結合,同理,「黌」則定義如下:
009ECC00|黌0=00D07E66B黃0156AD78A
改為上下部件的結合。當然,目前的實做還很陽春,但已經看得出效益,以目前的stroked font engine來說,只要先描述以上三個組件,如「黃」與「主」:
/* 0x9ec3 (黃) */
3, 66, 56, 0,
'm', 28, -36,
'2', 29, -36, 29, -36,
'2', 33, -37, 39, -37,
...
接著就採用single.fnt所定義的組字表示,去作遞迴表示即可,大幅省下儲存空間,也可避免許多維護成本,更重要的是,這一舉克服以往字型檔與程式碼不對稱的問題。除了中文動態組字外,其實Xorz/Embedded的繪字引擎也允許一些變化,比方說「Q版」的呈現,有點像是塗鴉文字,行文甚至有互相疊合的效果,這是為了配合某些特殊的應用,如廣告文字,所特別設計的系統,畢竟Xorz/Embedded一開始的定位就是針對嵌入式系統的特製輕量級圖形系統。

恰好TOSSUG在本週二也請到國內在動態組字學有專精的前輩,為我們分享中文缺字議題、動態組字技術,以及進行中的變革,詳情可參考「Tossug 2007 年第 7 場心得分享」,如果當天有空檔,或許筆者也可來作些介紹與展示。

2007年6月1日 星期五

build u-boot from sources

因為openmoko patch的u-boot有支援Samsung S3C24xx的stepping stone,所以build看看。

主要是follow這一篇文章 "Migration to bad block tolerant builds",說明比u-boot那一篇仔細 (但是我apply 609的patch沒有成功,所以還是使用main stream)。

工作的目錄是 /home/openmoko

裝好subvesion,設定svn使用proxy,在~./subversion/server中加入proxy server,port :

http-proxy-host = 10.1.1.200
http-proxy-port = 3000
checkout openmoko 到 openmoko 目錄
$ svn co https://svn.openmoko.org/ openmoko
安裝git-core,改變default git tool (debian etch)
$ aptitude install git-core
$ update-alternatives --config git
== 選 "git-scm"
export 好http_proxy,checkout u-boot
$ git clone http://www.denx.de/git/u-boot.git
(需要等待一段時間)

取得cross toolchain : 因為monotone出不去proxy (雖然mailing list中聲稱新版的monotone可以經過proxy,可是我這裡還是出不去),所以只好直接從 openmoko拿build 好的cross tool
$ wget -r -L http://buildhost.openmoko.org/tmp/cross
(需等待更長時間,且lib/下的檔案有些沒有抓回來,要確認一下,加上 "-c"抓沒抓到的folder。修改 bin 下的file,設為可執行。)

把抓下來的toolchain copy到 ..
/space/fic/openmoko/gta01/tmp/cross
設好PATH:
$ export PATH=/space/fic/openmoko/gta01/tmp/cross/bin:$PATH
u-boot - apply patch: (要先裝好quilt)
$ cd u-boot
$ export QUILT_PATCHES=/home/openmoko/openmoko/trunk/src/target/u-boot/patches
$ quilt push -a
Ok,沒有error message。

build u-boot - config and make:
$ make ARCH=arm gta01bv2_config
$ make ARCH=arm
完成。

2007年5月31日 星期四

組字技術與手持式裝置的新機會

專注於中文技術的剎那搜尋工坊推出新版 (2007.05.26) 的「剎那字引」軟體,其概念相當特別,以「部件」來分析漢字 (泛指中日韓漢字) 進而可做出正向或反向的資訊化操作。就完整的中文處理系統來說,不僅要考慮畫面或裝置輸出,還有繁瑣的輸入法,但受限於異體字、錯別字,或可用性等考量 (特別是手持式裝置來說,得提供一定程度的「漢字容錯」處理),每每挑戰著設計者的技術水準,但這方面的議題並不是建立大量的state machine就可克服的,我們得從漢字本質去思考。

剎那字引」的執行畫面如下: (Win32/Delphi Application running via WINE/Linux)
我們可一目了然得知特定部件與其對應的漢字,這可用一致性的數學模式去表示,不過這裡就不贅述了,可參考Foxman前輩發表的一系列文章。對於手持式裝置來說,漢字的輸出與輸入之間即有一定程度的關聯,比方說手寫辨識就與組字在概念上有共通處,而漢字構形資料可作反拆或逆向查詢與推斷,意味著可運用於輸入法的輔助索引處理的機制,是此,即使是手寫辨識的操作,甚至可簡化為只需書寫偏旁,系統反推並決定候選字 (與其組合),大幅降低辨識的複雜度,或考慮到傳統的輸入法,這就是一個相當有效率的「過濾器」。

再來我們可回頭思考漢字系統長久以來的缺字問題,儘管桌面應用已經逐步改善此議題,對於手持裝置來說,仍是極大的衝擊。當然,國際大廠注意到這類需要對資源錙銖必較的裝置上,做完整中日韓多國語文處理的議題,本身就是兼顧技術、可用性、價格成本,與後端交換碼種種妥協的設計,所以IICore (International Ideograph Core) 標準被提出,預期成為手機、PDA等移動通訊產品的重要規格,原則上不超過一萬字,是Unicode的子集 (碼位大幅調整)。問題是,我們應著眼於深入更多觸角的移動通訊運算,不該僅用常用的表意文字來限制資訊系統的使用。人們都有使用行動通訊裝置的自由,卻往往受限於種種預設立場的桎梏,這是相當不合理的事情,勢必,技術上得有所突破。

基於以上考量,動態組字技術於手持式裝置的需求,越來越顯見其重要性,正如之前文章「紀錄:可攜式造字引擎專利釋放暨成果發表會」所提及的概念,我們可發現運算技術、文化需求,以及M化等因素的交錯即將邁入臨界點,未來將以何種方式呈現?不得而知,但我們實在有必要將基礎建設完善化。

2007年5月30日 星期三

GSM modem裝置模擬

系統模擬對於嵌入式系統開發來說,是相當重要的里程,不僅晶片層面如此,對於週邊來說,更可對應用程式開發帶來立即的效益,現在,OpenMoko-emulator也提供虛擬GSM modem的模擬。首先,依據之前的文章「透過USB連線與OpenMoko模擬裝置互動」,建立虛擬USB network連線,並透過ssh連線到虛擬硬體中,接下來就可以進行GSM modem的操作,畫面如下:(粗體字是打入的指令)

$ ssh root@192.168.0.202
root@192.168.0.202's password:
root@fic-gta01:~$ libgsmd-tool -m shell
libgsm-tool - (C) 2006 by Harald Welte
This program is Free Software and has ABSOLUTELY NO WARRANTY

O
# # Power-On
R
# Register
也可以不透過OpenMoko的工具,直接下AT command:(粗體字是打入的指令)
root@fic-gta01:~$ /etc/init.d/gsmd stop
Shutting down gsmd: Terminated
root@fic-gta01:~$ echo 1 >/sys/bus/platform/devices/gta01-pm-gsm.0/power_on
root@fic-gta01:~$ cu -E @ -l /dev/ttySAC0
Connected.

ATE1
OK
詳情可參考Marcin Juszkiewicz的文章 "How to check does GSM modem works",但對於openmoko-emulator也適用,甚至我們還可以模擬出各種不同的反應,卻不需要任何實體環境介入,這是相當有意思的手機軟體開發方式。

quilt - patch tools

quilt 是用來patch很多patches時使用,使用的方法是

quilt cmd
可以用
quilt cmd -h
來看可用的command有哪些。

因為是多個patch files,所以有一定的patch 順序,quilt會幫我們handle這些順序 (因為當初這些patch 也是由quilt 產生的呀)。就像stack操作一樣,push (apply) 一個patch;用pop 把sourcecode回到上一個沒patch的狀態。

所以,quilt也可以當作是簡易的Version control system用。

quilt的操作,將所有的pacth檔都放在要patch的source directory中的"patches"目錄。 (可以是symbolic link)

剛剛講的patch stack (patch 順序) 就紀錄在 "patches/series" 這個file中。

所以openmoko 的bootloader patch apply 的方法就是:
  • download u-boot latest versio (svn checkout lateset version)
  • download openmoko u-boot patch (是一個folder)
  • 把這個patch folder copy 到 download 的u-boot folder中
  • run quilt push -就會依照應有的順序apply 所有的patch.
That's all.

2007年5月26日 星期六

GCC Visibility與軟體最佳化

以前在blog文章「Qt Library 的精簡」提到GCC的C++ Visibility,其實官方的wiki已經描述相當清楚,引述如下:

"Why is the new C++ visibility support so useful?

Put simply, it hides most of the ELF symbols which would have previously (and unnecessarily) been public. This means:

  • It very substantially improves load times of your DSO (Dynamic Shared Object). For example, a huge C++ template-based library which was tested (the TnFOX Boost.Python bindings library) now loads in eight seconds rather than over six minutes!

  • It lets the optimiser produce better code. PLT indirections (when a function call or variable access must be looked up via the Global Offset Table such as in PIC code) can be completely avoided, thus substantially avoiding pipeline stalls on modern processors and thus much faster code. Furthermore when most of the symbols are bound locally, they can be safely elided (removed) completely through the entire DSO. This gives greater latitude especially to the inliner which no longer needs to keep an entry point around "just in case".

  • It reduces the size of your DSO by 5-20%. ELF's exported symbol table format is quite a space hog, giving the complete mangled symbol name which with heavy template usage can average around 1000 bytes. C++ templates spew out a huge amount of symbols and a typical C++ library can easily surpass 30,000 symbols which is around 5-6Mb! Therefore if you cut out the 60-80% of unnecessary symbols, your DSO can be megabytes smaller!

  • Much lower chance of symbol collision. The old woe of two libraries internally using the same symbol for different things is finally behind us with this patch. Hallelujah! "


事實上,對於許多採用C語言撰寫的專案也適用,而且效果很不錯。嵌入式系統開發時常常得控制程式空間使用量,咱們就來看看具體的案例,包含Nokia 770/800與OpenMoko在內的許多專案,採用X Window System,server端的實做是KDrive,而client端雖然只要能跟X Protocol即可,不限定程式語言與實做,但往往我們會透過libX11。就如筆者之前的演講與blog提及,X本身的效率其實很好,但問題在於複雜的軟體實做,其中有許多改進的空間,libX11就是一例。

剛剛做了些hacking,發現光是利用GCC的C++ Visibility來隱藏非公開的API/ELF symbol,即可大幅降低空間使用量,並提昇載入應用程式速度。

在Ubuntu 7.04上進行測試,同樣的libX11套件,施加我的修改:libX11-visibility.patch後重新編譯,比較兩者的差異: (stripped)
  • /usr/lib/libX11.so.6.2.0 (原本) - 964K
  • dist/usr/lib/libX11.so.6.2.0 (修改過) - 839K
相當顯著的差異,接著比較兩者透過size指令的落差:
textures datatype bss_seg decided hexunfilenamefilename
966896 14496 1596 982988 effcc/usr/lib/libX11.so.6.2.0 (原本)

textures datatype bss_seg decided hexunfilename
827962 11336 1224 840522 cd34adist/usr/lib/libX11.so.6.2.0 (修改過)

於是乎,我們可參照wiki上對於DSO的描述,這之間的意義不僅是空間的降低,對於Code optimizer來說,也允許更多積極的處理方式,最重要的是,符號解析的速度提昇,也避免潛在的符號衝突。這是很簡單的修改,但影響卻相當顯著,我們也可看到整個Gtk+/GNOME的架構仍有最佳化的空間。

2007年5月25日 星期五

OpenMoko演講影片上線


psilotum的協助下,5/8在Tossug聚會所演講的「Free your phone! OpenMoko」過程都完整的錄影下來了,在 Google Video 上甚至還可以清楚看到簡報內容。請享用!

Credits:

Speakers: Sean Moss-Pultz/Harald Welte
Host: Tossug/Ping Yeh
Organizer: Rex Tsai
Producer: psilotum


備註: 我們不是在甚麼奇怪的地方,背景是天邊一朵雲的法國版海報,Cafe Lumiere 只是一家貼滿海報的咖啡店而已。


Source: http://people.debian.org.tw/~chihchun/2007/05/25/talk-of-openmoko-is-online/

串連WIFLY與FON AP

四元(4$) 一直對小巧可愛的路由器非常感興趣,他寫了一篇關於 「Linux絕對有支援的無線網路卡」提到了ASUS WL-330gD-Link DWL-G730APBelkin Wireless G Travel Router 等非常省電容易攜帶的產品。

4$動了一個主意,想把可愛的La Fonera改裝成類似上述的產品,可以透過Ethernet 連上WiFi AP,再透過WiFi AP連上外部的網路。由於4$Hackathon的時,在cclien的協助下,成功的編譯了OpenWrt的開發版 Kamikaze,並燒進FON La Fonera中,因此他需要做的只是再把設定寫進去即可。

Hacking La fonera

2007年5月23日 星期三

ARM模擬的狀態保存

前文「透過USB連線與OpenMoko模擬裝置互動」指出現在透過qemu來模擬openmoko已有相當便利的互動機制,我們也隨時可在Qemu Monitor中監看與控制虛擬機器的狀態,Andrzej Zaborowski最近實做了ARM模擬的狀態保存,所以現在可快速load/save vm,如此一來,應用程式的開發與驗證更加便利。目前也整合到openmoko-emulator中,取得最新的發展版本:

$ svn co https://OpenSVN.csie.org/openmoko_addons/openmoko-emulator
現在openmoko/run.sh這個script已處理qemu-img的操作,所以我們只要如往常一般編譯與執行即可。舉例來說,我們希望保存開機完成、見到整個OpenMoko UI的狀態,那麼只要按下Ctrl-Alt-2以切換到Qemu Monitor畫面,在提示符號下先暫停虛擬機器的系統模擬動作:
(qemu) stop
接著就可以保存狀態:
(qemu) savevm mainwindow
參數 "mainwindow" 只是一個識別名稱,事實上我們可以在不同的狀態給予特定的識別,這時候我們可以結束虛擬機器的執行:
(qemu) quit
然後我們重新啟動openmoko-emulator (run.sh),立刻切換到Qemu Monitor,隨後在命令提示打入指令以查看保存的狀態:
(qemu) info snapshots
應該會得到類似以下的輸出:
Snapshot devices: mtd
Snapshot list (from mtd):
ID TAG VM SIZE DATE
1 mainwindow 22M 2006-05-23 11:11:35
要還原已保存的狀態相當直覺,只要打下指令:
(qemu) loadvm mainwindow
再按鍵Ctrl-Alt-1切回執行畫面,這時候就可以看到上次我們保存的狀態與畫面了,當然,配合前次提到的Linux gadgetfs,我們還可存取USB (emulated) network,這樣進行應用程式開發的彈性也提昇許多,若再引入自動化的機制,未來要實做「時光機器」也是相當可行的。

2007年5月21日 星期一

OpenMoko at Tossug

Sean Moss-Pultz

5/8在Tossug舉辦的分享活動算是相當成功,當天總共來了超過五十位聽眾。許多朋友也留下聯絡資訊,或許可以加入開發社群或即將成立的OpenMoko公司

演講分為兩節,Sean Moss-Pultz介紹關於OpenMoko的背景故事、起源與目標。而 Harald Welte 則介紹軟硬體等技術細節。

Harald Welte

演講完整錄影,影片將上傳至網路,簡報一併於稍後提供。謝謝psilotum攝影,以及Tossug工作人員的辛苦籌備。

原文: http://people.debian.org.tw/~chihchun/2007/05/17/openmoko-at-tossug/

Working on Neo1973

Working on Neo1973

這是4/14在Mix coffee & tee的工作畫面 (工作紀錄, Minicom log for reflash images on Neo 1973),我們將Neo1973拆解,並試著reflash與裝上debug board。我很喜歡這張照片,謝謝psilotum的攝影。

原文: http://people.debian.org.tw/~chihchun/2007/05/17/working-on-neo1973/

Cheapest ttl2usb converter for la fonera

本來是想一起參加台灣黑客鬆的聚會,因為Jserv跟幾位朋友想在La Fonera上動動手腳,試著在La Fonera上玩玩AJAX/Web Server for embedded system。然而因為會議太忙,兩天都沒辦法出席,真是對不住。cclien寫了一篇相當不錯的文章,紀錄了黑客鬆的過程。最後他們是將Wt移植到La Foera 上,Jserv於OSDC中也針對此議題給了一個 lighting talk

EGLIBC初探

在Embedded的環境下,我們有許多C Library的選擇,從BSD libcuClibcglibcdietlibc,甚至是klibc (配合initramfs),過去我們考量到footprint,往往會捨棄發展活躍的GNU C Library (glibc),轉而以uClibcdietlibc來建構系統,正如uClibc的FAQ網頁提及的項目 "What's wrong with glibc?" 所說:

"The GNU C library is a great piece of software, make no mistake. It is compliant with just about every standard ever created, and runs on just about every operating system and architecture -- no small task! But there is a price to be paid for that. It is quite a large library, and keeps getting larger with each release. It does not even pretend to target embedded systems. To quote from Ulrich Drepper, the maintainer of GNU libc: "...glibc is not the right thing for [an embedded OS]. It is designed as a native library (as opposed to embedded). Many functions (e.g., printf) contain functionality which is not wanted in embedded systems." 24 May 1999"
以及下一條 "So uClibc is smaller then glibc? Doesn't that mean it completely sucks? How could it be smaller and not suck?" 所說:
"uClibc and glibc have different goals. glibc strives for features and performance, and is targeted for desktops and servers with (these days) lots of resources. It also strives for ABI stability. On the other hand, the goal of uClibc is to provide as much functionality as possible in a small amount of space, and it is intended primarily for embedded use. It is also highly configurable in supported features, at the cost of ABI differences for different configurations."

所以很明顯,glibc考量到通用性系統的需求,許多部份會考量到效能的最佳化處理,所以光是字串函式往往就可能拆成許多程序來實做,以針對不同的資料量給予最佳效能的處理方式,但往往也必須付出大量的footprint衝擊。Greg Alexander甚至寫了一篇用詞尖銳的文章 "GLIBC SUCKS" 來闡述他的觀察:就算是簡單只用printf()函式的 "Hello World" 程式,竟然也不成比例的龐大,引述如下:

Let's perform some more GLIBC2 vs. BSD libc comparisons:

[greg@linux] ~$ gcc -static -o hello hello.c; strip hello
[greg@linux] ~$ du -sk hello
416 hello
compared to:
[greg@freebsd] ~$ gcc -static -o hello hello.c; strip hello
[greg@freebsd] ~$ du -sk hello
44 hello
Yeah, that's right, when statically linked GLIBC2's printf() and support routines are about 10x as big as BSD's. We're on computers, a 15% improvement is considered worth looking at so you can copy their techniques. An "order of magnitude" is 2x. You simply aren't expecting 10x differences between extremely simple code that hasn't advanced, technologically, in more than two decades.
可見如此簡單的應用程式,其空間使用竟然達十倍之譜,在筆者的「深入淺出Hello World」系列演講也提及許多glibc與gcc潛藏的神秘性質,這些對於有特定目標、空間侷限的系統來說,是很難允許的。但採用非glibc的解決方案雖可大幅降低footprint與系統複雜度,卻可能因而限制可用的應用程式,最有名的例子就是Mozilla一直無法在uClibc上正確編譯與執行,這也辜負了採用GNU/Linux作為Embedded system作業系統的美意。過去我們得因應需求與彈性考量,多方取捨並周旋於前述的C Library實做中。

專注於GNU開發工具研發與客制化的CodeSourcery公司與若干嵌入式系統大廠,諸如MontaVista、Freescale,及WindRiver等廠商合作,針對glibc的改進計畫 (自2.5版開始),實做出更適合Embedded環境的C Library實做 -- EGLIBC,並承諾與glibc的binary/source compatibility,其明確的目標可參考EGLIBC::Mission網頁:
" Expand and enhance the capabilities of the GNU C Library (GLIBC) to support embedded systems for diverse environments, and maintain an open development environment encouraging broad, cooperative developer participation."
所以採取同樣的codebase (svn merged from FSF),同時也確保是Free Software (copyright holder為FSF),在mailing-list也可見到「借力使力」的發展模式,如Joseph S. Myers的post "[patches] EGLIBC 2.6 created"。Jollen兄日前在「Embedded Device 等於 PC」一文提及以下概念:
「就現代的硬體來說,embedded device 和 PC 的界線是越來越小了,雖然有時參與的 project 是 'embedded device',但是技術本質上就好像在做 PC 一樣。」
這是非常有趣、值得思索的趨勢,拜硬體蓬勃發展所賜,我們得以在此時間點大量採用原本桌面系統的軟體建設,知名的OpenMoko計畫就是最好的明證,但畢竟嵌入式系統的考量仍有差異,所以今日我們有以下發展理念:
  • 銜接活躍的自由軟體開發
  • 不只採用開放的系統,更要有開放的發展心態
  • 將力量集中於刀鋒上,創造核心價值
這使得採用EGLIBC成為多贏的解決方案,於是OrzLab也開始評估這些嶄新技術。延續之前的分析與模擬驗證 (詳見「視覺化系統模擬與偵錯」一文),最近的重心放於ARM Embedded ABI、GCC 4.2,與EGLIBC等最新的技術,為了簡化進行流程,我改了簡單的script:toolchain-eglibc.sh,這可自動擷取原始程式碼並建構。執行方式很簡單:
./toolchain-eglibc.sh arm
成功編譯後,會在$HOME/cross-build/arm-none-linux-gnueabi目錄下建立以下子目錄:
  • obj : 建構過程的目的檔,可忽略
  • tools : 包含GNU Toolchain
  • sysroot : 置入target的Runtime (root file system)
稍後筆者會探討如何利用系統模擬器來驗證,並探討整體效能與記憶體使用的提昇。

Update: Jick的更新與修正可參考「EGLIBC: Embedded GLIBC 体验

2007年5月19日 星期六

避免cross-compile的陷阱:libtool

在Unix系統上,有個知名的 "make" 工具,可協助開發程式,但是隨著程式開發複雜度的提昇,已經很難用有限的 "make rules" 來滿足多變的需求,所以Cygnus/RedHat的Tom Tromey就設計autoconfautomake等工具,期望大幅降低異質性平台開發的困難。這也包含所謂的cross-compile,為了克服不同平台的函式庫編譯落差, libtool也被提出,立意甚好但往往讓我們遇到不少問題,比方說知名的hacker - Casey Marshall - 就在與這些上萬行的工具程式奮戰一段時間後,寫了篇短文 "Avoiding libtool minefields when cross-compiling"。autoconfautomake等工具最核心的想法就是希望編譯過程可以簡化成如下: (以x86下進行ARM-Linux程式編譯為例)

./configure --host=arm-linux \
--prefix=/usr \
--enable-shared \
--enable-Feature1 \
--disable-Feature2
筆者參與的若干自由軟體計畫中,也陸續導入此設計,如上的組態所示,我們指定cross-compile的對象為arm-linux,automake會依據特定條件去找尋與測試編譯環境,同時我們啟用Feature1與抑制Feature2,接著一堆上萬行的Makefile就會乖乖建構了。那麼,問題在哪呢?我們很常見到以下的編譯錯誤:
/bin/sh libtool --mode=link target-gcc -c -O2 -o libbar.so ... -lfoo
target-gcc -c -O2 -o libbar.so ... /usr/lib/libfoo.so
/usr/lib/libfoo.so: could not read symbols: File in wrong format
collect2: ld returned 1 exit status

很明顯,libtool被誤導,原本該尋找arch = arm的程式檔案,沒想到抓到host (x86)上的檔案,為何如此?我們隨便挑一個描述程式連結資訊的*.la檔案:
$ cat /usr/lib/libesd.la
# libesd.la - a libtool library file
# Generated by ltmain.sh - GNU libtool 1.5.6 (1.1220.2.95 2004/04/11 05:50:42) Debian: 224 $
#
# Please DO NOT delete this file!
# It is necessary for linking the library.

# The name that we can dlopen(3).
dlname='libesd.so.0'

# Names of this library.
library_names='libesd.so.0.2.36 libesd.so.0 libesd.so'

# The name of the static archive.
old_library='libesd.a'

# Libraries that this one depends upon.
dependency_libs=' -L/usr/lib /usr/lib/libaudiofile.la -lm'

# Version information for libesd.
current=2
age=2
revision=36

# Is this an already installed library?
installed=yes

# Should we warn about portability when linking against -modules?
shouldnotlink=no

# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''

# Directory that this library needs to be installed in:
libdir='/usr/lib'
再清楚不過,這肇因於將libdir指向Host/x86上的目錄下,但這些*.la檔案已經置放於 "staging" (工作區),於是我們可用GNU sed去更動。比方說 "staging" 目錄於 /tmp/rootfs,那麼:
sed -i~ -e "s;/usr;/tmp/rootfs/usr;"
這之間有頗多繁瑣的工作,還好OpenEmbeddedautoconfautomake,與libtool作了修正,所以大部分的Automake-based applications可以很容易透過OpenEmbedded去建構,但副作用則是需要re-generated,又,這樣的套件或應用程式往往佔多數,耗費的時間也相當可觀。

透過USB連線與OpenMoko模擬裝置互動

前幾篇文章介紹如何透過qemu來模擬openmokoPoky,這部份的開發逐漸穩定,而qemu現在對於硬體的模擬也頗完整,很多時候我們可直接指定Ethernet模擬來作PXE/BOOTP/TFTP開機或DHCP,於是Host與(Emulated) Target互動就相當簡單。但,如果是openmoko Neo1973/GTA01這類沒有Ethernet (頂多只有Wifi或Bluetooth)的硬體裝置,該如何互動呢?最近加入USB gadget模擬的支援,可將USB slave轉包到Linux 2.6的gadgetfs,如此一來,我們就可建立USB (emulated) network,兩端也可用NFS或sshfs來作檔案分享存取。

在Ubuntu 7.04上操作的方式如下,注意,建議使用一般權限進行,並善用sudo的機制。

取得Linux Kernel原始程式碼:

$ apt-get install linux-source-2.6.20
解開檔案並給予目前的組態:
$ cd /usr/src
$ tar jxf linux-source-2.6.20.tar.bz2 && cd linux-source-2.6.20
$ cp /boot/config-`uname -r` .config
因為Ubuntu預設的USB Gadget/Peripheral controller是實體裝置,但我們需要dummy_hcd (Dummy/Loopback USB host and device emulator driver),所以我們得調整設定:
$ patch -p0 < dotconfig_dummy_hcd.patch
然後建構我們需要的核心模組:
$ make MODVERDIR=drivers/usb/gadget \
drivers/usb/gadget/dummy_hcd.ko \
drivers/usb/gadget/gadgetfs.ko
順利的話就會有兩個 .ko檔,接著就安裝:
$ sudo insmod drivers/usb/gadget/dummy_hcd.ko
$ sudo insmod drivers/usb/gadget/gadgetfs.ko default_uid=`id -u`
Host端需要一個名為/dev/gadget的目錄,以掛載gadgetfs:
$ sudo mkdir -p /dev/gadget
$ sudo mount -t gadgetfs gadget /dev/gadget -o noauto,user,group
核心的部份告一段落,接著我們要來建構qemu,取得最新的openmoko-emulator:
$ svn co https://OpenSVN.csie.org/openmoko_addons/openmoko-emulator
編譯時期需指定kernel header (Ubuntu預設沒有打包全部USB gadget的header):
$ cd openmoko-emulator
$./configure --cc="gcc-3.4 -I/usr/src/linux-source-2.6.20/include"

在最後一行輸出應該要有以下字樣:
USB Gadgetfs support yes
接著就打 "make",順利的話會在arm-softmmu目錄產生名為qemu-system-arm的執行檔。我們可透過script自動下載u-boot、kernel,與rootfs等images並「燒」入我們的模擬硬體中,操作如下:
$ ./openmoko/download.sh
$ ./openmoko/flash.sh
正確的話,畫面會提示run.sh的script檔案被生成,咱們就來跑看看:
$ ./openmoko/run.sh
操作方式在前文「OpenMoko/Neo1973硬體模擬」已提及,不贅述。等X Window的畫面都出現後,就是運用gadgetfs的時機。按下Ctrl-Alt-2組合鍵切入Qemu Monitor,我們可監控與管理Qemu的狀態,當我們打入"info usbslave"指令時,應該有如下的輸出:
USB2.2 device 1457:5122:
Manufacturer: Linux 2.6.20.7-moko8/s3c2410_udc
Product: RNDIS/Ethernet Gadget
Configuration 0: RNDIS
Configuration 1: CDC Ethernet
因為openmoko在啟動X的時候會順便將USB network帶起,這時候我們就可透過gadgetfs去讓Host與(emulated) target互動。同樣在Qemu Monitor畫面,打入 "usb_add gadget:1" 指令,若無錯誤訊息,表示已成功。在Host上的終端機檢查USB gadgetfs的狀態:
$ lsusb -v | grep -A10 -B12 s3c2410
應該會有以下輸出:
Bus 004 Device 003: ID 1457:5122
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 2 Communications
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x1457
idProduct 0x5122
bcdDevice 2.12
iManufacturer 1 Linux 2.6.21.1-moko8/s3c2410_udc
iProduct 2 RNDIS/Ethernet Gadget
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 80
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 7 CDC Ethernet
這時候就可透過CDC Ethernet操作USB network,openmoko在啟動該裝置時就設定IP與route,所以我們只要在Host設定必要的網路組態,即可連線到模擬的裝置:
$ ifconfig usb0 inet 192.168.0.200 netmask 255.255.255.0
$ ssh root@192.168.0.202
順利的話就會看到命令提示畫面:
root@fic-gta01:~$
當然,拿到shell後,什麼事情都可以作。

注意,在關閉openmoko-emulator前,請切換到Qemu Monitor,並打入"usb_del gadget"的指令,要求將gadgetfs的存取關閉,否則很可能會kernel panic。這時候Host的dmesg輸出應該類似以下:
[ 4751.700000] dummy_udc dummy_udc: unregister gadget driver 'gadgetfs'
[ 4751.700000] gadgetfs: disconnected
[ 4751.700000] dummy_hcd dummy_hcd: port status 0x00010100 has changes
[ 4751.700000] dummy_hcd dummy_hcd: port status 0x00010100 has changes
[ 4751.700000] usb 4-1: USB disconnect, address 3
[ 4751.700000] usb0: unregister 'cdc_ether' usb-dummy_hcd-1, CDC Ethernet Device
[ 4753.856000] usb usb4: dummy_bus_suspend
另外,Win32的USB redirection實做我也開始進行,希望不久後也可在Win32進行openmoko的模擬與開發工作。本文內容僅供參考與進度展示,後續的更新會發佈於openmoko官方的wiki: OpenMoko_under_QEMU