2010年5月1日

Ubuntu上安裝Marvell Gigabit LAN Driver

這篇算是補充,既然都寫了新版patch,舊聞也順便寫寫。

P5Q-E是張C/P值頗高的主機板,內建Dual Gigabit LAN,廠牌型號是Marvell 88E8056/88E8001,在Linux上支援備援線路於斷線時自動切換(Linux上看起來不支援頻寬合併,如有支援的消息請告知)。
這邊順便的告訴大家,現在買主機板時,幾乎都內建Gigabit LAN了,其中許多都是Dual NIC,當主機板支援Dual NIC時,哪個LAN要當主要的LAN要注意,可以仔細看說明書或者上網查主機板的規格,Dual NIC通常是一個PCI-E配一個PCI的,只有PCI-E的才能發揮Gigabit LAN的全部效能。
以P5Q-E來說,它內建的chip型號為88E8056/88E8001,會有2個型號,原因就在於它的Dual NIC,一個型號是PCI-E(88E8056),另一個則是PCI(88E8001)。
因為如此,在Linux當中兩個LAN Port的Driver並不同,分別是PCI-E(88E8056)的skge、PCI(88E8001)的sky2。
其中因為sky2是實驗性的Driver,因此穩定性是公認的糟糕,而我個人使用上,發現skge的穩定性也不怎麼好,高流量時也會出現watchdog timeout。
解決方案很簡單,使用Marvell原廠提供的sk98lin Driver即可,sk98lin Driver可同時支援88E8056和88E8001,安裝後可以直接取代skge和sky2。

而sk98lin安裝很討厭,要進行些步驟才能安裝成功,下面列出我的安裝步驟,如果有要安裝的看到本篇可以節省些時間,以下安裝是在Ubuntu上進行,相信Debian差別不大,其他則不確定。

1. 安裝或確認sk98lin安裝所需的套件
確定有安裝下列套件:
.Linux Kernel對應的linux headers
.Linux Kernel對應的linux source
.kernel-package
.libncurses5-dev

以Ubuntu 10.04版本來說,目前的Kernel版本為2.6.32-21-server(執行uname -a可查看),就需要安裝:
.linux-headers-2.6.32-21
.linux-source-2.6.32
.kernel-package
.libncurses5-dev

2. 下載sk98lin Driver

3. 設置或確認sk98lin安裝時所需的連結或目錄
.確認linux kernel source有解壓縮
Ubuntu/Debian的linux source套件只會下載linux kernel的壓縮到到/usr/src,不會自動解壓縮,所以先執行下面指令解壓縮:
# cd /usr/src
# tar jxvf linux-source-2.6.32.tar.bz2

.確認目前系統的kernel config已放入linux source目錄
sk98lin安裝編譯時,會要求要有kernel的config檔案,請到/boot/查找目前系統用的kernel(可用uname -a查詢)的config檔案。
例如:
# uname -a
Linux file 2.6.32-21-server #32-Ubuntu SMP Fri Apr 16 09:17:34 UTC 2010 x86_64 GNU/Linux

則config檔案是/boot/config-2.6.32-21-server

接著把這個檔案複製到linux kernel source的目錄中,如下:
# cd /usr/src/linux-source-2.6.32
# cp /boot/config-2.6.32-21-server ./.config


.確認目前系統的kernel module目錄下是否有kernel source的連結
sk98lin安裝編譯時,會要求要有kernel module的目錄下要有linux kernel source的連結,如下建立:
# cd /lib/modules/2.6.32-21-server
# ln -s /usr/src/linux-source-2.6.32 source


/lib/modules/的目錄,一樣參考目前系統的kernel版本。

.確認有定義IGNORE_HEADER_MISMATCH這個環境變數
因為sk98lin安裝編譯時,會查詢目前的linux headers和目前系統的kernel是否符合,不符合不動作,但Ubuntu上headers和kernel通常版本不完全符合,因此要加上這個環境變數,如下。
(bash)
# export IGNORE_HEADER_MISMATCH=1
(tcsh)
# setenv IGNORE_HEADER_MISMATCH 1

4. 解開壓縮檔
# cd /tmp
# tar jxvf install_v10.84.3.3.tar.gz
# cd DriverInstall


5. 修改install.sh
#!/bin/sh改為#!/bin/bash,如下:
# vi /tmp/DriverInstall/install.sh
#!/bin/sh

to
#!/bin/bash


6. 執行sk98lin安裝程式
# ./install.sh

Q1:
1) installation 3) generate makefile
2) generate patch 4) exit

A1:
1

Q2:
Do you want proceed? (y/N)
A2:
y

Q3:
1) Do nothing
2) Deactivate diver
3) Remove driver

A3:
1

即會自動編譯sk98lin模組。

7. 載入sk98lin module
順利編譯成功後,可載入sk98lin module,執行如下:
# modprobe sk98lin

8. 修改blacklist.conf,強制不使用skge、sky2
編輯/etc/modprobe.d/blacklist.conf,檔案最上面加入
/etc/modprobe.d/blacklist.conf
blacklist sky2
blacklist skge
.....


9. 重新開機
# reboot

即可完成

2010年4月30日

Ubuntu 10.04與sk98lin

前面來點前言,我用的主機板是P5Q-E,這塊主機板不錯,C/P值也頗高,內建的Gigabit LAN Controller是MARVELL,要說差也不差,但Linux內建的Driver(skge/sky2)就是很鳥,因此都得用原廠的sk98lin,但每次kernel一升級,就經常無法編譯通過,這次Ubuntu 10.04同樣遇到了!
因為Ubuntu 10.04還太新了,目前沒google到patch,我所幸自己試著抓抓改改,目前看來應該ok!

安裝時編譯錯誤程式碼如下:
/tmp/Sk98IpXJpMHrIbXnZSVQLQbMS/all/skge.c: In function 『SkGeTestIsr』:
/tmp/Sk98IpXJpMHrIbXnZSVQLQbMS/all/skge.c:1750: error: 『TASK_NORMAL』 undeclared (first use in this function)
/tmp/Sk98IpXJpMHrIbXnZSVQLQbMS/all/skge.c:1750: error: (Each undeclared identifier is reported only once
/tmp/Sk98IpXJpMHrIbXnZSVQLQbMS/all/skge.c:1750: error: for each function it appears in.)
/tmp/Sk98IpXJpMHrIbXnZSVQLQbMS/all/skge.c: In function 『SkGeTestMsi』:
/tmp/Sk98IpXJpMHrIbXnZSVQLQbMS/all/skge.c:1780: warning: passing argument 2 of 『request_irq』 from incompatible pointer type
include/linux/interrupt.h:117: note: expected 『irq_handler_t』 but argument is of type 『int (*)(int, void *)』
/tmp/Sk98IpXJpMHrIbXnZSVQLQbMS/all/skge.c:1790: error: 『TASK_UNINTERRUPTIBLE』 undeclared (first use in this function)
/tmp/Sk98IpXJpMHrIbXnZSVQLQbMS/all/skge.c:1790: error: implicit declaration of function 『schedule_timeout』
make[2]: *** [/tmp/Sk98IpXJpMHrIbXnZSVQLQbMS/all/skge.o] Error 1
make[2]: *** Waiting for unfinished jobs....


注意到,
Q1:
TASK_NORMAL、TASK_UNINTERRUPTIBLE 沒定義

Q2:
schedule_timeout 無法被skge.c直接呼叫

cscope之後發現 TASK_NORMAL、TASK_UNINTERRUPTIBLE、schedule_timeout 都在 sched.h中。

因此,修改 DriverInstall/sk98lin.tar.bz2 壓縮檔中的 2.6/skge.c
(DriverInstall/sk98lin.tar.bz2:/2.6/skge.c)
.....
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
static int __devinit SkGeTestIsr(int irq, void *dev_id)
#else
static int __devinit SkGeTestIsr(int irq, void *dev_id, struct pt_regs *ptregs)
#endif
{
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)
struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
.....
static int __devinit SkGeTestMsi(struct SK_NET_DEVICE *dev, SK_AC *pAC)
{
#define TASK_UNINTERRUPTIBLE 2

struct pci_dev *pdev = pAC->PciDev;
.....
SK_OUT8(pAC->IoBase, B0_CTST, CS_ST_SW_IRQ);
SK_IN8(pAC->IoBase, B0_CTST, &test8);

extern signed long schedule_timeout(signed long timeout);
extern signed long schedule_timeout_interruptible(signed long timeout);
extern signed long schedule_timeout_killable(signed long timeout);
extern signed long schedule_timeout_uninterruptible(signed long timeout);

wait_event_timeout(pAC->msi_wait, (pAC->AllocFlag & SK_ALLOC_MSI), HZ/10);
.....


skge.patch
--- skge.old 2010-04-30 20:31:24.502166321 +0800
+++ skge.c 2010-04-30 20:34:07.902165413 +0800
@@ -1732,6 +1732,9 @@
static int __devinit SkGeTestIsr(int irq, void *dev_id, struct pt_regs *ptregs)
#endif
{
+#define TASK_INTERRUPTIBLE 1
+#define TASK_UNINTERRUPTIBLE 2
+#define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)
struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
DEV_NET *pNet;
SK_AC *pAC;
@@ -1768,6 +1771,8 @@
*/
static int __devinit SkGeTestMsi(struct SK_NET_DEVICE *dev, SK_AC *pAC)
{
+#define TASK_UNINTERRUPTIBLE 2
+
struct pci_dev *pdev = pAC->PciDev;
int Ret;
SK_U32 test32;
@@ -1787,6 +1792,11 @@
SK_OUT8(pAC->IoBase, B0_CTST, CS_ST_SW_IRQ);
SK_IN8(pAC->IoBase, B0_CTST, &test8);

+extern signed long schedule_timeout(signed long timeout);
+extern signed long schedule_timeout_interruptible(signed long timeout);
+extern signed long schedule_timeout_killable(signed long timeout);
+extern signed long schedule_timeout_uninterruptible(signed long timeout);
+
wait_event_timeout(pAC->msi_wait, (pAC->AllocFlag & SK_ALLOC_MSI), HZ/10);

if (!(pAC->AllocFlag & SK_ALLOC_MSI)) {


最後附上幾個改過得檔案連結:
skge.patch
sk98lin.tar.bz2

2010年4月8日

台灣~核能發電~再生能源

這篇是我發表在mobile01上的回文,因此同步po在blog上當作台灣能源發展現況的介紹。

核能目前還是效益、乾淨度最高的發電方式。

再生能源很多,目前講得出來的有一堆,但多半都兩個根本上的問題:
1. 穩定性很差
2. 發電效益很差

風力發電是不錯的發電方式,風轉成電的轉換效率不錯,但問題在於,風力發電受限於風,風並不是穩定的一直吹,而是有時大有時小,這會造成發出來的電力有時多有時少,穩定性並不好。
同樣的一點,風力發電的風必須要是穩定吹送的風,風太小不能發電,風太大也不行,所以說,颱風來襲時,風力發電機並不是火力全開,而是全部關閉,否則機組會損壞。

太陽能發電更慘,太陽能發電一樣有穩定性不好的問題,太陽越大發出的電越多,因此晚上不能發電(一天只有一半的時間有機會發電),另外遇到陰天也不大能發電。
那台灣北部,冬天(像現在)會經常有寒流通過,這段時間經常會下雨、陰天,就不適合發展太陽能發電。
令一個太陽能發電的最大問題是轉換效率很差,目前網拍買得到的太陽能發電產品,上面硬的太陽能板轉換效率大概只有15%上下,100單位的光只能產生15 單位的電,很低。
這邊順便可以提一下,有一種太陽能商品,太陽能板是軟的,通常縫在背包或衣服上,看似方便,但那種太陽能板轉換效率只有6%左右。
商業運轉的太陽能發電廠,轉換效率高很多,但也只有26%左右。
考慮到一天只有半天能發電,陰天也不能發電,穩定性差,轉換效率又低,就知道為甚麼台電不很願意投資太陽能電廠了。(儘管如此,基於節能環保的政策,目前台電正在南部蓋一座「世界第二大的太陽能發電廠」(僅次於西班牙),新聞中台電明白說了,主要就是宣示意義,實際上對台電整個發電幫助有限,但未來我們有新景點可以觀光了)

最後,太陽能發電還一個大麻煩,太陽能板是「耗材」,它用久了轉換效率會越來越差,最後就得更換,我到現在都很懷疑,搭太陽能發電板發出的電,一直到它無法運作為止,到底成本能不能攤平。

水力發電不錯,但很不幸的,台灣目前水力發電廠已經蓋到爆炸了,沒地方可以蓋水力發電廠了,台灣的水力發電廠蓋得很誇張,不是一條河一座,是一條河從上游蓋到下游,蓋個4,5座,所以很不幸,水力發電台灣已經做到極限了。

至於其他的發電方式,常聽到的像是地熱、潮汐。
台灣的地熱資源做發電,經濟效益不夠,也就是說,可能電廠蓋起來,發出的電連電廠成本都攤不平。

潮汐發電目前國外有研究,台電n年前有實驗性的去做,目前這些潮汐發電機都爛光了,原因何在?
潮汐發電你要把發電機組放在海上,海水本身有鹽份,會腐蝕發電機組,因此用一段時間(幾年後)這些機組就會被腐蝕生鏽,然後就是損壞無法使用。

目前台灣主要的發電就是核能、火力、水力三種發電方式。
核能和火力為主,原因在於這兩者的穩定性最好,發電量不會忽高忽低,所以台電有個稱呼,叫做「基載發電」,顧名思義就是以這兩種發的電為基礎,供應全台灣用電主要負載。
水力發電在台灣,像日月潭水庫,白天從上游把水沖下來發電,晚上把水打上去放,加上有時水量低,所以發電量不穩定,因此沒辦法當基載發電。

而火力發電廠和核能發電的發電量差很多(水力對火力也是),加上台灣沒汽油、沒煤炭、天然氣少得可憐,所以火力發電並不是很好的選擇,之前有新聞,全台灣的汽油、煤油、天然氣存放場,只夠全台灣用3天(包括火力發電)3天內一定要有油輪、天然氣輪靠港送燃料。前幾年颱風來,滯留台灣,就讓台電、中油嚇很大,就擔心汽油、煤油、天然氣不夠用。

前幾年反核四,核四停工,問題是電會不夠用怎麼辦?結果就是政府發一堆火力發電廠的執照,增加火力發電廠的機組,這樣就是環保嗎?

目前為何西方國家很多都回頭搞核能發電,就因為全世界講減碳,基載發電也就核能跟火力,限制火力發電來減少碳排放,那當然就是發展核能阿!這很清楚明白~

至於反核,西方國家最早講反核,是反「核子武器」,不是反「核能發電」。
每次都會提到車諾比事件,車諾比那個「不是核能發電廠」,是「核子實驗室」,車諾比的核能,是「核子實驗為主,主要生產核子彈原料鈽,發電為輔」,發電只是順便而已。
講白了,爆炸就是做實驗做到爆炸,不是在穩定環境下的結果。目前以穩定發電為主的核能發電廠,全世界都沒有發生過爆炸。
台灣發展原子彈的歷史大家都知道,美國直接派人把我們的實驗機組封了(整個反應爐灌水泥,沒救了),所以我們沒有發展核子彈的能力,也沒辦法發展,核能就是只有發電而已,不搞實驗。

所以,還是把專業回歸專業吧!

最近幾個月有不少有趣的新聞可以注意,像有新聞提到美國有公司提出超小型的核能發電機組,似乎可以小部份修改就替換火力發電的發電機組,這似乎滿有趣的。
另一個新聞就是台灣黑潮,看來似乎比風力、潮汐、地熱、太陽能都有潛力,值得注意。

最後一點,現在有很多假環保之名行欺騙之實的,有板主說的商人,但也有不少團體。
5,6年前風力發電沒現在盛行,就說應該用風力發電,那個環保,現在台灣風力發電機組也蓋了100多台了,就開始出現風力發電不環保的聲音。
正如上幾篇大大提到的,只要是發電,就一定會對環境造成影響,問題是,同樣是發電,當然選對環境傷害小的阿,不能一邊說這個很糟糕,一邊又說那個也不怎麼樣,一定是在兩個裡面選一個比較好的來做吧!每個都有意見就是甚麼都不做,甚麼都不做就會是好的嗎?

我舉個可能不很好的例子,每個人都有排泄物,當只有幾個人的時候,對著河釋放排泄物,河川影響不會很大,但當人數變成幾十萬人的時候,同樣都是對著河釋放排泄物,就變成以前的淡水河。
可是我們甚麼都沒做阿~就因為甚麼都沒做才變成這樣,那所以,就蓋了污水處理廠,接著河水淨化。

這個世界本來就是平衡,凡事過猶不及,當人數少、污染少、數量少時,問題都不大,但是當規模變得很大時,就得要想些方式解決產生的問題。
減碳就是這樣,以前瓦特發明蒸汽機時,誰會想到燒煤炭會搞到地球溫室效應,但當時量事實上也沒有很誇張,近100年來,人類對石化能源的需求,讓地球溫室效應的影像以等比級數在增加,這就可以想見人類對石化能源的使用誇張到離譜,規模大到這種地步,自然就得分散使用其他能源來解決問題。

2010年3月15日

舊文新貼-NetBSD與ARM的邂逅~

ARM NetBSD 手記:

總整理:

Linux 有許多優點,但也有許多缺點,他最大的缺點,就是沒什麼隱私,
你有修改過,就必須按照規矩放出來給大家看,儘管有許多人規避它,
但現階段,這個規矩還不能改變,而 NetBSD 承襲了 BSD 的優點,
完全的自由,完全的合法,你用它惡搞,當商品,都不管你。
而且因為 BSD 社群的習慣性(比較保守),它的程式碼都有不錯的穩定性,
雖然因此來說效率較差,但的確是值得當作 base 來開發。

BSD 的主要缺點就是支援嚴重缺乏,舉個例子,
當 Linux 都已經把許多 USB 設備驅動起來,
甚至 webcam 和 Videl For Linux 被大家開發到非常容易就可以使用,
而 FlashROM 的驅動,甚至還設計了 MTD 還有 JFFS、YAFFS 之類的 FS,
BSD 在這方面是完全沒有的。

因此,這樣的東西,假以時日,是可以成為非常不錯的 base,有無限的潛力。

NetBSD 在 ARM 上的環境可以用賓士車來形容,
從 Compiler、Kernel、rootfs、Application 全包,
而且寫好 build.sh 這樣的 script,
要安裝、編譯都非常容易,而且整個編排非常有系統,
對於初踏入嵌入式系統的人,會好理解得多,這是很棒的事情。

編譯方式如下:

1.編譯出 Compiler Tools

ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-3.0.1/source/sets/

下載
  • src.tgz
  • syssrc.tgz
  • share.tgz
  • gnusrc.tgz

到 / 解壓縮,它會解到 /usr/src

而它的編譯環境很棒,是跨平台的,
目前看起來,Linux 和 FreeBSD 都可以建立,
需要注意的是,在 Linux 上建立時,
用 gcc-4.1.2 會編譯失敗,用 gcc-3.3、gcc-3.4 則非常正常,
因此要先將 gcc...等幾個 4.1 的編譯程式改 link 到 gcc-3.x,
執行如下:
# cd /usr/bin
# rm cpp gcc g++
# ln -s gcc-3.4 gcc
# ln -s g++-3.4 g++
# ln -s cpp-3.4 cpp


要復原則執行
# cd /usr/bin
# rm cpp gcc g++
# ln -s gcc-4.1 gcc
# ln -s g++-4.1 g++
# ln -s cpp-4.1 cpp

(要視目前版本而修正)

此外,它編譯時會需要 zlib.h,
在 Debian 上,它是在 zlib1g-dev 這個套件中。
此外,當出現
terminal.o(.text+0x40): In function `terminal_begin_using_terminal':
的錯誤時,是因為在 Debian 上,它需要 libncurses5-dev。

補充一點,build.sh 在執行時會有問題,問題是發生在 TOP 這個變數,
因此要編輯 build.sh,把
TOP=$(/bin/pwd -P 2>/dev/null)
改為
TOP=/usr/src

2.開始建立環境
# cd /usr/src
# mkdir ../obj
# chmod 755 build.sh
# ./build.sh -m evbarm tools


-m 表示指定編譯環境是 evbarm
tools 表示要編譯出 tools

說明可以執行 build.sh --help 後觀看。

另外,我們也可以用較為複雜的參數來編譯,雖然較為複雜,不過我們可以自行指定路徑,如下:
# ./build.sh -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release tools

-O /home/2410/netbsd/obj //obj 目錄
-T /usr/local/arm/netbsd //Compiler 目錄
-D /home/2410/netbsd/build //build 目錄
-R /home/2410/netbsd/release //release 目錄

此外,我在後來編譯的環境改用 coLinux 來進行,coLinux 安裝後和一般的 Debian 相同,
唯一差別是似乎不支援 kernel module,
而使用 coLinux 編譯環境時,以下是我使用到的 coLinux base 安裝套件列表:
aee ee bzip2 g++ gcc joe nfs-user-server libncurses5-dev ssh tcsh vsftpd zlib1g-dev make locales less

再來,前面提到可用較為複雜的參數來編譯,我們可以將整個 NetBSD 連同所有 evbarm source 都編譯出來,
整個參數如下:
./build.sh -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release tools && \
./build.sh -U -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release build && \
./build.sh -U -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release release && \
./build.sh -U -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release kernel=SMDK2410_INSTALL


-u //不要執行 make clean
-U //不需要 root 權限
-O /home/2410/netbsd/obj //obj 目錄
-T /usr/local/arm/netbsd //Compiler 目錄
-D /home/2410/netbsd/build //build 目錄
-R /home/2410/netbsd/release //release 目錄

再修正
./build.sh -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release tools && \
./build.sh -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release build && \
./build.sh -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release release && \
./build.sh -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release kernel=SMDK2410_INSTALL


這樣會編譯出
build ;也就是 obj 目錄,將全部東西 build 一次,包括 fs,application,kernel...等
release ;內含完整 evbarm 的 source,也就是會將上面的 fs,application 打包,kernel 檔也通通會編譯
kernel ;目前沒改過,則會編譯出預設的 kernel

3.要正式編譯 NetBSD 的 kernel 之前,NetBSD 製作出來後會無法開機,要如下修改才能進入 kernel:

sys/arch/evbarm/smdk2xx0/smdk2410_start.S


......
_C_LABEL(smdk2410_start):
/* Disable interrupt */
mrs r0, cpsr
orr r0, r0, #I32_bit
msr cpsr, r0

#ifdef SMDK2XX0_CLOCK_CONFIG
adr r4, clock_config_data
......

改為
......
_C_LABEL(smdk2410_start):
/* Disable interrupt */
mrs r0, cpsr
orr r0, r0, #I32_bit
msr cpsr, r0

/* flush v4 I/D caches */
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */

/* disable MMU stuff and caches */
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
mcr p15, 0, r0, c1, c0, 0

#ifdef SMDK2XX0_CLOCK_CONFIG
adr r4, clock_config_data
......


另外,它預設的 SDRAM size 是和板子不合的,
僅僅是不合就算了,可是因為我們的 image 有 27 MB,
不合的 SDSRAM size 造成 RAM 不夠,執行時就會有問題,
而修改很容易,如下:

sys/arch/evbarm/smdk2xx0/smdk2410_machdep.c


......
#ifndef SDRAM_START
#define SDRAM_START S3C2410_SDRAM_START
#endif
#ifndef SDRAM_SIZE
#define SDRAM_SIZE (32*1024*1024)
#endif

......


改為
......
#ifndef SDRAM_START
#define SDRAM_START S3C2410_SDRAM_START
#endif
#ifndef SDRAM_SIZE
#define SDRAM_SIZE (64*1024*1024)
#endif

......


如果我們要讓它支援超過 3M 的 rootfs 時,需要如下修改:
修改程式碼如下:
sys/arch/evbarm/smdk2xx0/smdk2410_machdep.c
.....
#define KERNEL_VM_BASE (KERNEL_BASE + 0x01000000)
.....
#define KERNEL_PT_KERNEL_NUM 2 /* L2 tables for mapping kernel VM */
.....


改為
.....
#define KERNEL_VM_BASE (KERNEL_BASE + 0x02000000)
.....
#define KERNEL_PT_KERNEL_NUM 8 /* L2 tables for mapping kernel VM */
.....


設定部份為:
sys/arch/evbarm/conf/INSTALL
options MEMORY_DISK_ROOT_SIZE=6510
改為
options MEMORY_DISK_ROOT_SIZE=49152
NetBSD 對 RAM Disk 的大小是有設定的,它的設定是定義在
/usr/src/sys/arch/evbarm/conf/INSTALL

要知道為何是這個設定檔,我們看到
/usr/src/sys/arch/evbarm/conf/SMDK2410_INSTALL

它裡面只有 include 其他檔案,一個是
/usr/src/sys/arch/evbarm/conf/SMDK2410

另一個是
/usr/src/sys/arch/evbarm/conf/INSTALL

而 /usr/src/sys/arch/evbarm/conf/INSTALL 裡面定義的,
就是 RAM Disk 的大小和一些嵌入式系統的 RAM 設定,
而它預設值是 6510,其實就是 3 MB 再大一點點,
而這個值的算法可以參考「製作嵌入式晶片s3c2410板卡的NetBSD啟動鏡像」,
它是
6510 x 512 / 1024 = 6150 / 2 =3075k

也就是說,6510 / 2 / 1024,就是約略的 MB 數。

4.要編譯 NetBSD 的 kernel 十分容易
將 /usr/src/tooldir.Linux-2.6.17-unknown/bin 加入 PATH 中
(tooldir.Linux-2.6.17-unknown 是編譯環境時,依據 OS 來命名的)

PATH 更新後,執行如下:

./build.sh -m evbarm -u kernel=SMDK2410_INSTALL

它就會編譯 SMDK2410 的 kernel 了。

假如出現找不到 Compiler Tools 的情況時,我們可以用較複雜的參數來編譯,
自行指定 Compiler 路徑,如下:
./build.sh -U -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release kernel=SMDK2410_INSTALL

而 kernel 內容的修改和之前 FreeBSD 類似,連目錄結構都很相似,
它是放在
sys/arch/evbarm/conf/SMDK2410

對照以前 FreeBSD 的 kernel 路徑
/usr/src/sys/i386/conf/GENERIC

而這次的則是
/usr/src/sys/arch/evbarm/conf/SMDK2410

真的是很相似,很有 BSD 的味道。

參考文件是:
製作嵌入式晶片s3c2410板卡的NetBSD啟動鏡像

5a.以 NFS rootfs 方式開機進入

NFS rootfs 大概是最方便的作法了,這邊指的方便,指的是方便開發 application,
還有方便修改執行檔之類的動作。

不過在 NetBSD 上,動作流程比 Linux 麻煩許多,
最討厭是竟然要動到 DHCP Server,以下是流程:

NFS and DHCP Howto
1.重點,設定 DHCP Server 如下指定:
host my2410.home {
hardware ethernet 00:0a:b1:00:01:ff;
fixed-address 192.168.1.100;
next-server 192.168.1.18;
option root-path "/home/nfsroot/root";
}


網卡卡號在 NetBSD 開機時會顯示,如下:
cs0 at ssextio0 addr 0x18000000 intr 9
cs0: CS8900 rev. K, address 00:0a:b1:00:01:ff, media UTP


next-server 很重要,它表示了 NFS Server 的 IP,
option root-path 也很重要,它表示 NFS Server 上 rootfs 的路徑

2.NFS設定如下:
/home/nfsroot/root 192.168.1.0/255.255.255.0(rw,no_root_squash,sync)
/home/nfsroot/swap 192.168.1.0/255.255.255.0(rw,no_root_squash,sync)


rootfs 和 swap 要分開設,原因目前不清楚,按照 ko 設定的。

swap 建立方法如下:
dd if=/dev/zero of=swap bs=4k count=8k

3.NetBSD 設定如下:
etc/myname
my2410

etc/mygate
192.168.1.3

etc/rc.conf
rc_configured=YES

# Add local overrides below
#
nfs_client=YES
wscons=YES
sshd=NO
sendmail=NO

etc/hosts
192.168.1.100 my2410
192.168.1.18 coDebian

etc/fstab
192.168.1.18:/home/nfsroot/root / nfs rw 0 0
kernfs /kern kernfs rw
procfs /proc procfs rw,noauto
192.168.1.18:/home/nfsroot/swap none swap sw,nfsmntpt=/swap

4.建立 kern 和 proc 目錄
mkdir kern proc

5.NetBSD kernel
不要用 SMDK2410_INSTALL

修改 SMDK2410 後,直接使用 SMDK2410 來編譯 kernel
SMDK2410_INSTALL 內主要設定的,就是用 RAM Disk 時的設定

SMDK2410 要改的不多,如下:
config netbsd root on ? type ?

改成
config netbsd root on ? type nfs

6.編譯成功後,不需要之前的 RAM Disk 一堆步驟,直接用 netbsd.bin 即可。

以下是第一次成功畫面:
SMDK2410 # nfs 0x30200000 192.168.1.18:/home/2410/netbsd/netbsd.bin;go 30200000
File transfer via NFS from server 192.168.1.18; our IP address is 192.168.1.100
Filename '/home/2410/netbsd/netbsd.bin'.
Load address: 0x30200000
Loading: #################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#####################################################
done
Bytes transferred = 2597192 (27a148 hex)
## Starting application at 0x30200000 ...
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 3.0.1 (SMDK2410) #1: Fri Sep 29 07:36:19 UTC 2006
root@coDebian:/home/2410/netbsd/obj/sys/arch/evbarm/compile/SMDK2410
total memory = 65536 KB
avail memory = 58680 KB
mainbus0 (root)
cpu0 at mainbus0: ARM920T rev 0 (ARM9TDMI core)
cpu0: DC enabled IC enabled WB enabled EABT
cpu0: 16KB/32B 64-way Instruction cache
cpu0: 16KB/32B 64-way write-back-locking-A Data cache
ssio0 at mainbus0: fclk 200 MHz hclk 100 MHz pclk 50 MHz
ohci0 at ssio0 intr 26
ohci0: OHCI version 1.0
usb0 at ohci0: USB revision 1.0
uhub0 at usb0
uhub0: Samsung OHCI root hub, class 9/0, rev 1.00/1.00, addr 1
uhub0: 2 ports with 2 removable, self powered
sscom0 at ssio0 unit 0: UART0 addr=50000000
sscom0: console (major=104)
sscom1 at ssio0 unit 1: UART1 addr=50004000
ssextio0 at ssio0
cs0 at ssextio0 addr 0x18000000 intr 9
cs0: CS8900 rev. K, address 00:0a:b1:00:01:ff, media UTP
lcd0 at ssio0
wsdisplay0 at lcd0 kbdmux 1
wsmux1: connecting to wsdisplay0
ssspi1 at ssio0 unit 1
sskbd0 at ssspi1 intr 1
wskbd0 at sskbd0 mux 1
wskbd0: connecting to wsdisplay0
clock: hz=100 stathz = 64 PCLK=50000000 prescaler=2 tc=24414
boot device:
root on cs0
nfs_boot: trying DHCP/BOOTP
cs0: failed to enable memory mode
nfs_boot: DHCP next-server: 192.168.1.18
nfs_boot: my_domain=home
nfs_boot: my_addr=192.168.1.100
nfs_boot: my_mask=255.255.255.0
nfs_boot: gateway=192.168.1.3
root on 192.168.1.18:/home/nfsroot/root
warning: no /dev/console
init: Creating mfs /dev (409 blocks, 1024 inodes)
Fri Sep 29 07:43:12 UTC 2006
Checking for botched superblock upgrades: done.
Starting file system checks:
Setting tty flags.
Setting sysctl variables:
Starting network.
Hostname: myname
IPv6 mode: host
Configuring network interfaces:.
add net default: gateway 192.168.1.3
Building databases...
wsdisplay0: screen 1 added (30x32bpp8, vt100 emulation)
wsdisplay0: screen 2 added (30x32bpp8, vt100 emulation)
wsdisplay0: screen 3 added (30x32bpp8, vt100 emulation)
wsdisplay0: screen 4 added (30x32bpp8, vt100 emulation)
Starting syslogd.
Checking for core dump...
savecore: /netbsd: kvm_openfiles: /netbsd: No such file or directory
Sep 29 07:43:22 myname savecore: /netbsd: kvm_openfiles: /netbsd: No such file or directory
Mounting all filesystems...
mount: realpath /kern: No such file or directory
Clearing /tmp.
Creating a.out runtime link editor directory cache.
Checking quotas: done.
Setting securelevel: kern.securelevel: 0 -> 1
mount_nfs: realpath /swap: No such file or directory
swapctl: 192.168.1.18:/home/nfsroot/swap: mount failed
/etc/rc: WARNING: No swap space configured!
Starting virecover.
Starting local daemons:.
Updating motd.
Starting inetd.
Starting cron.
Fri Sep 29 07:43:30 UTC 2006



NetBSD/evbarm (myname) (console)

login: root
Sep 29 07:43:36 myname login: ROOT LOGIN (root) ON console
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 3.0.1 (SMDK2410) #1: Fri Sep 29 07:36:19 UTC 2006

Welcome to NetBSD!

Terminal type is vt100.
We recommend creating a non-root account and using su(1) for root access.
myname#


5b.使用 RAM rootfs 方式在本機載入

1.以 NFS rootfs 成功的版本進行修改,修改下面幾個檔案:

etc/rc.conf
rc_configured=YES
wscons=YES
sshd=NO
sendmail=NO
no_swap=YES
swapoff=YES



etc/fstab
/dev/md0a / ffs rw 1 1
kernfs /kern kernfs rw
procfs /proc procfs rw,noauto


2.修改 /usr/src/sys/arch/evbarm/conf/SMDK2410


config netbsd root on ? type nfs

改回
config netbsd root on ? type ?

3.修改進入 multi-user mode
要進入 multi-user mode,有幾個項目:

1. rc.conf 內的 rc_configured 要設為 YES
2.在 RAM rootfs 模式時,SMDK2410_INSTALL 要修改,如下:

sys/arch/evbarm/conf/SMDK2410_INSTALL
#options BOOTHOWTO=RB_SINGLE

要改為
options BOOTHOWTO=0


至於
sys/arch/evbarm/conf/INSTALL


MEMORY_RBFLAGS=0x00

可以不需要設定,我懷疑這個設定在 BOOTHOWTO=0 幫你設了。

4.建立 image 檔案
NetBSD 的 kernel 和 rootfs 是綁在一起的,要在 kernel 當中先設定好 rootfs 的大小,如下:
sys/arch/evbarm/conf/INSTALL
options MEMORY_DISK_ROOT_SIZE=6510

改為
options MEMORY_DISK_ROOT_SIZE=49152

之後按照下面的步驟建立 image 檔案:

要建立 image.fs 這樣的 RAM Disk 影像檔,指令如下:
nbmakefs -s 24m -t ffs image_24m.fs rootfs

-s 影像檔大小
-t 影像檔檔案系統格式(只有 ffs 可以用)
image_24m.fs 目的影像檔檔名
rootfs 來源目錄
=========================================

http://www.bsdnewsletter.com/2003/09/Features102.html

要將 kernel 和 rootfs 合併,動作如下:
cp sys/arch/evbarm/compile/obj/SMDK2410_INSTALL/netbsd .
arm--netbsdelf-mdsetimage -sv netbsd image.fs
arm--netbsdelf-objcopy -S -O binary netbsd netbsd.bin

6.透過 u-boot 載入
最後要載到板子上,要使用如下參數來下載啟動:

啟動 NetBSD 語法如下:
tftp 30200000 netbsd.bin; go 30200000

也可以用 NFS 方式載入,如下:
nfs 0x30200000 192.168.1.18:/home/2410/netbsd/netbsd.bin;go 0x30200000

備註:
關於 dev/ 的裝置,可能會出現警告的訊息,目前不清楚 dev/ 的裝置是不是必要的,
而要建立 dev 的裝置方法很簡單~~

要建立 dev 的裝置,NetBSD 很貼心的提供了 MAKEDEV 的 script 來幫忙建立,
可以依據不同類別來建立,目前類別有下列這些:
default
floppy
init
local
ramdisk
std
usbs
wscons

另外還有一個類別是
all

all 類別包含全部的裝置檔。

因此要建立,是很簡單的,在 NetBSD 下只要執行:
./MAKEDEV ramdisk

而前面我們編譯過的 Compiler Tools 裡面有包含了 mknod,它改名叫做 nbmknod,
因此在其他平台要使用它,則要執行:
./MAKEDEV -m /usr/local/arm/netbsd/bin/nbmknod ramdisk

-m mknod 的呼叫檔名和完整路徑

要編譯 evbarm 的檔案時,我們知道有
nbmake

可以使用,但是就算用 nbmake,經常會碰到環境變數的問題,
其實 NetBSD 已經幫我們想到了,可以直接用
nbmake-evbarm

它只是個 script 的檔案,裡面就只是設定一些環境變數,之後就去呼叫 nbmake,非常的方便~~

(2006-10-06)
小型化 rootfs 製作手記:

busybox 在 Embedded Linux 上很有名,它將 Linux 上常見的 tools 進行打包,讓 tools 的體積大幅縮小,
它用的技巧很簡單而有效率,方法是:

我們知道 application 有 靜態編譯 和 動態編譯 兩種,
靜態編譯是把 library 編譯後放入特定目錄,像是 /lib,
需要用到的 application,會在使用時自己去 /lib 下面找 library,
動態編譯則是把 library 和 application 編譯在一起,
這樣的好處是 application 在執行的時候,不需要去特定的目錄搜尋 library,
因此只要是同一個平台的程式,直接 copy application 檔案過去即可使用,
不需要再找一堆 library 並一個一個複製過去~~
可是靜態編譯的缺點是檔案多半都很大,隨便一個 application 檔案,都會需要到好幾 MB。

busybox 這類的程式則是採取了折衷的辦法,我們先將需要的 application 進行選取,
之後 busybox 再編譯這些 application,以「靜態編譯」的方式將它們編譯成「一個執行檔」,
這樣的結果是,許多用同一個 library 的 application,它們的 library 只會放一份在「這個執行檔」中,
有類似動態編譯時,所有 application 都到 /lib 找 library 的味道,
但是又能做到「靜態編譯」的優點,只需要一個執行檔,就能夠在相同平台直接執行使用,不需要另外找 library,
減少了移植的麻煩,也減少了 code size。

在 BSD 當中,沒有 busybox,busybox 也不支援 BSD,不過 BSD 有 crunchgen,
crunchgen 的原理和 busybox 相同,不同的地方在於,
他的設定檔需要自行編寫,之後透過它產生一個制式化的 Makefile,
接著 make 出來的檔案,就會有和 busybox 一樣風格的「執行檔」,
crunchgen 我們可以說他是 busybox 的手動版,但正因如此,它多了很大的彈性~~

下面動作我是參考
http://www.bsdnewsletter.com/2003/09/Features102b.html

的說明,加上自己的測試使用後得出的步驟、方法、技巧:

首先,我先把整個流程、步驟先寫上,之後在對細節做些說明:
1.編寫 mytiny.conf (檔名可自訂,但下面所有 mytiny 都需要改成自己的檔名),下面是我依照網站內容編寫:
srcdirs /home/2410/netbsd/usr/src/bin /home/2410/netbsd/usr/src/sbin /home/2410/netbsd/usr/src/usr.bin /home/2410/netbsd/usr/src/usr.sbin /home/2410/netbsd/usr/src/libexec

progs pwd_mkdb passwd login init sh mount_ffs mount_kernfs mount_procfs mount newfs ls reboot mount_nfs ttyflags getty

ln sh -sh
ln newfs mount_mfs

libs -lutil -lcrypt -ledit -ltermcap -ll


2.執行如下:
cd /home/2410/netbsd/usr/mytiny
nbcrunchgen -m Makefile mytiny.conf
nbmake-evbarm -f Makefile objs exe


3.要重新編譯的時候,執行如下:
cd /home/2410/netbsd/usr/mytiny
nbmake-evbarm clean
rm mytiny.c mytiny.cache Makefile
vi /home/2410/netbsd/usr/mytiny/mytiny.conf(編輯設定檔)
nbcrunchgen -m Makefile mytiny.conf
nbmake-evbarm -f Makefile objs exe


4.執行時,我們會發現出現錯誤,要修改這幾個檔案:
/home/2410/netbsd/usr/src/usr.bin/passwd/Makefile

# $NetBSD: Makefile,v 1.40 2005/03/04 20:41:09 he Exp $
# from: @(#)Makefile 8.3 (Berkeley) 4/2/94

.include

PROG= passwd
SRCS= local_passwd.c passwd.c
MAN= passwd.1

CPPFLAGS+=-I${.CURDIR} -DLOGIN_CAP

DPADD+= ${LIBCRYPT} ${LIBUTIL}
LDADD+= -lcrypt -lutil

BINOWN= root
BINMODE=4555

.include


/home/2410/netbsd/usr/src/usr.bin/login/Makefile
# $NetBSD: Makefile,v 1.45 2005/03/04 20:41:09 he Exp $
# @(#)Makefile 8.1 (Berkeley) 7/19/93

.include

WARNS= 2
PROG= login
SRCS= copyrightstr.c
DPADD+= ${LIBUTIL} ${LIBCRYPT}
LDADD+= -lutil -lcrypt
BINOWN= root
BINMODE=4555

SRCS+= login.c
CPPFLAGS+=-DLOGIN_CAP -DSUPPORT_UTMP -DSUPPORT_UTMPX

CLEANFILES+= copyrightstr.c

copyrightstr.c: ${NETBSDSRCDIR}/sys/conf/copyright
${_MKTARGET_CREATE}
rm -f ${.TARGET}
awk '\
BEGIN { print "const char copyrightstr[] =" }\
{ print "\""$$0"\\n\""}\
END { print "\"\\n\";" }\
' ${.ALLSRC} > ${.TARGET}

.include


5.順利編譯之後,便會產生 mytiny 的執行檔。

問題與說明:

Q:crunchgen 檔案在哪裡?
A:
NetBSD 真的很方便,它已經將 Compiler Tools 很完整的準備好了,像 crunchgen 這樣的工具也一併提供了,
此外,它還依據平台將它們重新命名,以 evbarm 來說,所有工具前面都會冠上 nb 字頭,
crunchgen 就更名為 nbcrunchgen,
make 就更名為 nbmake,
此外,前面提到過了,它還很貼心的提供了 nbmake-evbarm 這樣的 script,
差別在於會先設定好環境變數,接著呼叫 nbmake 執行。

而以我來說,nbcrunchgen 會放在前面提過的目錄,以我來說就是 /usr/local/arm/netbsd/bin/


Q:要怎麼查詢 library?mytiny.conf 裡面需要指定 libs 哩~~
A:
查詢方法有兩種,而且以第二種較確實。

第一種:
在 ARM 板子上,使用 ldd 查詢,指令如下:
ldd /bin/sh /bin/ls

可以指定多個指令,會全部列出~~

第二種:
第一種方法雖然可以列出執行檔所需的 library,可是按它的要求修改,有時候好像還是不行耶,怎麼辦?
我們這時候可以直接去看該指令(執行檔)的 source code 目錄下的 Makefile,
以 /bin/sh 來說,它的目錄會是在 usr/src/bin/sh/,這時去看它的 Makefile(usr/src/bin/sh/Makefile),
看到如下內容:
......
LDADD+= -ll -ledit -ltermcap
......


sh 需要的 library 就是 -ll -ledit -ltermcap 這幾個~~~

其他的執行檔搜尋方式雷同,而需要的 library 在 mytiny.conf 中只需要列一次,不需要重複列出~~

另外要注意的是,當出現下面的錯誤時,就是有缺 library:
/usr/local/arm/netbsd/bin/arm--netbsdelf-gcc -Wl,-nostdlib -static -o mytiny -Wl,-rpath-link,/home/2410/netbsd/build/lib:/home/2410/netbsd/build/usr/lib -L/home/2410/netbsd/build/lib -B/home/2410/netbsd/build/usr/lib/ -B/home/2410/netbsd/build/usr/lib/ mytiny.o pwd_mkdb.cro passwd.cro login.cro init.cro sh.cro mount_ffs.cro mount_kernfs.cro mount_procfs.cro mount.cro newfs.cro ls.cro reboot.cro mount_nfs.cro ttyflags.cro getty.cro -lutil -ledit -ltermcap -ll -L/home/2410/netbsd/build/usr/lib -L/home/2410/netbsd/build/usr/lib
passwd.cro(.text+0x54): In function `$a':
: undefined reference to `crypt'
passwd.cro(.text+0x1e4): In function `$a':
: undefined reference to `pw_gensalt'
passwd.cro(.text+0x210): In function `$a':
: undefined reference to `crypt'
login.cro(.text+0x54c): In function `$a':
: undefined reference to `crypt'
init.cro(.text+0x770): In function `single_user$$from$$init':
: undefined reference to `crypt'
collect2: ld returned 1 exit status


以這個為例,就是 passwd 這個執行檔編譯沒過,它還說 crypt 沒有定義,
此時可以以 grep 的方式搜尋 crypt,看看是什麼 lib 有包含 crypt 的定義,
便可發現,可能是 -lcrypt 缺了~~

Q:為何要修改 passwd 和 login 的 Makefile?
A:
在編譯時,一直發生錯誤,而且錯誤都出在 passwd 或 login 裡面,
此時看看它們的 Makefile,發現頗複雜,主要是它提供了參數來讓你設定,
類似如下:
BINMODE=4555

.if (${USE_KERBEROS} != "no")
CPPFLAGS+= -DKERBEROS5 -I${DESTDIR}/usr/include/krb5
SRCS+= krb5_passwd.c

DPADD+= ${LIBKRB5} ${LIBCRYPTO} ${LIBASN1} ${LIBCOM_ERR} ${LIBROKEN} ${LIBCRYPT}
LDADD+= -lkrb5 -lcrypto -lasn1 -lcom_err -lroken -lcrypt
LINKS+= ${BINDIR}/passwd ${BINDIR}/kpasswd
MAN+= kpasswd.1
.endif

.if (${USE_PAM} != "no")
CPPFLAGS+=-DUSE_PAM
SRCS+= pam_passwd.c
LDADD+=-lpam ${PAM_STATIC_LDADD}
DPADD+=${LIBPAM} ${PAM_STATIC_DPADD}
.endif

.include


我們知道 PAM 我們並不需要,而且加了,增加了許多 code 也增加了其他 library 造成檔案更大,
而目前,我還不會加入參數來將它略過,因此我使用較為土法煉鋼的方式,
將這段 code 直接拿掉~~~

因此整個 code 拿光了,變成如下:
# $NetBSD: Makefile,v 1.40 2005/03/04 20:41:09 he Exp $
# from: @(#)Makefile 8.3 (Berkeley) 4/2/94

.include

PROG= passwd
SRCS= local_passwd.c passwd.c
MAN= passwd.1

CPPFLAGS+=-I${.CURDIR} -DLOGIN_CAP

DPADD+= ${LIBCRYPT} ${LIBUTIL}
LDADD+= -lcrypt -lutil

BINOWN= root
BINMODE=4555

.include


要拿掉的部份,就是看 .if 和 .endif,像 HTML 那樣成對的拿掉~~~

Q:要如何使用?
A:
最後要用,依網站所述即可,作法類似如下:
mkdir /home/nfsroot/sbin
mkdir /home/nfsroot/bin
......
cp mytiny /home/nfsroot/root/sbin/init
ln /home/nfsroot/root/sbin/init /home/nfsroot/root/bin/sh
ln /home/nfsroot/root/sbin/init /home/nfsroot/root/bin/ls
......

這邊注意一點,我們直接用 ln 不加任何參數即可,
ln 不加任何參數,則 link 出來的檔案,每個都沒有實體,
都會指向到 init,所以每個檔案大小都相同,
而且有趣的是,當 init 更新之後,所有檔案也都會更新(因為沒有實體),
檔案大小都會是新 init 的 size。

Q:要如何更改 passwd 內容或 root 密碼?
A:
要變更 passwd 我是參考
http://web.bsdlab.idv.tw/FreeBSD_CVSup_Source.htm

其實關鍵在於如何使用 pwd_mkdb,而以我的環境來說,作法如下:

1.修改 passwd
vi /home/nfsroot/root/etc/passwd

2.修改 master.passwd
vi /home/nfsroot/root/etc/master.passwd

3.使用 pwd_mkdb
cd /home/nfsroot/root/etc
nbpwd_mkdb -p -d /home/nfsroot/root ./master.passwd

2010年3月13日

洗電路板初體驗

雖然以前讀高職科時有焊板子,不過當時可能因為危險或其他因素,所以並沒有洗電路板,事實上現在科大、職校洗電路板應該都不多吧!

繼前篇自製曝光機後,本篇就延續下去,把洗電路板過程有拍到的照片也po出來。

洗電路板的過程基本上如下:
  1.  製作電路投影片
  2.  曝光機曝光
  3.  顯影劑顯影
  4.  氣泡蝕刻機蝕刻
  5.  完成

要看完整的過程影片,可以參考台灣金電子製作的感光板製作流程,如下:


我自己的過程基本上和上面影片差不多,不過因為在陽台,位置比較克難就是了。

  1. 電路板投影片
  2. 因為是第一次,對於畫電路目前不很清楚,在高職時曾經教過protel,不過當時protel還DOS版,而且n年沒碰過,現在完全不會了,因此直接用現成的。 現成的電路板很好找,我找了LM2576的電路板(附在DataSheet內)AVR-Doper的,並且印成投影片。 在確定要曝光前,先要拿投影片和感光電路板比對一下,也要和正面的圖片比對一下,根據元件位置來確定沒有曝光顛倒,洗完才發現洗顛倒,會很想哭吧... 感光電路板照片如下:
    感光電路板 - 未拆封
    感光電路板 - 正面
    感光電路板 - 背面(曝光面)
  3. 曝光機曝光
  4. 這部份很不幸的,因為感光電路板保護膜撕掉後,我擔心曝光到,所以就急著曝光了,因此過程沒有拍照。 曝光時間,第一次我抓3分鐘,發現有點過曝,第二次抓2:45,狀況似乎好一點,下次也許可以試試看2:30。
  5. 顯影劑顯影
  6. 曝光完後,就是拿顯影劑進行顯影,我是按照網路上教的,買澆花用的器具來噴顯影劑顯影。 顯影完後的電路板照片如下:
    感光電路板曝光完成
  7. 氣泡蝕刻機蝕刻
  8. 首先,先將氣泡蝕刻機準備好,插電給它加熱。
    氣泡蝕刻機準備
    接著要正式開始洗電路板了,洗板子前先確定氣泡蝕刻機的溫度是否到達標準(40度C~60度C),洗板子當天寒流,溫度很低,當時室外溫度13度C左右,將加熱器調到60度C,溫度才升到40度。
    氣泡蝕刻機準備,到達需要溫度
    接著把電路板放入裡面開始蝕刻。
    電路板開始蝕刻
    蝕刻到一半左右
    蝕刻快完成囉
  9. 電路板完成
  10. 電路板洗好後,即可拿起來。 完成照:
    電路板完成

警語:
洗電路板式會有環境污染的,相信洗電路板的文章都會提到,既然我要上,自然會事先有相關的注意。
洗電路板最主要的危害是藥劑。
上網看,顯影劑的危害似乎還好,一般都還是倒掉即可,主要的危害是蝕刻劑
蝕刻劑的危害有二:
  1. 蝕刻劑為強酸
  2. 因為要腐蝕金屬銅,因此蝕刻劑為強酸,強酸當然對環境有害。
  3. 蝕刻劑含重金屬銅
  4. 因為蝕刻劑洗電路板,主要作用是把電路板表面的銅腐蝕,銅被腐蝕後就會溶入蝕刻劑中,如果隨意的亂倒,就會把土壤、水源污染,變成重金屬污染

為了解決危害,我一方面使用環保蝕刻劑,另一方面我在蝕刻後,用3個600cc的寶特瓶將這些蝕刻劑另外保存,所以只有電路板的清潔和少量的蝕刻劑不小心溢出。
如此一來蝕刻劑可重複使用,最後再用處理劑(搭配環保蝕刻劑用的)處理。
我想,以我的使用率和使用量,這批藥劑大概可以用個10年吧!

自製電路板用曝光機(使用掃瞄器改裝)-實作

在上篇對曝光機的事前規劃、成本計算後,這篇將實做的曝光機照片和過程貼出來。


  1. 二手掃瞄器(已拆解)
  2. 如果還留有掃瞄器的,可以直接使用,家裡曾經有一台,但幾年前就丟了,這台則是上網拍買的,基於回收價格多半都NT 100元,因此網拍大概都是NT 100元比較多也比較合理。 至於哪種好?反正都是要拆的,差別不大,我當時的需求是高度要10cm上下,當時是考慮到可能用日光燈管和燈座,但使用LED的話,高度問題比較小,如果有疑慮,可以找差不多8cm~10cm高的掃瞄器。 下面是掃瞄器的照片:
    曝光機外觀
    曝光機拆解1
    曝光機拆解2
  3. UV LED洞洞板
  4. 前篇成本篇計算過,要作曝光機,UV LED的C/P值高,而在真正製作時,我們需要洞洞板。 常見的洞洞板有兩種,綠色的是玻璃纖維板;咖啡色的是電木板。一般來說,玻璃纖維板比電木板耐用很多,不過價格也貴很多。基於高職時候做的8051板子到現在都還能動,電木板材質的板子也都一切正常,加上最重要的價格因素,因此我還是買了電木板。 施工過程並沒有拍照,因此只有完成品,但差別僅在於電烙鐵的銲接。 UV LED電路板照片:
    UV LED電路板正面
    UV LED電路板背面
  5. 掃描器+UV LED電路板
  6. 在UV LED電路板完成後,接著就是把它和掃描器結合,這邊比較麻煩的是電源接頭的固定,我最後是在掃描器背後打兩個洞,用螺絲倒鎖卡住電源接頭,效果相當不錯。雖然解釋的不清楚,但大家可以點選下面第一張照片放大來看,注意到電源部份,就可以清楚看到固定用的螺絲了。
    掃描器、UV LED電路板結合照1
    掃描器、UV LED電路板結合照2
    曝光機完成照
  7. 實際測試
  8. 曝光機至此已完成,接著實際插電測試看看。
    曝光機測試照

2010年3月3日

自製電路板用曝光機(使用掃描器改裝)-前傳(成本計算)

最近打算開始自己洗電路板,因此著手購置相關器具。
在網路上搜尋後得知,要洗出成功好看的電路板,曝光的程序是很重要的。
常見的曝光包括:
1. 曬太陽,這方法穩定性不好,時間不好掌控。
2. 檯燈+玻璃(或壓克力板),這方法滿常見的,但檯燈會有死角,而且我手邊沒有大玻璃或大壓克力板,買起來都不便宜
3. 專用曝光機,這個效果當然一級棒,但機器很貴,家裡不可能有
4. 投影機曝光,這個很新奇,看起來效果也不錯,可是我家也沒有投影機

基於上述理由,加上網路搜尋後,發現自行DIY曝光機的人很多,我稍微列出一些相關的網頁:
中文:
http://www.haifeng.idv.tw/leo/cgi-bin/topic.cgi?forum=241&topic=3&show=0
http://61.70.96.216/phpbb2/viewtopic.php?f=3&t=118&start=0

英文:
http://www.scienceprog.com/pcb-exposure-using-uv-light-led-box/
http://hackedgadgets.com/2009/04/21/diy-uv-led-double-sided-pcb-exposure-box/
http://www.embedds.com/ultraviolet-light-box-for-pcb-exposure/
http://www.webtreatz.com/index.php/projects/39-electronic-projects/60-uv-led-based-pcb-exposure-unit

中文的大概是上述兩個最經典,是使用掃瞄器+日光燈管或UV燈管製成的。
英文的則不少,很多是隨便找個工具箱就做了,另外,注意到很多都是用UV LED來製作。

接著,開始計算成本。
1. 二手掃瞄器,網拍很多,NT $100

使用燈管製作時,需要2組日光燈,包括2組燈座、2組電子安定器、2根燈管。
粗略估計
2a. 電子安定器約 NT $100 x 2
2b. 燈座(沒查,估計一組低於 NT $100) x 2
2c. 燈管,如果是日光燈管,一根約 NT $30 x 2;如果是UV燈管,一根約 NT $200~NT $350 不等 x 2

如果用日光燈管製作,估計成本大概要 NT $500 左右,應該可以低於NT $500。
但日光燈曝光時間大概需要10分鐘左右。

而如果用UV燈管製作,則成本大概要到NT $800 ~ NT $1000,要看UV燈管的價格而定。
使用UV燈管曝光時間大概只需要1分鐘~2分鐘的時間。

而使用UV LED製作,需要n顆UV LED、多張洞洞板、多顆電阻、一個變壓器、一個電源母座、一堆銅柱。
2a. UV LED我在露天拍賣有找到一顆NT $3,根據我在國外網站的搜尋,大概需要56~90不等的數量,這要根據LED矩陣的鋪設來決定,目前我使用88顆
2b. 洞洞板,因為洞洞板尺寸和一般的紙不大一樣,我設計時以A4為大小,因此準備了4張洞洞板,每張為10cm x 16cm,價格一張NT $30
2c. 多顆電阻,因為LED是二極體,需要有電阻來匹配,因此需要多顆電阻,電阻數量根據變壓器的輸入電壓、LED電壓、電流、串並聯方式而定,關於電阻的選擇,可以用這個網站幫你計算,原則上來說,變壓器的輸入電壓越大,LED可以串連越多,則矩陣並聯數量越少,電阻需要量也越少。以我這邊來說,需要16根150歐姆電阻,2根330歐姆電阻。購買UV LED時,網拍很貼心的有附上電阻和二極體,如果剛好和需要的一樣,則可以省下電阻費用,電阻一顆NT $0.5
2d. 變壓器很貴,尤其大電壓大電流的更貴,不過好在現在筆記型電腦便宜,幾乎人手一台,像我有報廢的舊筆電,變壓器都剩下來了,筆電的變壓器除了小筆電外,幾乎都是19V,電壓夠大,電流更是不用說,可以到2A以上,非常適合拿來替用,因此費用可以省下來
2e. 電源母座,找個筆電變壓器可以插的母座接頭,一個大概NT $3。
2f. 銅柱,用來把電路板固定在掃瞄器裡面的,因為有4塊電路板,至少需要16根銅柱,一個NT $2~NT $3。

整個成本算下來,大概在NT $500上下,和日光燈版的曝光機差不多費用,但UV LED曝光時間大概只要2~3分鐘,看起來C/P值很高,因此最後決定使用UV LED製作曝光機。

2010年1月7日

FFMpeg與SDL之播放器~心得 - 1

FFMpeg是Linux上知名的影音編解碼函式庫。
有多知名呢?這樣描述吧~Linux上播放程式並不多,但有數的播放程式幾乎都靠它進行解碼,就算這類播放程式有自帶解碼器或介面,也都會支援FFMpeg。

在這篇開始之前我必須要說清楚,FFMpeg是有軟體專利問題的,理論上無法用於商業開發,一旦被軟體專利的組織查到,是要花大錢的。
我在一年前左右就開始看FFMpeg,當時就是因為看到軟體專利問題,就停止了,這次會繼續的原因主要是:
1. FFMpeg是Linux上主要的編解碼函式庫,除了它別無選擇,Google Chrome的影音播放器目前也是以它為基礎,連Google Browser都用它,我只能相信在一般使用上,軟體專利問題應該不很大。
2. FFMpeg本身其實只是個編解碼函式庫的介面,意思是它在編譯時,可以選擇要編譯的編碼器和解碼器,我認為在商業化使用時,應該可以把有問題的編解碼器全部拿掉,只留下沒問題的(theora/ogg),如此一來對於自主的播放器來說,沒有軟體專利的問題,但程式又不需要更動即可使用。
3. 現在新版的FFMpeg有提供Nvidia的VDAPU的支援,可以直接用VDAPU進行H264的解碼,我一廂情願的認為,Nvidia的VDAPU應該已經有付過相關解碼器的專利費用了,所以用FFMpeg的VDAPU對影片解碼應該是沒軟體專利的問題。

因為上述的幾個想法,所以決定繼續FFMpeg和SDL的學習。

FFMpeg和SDL的播放器,最主要的學習是以An ffmpeg and SDL Tutorial - ffmpeg tutorial為主,不幸的是,隨著2010年跨年,跨完年它網站資料就不見了...@_@!
好加在它html雖然都不見了,但txt和source code倒是到還在,連結如下:
Tutorial 01文字版 Tutorial 01原始碼
Tutorial 02文字版 Tutorial 02原始碼
Tutorial 03文字版 Tutorial 03原始碼
Tutorial 04文字版 Tutorial 04原始碼
Tutorial 05文字版 Tutorial 05原始碼
Tutorial 06文字版 Tutorial 06原始碼
Tutorial 07文字版 Tutorial 07原始碼
Tutorial 08文字版 Tutorial 08原始碼

最後,有一點必須要說的,整篇FFMpeg與SDL的教學,是基礎在ffplay這個播放器,我按照他的教學寫了2週,在EeePC上播放都有問題,一執行CPU就滿載且播放一陣子程式就卡住,必須要強制關閉,結果搞半天,我用ffplay也遇到一樣的問題,所以測試上有問題,目前我打算改看mplayer,看播放器的設計上有何不同,來瞭解ffplay為啥在EeePC上執行會有這樣的問題。
前言結束。

第一篇:
本篇的教學在理解之後其實很簡單,目前網路上找得到的FFMpeg範例,程式碼幾乎都類似這篇的內容,如果只是想要進行影片的轉檔(不含聲音),那麼本篇足矣。

再次重申,FFMpeg是影音的編碼/解碼函式庫,因此它的主要工作都是在編碼解碼上,今天我們要寫個播放器,那麼單單只有FFMpeg是不夠的,所以還會需要SDL這樣的函式庫,不過這在第二篇才會細說,這邊僅針對FFMpeg的影片解碼過程進行解說(不含聲音)。

在瞭解FFMpeg的操作前,我們要先瞭解兩樣東西,一個是「檔案讀取流程」,另一個是「FFMpeg解碼處理流程」。
首先我們看到「檔案讀取流程」 。

檔案讀取流程:
char ch;
FILE *fp = fopen("test.txt","r");
while((ch = fgetc( fp )) != EOF)
printf("%c", ch);
fclose(fp);


上述這是一個非常常見的檔案讀取的程式段,它的流程很單純,就是下面三個步驟:


這裡關於流程圖的符號細節我們就不要考究了,菱形、圓弧型之類的會讓圖片一大團。

在FFMpeg也是一樣,FFMpeg操作的大架構事實上和檔案讀取相同,下面是它部份的程式段:
AVFormatContext *VideoFormatInfo;
av_open_input_file(&VideoFormatInfo, "test.mpg", NULL, 0, NULL);
.....
while(av_read_frame(VideoFormatInfo, &VideoPacket) >= 0)
{
影片操作;
.....
}
av_close_input_file(VideoFormatInfo);


操作上大概就上述這樣,不過我把大部分細節都去除了,因為這部份還沒提到。
這裡要讓人瞭解的是,FFMpeg的核心操作,其實就像是檔案讀取一般,只是FFMpeg要使用
1. av_open_input_file() 代換 fopen()
2. av_read_frame() 代換 fread()
3. av_close_input_file() 代換 fclose()

接著我們看到「FFMpeg解碼處理流程」。

FFMpeg解碼處理流程:
要瞭解FFMpeg的對影音檔的處理流程,基本上流程如下圖:


幾乎所有的播放程式,解碼的處理流程都像上圖這樣。

上述圖片中,關於聲音處理的部份都以半透明方式表示,原因在於,目前這篇文章僅討論影片處理,並沒有處理聲音部份,因此聲音部份並沒有在下面的程式碼和說明中。

上述的流程相對應到FFMpeg,會類似下面這樣的程式段:
.....
1. 解析出影音檔中的串流資訊
av_find_stream_info(VideoFormatInfo);
.....

2. 從影音檔的串流資訊取得影片軌是哪一軌
int VideoStreamIndex = -1;
int i = 0;
for(; i < VideoFormatInfo->nb_streams; i++)
{
if(VideoFormatInfo->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
{
VideoStreamIndex = i;
break;
}
}
.....

3. 從影片軌中取得影片的編碼
AVCodecContext *VideoCodecInfo = VideoFormatInfo->streams[VideoStreamIndex]->codec;
.....

4. 根據影片的編碼找出相對應的解碼器
AVCodec *VideoDecoder = avcodec_find_decoder(VideoCodecInfo->codec_id);
.....

5. 開啟解碼器
avcodec_open(VideoCodecInfo, VideoDecoder);
.....

6. 對讀取出來的影片資料進行解碼
avcodec_decode_video(VideoCodecInfo, VideoFrame, &frameFinished, VideoPacket.data, VideoPacket.size);
.....


到此,FFMpeg解碼的主要部份都解說了,接著我們把讀取影音檔的程式段和影片解碼的程式段整合,並且加入一些細節做說明。
#include "libavcodec.h"
#include "libavformat.h"
#include "stdio.h"

int main(int argc, char **argv)
{
//註冊所有FFMpeg的編碼器
av_register_all();

AVFormatContext *VideoFormatInfo;

if( av_open_input_file(&VideoFormatInfo, argv[1], NULL, 0, NULL) !=0 )
return -1; // Couldn't open file

if( av_find_stream_info(VideoFormatInfo)< 0 ) return -1; //顯示 dump_format(VideoFormatInfo, 0, argv[1], 0); AVCodecContext *VideoCodecInfo; int VideoStreamIndex = -1; int i = 0; for(; i < VideoFormatInfo->nb_streams; i++)
{
if(VideoFormatInfo->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
{
VideoStreamIndex = i;
break;
}
}
if(VideoStreamIndex == -1)
return -1;

VideoCodecInfo = VideoFormatInfo->streams[VideoStreamIndex]->codec;

AVCodec *VideoDecoder;

VideoDecoder = avcodec_find_decoder(VideoCodecInfo->codec_id);
if(VideoDecoder == NULL)
{
fprintf(stderr, "Unsupported codec!\n");
return -1;
}

if(avcodec_open(VideoCodecInfo, VideoDecoder) < 0) return -1; int frameFinished; AVPacket VideoPacket; i = 0; while(av_read_frame(VideoFormatInfo, &VideoPacket) >= 0)
{
if(VideoPacket.stream_index == VideoStreamIndex)
{
avcodec_decode_video(VideoCodecInfo, VideoFrame, &frameFinished, VideoPacket.data, VideoPacket.size);

if(frameFinished)
{
//影片檔圖片讀取完成,進行圖片操作或影像處理
}
}
av_free_packet(&VideoPacket);
}

av_free(VideoFrame);
avcodec_close(VideoCodecInfo);
av_close_input_file(VideoFormatInfo);

return 0;
}


上述的程式碼比之前2段程式段都更複雜些,但相似度非常高,沒加入的部份很少,這裡會對沒加入的部份進行說明。
這個程式碼應該算是可以動作的,但它並不會對取出的影片圖片進行處理,只是單純的解碼而已,更完整的部份再接著才會進行。
在這個程式碼中,有幾個前面沒提到的部份。
首先:
av_register_all();
這個function是用來告訴FFMpeg,我們要註冊所有的FFMpeg解碼器,註冊之後,我們後面的解碼器操作才能順利進行。

接著:
while(av_read_frame(VideoFormatInfo, &VideoPacket) >= 0) //跟讀取檔案方式相同,只要影片還有 Frame,就一直讀,av_read_frame會將讀到的 Frame 放入 AVPacket結構 中
{
// Is this a packet from the video stream?(這個 packet 是從 video stream 來的?)
if(VideoPacket.stream_index == VideoStreamIndex) //從已經讀到的 AVPacket結構 中,判斷這個 Packet 是哪個 stream 的,在這裡我們只需要 video stream,因此這行判斷
{
}
}

在使用av_read_frame()遞迴的讀取時,因為讀取到的影音資料是影片、聲音混合的,所以我們在讀取後要使用 if(VideoPacket.stream_index == VideoStreamIndex) {} 來判斷影片或聲音,判斷出影片後才能進一步操作,聲音在此則不管它。

接著:
if(frameFinished)
{
//影片檔圖片讀取完成,進行圖片操作或影像處理
}

這裡這段想必會很疑惑,frameFinish用途何在。
其實FFMpeg使用 av_read_frame() 讀出時,讀出的單位並不是一張圖片,而是影音的 Packet(封包),因為一部分的「Packet」並不能表示成一張「畫面」,因此我們在使用 avcodec_decode_video() 進行影片解碼時,要傳入 frameFinish,讓FFMpeg透過 frameFinish 告訴我們是否完成了一張完整的圖片解碼,當完成了一張圖片解碼時,if(frameFinished) {} 才會符合,我們也才能對這個解出的圖片(畫面)進行進一步的處理。

為了讓這個程式有意義,而不是虛無飄渺的甚麼東西都沒有,我們加上最後一個部份,把解碼出來的畫面進行輸出,整個程式可以把影片的最前面5張畫面輸出成5個圖片檔。

首先加入下面這段程式碼:
void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
FILE *pFile;
char szFilename[32];
int y;

// Open file
sprintf(szFilename, "frame%d.ppm", iFrame);
pFile=fopen(szFilename, "wb");
if(pFile==NULL)
return;

// Write header
fprintf(pFile, "P6\n%d %d\n255\n", width, height);

// Write pixel data
for(y=0; ydata[0]+y*pFrame->linesize[0], 1, width*3, pFile);

// Close file
fclose(pFile);
}


這段程式碼功能很簡單,將讀取出來的畫面(圖片),以 fwrite() 的方式寫入到檔案中,就成為了 ppm 格式的圖片檔。

為了要能使用 SaveFrame(),我們還需要改寫剛剛的程式碼。
.....
if(avcodec_open(VideoCodecInfo, VideoDecoder) < 0) return -1; //針對 SaveFrame() 新加程式段 開始 AVFrame *VideoFrame; AVFrame *VideoFrameRGB; VideoFrame = avcodec_alloc_frame(); VideoFrameRGB = avcodec_alloc_frame(); if(VideoFrameRGB == NULL) return -1; uint8_t *VideoBuffer; int numBytes; numBytes = avpicture_get_size(PIX_FMT_RGB24, VideoCodecInfo->width, VideoCodecInfo->height);
VideoBuffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

avpicture_fill((AVPicture *)VideoFrameRGB, VideoBuffer, PIX_FMT_RGB24, VideoCodecInfo->width, VideoCodecInfo->height);
//新增 結束

int frameFinished;
AVPacket VideoPacket;
i = 0;
while(av_read_frame(VideoFormatInfo, &VideoPacket) >= 0)
{
.....
if(frameFinished)
{
//針對 SaveFrame() 新加程式段 開始
if(new_img_convert == NULL)
{
new_img_convert = sws_getContext(VideoCodecInfo->width, VideoCodecInfo->height, VideoCodecInfo->pix_fmt, VideoCodecInfo->width, VideoCodecInfo->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
}
if(new_img_convert == NULL)
{
fprintf(stderr, "Cannot initialize the conversion context!\n");
exit(1);
}
sws_scale(new_img_convert, VideoFrame->data, VideoFrame->linesize, 0, VideoCodecInfo->height, VideoFrameRGB->data, VideoFrameRGB->linesize);

// 將 frame 存入檔案中
if(++i <= 5) { SaveFrame(VideoFrameRGB, VideoCodecInfo->width, VideoCodecInfo->height, i);
}
}
.....

最後,下面這個連結就是完整的程式碼檔案。
ffmpeg_1x.c

2009年9月14日

LUXGEN7 MPV試駕開始~

之前blog的台灣~裕隆~汽車設計提到現在裕隆正在自製汽車,最近這段時間可以注意到,開始陸續有廣告出現,mobile01也出現了LUXGEN的版面和相關活動介紹。

雖然我買不起,但支持還是要的,針對這台非常現代化的自製汽車,專業介紹很多,我也就不獻醜了。

網路雜誌對LUXGEN7 MPV的介紹:
汽車線上:【國內試駕】LUXGEN7 MPV <上>
汽車線上:【國內試駕】LUXGEN7 MPV <下>

網友的試駕心得:
智慧車款新體驗-LUXGEN7 MPV試駕分享

從這台車的介紹看起來,我個人覺得它倒車攝影機相當方便,和我之前想到的想法差不多,把攝影機放置在後照鏡,可以方便的透過LCD即可看到後方的狀況,是很方便的設計,想想看,每次開車看後照鏡時,總是會卡一條黑邊擋住視線,或者有些地方就是因為鏡子角度不好橋看不到,能夠有個這樣的攝影機可以無死角的看到後方,真的是很棒;此外,它的夜視系統真的很不錯哩,0.1流明的極低亮度下,可以看到前方100公尺,寬度40公尺範圍內的畫面,這性能相當的好。

其他部份,我沒親自看過車,對汽車瞭解也不深,也就不方便評論太多(好壞不會分),不過站在資工人的角度來看,它的電腦系統還有剛剛提到的夜視系統和攝影系統,我覺得相當的先進。

對於mobile01上一些人批評它只是加了電子設備的飛羚101,或者說這台車號稱世界第一的智慧型汽車,根本沒把大廠車放眼裡...等等的說法,我只能說,這台車好歹是台灣人自己做的,未來要賣大陸賣歐洲賣美國的,這台車在研發過程中,夜視系統跟中科院技轉,酒精測試系統跟工研院,使用了醫療上的無接觸感測技術,加上它電腦系統跟HTC合作,這些裝置、設備、技術還有和汽車本身的高度整合,並不是全世界所有車廠都有的,你可以說它某部份比不過BMW、賓士、Toyota(像停車輔助系統,BMW、賓士都提供自動停車),但這台車並不是所有技術其他車廠都有,有些是它才獨有的,有些則是賓士、BMW這種高級車款才有的,如果僅僅只是在旁邊打嘴砲,看看DM就說這個賓士有、這個BMW有,這個Toyota做更好是不公平的,因為最終能夠把這些技術統統整合放入一台汽車中,售價又能比賓士、BMW低很多符合台灣人口袋的水準,那就是一台好車,對於這樣的車子,只是在旁邊看熱鬧,那就多點讚美少點批評吧!!

2009年8月21日

軌跡記錄器有無機會變成自救器?

這次風災,開始出現一些新聞是討論空投位置錯誤,因此拿不到救援物資,也出現了女兒給國軍座標後,救出父親的新聞。

在現在這個資訊發達的時代,GPS & GIS已經普遍到深入一般人的生活中了,而在遇到災難時,只要能夠有GPS座標且人沒死,能夠獲救的機會就很大。

目前軌跡記錄器已經十分普遍了,記錄器本身其實就是GPS,透過不斷地紀錄目前位標,最後透過USB傳輸線傳回電腦後,和GIS結合並顯示。
既然這樣,有沒有可能把軌跡記錄器和救生器結合?當發生意外時(按下按鈕或者受到強烈碰撞),記錄器便會自動發送訊號,告知目前的GPS座標,如此一來就能自救。
我認為這樣的想法不錯,但最大的問題可能是在「發送訊號」這部份,是要送出無線電信號(摩斯電碼)?SMS簡訊?無線網路?3G?

我個人是覺得,如果size許可,軌跡記錄器結合無線電,在遭遇災難時,固定30分鐘或1小時發送一次SOS+GPS座標的無線電信號,應該是不錯的idea。

2009年8月14日

颱風災情嚴重,請大家有錢出錢有力出力

首先,我在今天下午終於辦完離校,拿到畢業證書了,雖然還要留學校幾天寫交接文件和測試,但這算是負責了~沒有直接跑掉~

回主題~
先po上我最近幾天的MSN標題:
讓我們一起用愛與善款幫助88水災受難者!我決定捐出半個月薪水3000元給紅十字會!http://tw.charity.yahoo.com/

因為我還算是學生身份,薪水還只有6000元,我在8/11號已經透過Yahoo!奇摩 公益捐出半個月薪水3000元,我想這是目前我還有能力做到的事情。
我其他實驗室的同學在口試完畢後,因為他們老闆並沒有太多要求,沒什麼事情~已經去當義工幫忙好幾天了!

這次捐款也是我繼上次四川震災後的第二次捐款,金額也都是3000元。

我的捐款紀錄
日期公益團體專案名稱需求名稱捐款金額方式
2009/08/11中華民國紅十字會八八水災援助計畫災後重建3,000信用卡


這次的風災災情非常誇張,南台灣降下2500毫米以上的雨,這樣的量已經超過了200年防洪標準,我相信就算在美國、日本等更先進的國家,這樣的雨量造成的災害並不會比較好。
這次風災,似乎也是第一次看到派出特戰隊員去搜救探路,我不確定之前有沒有過,但上新聞應該也是第一次,值得鼓勵,畢竟養兵千日,就是用在這時候。

我相信目前的物資應該已經夠了,救災物品應該已經爆了,特別把捐款紀錄列出來不是炫耀,是建議可以把錢捐給災後重建,我認為:
1. 目前看來物資不缺,再捐物資意義不大且浪費資源
2. 目前快進入災後重建的步驟,災後重建就會開始需要花錢
3. 災後重建需要的費用更高,而且耗費時間更長
4. 這時候在無法預料未來需求時,錢比物資更有用
5. 到災後重建的階段,大家心都冷了,捐款會變少,到時候指定用途為救災用途的捐款可能會過多卻沒用,變成浪費

基於上述5點,我把錢捐來做「災後重建」,相信可以讓3000元達到最大的效力,也希望大家還要捐款、捐愛心的,有錢可以捐給重建基金,有力有時間的可以去當義工幫忙。

2009年8月3日

PDAMessager成果展示

口試結束了~搞了四年終於快畢業了~
口試後 新Media Center 計畫繼續。

新Media Center打算用朋友建議的,主機和外接盒分離,外接盒部份就只放光碟機、讀卡機...等,主機部份就用個舊PC殼加上Core 2 Pentium CPU、入門主機板和N9400GT顯示卡。

因為目前的Media Center-ASUS DigiMatrix是有個小小地LED顯示幕的,我上面透過程式擷取中央氣象局的資訊,它能顯示時間和目前的氣溫。
為了能夠有同樣的訊息顯示,我考慮在外接盒上加入一個LCM顯示幕,不過後來受到銀欣 GD02-MT 家庭劇院機殼銀欣 CW03-MT 全鋁家庭劇院機殼的啟發,想到可以仿照它的方式,加個LCD顯示器,而這樣的LCD顯示器不過就是個ARM開發板+LCD螢幕罷了,在網拍後發現目前舊的PDA價格非常不錯,NT 1000多就可以買到iPAQ 3xxx(3600、3800、3900都有),而LCM顯示幕一塊128x64 藍底白字版本,網拍要NT 500,光華要NT 800,這還不算Printer Port...等零件的費用,考慮到CP值,用舊PDA當然划算,因此就有了PDAMessager的計畫。

PDAMessager功能上,就是一個類似捷運的資訊看板,它的主要功能就是替代ASUS DigiMatrix上氣溫、時間的顯示,不過既然全彩又更大,當然希望加些新功能,因此開發上訴求是:
1. 要能顯示時間、溫度
2. 要能夠按遙控器時,顯示訊息(像「播放」)
3. 因為PC不可能一直開著,當PC關機時,要能顯示PC為關機狀態

這次這個是口試後開工的成果,到目前為止大概花了3周的時間,原則上就是SDL + Socket Server的成品。

首先如下圖,這是測試的示意圖,原則上它就是USB接電腦,USB網路就會自動連線並設定好IP。
寄件者 iPAQ3950


接著看到它的成果影片:


畫面的內容是這樣的:
當程式啟動後,會進入MODE 1,也就是一般的天氣、時間顯示的模式。

當PC關機時,我們可以透過Socket Client的方式下指令,讓它進入MODE 0,也就是畫面切換成只有時間的模式,注意看,右下角有個關機。

再來展示的是當遙控器按下時,PC同樣可以透過Socket Client下指令,將要顯示的文字、字體大小、顏色(RGB)傳過去,之後切換到MODE 2,即可顯示出文字內容,為了展示這個程式可以支援多國語言,因此顯示了「中文 にほんご EN」,表示中文、日文、英文都ok。

再來看到畫面變成了一張風景照,這是考慮到傳入的訊息,如果只是文字可能太單調了,顏色又只有一種,也許未來可以在PC端即時的產生「圖片」來顯示,因此也提供了可以傳入圖片顯示的功能,這功能說不定還能當作相簿來使用。

最後我們看到最後一個畫面,同樣也是風景照,但是上面印了文字「風景照片」四個字,這是考慮到遙控器動作時,可能希望顯示個背景加上訊息,因此結合了上面顯示文字和顯示圖片的功能,讓它能夠同時顯示圖片和文字。

2009年6月28日

FreeBSD MPD PPPoE斷線檢查Script

家裡是用中華電信FTTB的VDSL,設定實際上就是PPPoE的設定,而我使用FreeBSD+pf+mpd當NAT。

雖然中華電信大部分情況下都滿穩的,不大會斷線(可能VDSL過熱、機房改設定...等原因吧),但有時候就是會不知道什麼原因斷線,mpd上關於重新連線的設定雖然有加,但似乎沒啥效果,斷線後就是沒IP不會重新連線。

這次又發生了這樣的情況,為瞭解決這樣的問題,寫了個超簡單斷線檢查Script,在發生PPPoE斷線時自動把電腦重新開機。

#!/bin/tcsh

if(== `/sbin/ifconfig | /usr/bin/sed '/-->/\\!d' | /usr/bin/awk '{ print $2 }'`) then
/sbin/reboot
endif


程式碼超級簡單,當執行它之後,它會執行

/sbin/ifconfig | /usr/bin/sed '/-->/\!d' | /usr/bin/awk '{ print $2 }'


也就是執行ifconfig,然後找「-->」,找到後把第二個字串取出(PPPoE取得的IP),如果找不到,顯然就是PPPoE斷線了。
接著透過 tcsh 的 if 判斷式,判斷上述指令「找不到時」,就執行裡面的指令

/sbin/reboot


完成後改好權限,把它放入/etc/crontab中

*/30 * * * * root /usr/local/bin/disconnect-check.sh


如此一來,每30分鐘它都會執行一次,看看PPPoE有沒有秀斗,如果秀斗了,就把電腦重開。

我有測試過,應該是能夠work的。

2013-08-30更新
程式更新如下
#!/bin/tcsh

if( ! -e /var/log/disconnect-reboot.log ) then
  touch /var/log/disconnect-reboot.log
endif

if(== `/sbin/ifconfig ng0`) then
  echo `date +%Y-%m-%d\ %H:%M:%S` reboot >> /var/log/disconnect-reboot.log
  reboot
else
  if(== `/sbin/ifconfig ng0 | /usr/bin/sed '/-->/\\!d'`) then
  echo `date +%Y-%m-%d\ %H:%M:%S` mpd restart >> /var/log/disconnect-reboot.log
  /usr/local/etc/rc.d/mpd5 restart
  endif
endif

新增與修改:
1. 檢查log檔案是否存在,不存在則建立
2. 如果裝置ng0不存在,重新開機(異常情況)
3. 如果裝置ng0存在,但沒有IP,將mpd重新啟動(通常的斷線情況)

2009年5月15日

FreeBSD登入後中文亂碼問題

在 FreeBSD 中,雖然已經支援 Unicode(UTF-8) 了,但如果我們只有設定在 csh.cshrc 中,我們會發現登入後的訊息依然是亂碼,原因是在於登入時候的環境設定並沒有設定成 zh_TW.UTF8。

這意思是說,雖然我們在 csh.cshrc 裡面設定了環境是 zh_TW.UTF8,但在我們登入時,系統完成認證,並執行 SHELL 的時候,並沒有設定環境是 zh_TW.UTF8,因此這時候的訊息如果是 UTF-8 的編碼,會是亂碼的狀況。

解決辦法很簡單,我們在 /etc/login.conf 裡面加入相關設定,修改如下:
default:\
:passwd_format=md5:\
:copyright=/etc/COPYRIGHT:\
.....
:ignoretime@:\
:umask=022:


改成
default:\
:passwd_format=md5:\
:copyright=/etc/COPYRIGHT:\
.....
:ignoretime@:\
:charset=zh_TW.UTF-8:\
:lang=zh_TW.UTF-8:\
:umask=022:


修改完畢後,要記得執行如下指令,將設定寫入系統中:
# cap_mkdb /etc/login.conf

即可!

2009年4月8日

永豐開戶ok嚕~~

今天天氣不錯,特別在下午跑了一趟永豐銀行。

永豐銀行的無摺戶我想不用再介紹了,它的跨行免手續費很優,我就是衝著這點辦的(4/1開始,跨行提款、轉帳免手續費改成4次,不再是8次了),在此之前,我是用富邦的V Banking,不錯是不錯,一家富邦分行離我家又超近(走路就可以到了),但它只有2次跨行轉帳免手續費,有時候會不大夠用。

也剛好有一家永豐銀行離學校不會非常遠,以距離來說,從學校出發,到永豐的距離比到富邦近。

今天開戶很順利,並不像網路說的被一直刁難,倒是有說我不是在戶籍地,我就直接說我是學校的學生,然後服務小姐跟我要學生證,整個過程都很順利,幾乎就簽簽名,填填個人資料就完成了。
接下來就是等下週去銀行拿提款卡嚕~~

Google App Engine支援Java啦~

自從去年的Google Developer Day之後,我就對Google App Engine頗有興趣,想想看,我們能夠免費的利用到Google龐大的Cluster系統,是一件多棒的事情阿!
可惜它一直以來都只支援Python,我跟它完全不認識,因此對Google App Engine一直都只能看著流口水.....
現在不同了~Google App Engine在昨天4/7正式發佈支援Java,未來我就可以用熟悉的Java來開發App Engine,不論是玩票性質的寫個留言板,還是其他奇怪的想法,都會是很棒的事情。

2009年3月29日

Smoothie光合舒果昔試飲心得

每次到便利商店要買喝的,看到琳瑯滿目的飲料都不知道要買什麼才好。
看到果汁、蔬果汁,就會注意到果汁成份只有30%、50%,甚至還有10%的。
喝紅茶、綠茶、奶茶,就會發現裡面果糖加很大,好像整瓶果汁有半瓶都是糖的感覺。
喝烏龍茶、綠茶儘管不錯,也有無糖可以選,但永遠都只有烏龍茶和綠茶可以選。

這次因為看到「Smoothie光合舒果昔」的試飲心得活動,我注意到了這個新的飲料,更因此愛上了它。


Smoothie光合舒果昔從拿在手上到喝下第一口的感覺,都讓我注意到了它的用心,它使用的不是傳統的鋁箔包,而是目前最新的「利樂鑽包裝」,這種包裝拿在手上握感很不錯,不像傳統的鋁箔包,哪個方向握感覺都怪怪的;此外這種包裝和傳統的鋁箔包相比,從表面看感覺大小差不多,但它的內容量卻足足有330ml,份量比傳統的鋁箔包多了很多。

一個新的飲品單單只有包裝好是沒有用的,Smoothie光合舒果昔的口感相當的棒。

我這次買的是「strawberry & banana」的口味,正如名字中的Smooth,飲料倒入嘴巴、滑過喉嚨的感覺非常滑順,不會有喝冰水的刺激感;此外,非常值得一提的,在喝過後一陣子,不會殘留不自然的甜味或化學糖份的苦味、澀味。
喝一口放入口中,香蕉的綿密感讓人印象深刻,其他的水果像是草莓、水蜜桃、蘋果的香甜滿溢口中,此刻會有一種幸福的感覺,好像煩惱都煙消雲散一般。

感謝7-11能夠研發出這麼讚的飲品,讓我自烏龍茶、綠茶後,又找到一個新的選擇。

下面是我和它的親密合照。



晚餐與它的合照。


http://blog.7-11.com.tw/diary.asp?blogid=153

2009年3月27日

FON變身大絕招

剛剛因為學弟send給我關於FON賺錢相關的文章,勾起了我對FON的回憶。

之前曾經google過FON可以怎麼改裝,而查到下面這個網址:
http://www.lefinnois.net/wpen/index.php/2007/05/13/i2c-bus-for-la-fonera/

當然還有其他類似的網站,原則上以「FON i2c」來搜尋就能找到了。

很多人都會問,FON要怎麼改裝?能夠變成怎樣?能不能當電話?能不能跑BT?
但大部份都還侷限在軟體相關的服務,通常把它和無線基地台或IP分享器劃上等號,然後查詢或試想能做什麼。

但其實~FON它還有個很棒的地方,就是它是個超小且支援802.11g的嵌入式開發板,它上面同樣有I/O可以使用。
這時候我們終於介紹到上述網站的內容了。

在國外瘋狂的FON hacker的努力下,FON已經被完全且深入的瞭解了。

FON內建的I/O並不多,經過「處理」後(以4根GPIO模擬2組I2C介面),FON可以拉出「2組I2C」介面,這是FON僅能利用的I/O介面,但對於電子相關科系的同學們來說,這已經足以讓我們開始各種惡搞計畫。

I2C是近年熱門的介面,它有幾種表示方式,IIC、I2C,其中的2其實是平方,因為打字的關係,通常連著打。
在電子相關科系中,大部分同學可能還沒聽過它,但它被用的很多了。
I2C其實和RS-232(UART)差不多,同樣是串列傳輸埠,但它只需要2條線就能動作了,I2C因為只有2條線,又只是high/low的表示,因此在遇到沒有內建I2C的時候,可以用2根標準IO來模擬出I2C的動作,而目前一些單晶片像是部份AVR就有內建I2C介面。

既然FON有I2C可以操作,而且還有2組,我們就能夠透過I2C將FON和AVR之類的單晶片進行連接,由FON對AVR下指令,再由AVR實際動作,開發上其實和PC<->RS232<->8051差不多。

有了類似AVR這樣的單晶片,我們就能夠用AVR開發各類電子專題,像是常見的自走車、警報器...等。
AVR+FON,我們就能夠開發802.11g的遙控自走車。

人家說沒圖沒真相,事實上國外已經有不少人以FON開發出自走車,原理不外乎就是FON+單晶片組合而成,影片如下:
http://www.youtube.com/watch?v=7qqthHWTheA
http://www.youtube.com/watch?v=2hBb3F27Tsc
http://www.youtube.com/watch?v=A4wdrhiMO0s

而關於FON的I2C介面如何拉出來,下面的blog有不錯的教學:
i2c bus for La Fonera

另外,下面這個網頁雖然不是拉出I2C,拉出來的是SPI介面,但用的I/O腳相同,同樣可以參考:
Fonera SD Card Hack

2009年3月26日

該用64bit Linux嗎?(新測試已逆轉)

剛剛朋友問我,它們公司在考慮新環境是否該改用64bit Linux,問我是否適合換成64 bit,換了有什麼好處?效能表現差異多大?

我曾經在摩托學園詢問過Intel 64 bit 在 Debian 上要怎麼設定?,另外也搜尋到大家的 x86-64 CPU 都跑 amd64 還是 i386 呢?,看起來大部分都還是建議用32bit Linux。

而一般來說,64 bit Linux的效能應該會比較好,那以效能表現來說,64 bit Linux效能能好多少?是否以效能為考量的Linux Server用64 bit會比較好呢?
於是我用「32bit 64bit linux performance」為關鍵字在Google搜尋,找到下面2篇:
AMD Phenom 32-bit vs. 64-bit Performance
Ubuntu: 32-bit v. 64-bit Performance

這邊要特別注意,Ubuntu: 32-bit v. 64-bit Performance這篇是2006年的測試。

從上述2個網頁中,作者針對32bit和64bit的Linux的比較,我發現到幾個事情:
1. 在遊戲相關的效能中比較,64 bit Linux幾乎都比32 bit Linux差,而且差不少
2. 在I/O相關的行為上,包括RAM的讀寫...等,32 bit Linux和64 bit Linux表現差不多,32 bit Linux略快
3. 針對CPU處理頻繁的工作,包括kernel make(gcc compiler)、MP3轉檔(lame)、檔案壓縮(gzip)上,64 bit Linux的表現要比32 bit Linux好
4. 可能是因為硬體不同,也可能是新版有針對64 bit做最佳化,2006年的那份測試和2008年的測試,gzip的表現反應差異較大,lame的表現差距幅度也有差異

整體來說,我認為64 bit Linux應該只有在CPU關聯性大的工作會有較突出的效能表現,其他部份「效能不一定比較好」,此外,在摩托學園的討論中看得出來,目前64 bit Linux還是有不少應用程式不支援。
所以我認為,目前還不是全面使用64 bit Linux的時候,除非對於CPU效能極度要求的情況下,那麼我個人的建議是,先瞭解該Linux Server要運作的應用程式或服務,目前對64 bit Linux的支援狀況(包括相容性、是否針對64 bit指令集EM64T最佳化...等),全部確定後,一切ok再上路
如果是個人PC或桌面系統,那麼正如上面說的,我認為目前還不是使用64 bit Linux的時候。


感謝回覆留言的匿名網友,從最新的測試中可以發現,現在64 bit Linux在64 bit平台上效能已經超越32 bit,而且超越很多,上述評估已經不正確了。

2009年3月24日

詐騙電話

剛剛又接到詐騙電話了~
可能因為上次耍了他,這次打來一接就掛斷~
因此上網搜尋後,下面列出搜尋到的詐騙電話,未來會持續更新:
0913925523
0927344966
0927429858
0938822315
0938822531
0989041218
0989041220
0989041385
0989382037
0989385003
0989385004
0989385031
0989385032
0989385033
0989385034(我剛剛接到這隻)
0989385037
0989385039
0989385040
(以上來源:http://www.wretch.cc/blog/hsueh925/10138374)
0989677972
(以上來源:http://www.wretch.cc/blog/may931107/20411495)
0989565193
0989506753
(以上來源:http://blog.yam.com/speed777/article/14211587)
0982649297
0982752752
0923790350
(以上來源:http://blog.sina.com.tw/t_mango/article.php?comment_page=19&pbgid=1523&entryid=16674)
0980486012
(以上來源:http://www.mobile01.com/topicdetail.php?f=37&t=791387&p=7)
0980149288
(以上來源:網友留)
最後寫下防堵的辦法
如果使用新款的智慧型手機(高階手機),可以針對不同手機作業系統來找「來電黑名單(也叫來電警衛...等類似名稱)」軟體並安裝,輸入上述電話號碼後即可幫你自動過濾,未來有新的,再持續更新。
如果像我一樣使用舊款手機,我記得Sony手機有黑名單功能,之前的T68記得有看過,而我正在用的Nokia 6230沒有黑名單功能,不過Nokia手機可以設定「號碼分組」,目前設定一個「黑名單分組」,把上述號碼全部加入,接著錄製一段無聲鈴聲並設為分組鈴聲即可。