2011年4月4日

OpenOffice Calc BASIC Macro位址、名稱轉換

在OOo Calc中寫OOo BASIC時,會遇到個問題是,
要取得Cell時,常使用getCellByPosition() Method,例如:
oCell = oSheet.getCellByPosition(0,0)
oCell.String = now 'This function returns the current date and time

這樣可以取得A1這個Cell,並修改它的內容。

但getCellByPosition() Method使用的是0 Base,且X、Y都是數值,
可是在Calc當中,
我們一般操作都使用A1這樣的字母+數值,且是1 Base,
為了解決這個麻煩的小問題,我寫了個簡單的轉換函式,如下:
Function CellPositionToName(X As Integer, Y As Integer) As String
Dim LETTER_ARRAY As Variant
LETTER_ARRAY = Array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","AA","AB","AC","AD","AE","AF","AG","AH","AI","AJ","AK","AL","AM","AN","AO","AP","AQ","AR","AS","AT","AU","AV","AW","AX","AY","AZ","BA","BB","BC","BD","BE","BF","BG","BH","BI","BJ","BK","BL","BM","BN","BO","BP","BQ","BR","BS","BT","BU","BV","BW","BX","BY","BZ","CA","CB","CC","CD","CE","CF","CG","CH","CI","CJ","CK","CL","CM","CN","CO","CP","CQ","CR","CS","CT","CU","CV","CW","CX","CY","CZ","DA","DB","DC","DD","DE","DF","DG","DH","DI","DJ","DK","DL","DM","DN","DO","DP","DQ","DR","DS","DT","DU","DV","DW","DX","DY","DZ","EA","EB","EC","ED","EE","EF","EG","EH","EI","EJ","EK","EL","EM","EN","EO","EP","EQ","ER","ES","ET","EU","EV","EW","EX","EY","EZ","FA","FB","FC","FD","FE","FF","FG","FH","FI","FJ","FK","FL","FM","FN","FO","FP","FQ","FR","FS","FT","FU","FV","FW","FX","FY","FZ","GA","GB","GC","GD","GE","GF","GG","GH","GI","GJ","GK","GL","GM","GN","GO","GP","GQ","GR","GS","GT","GU","GV","GW","GX","GY","GZ","HA","HB","HC","HD","HE","HF","HG","HH","HI","HJ","HK","HL","HM","HN","HO","HP","HQ","HR","HS","HT","HU","HV","HW","HX","HY","HZ","IA","IB","IC","ID","IE","IF","IG","IH","II","IJ","IK","IL","IM","IN","IO","IP","IQ","IR","IS","IT","IU","IV","IW","IX","IY","IZ","JA","JB","JC","JD","JE","JF","JG","JH","JI","JJ","JK","JL","JM","JN","JO","JP","JQ","JR","JS","JT","JU","JV","JW","JX","JY","JZ","KA","KB","KC","KD","KE","KF","KG","KH","KI","KJ","KK","KL","KM","KN","KO","KP","KQ","KR","KS","KT","KU","KV","KW","KX","KY","KZ","LA","LB","LC","LD","LE","LF","LG","LH","LI","LJ","LK","LL","LM","LN","LO","LP","LQ","LR","LS","LT","LU","LV","LW","LX","LY","LZ","MA","MB","MC","MD","ME","MF","MG","MH","MI","MJ","MK","ML","MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV","MW","MX","MY","MZ","NA","NB","NC","ND","NE","NF","NG","NH","NI","NJ","NK","NL","NM","NN","NO","NP","NQ","NR","NS","NT","NU","NV","NW","NX","NY","NZ","OA","OB","OC","OD","OE","OF","OG","OH","OI","OJ","OK","OL","OM","ON","OO","OP","OQ","OR","OS","OT","OU","OV","OW","OX","OY","OZ","PA","PB","PC","PD","PE","PF","PG","PH","PI","PJ","PK","PL","PM","PN","PO","PP","PQ","PR","PS","PT","PU","PV","PW","PX","PY","PZ","QA","QB","QC","QD","QE","QF","QG","QH","QI","QJ","QK","QL","QM","QN","QO","QP","QQ","QR","QS","QT","QU","QV","QW","QX","QY","QZ","RA","RB","RC","RD","RE","RF","RG","RH","RI","RJ","RK","RL","RM","RN","RO","RP","RQ","RR","RS","RT","RU","RV","RW","RX","RY","RZ","SA","SB","SC","SD","SE","SF","SG","SH","SI","SJ","SK","SL","SM","SN","SO","SP","SQ","SR","SS","ST","SU","SV","SW","SX","SY","SZ","TA","TB","TC","TD","TE","TF","TG","TH","TI","TJ","TK","TL","TM","TN","TO","TP","TQ","TR","TS","TT","TU","TV","TW","TX","TY","TZ","UA","UB","UC","UD","UE","UF","UG","UH","UI","UJ","UK","UL","UM","UN","UO","UP","UQ","UR","US","UT","UU","UV","UW","UX","UY","UZ","VA","VB","VC","VD","VE","VF","VG","VH","VI","VJ","VK","VL","VM","VN","VO","VP","VQ","VR","VS","VT","VU","VV","VW","VX","VY","VZ","WA","WB","WC","WD","WE","WF","WG","WH","WI","WJ","WK","WL","WM","WN","WO","WP","WQ","WR","WS","WT","WU","WV","WW","WX","WY","WZ","XA","XB","XC","XD","XE","XF","XG","XH","XI","XJ","XK","XL","XM","XN","XO","XP","XQ","XR","XS","XT","XU","XV","XW","XX","XY","XZ","YA","YB","YC","YD","YE","YF","YG","YH","YI","YJ","YK","YL","YM","YN","YO","YP","YQ","YR","YS","YT","YU","YV","YW","YX","YY","YZ","ZA","ZB","ZC","ZD","ZE","ZF","ZG","ZH","ZI","ZJ","ZK","ZL","ZM","ZN","ZO","ZP","ZQ","ZR","ZS","ZT","ZU","ZV","ZW","ZX","ZY","ZZ","AAA","AAB","AAC","AAD","AAE","AAF","AAG","AAH","AAI","AAJ","AAK","AAL","AAM","AAN","AAO","AAP","AAQ","AAR","AAS","AAT","AAU","AAV","AAW","AAX","AAY","AAZ","ABA","ABB","ABC","ABD","ABE","ABF","ABG","ABH","ABI","ABJ","ABK","ABL","ABM","ABN","ABO","ABP","ABQ","ABR","ABS","ABT","ABU","ABV","ABW","ABX","ABY","ABZ","ACA","ACB","ACC","ACD","ACE","ACF","ACG","ACH","ACI","ACJ","ACK","ACL","ACM","ACN","ACO","ACP","ACQ","ACR","ACS","ACT","ACU","ACV","ACW","ACX","ACY","ACZ","ADA","ADB","ADC","ADD","ADE","ADF","ADG","ADH","ADI","ADJ","ADK","ADL","ADM","ADN","ADO","ADP","ADQ","ADR","ADS","ADT","ADU","ADV","ADW","ADX","ADY","ADZ","AEA","AEB","AEC","AED","AEE","AEF","AEG","AEH","AEI","AEJ","AEK","AEL","AEM","AEN","AEO","AEP","AEQ","AER","AES","AET","AEU","AEV","AEW","AEX","AEY","AEZ","AFA","AFB","AFC","AFD","AFE","AFF","AFG","AFH","AFI","AFJ","AFK","AFL","AFM","AFN","AFO","AFP","AFQ","AFR","AFS","AFT","AFU","AFV","AFW","AFX","AFY","AFZ","AGA","AGB","AGC","AGD","AGE","AGF","AGG","AGH","AGI","AGJ","AGK","AGL","AGM","AGN","AGO","AGP","AGQ","AGR","AGS","AGT","AGU","AGV","AGW","AGX","AGY","AGZ","AHA","AHB","AHC","AHD","AHE","AHF","AHG","AHH","AHI","AHJ","AHK","AHL","AHM","AHN","AHO","AHP","AHQ","AHR","AHS","AHT","AHU","AHV","AHW","AHX","AHY","AHZ","AIA","AIB","AIC","AID","AIE","AIF","AIG","AIH","AII","AIJ","AIK","AIL","AIM","AIN","AIO","AIP","AIQ","AIR","AIS","AIT","AIU","AIV","AIW","AIX","AIY","AIZ","AJA","AJB","AJC","AJD","AJE","AJF","AJG","AJH","AJI","AJJ","AJK","AJL","AJM","AJN","AJO","AJP","AJQ","AJR","AJS","AJT","AJU","AJV","AJW","AJX","AJY","AJZ","AKA","AKB","AKC","AKD","AKE","AKF","AKG","AKH","AKI","AKJ","AKK","AKL","AKM","AKN","AKO","AKP","AKQ","AKR","AKS","AKT","AKU","AKV","AKW","AKX","AKY","AKZ","ALA","ALB","ALC","ALD","ALE","ALF","ALG","ALH","ALI","ALJ","ALK","ALL","ALM","ALN","ALO","ALP","ALQ","ALR","ALS","ALT","ALU","ALV","ALW","ALX","ALY","ALZ","AMA","AMB","AMC","AMD","AME","AMF","AMG","AMH","AMI","AMJ")

If X < 1024 Then CellPositionToName = LETTER_ARRAY(X) + (Y + 1) Else MsgBox "Out Of Range" End If End Function

傳入X、Y 2個數值,回傳A3這樣的名稱,
因為X最大是AMJ(0~1023),因為數值並不大,
我直接定義成變數查表即可。

注意:已經自動轉換Base 0為Base 1,傳入時不用刻意加1。

2011年4月3日

007先生的交易歷程 的 讀後回文

本來在找匯率表之類的,就找到這個有趣的Blog,
007先生看來年紀跟我差不多,不是同年就是小個1~2歲,
整個Blog看下來後,我認為007先生實際的以金錢去做了個實驗,
實驗證明了,程式交易並不是神,
僅僅依靠程式交易搭配特定演算法就要套利,
結果就是直接被市場KO,
我後來想了想,覺得007先生這麼做,並以日記形式寫成Blog,
應該可以作為不錯的反向教材,
而在倒數第二篇文章中,因為007先生的不甘心,
提到「一定是哪裡出了問題」,
因此我把我這段時間的想法寫成回文,
這段回文,算是目前我對交易市場和程式交易的想法。


沒做過外匯,只有最近(算前陣子)台幣升值時有換一些美金玩玩。
我是看到「我知道必定是哪裡出了錯...」這句話,才想回應的。

我對程式交易有興趣,但我只打算用程式交易做股市中長期(月為單位、長期持有定存股),代替人工下單(上班沒時間)。
我目前認為,除非遇到系統風險或異常超跌,否則在交易市場要套利,應該很難和大戶或法人玩。

我目前認為,程式交易會失敗有幾個關鍵因素:
1. 常見的程式交易,都是用EasyLanguage去寫的,你仔細想一下,事實上它能做到的條件很死板,它的條件幾乎都是軟體寫好提供的,感覺有點像是說,給你玩個沒規則的遊戲,但只給你幾個條件去搭配判斷,這聽起來就很受限,只要我知道你能夠使用的條件,我想贏你的機會應該很大

2. 目前沒有任何聖杯,可以保證獲利,沒有任何條件套用在金融市場是百分百正確的,我們透過一連串無法保證的條件去判斷,並期望它要有6成勝率,那可能用亂數感覺還快些

3. 去年發生過一次美股異常交易的事件有上新聞,大家都知道,有人說可能是高頻交易引發的連鎖效應,我查了高頻交易,才知道國外很多大型投資公司用高頻交易套利,它們利用電腦,以「每秒400次成交」的速度,高速的進行買跟賣,利用利差來套利,甚至我認為,能以此掌握最短期的市場變化,在設備、環境、程式、資金大小、消息面都不對等的情況,我不認為我的程式有辦法跟這樣的程式作對

4. 程式是人寫的,換言之,它只能代替人去按照特定模式交易,既然你我都沒找到一個勝率達6成的模式,又怎麼能要求程式能有6成勝率?

最後,我想我可以把最近幾個月的想法說一下,我認為,憑空希望能透過投機的方式來獲利,不如注意系統風險的發生。
你買了這麼多書,相信有提到一點,交易市場會有系統性風險跟非系統性風險,系統性風險不可預期,且影響巨大,像金融風暴、次級房貸...等。
事實上你稍微注意一下會發現,當遇到系統風險時,該投資標的很有機會跌到非常不錯的價格,只要不破產,此時買入並長期持有(預期至少1~2年),那麼我認為績效應該都不會太差。
你前面常提到,有錢人一開始也是從無到有的,這點我認同,但不完全認同,一些人它可能父母有庇蔭,一開始就有一筆不少的資金,當他剛好遇到某個系統風險時,大膽的投入,運氣不好可能破產,但此時只要沒破產,勝率很高,且因為資金大,獲得的獲利非常可觀,原因是,在交易市場,你玩了這麼久就知道,它的獲利是以%數計算的,他有資金,又在系統風險最低點投入,上來時,那種以%數計算的獲利非常驚人。
最後,我們生在台灣,天生就不平等,你想想,我們辛辛苦苦一個月不過3,4萬,一個月有辦法也不過存2萬,美國人薪資是我們的2~3倍,扣除開銷和稅金,還是比我們多很多,他們的資金水平和我們不是同一個水平,對賠率的容忍度比我們高,這是沒辦法的事,但好消息是,跟對岸或東南亞國家相比,薪資水準、物價水平我們又好一些。

OpenOffice BASIC Macro資料庫操作-2

在上集中,我們完成了現在要使用的資料庫,
接著我們就可以透過OpenOffice BASIC來操作剛剛產生的資料庫。

在OOo BASIC中要操作資料庫,整個過程需要6個動作:
  1. 連結DataSource
  2. 取得查詢
  3. 連結SQL伺服器
  4. 從查詢中取得SQL Code,並查詢SQL伺服器
  5. 查詢完成,取出查詢結果
  6. 關閉SQL伺服器連線

整個程式碼如下:
Sub Main

REM 連結 DataSource
Dim DatabaseContext As Object
Dim DataSource As Object
DatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")
DataSource = DatabaseContext.getByName("OOoTEST")

REM 取得查詢
Dim QueryDefinitions As Object
QueryDefinitions = DataSource.getQueryDefinitions()
QueryDefinition = QueryDefinitions("ProductQuery")

REM 連結SQL伺服器
Dim InteractionHandler As Object
Dim Connection As Object
InteractionHandler = createUnoService("com.sun.star.task.InteractionHandler")
Connection = DataSource.ConnectWithCompletion(InteractionHandler)

REM 從查詢中取得SQL Code,並查詢SQL伺服器
Dim Statement As Object
Statement = Connection.createStatement()
ResultSet = Statement.executeQuery(QueryDefinition.Command)

REM 查詢完成,取出查詢結果
Dim DATA_ID As String
Dim DATA_NAME As String
Dim DATA_PRICE As String
If Not IsNull(ResultSet) Then
While ResultSet.next
DATA_ID = ResultSet.getString(1)
DATA_NAME = ResultSet.getString(2)
DATA_PRICE = ResultSet.getString(3)
MsgBox "ID:"+ DATA_ID + " 名稱:" + DATA_NAME + " 價格:" + DATA_PRICE
Wend
End If

REM 關閉SQL伺服器連線
Connection.Close()
End Sub


接著我們分段來解說每個部份:
1. 連結 DataSource
在OpenOffice中,所有要被Calc使用的資料庫都需要先被「註冊」,
在建立資料庫時,預設都會自動幫你把它註冊到OpenOffice當中,
回憶一下,如下圖:
當我們將資料庫註冊到OpenOffice後,
我們就可以將它當成DataSource進行連結,
這裡要注意到,註冊的名稱可以和DataBase名稱不同,
要以「註冊名稱」為「DataSource名稱」,
不過預設,兩者名稱相同。

在這裡,我們指定DataSource為剛剛建立好的資料庫OOoTEST,
分段程式碼如下:
Dim DatabaseContext As Object
Dim DataSource As Object
DatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")
DataSource = DatabaseContext.getByName("OOoTEST")

我們先定義DatabaseContext和DataSource這兩個變數,
接著建立DatabaseContext服務,
透過DatabaseContext服務來取得OOoTEST這個DataSource。

延伸:
這裡有個延伸的程式碼可以參考,如下:
Dim DatabaseContext As Object
Dim DataSource As Object
DatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")
Names = DatabaseContext.getElementNames()
For I = 0 To UBound(Names())
MsgBox Names(I)
Next I

我們可以透過這段程式碼,將所有註冊的資料庫全部列出。

2. 取得查詢
取得DataSource後,還記得剛剛我們在OOo Base裡面,
有建立好一個叫做ProductQuery的查詢項目。
接著,我們取得這個查詢,分段程式碼如下:
Dim QueryDefinitions As Object
QueryDefinitions = DataSource.getQueryDefinitions()
QueryDefinition = QueryDefinitions("ProductQuery")

定義QueryDefinitions這個變數,
透過DataSource的getQueryDefinitions() Method,
我們取得全部的Query,
並從裡面取出我們要使用的Query - ProductQuery。

延伸:
如果我們不清楚有哪些Query,希望透過Macro動態查詢,如下:
Dim QueryDefinitions As Object
QueryDefinitions = DataSource.getQueryDefinitions()
REM 顯示所有查詢
For I = 0 To QueryDefinitions.Count() - 1
QueryDefinition = QueryDefinitions(I)
MsgBox QueryDefinition.Name
Next I

我們可以用這段程式碼,將所有已經儲存的Query全部列出。

如果我們想要用Macro建立新的Query,我們可以使用下面的程式碼:
Dim QueryDefinitions As Object
QueryDefinitions = DataSource.getQueryDefinitions()
QueryDefinition = createUnoService("com.sun.star.sdb.QueryDefinition")
QueryDefinition.Command = "SELECT Name FROM ProductTable"
QueryDefinitions.insertByName("OurNewQuery", QueryDefinition)

透過這段程式碼,我們可以建立一個新的Query叫做OurNewQuery,
這個Query的SQL Code為「SELECT Name FROM ProductTable」。

3. 連結SQL伺服器
再來我們要正式連結SQL伺服器,分段程式碼如下:
Dim InteractionHandler As Object
Dim Connection As Object
InteractionHandler = createUnoService("com.sun.star.task.InteractionHandler")
Connection = DataSource.ConnectWithCompletion(InteractionHandler)

這裡我們要建立InteractionHandler服務,
接著使用DataSource的ConnectWithCompletion()來連結SQL伺服器。

4. 從查詢中取得SQL Code,並查詢SQL伺服器
SQL伺服器連結完成後,我們要查詢SQL伺服器,如下:
Dim Statement As Object
Statement = Connection.createStatement()
ResultSet = Statement.executeQuery(QueryDefinition.Command)

我們先定義Statement變數,
接著透過Statement的executeQuery()查詢SQL伺服器。

這邊注意到,事實上executeQuery()使用的是SQL Code,
因此我們要透過QueryDefinition.Command,
將剛剛我們取得的Query - ProductQuery內的SQL Code取出。

延伸:
因為executeQuery()使用的是SQL Code,
因此我們可以不透過Query,直接用SQL Code進行資料庫的查詢,
程式碼如下:
Dim Statement As Object
Statement = Connection.createStatement()
ResultSet = Statement.executeQuery("SELECT Name FROM ProductTable")

5. 查詢完成,取出查詢結果
如果資料庫是INSERT或者UPDATE的操作,不需要取得資料,
那麼這個步驟是完全不需要的,這個步驟只有在查詢資料,
需要從資料庫中取得資料才需要。

分段程式碼如下:
Dim DATA_ID As String
Dim DATA_NAME As String
Dim DATA_PRICE As String
If Not IsNull(ResultSet) Then
While ResultSet.next
DATA_ID = ResultSet.getString(1)
DATA_NAME = ResultSet.getString(2)
DATA_PRICE = ResultSet.getString(3)
MsgBox "ID:"+ DATA_ID + " 名稱:" + DATA_NAME + " 價格:" + DATA_PRICE
Wend
End If

這裡很簡單,在前面步驟4的最後,
我們透過executeQuery()查詢資料庫後,
結果會儲存在變數ResultSet當中,
這裡我們先檢查ResultSet,確定它是有東西的,
接著使用ResultSet.next取出每條結果,
再來我們使用ResultSet.getString(1)取出第1個欄位資料,
使用ResultSet.getString(2)取出第2個欄位資料,
再利用MsgBox將資料用訊息視窗顯示出來。

6. 關閉SQL伺服器連線
最後,我們要有好習慣,將SQL伺服器斷線,分段程式碼如下:
Connection.Close()
到這裡,整個資料庫的查詢全部完成。

這裡延續前面的慣例,可以出個作業,
這裡我們完整的取得了資料庫的資料,
那要如何填入OpenOffice的Calc呢?

OpenOffice BASIC Macro資料庫操作-1(資料庫建立)

要操作資料,或者進行歷史資料處理,資料庫的操作都是不可避免的,
在前面入門課題結束了,我們就開始直奔主題,而第一個po的心得,
就是頗有難度,但在資料處理上很重要的,資料庫操作,這裡是操作讀取,
但寫過資料庫程式的都知道,讀取比寫入麻煩,會讀取,要會寫入都不難。
因為篇幅可能會比較長,我分上下兩集介紹,上集是建立資料庫。

開始工作前,首先需要個資料庫,在這裡我們使用OpenOffice Base的資料庫來操作。

1.建立資料庫,並存檔為OOoTEST.odb放置於桌面



2. 建立Table、輸入資料



3. 建立查詢,查詢ProductTable內全部項目


如果偏好直接用SQL Code,也可以用下列SQL Code直接建立:
SELECT "ID", "Name", "Price" FROM "ProductTable";

4. 至此,資料庫和查詢建立完成,可以開始透過Macro操作了

2011年3月19日

日本祈福與福島核災

日本這次發生誇張的地震和歷史性的海嘯,在慶幸不是台灣的同時,
祝福他們,希望他們能夠早日重建完成,我相信強大的日本,
絕對可以在短時間內重建,恢復如常。

這次,我繼四川地震、八八風災後,第三次捐款,
同樣捐助了3000元台幣,雖然不算太多,但以我目前的收入來說,
是3日所得,算是我能力所及的,因為我最近比較忙碌,
經常加班,恐怕沒辦法有力出力,錢,大概也只能出這些,
希望大家都能幫忙,讓日本能更快得回覆原來生活。

至於福島的核災,現在很多媒體報導的很誇張,
我實在不想點名,但有些新聞台報導的實在太離譜了,
記得第二天某新聞台的報導,
一邊說原能會說輻射線對台灣沒影響,風向也不對,
但另一邊打跑馬說輻射線晚上就會來台灣,這實在是......

在到達第4天時,某新聞台晚上的新聞評論,
幾個名嘴一邊說反應爐已經破洞了,一邊說水不夠,
一邊說他們拿水桶衝過去潑水,
這看得我笑到眼淚都噴出來了,這也太扯了......

我認為,日本核電廠的問題算嚴重,
但並沒有嚴重到會發生核子爆炸,也不會發生核子爆炸,
事實上,他們第一時間反應爐就停機了,
核子反應第一時間就降到最低了,所以不會核爆,
但因為核子反應「不會完全停止」,因此需要持續水循環作降溫,
而供水設備沒電、故障,才引發後續問題。

到了現在第6天,事實上狀況「漸趨穩定」了,
從新聞來看,他問題的背景是:
遭遇地震+海嘯時
1號、2號、3號反應爐機組運作中
4號、5號、6號停機歲修中(全世界核電廠的反應爐機組,運作1年半都要歲修一次)

所以4、5、6正常來說,反應爐是不應該有問題的。
所以4號失火,第一時間日本官防長官(台灣的行政院長)說正在瞭解情況,
因為不應該有問題,而之後的瞭解是,「廢燃料棒儲存槽失火」。

到今天(2011-03-19)原能會發佈的狀況是:
1號反應爐機組,反應爐圍阻體正常,冷卻水(海水)有進入,勉強可控制
2號反應爐機組,反應爐圍阻體「可能受損」,冷卻水無法進入,無法控制
3號反應爐機組,反應爐圍阻體「可能受損」,冷卻水無法進入,無法控制
4號「廢燃料棒儲存槽」「可能受損」,冷卻水無法進入,無法控制
5號「廢燃料棒儲存槽」原本水位降低,柴油發電機已能正常動作,冷卻水循環已經正常
6號「廢燃料棒儲存槽」和5號相同,柴油發電機已能正常動作,冷卻水循環已經正常

所以現在要注意的是:
1. 4號儲存槽是否有受損,這關係到輻射線是否外洩?
4號儲存槽的冷卻水循環何時能恢復?
2. 2號跟3號的反應爐圍阻體到底受損多嚴重,是變形還是破洞?
因為這關係到輻射線外洩的嚴重程度
3. 2號跟3號的冷卻水循環,或者外部海水注入,何時可以完成?

這3個點才是目前要關注的,這3個點,也才是輻射線外洩程度的關鍵問題。
至於爆炸,目前我認為再發生爆炸的機會不大,核爆的可能性更低,
而輻射線外洩,是「已經洩了」,但「洩漏程度」是目前的問題點。

至於台灣,我認為台灣的核電廠安全係數比福島的高一些,
就原能會的新聞來看,台灣核電廠的選址地形、備援機制都要比日本福島的好很多,
同樣的災難發生在台灣,可能不至於讓核電廠出問題,
但我認為,台灣的核電廠未必會出現和日本一樣的災難,
卻可能因為其他災難造成其他問題,因此我認為,加固或增加安全機制有必要性,
但因此反核我就不認同了。

最後,我的結論是,在為日本祈福,有錢出錢有力出力的同時,
對於核能的問題,還是應該理性一點看待,不應該被一些怪怪的媒體報導左右,
然後搞得認為世界末日或者福島要核彈爆炸了,
以冷靜的腦袋,儘可能的瞭解資訊,讓自己不要驚慌,應該是這時候比較適合做的事。

OpenOffice巨集參考資料

繼上篇的UNO架構介紹和上上偏的簡單範例後,
相信已經有能力寫個HelloWorld的Macro(巨集;之後都會直接用Macro表示)了,
但記得我在很多年前寫過,要學習一個新的程式語言,需要知道幾個部份:
1. Main結構
2. 程式語法
3. API或Class Reference

從上上篇的範例看完,以及上篇的UNO解說,
我相信1和2大概都能掌握了,接著是3的部份,而這篇,
就是列出一些我在寫OpenOffice時,參考的網站、文件。

書:
我在學習OpenOffice Macro時,第一個找的是書,但很不幸的,
中文書是完全沒有的(正體、簡體),
我找到的一本值得的書是:

這本書基本上不錯,但仍舊有缺點,它細節的部份很多都略過了,
所以看起來也會有一知半解的感覺。

文件:
針對OpenOffice Macro的基本概念和語法教學,寫得最好的我認為是:
這個算是Oracle(前Sun)提供的官方教學文件,
針對OpenOffice的BASIC Macro寫得非常詳盡,
事實上,我認為前面介紹的書,有一些是從這裡面Copy出來的。
雖然文件是介紹StarOffice的BASIC,
但事實上,
OpenOffice的BASIC和StarOffice的BASIC在語法上幾乎是一樣的。

網頁:
 針對OpenOffice BASIC,OpenOffice網站的教學當然不能錯過:
OpenOffice.org BASIC Programming Guide

這個教學頁面有提供簡體中文的翻譯,如下:
OpenOffice.org BASIC 編程指南
這個教學頁面我認為部份內容寫得還ok,
但它幾乎沒有圖片,解說內容也很少,看得很模糊,
看完之後,感覺上還是甚麼都沒看懂,
但基本上,有比沒有好,還是一個值得參考的教學頁面。

OpenOffice.org Developer's Guide
這個同樣是OpenOffice wiki內的教學頁面,
它的特點是,它介紹了OpenOffice內多種語言的開發,
包括OOo BASIC、Java、C++...等,
但如果前面的BASIC Programming Guide是有比沒有好的話,
這個頁面就實在是不怎麼樣,每個篇幅看下來,
反應就是,只有2句話我能看懂甚麼... :(
但,憑著它有多個語言的描述,勉強可以參考參考。

The OpenOffice.org API Project
OpenOffice.org Global Index A
OpenOffice.org Module star
這3個網頁是OpenOffice API內的頁面,
它們其實是同一串網頁的東西,
它們其實就是UNO的API Reference,
第2個網頁是將所有Service、Method、Properties全部以字母排列,
然後列出來。

第3個網頁則是以Module Name來排列描述的樹狀頁面。

第1個網頁則是它們的首頁,
如果知道Module、Method、Property的名稱,
首頁提供了很難用的搜尋引擎可以直接尋找。

我認為這幾個API Reference的頁面非常重要,
它提供了OpenOffice能夠使用的所有API的說明,
也非常有價值,但它寫得很爛,遠比Java在使用的API Reference爛得多,
我不瞭解,明明有Java的API Reference這麼好得樣板,
為啥還要作成這種鬼樣子。

Calc Functions listed by category
這同樣是OpenOffice wiki的網頁,但內容非常不錯,
我們回到最初提過的,我們這麼辛苦的學習OOo Macro,
就是為了使用它的Calc幫助我們運算和資料整理,
Calc裡面最強大的莫過於它的許多「function」,
這些function能幫助我們進行數學、財經...等運算,
透過Macro,我們還是要知道這些function怎麼用,
這個頁面,就是列出了所有Calc的function,
並有簡單的解說和Example教我們怎麼使用它。

The OpenOffice.org Wiki
因為前面的推薦頁面中,很多個都來自OpenOffice的wiki,
因此,還是把它的首頁列出來推薦,
這個可以算是前面幾個教學頁面的目錄。
不過因為它是針對OpenOffice的wiki,
而不是專門針對OpenOffice開發,
所以大部分的教學都還是針對OpenOffice的操作進行說明和教學。

OpenOffice Help:
沒看錯,就是OpenOffice的Help,
和前面的Calc Functions listed by category類似,
OpenOffice的Help能夠提供我們Calc Function的使用說明,
還有一部分BASIC的解說,包括OOo BASIC的資料型態,
運算符號和方式...等。
OpenOffice的Help最方便的地方在於,它可以直接搜尋,
雖然命中率有點低,但相對來說,還是比較方便的。

範例程式:
要使用OpenOffice的Macro,通常需要安裝OpenOffice SDK,SDK安裝好後,除了相關的Library外,還提供了一些範例和說明,
路徑在:
OpenOffice.org 3\Basis\sdk\examples

這裡必須要提一下,它的範例,我個人覺得有些複雜難懂。

論壇:
Macros and UNO API(OpenOffice Forum)
壓箱寶一定要放在最後面。
因為OpenOffice的Macro開發實在是文件稀少,
很多人都有相關的疑問,因此它的Forum真的是很熱鬧,
裡面有幾個國外的高手,看起來從很早前就在用OOo Macro了,
不少相關的解說和文章都相當的有用,直接提供了Code。
事實上,我看了前面的API Reference,
還是沒辦法獨立的根據API Reference寫出OOo的BASIC程式,
需要到Forum裡面查看看有沒有人有寫過並po文,
交互參考後才寫得出來,由此可知這個Forum的強大。

到這裡,我認為OpenOffice Macro入門所需的知識應該已經夠了,
下一篇開始,我會將這段時間的研究後得到的一些技巧性的程式段po出來,
一些是來自於論壇的Code的改寫,一些則是翻翻找找後拼湊出來的,
還請期待。

OpenOffice Macro API(UNO)架構說明

承接前一篇,在知道了簡單的開發環境和程式流程後,
這篇簡單的介紹OpenOffice Macro的API的架構,
瞭解架構後,可以比較容易瞭解API怎麼使用。

要接觸OpenOffice BASIC前,
我原本認為它的BASIC語法應該會跟VBA差不多,
學習下去後才發現,它跟VBA完全不同,類似的只有基本語法,
但API的使用,操作完全不同,基本上沒辦法無痛,
一定要下去瞭解UNO才有辦法使用。

OOo(OpenOffice.org簡稱)的Macro支援很多套程式語言,
包括:BASIC、Java、Java Script、C++、Java BeanShell Script

它們的核心,都是呼叫OOo提供的一整套API,
這套API被稱為UNO(Universal Network Objects),
透過UNO,上述所有語言都能呼叫和操作OpenOffice,
好處是跨語言,壞處是,就算只是想學BASIC,也得瞭解UNO。

如果先前學的是Java,要瞭解UNO很容易,UNO不愧是Sun設計的,
很有Java的概念。

一般來說,常見的UNO概念圖如下:

這裡我不得不說,我第一次看得時候,看一眼就沒興趣了,
但事實上它只是描述了一個簡單的架構。

UNO(Universal Network Objects),我猜測,
也許是為了要設計一個能跨平台使用的溝通模式,
又因為是Sun,所以以Java的物件導向為架構,用網路來實做,
我想用網路而不用其他溝通機制的原因,
應該是因為網路是各平台都有,
而且在UNIX、Linux的環境,他是很基本又常見的溝通機制,
也因為這樣,取名為Universal Network Objects。

簡單的說,它跟Java的物件導向概念雷同,它們的類比如下:
UNO Service → Java Class
UNO Properties → Java Object Properties
UNO Method → Java Object Method

簡單的說,它是以Java的物件導向為基本概念,
所有的Java Class在UNO上,都稱為Service,
每個Service都有自己的Properties和Method。

要使用Service,則和使用Java Object有些許不同,類比如下:
UNO:
Dim oDesk as Object
oDesk = createUnoService ("com.sun.star.frame.Desktop")


Java:
Object oDesk;
oDesk = new com.sun.star.frame.Desktop();


這樣應該很清楚,差異在於,要定義物件時,使用
Dim <名稱> as <物件名稱>

要實體化時(UNO下應該說是建立Service),使用
<名稱> = createUnoService("com.sun.star.frame.Desktop")

這樣描述,應該就能清楚的瞭解UNO的Service概念,
而要使用UNO Service也很容易,同樣以上面的oDesk為例子,
可以如下使用:
Dim oDoc as Object
oDoc = oDesk.loadComponentFromUrl("private:factory/scalc", "_blank",0,Array ())


在這裡,loadComponentFromUrl()就是com.sun.star.frame.Desktop的Method,
使用上和Java的語法差不多。

要定義或修改Properties也很容易,類似如下:
oCell.String = "我的第一個Input"

這樣就能修改oCell的String這個Property,
並將內容改為"我的第一個Input"。



最後,同樣出個簡單的問題,答案很好找,
卻在使用時頭一個會遇到疑問。
在Java中,每個Object幾乎都有相對應的Object名稱,
例如:
JFrame f = new javax.swing.JFrame();

像是JFrame f裡面的JFrame。

那類比到UNO Service時,這個建立後的Service,
是否也有獨立的名稱?
如果有,那會是甚麼?
如果沒有,那又會是甚麼?

補充:
漏了一個部份.....
我們回到前面常見的UNO概念圖,圖上在Service的外圍,
有一個Module將Service包裹住,Module是甚麼?
這也是很簡單的概念,同樣取自Java,類比如下:
UNO Module → Java Package

實際上,和Java的Class一樣,OpenOffice的Service根據不同的用途,
會被包裹在不同的Module裡面,例如:
javax.swing.JFrame

我們可以知道JFrame屬於javax.swing這個Package,同樣的,在UNO中
com.sun.star.frame.Desktop

Desktop就是屬於com.sun.star.frame這個Package。

2011年2月28日

OpenOffice Calc巨集最簡範例

很久很久沒更新了,主要是工作忙碌,一個個bug接著來,一直處於很忙碌狀態。

從上次po文說要開發Stock程式後沒多久,
我開始轉移方向到OpenOffice巨集的學習,
原因是,Stock程式的前段、後段都完成了
(前段,透過AutoIT控制證券軟體後,DDE取得即時資料;後段,透過AutoIT控制證券軟體或網頁下單),
而最關鍵的行為判斷(也就是演算法)的開發一直沒有很好得構想,
我的期望是,能夠有個簡易但富有彈性的開發環境可以進行演算法開發和評估,
但Java要開發這樣的程式,實在是不大方便,要作所謂的回測(用歷史資料測試效果)也沒辦法,
曾經考慮過整個用Java寫,也考慮過修改OpenSource的看盤軟軟體,
但感覺效果都很差,複雜度都很高,最後回頭看Excel,
考慮到Linux,因此決定改以OpenOffice為中心,連結先前開發的前段和後段,
以OpenOffice的Calc來開發和測試演算法的部份,
這部份在今天有很大的突破,以後再說。

這裡這篇,我寫上OpenOffice Calc的簡單巨集開發,算是熱身,
之後再陸續貼些在使用不錯的Macro。

環境:Windows or Linux 均可
OpenOffice版本:3.2.1(新版亦可)

1. 開啟OpenOffice Calc後,點選
工具→巨集→組織巨集→OpenOffice Basic

2. 選取要編輯的巨集(Macro)檔案
我的巨集→Standard→Module1→Main→編輯

3. 巨集(Macro)編輯視窗簡介

4. 輸入程式碼
在剛剛看到的Sub Main和Sub之間輸入如下程式碼:
Sub Main
Dim oDoc As Object
Dim oSheet As Object
Dim oCell as Object

REM 新建一個試算表檔案
oDoc = starDeskTop.loadComponentFromUrl ("private:factory/scalc", "_blank",0,Array ())
REM 開啟目前的試算表視窗
REM oDoc = StarDesktop.CurrentComponent

REM 建立新試算表分頁
REM http://docs.sun.com/app/docs/doc/819-0439/faail?l=en&a=view
oSheet = oDoc.createInstance("com.sun.star.sheet.Spreadsheet")
oDoc.Sheets.insertByName("Stock1", oSheet)
REM 取得試算表分頁
oSheet = oDoc.Sheets.getByName("Stock1")
REM 取得第幾個試算表分頁
REM oSheet = oDoc.Sheets(0)

oCell = oSheet.getCellByPosition (0,0)
oCell.String = "我的第一個Input"
End Sub


如下圖:

5. 執行
將游標移到「Sub Main」,接著點擊「執行」按鈕

6. 執行結果
執行後,會發現新開了一個新的Calc試算表視窗,如下圖:

這個新的試算表視窗,就是透過剛剛的巨集(Macro)程式建立的,
而其中可以注意到,它會多一個叫做「Stock1」的試算表分頁,
這也是剛剛巨集(Macro)程式產生的。

接著我們點擊切換到Stock1分頁,如下圖:

我們可以發現,在「A1」這個 Cell 當中,會顯示「我的第一個Input」,
BINGO,這也是我們剛剛寫在巨集(Macro)裡面的程式碼。

至此,我們整個巨集(Macro)的開發流程就很確定了。

接著,可以出個作業自己玩玩看,
用單步執行的方式,把剛剛的巨集(Macro)程式執行一次,
搭配程式碼的註解來看看,可以對整個程式內容更有感覺。

2010年10月24日

AutoIT自動化證券下單伺服器

簡介:
去年開始開發自己的程式交易系統,目前還在開發中,而目前已經有一部分成果,下單伺服器便是其中一個重要的成果。
有鑑於下單伺服器需要長期的維護、更新,個人力量有限,因此將它Open出來,歡迎大家加入修改與使用。
目前「AutoIT自動化證券下單伺服器」已經註冊為自由軟體,並放置在http://www.openfoundry.org/of/projects/1741,歡迎大家使用、修改、更新,提出建議。

前言:
目前在網路上看到的下單系統通常有2類,一類是證券公司或第三方公司提供的API,利用API撰寫程式後開發而成;另一類則是利用AutoIT、按鍵精靈...等撰寫出獨立的UI下單程式。
第一類程式有些限制,證券公司提供的API,經常會限制每個月的交易額,以我這種少量長期且定期定額購買的人來說就不合適,第三方公司提供的API,則通常都要花錢,
最大的麻煩是,不論是證券公司提供的API或者第三方公司提供的API,幾乎都綁定Windows,要在Linux平台開發有其困難。

為了符合我想要的環境,我希望系統的核心部份能夠運作在Linux或Windows上,下單、資料擷取等子系統相互獨立在不同平台,且各子系統間能夠溝通,
因此想到了使用AutoIT為基礎開發一個TCP Socket的下單機,如此一來,我可以用獨立的電腦,或者虛擬電腦來安裝Win2000、XP(目前我使用Win2k+IE6),
以這台獨立的電腦來執行AutoIT的下單伺服器和證券軟體(網頁或應用程式),其他包括分析系統...等直接透過Socket(telnet)下指令給它,完成下單動作。

下單系統功能:
目前的下單機版本為0.2-beta版,是我目前在使用的版本,它有如下功能:
1. TCP Socket(telnet) 命令式交談介面
2. 支援寶來證券、日盛證券股票下單
3. 股票下單支援現貨、零股、盤後交易(盤後交易沒用過)
4. 寶來證券支援下單與成交回報;日盛證券僅支援下單
5. 下單系統的下單功能使用證券公司網頁下單(日盛證券的下單支援程式下單和網頁下單),網頁下單不會有多久沒交易後,停用系統的問題(日盛證券目前3個月沒交易,HTS禁止使用,網頁下單無此限制)。
6. 本系統正式註冊為「自由軟體」,為GPL3.0授權,可任意使用、傳播,唯一要求,修改過、增加功能後,請協助更新下單系統功能,至少請把程式碼公佈。

下單系統原理:
下單系統以AutoIT撰寫而成,原理很如下:
系統核心為一個AutoIT的TCP Socket Server,當連入後,可以以命令方式下達指令。
當系統收到指令後,按特定指令進行特定的操作,例如:login IEHTS2 A1234567890,xxxxxxxx。
便會自動的打開IE,自動登入到日盛證券。

下單系統系統需求:
1. 獨立的Windows系統(目前我使用Win2K)
2. IE6(IE7沒測試過)
3. AutoIT v3
4. 記憶體至少256MB
5. .Net 2.0(此為證券軟體、及之後其他相關程式需要)
6. Java 6(此為證券軟體、及之後其他相關程式需要)

我這邊的虛擬電腦分配給它的是:
Win2K+IE6+256MB RAM

下單系統簡單操作方法:
1. 拿到程式後,如果是.exe檔,直接執行即可;如果是整個SourceCode,直接執行StockServer.au3。
2. 連接埠預設為58890
3. telnet連入後(請使用linux的telnet或Windows的PieTTY,,不要使用Windows命令提示字元的telnet,會有顯示和輸入問題),可輸入help,即可顯示出使用的指令和參數說明。如下:
xxxx [/xxxx] -oooo- telnet 192.168.1.1 58890
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.
help
200--
Command list:
login [HTS2|IEHTS2|IEFin|EWinner] [Account],[Password]
Ex: login HTS2 A123456789,12345678

logout [HTS2|IEHTS2|IEFin|EWinner]
Ex: logout HTS2

trade [HTS2|IEHTS2|IEFin] [buy|sell],[spot|fractional|afterhour],[StockID],[StockPrice],[StockCount]
Ex: trade IEFin buy,spot,2002,29.3,2

report
Ex: report

exit
Ex: exit

shutdown
Ex: shutdown
200--

4. HTS2表示日盛證券程式版;IEHTS2表示日盛證券網頁版;IEFin表示寶來網頁版;EWinner表示寶來程式版(寶來點金靈)
目前寶來點金靈只支援程式開啟,不支援下單與查詢動作。
IEFin支援下單與查詢。
HTS2和IEHTS2均支援下單,不支援查詢。

下單系統0.2-beta注意事項:
1.
這個版本雖然是beta版,但它是我目前正在使用的版本,穩定性我認為還算可以接受。

2.
因為我自己是在寶來松山分行開戶的,因為寶來網頁的分行選擇是用select group,不大會處理,因此當時就先寫死了。
目前暫時性的解法是,先連上寶來的
https://trade.finairport.com/FinTradeSys/Utility/login/login_page.asp
然後按選擇分公司,然後看自己是哪個分公司,接著數數看,是0-base,這表示「忠孝分公司」是0,接著往下數,目前預設是「松山分公司」,是「17」,如果是「土城分公司」,就是「4」。
確定數值後,下載「AutoStockServer-src.7z」,並解開,修改「IELogin.au3」,把
_IEFormElementOptionSelect ($oUNITNO, 17, 1, "byIndex")
改為(以「土城分公司」為例)
_IEFormElementOptionSelect ($oUNITNO, 4, 1, "byIndex")
即可正常使用IEFin下單。
如果要透過AutoStockServer啟動EWinner,同樣的,要修改分公司,
啟動EWinner後,看看自己分公司,假設還是「土城分公司」,則複製「9794 - 土 城」,然後修改「EWinnerLogin.au3」,把
ControlSetText("系統登入", "", "[CLASS:Edit; INSTANCE:2]", "979H - 松 山")

改為
ControlSetText("系統登入", "", "[CLASS:Edit; INSTANCE:2]", "9794 - 土 城")
即可登入EWinner。

3.
這個版本我忘了把GPL3.0 Licenses File加入,此時成為GPL3.0授權。

4.
操作方法、說明目前還沒準備好,應該會在下週或下下週處理。

5.
這個專案還很新,還有不少需要修改的部份,也歡迎會或熟AutoIT並對程式交易有興趣的同好加入修改,雖然code有點醜,但想寫新功能或其他證券公司支援的,都歡迎加入。

6.
雖然目前還沒寫使用說明,但操作原則上如下:
a. 先確定有安裝AutoIT v3,如果沒有,請到
http://www.autoitscript.com/autoit3/downloads.shtml
下載安裝,這是免費的,不需要花錢或註冊。
b. src要執行,解壓縮到某個目錄後,直接執行「StockServer.au3」,右下角狀態列出現AutoIT圖示,即表示執行中。
c. 目前預設的TCP Port是58890(要改,請修改StockServer.au3,改Global Const $Port = 58890),要使用,可用Linux上的telnet連入58890(Windows可以使用PieTTY,不要使用Windows命令提示字元的telnet,顯示會有問題)
d. 連入後,可直接打help,即可出現所有操作的說明

7.
目前功能中的report,僅支援寶來證券的IEFin(寶來網頁)的回報,且回報部份文字顯示的分隔還有些問題。
日盛證券的部份,目前report遇到瓶頸,還沒辦法成功實做出來。

8.
目前僅支援「股票下單」,不支援期貨下單;股票下單支援「現貨」、「零股」,程式支援盤後交易,但我自己沒玩過。

9.
本程式因為使用AutoIT操作系統,會類比的模擬鍵盤和滑鼠的輸入,因此強烈建議讓程式執行在獨立電腦或者虛擬電腦上,避免人為介入後影響程式動作。
如果有興趣又有些無聊,可以跟我一樣,下指令後,看著它操作程式。

10.
本程式僅供測試、研究使用,如果因為錯誤操作造成巨大損失(例如下單買現貨或賣現貨,單位/數量輸入錯誤);又如果因為證券公司網頁修改、作業系統不穩、個人憑證沒更新...等問題導致下單失敗,作者概不負責。

下單系統專案網站與下載連結:
專業網站:http://www.openfoundry.org/of/projects/1741
下載位置:http://www.openfoundry.org/of/projects/1741/download

2010年10月19日

減慢更新速度...

因為開始上班了,每天過著忙碌而疲勞的生活,因此更新速度會減慢很多。
另外,從去年金融風暴前後開始,開始注意到股票交易,因此從去年開始了新的計畫~自己的程式交易系統。
雖然離「堪用」還有段距離,但開始有些心得了!
因此之後也許會開始po一些跟股票交易相關的程式。
但身為工程師,相關的程式應該會跟一般認知上的有些差異,
不會有明牌,不會有股票名,會出現的會是AutoIT操作心得、DDE操作心得之類的。
還請有點耐心,有空再來更新。

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製作曝光機。