- 12月 02 週四 201011:04
DesireHD ROM移植HD2近況
- 12月 01 週三 201011:43
移植MySQL to ARM
最近需要在pxa270的嵌入式平台上資料庫進行通信信息管理,在網上一查才知道mysql 根本很少用於嵌入式環境!搜索有沒有mysql在arm平台移植的相關文章,幾乎找不到相關資料。沒辦法,只能硬著頭皮自己動手了。幸好經過一番努力,終於克服了所有障礙,讓mysql在270板子上跑了起來!而且簡單的測試也都收到了預期的效果。
現在將mysql 的arm+linux移植經驗出來,希望對以後做相關方面工作的人有所幫助.首先是要從網上獲取mysql的源碼包
以下分幾個階段來介紹:
一: configure
解開包以後得到文件夾mysql-5.0.22我將其改名為mysql-pc,進入目錄後,首先要做configure 來生成交叉編譯的Makefile文件,編譯的時候一般configure是都能通過的但我用./configure --host=arm-none-linux-gnueabi來生成Makefile時卻出現了多個錯誤,如下:
1) return type of sprintf : error: cannot run test program while cross compiling
檢查configure腳本,發現腳本在檢測到在做cross-compile時就提示以上錯誤並退出,說明至少是這個版本的mysql並不支持交叉編譯,但我用了最新的版本試了也還是有同樣的錯誤,基本可以肯定mysql還沒有支持交叉編譯的版本出現.但為了讓編譯繼續,我在configure腳本中將多處這樣的命令全都註釋掉以讓configure通過.
2) error: Your compiler cannot convert a longlong value to a float!
這個問題在較低版本的mysql中是一個bug,但5.0的版本已經修復了這個問題,有可能是交叉編譯器的問題,找不到解決的方法,這裡我也將它註釋屏蔽了.
3) error: No curses/termcap library found
缺少curses和termcap的庫,反覆安裝了各種相關的軟件包,還是解決不了這個問題,最後是在configure的參數里直接指定了安裝的ncurses-5.6下的libncurses.a庫根據我的路徑參數設置如下:
--with-named-curses-libs=/home/huaming/mysql/ncurses-arm-d501/lib/libncurses.a
(這裡要注意的是ncurses的安裝也要採用交叉編譯的方式在pc上裝好,否則後面做make的時候編譯器會指出libncurses.a的格式不對)
經過反覆嘗試最後使用的參數如下:
./configure --host=arm-none-linux-gnueabi --with-named-curses-libs=/home/huaming/mysql/ncurses-arm-270/lib/libncurses.a --prefix=/home/huaming/mysql/mysql_arm_270 --without-debug --without-docs --without-man --without-bench --with-extra-charset=big5
二: make
這一步遇到的問題最難解決:
1) ../extra/comp_err: ../extra/comp_err: cannot execute binary file
編譯過程中要運行comp_err命令,但這個命令是arm格式的在pc機上運行不起來,解決方法是要編譯好一個在pc上運行的mysql,從相應的目錄下拷出comp_err命令覆蓋extra下的這個arm格式的comp_err命令(這裡要注意的是這個pc機上運行的mysql編譯路徑要和現在這個arm上運行的mysql路徑完全相同,否則後面同樣的問題中執行命令時涉及到路徑問題,解決辦法是先把現在編譯的mysql-pc目錄改為其他名稱,再解一個mysql包改名為mysql-pc將其編譯成pc上運行的版本,只要簡單的用./configure |make就行了,再把現在這個mysql-pc改為別的名稱,將原來的那個名稱改回mysql-pc)
2) /home/huaming/mysql/mysql-pc/sql 目錄下出現:
./gen_lex_hash: cannot execute binary file
原因和解決方法基本和上面遇到的問題相同,但這裡還要加一命令:
touch –m sql/gen_lex_hash
上面的命令是改變gen_lex_hash的最後修改時間,這樣做的目的是告訴編譯器gen_lex_hash已經是最新的了,不要重新生成它,否則編譯器檢查gen_lex_hash和它的依賴文件的最後修改時間會發現gen_lex_hash比它的依賴文件更舊,就會重新交叉編譯生成它,這樣不管我們做幾次覆蓋的工作錯誤都還會再現.
3)還是在sql這個目錄下出現了類似如下的錯誤:
gen_lex_hash.o: could not read symbols: File in wrong format或
./gen_lex_hash > lex_hash.h
g++: ../zlib/.libs/libz.so: No such file or directory
經過對Makefile文件的觀察,發現這些錯誤都是在生成lex_hash.h文件的時候產生的,所以直接從pc上運行的版本中拷貝這個文件到此目錄下,同樣要執行touch –m lex_hash.h
否則會陷入一個循環的需要arm上運行的文件和pc上運行的文件的錯誤中出不來.
Make 的過程總結起來主要就是以上幾個錯誤,但我的configure參數中已經去掉了幾個模塊的編譯,如果不去掉這幾個模塊還會有更多錯誤出現.
- 11月 25 週四 201015:40
在.NET使用ActiveX控制項
開發.NET系統整合的時候,最常要處理、也是最棘手的問題都是廠商提供元件,什麼鬼都會遇到,雖然現在.NET已經慢慢腐蝕(?)廠商的技術人員,慢慢慣用.NET開發元件,但還是很多元老硬體廠商依然用微軟的老技術'提供給使用者,像.Lib/.h的靜態資函數、或是dll等動態連結資函數,甚至連OCX等ActiveX都會遇到。
給你.Lib/.h靜態資料庫,你就只有一個方法解,使用Visual C++去coding;給你動態連結好一點,建立一個import函數對應,只要他的型別不太複雜,這點可以放心,因為廠商也希望函數越簡單越好;而OCX通常是必須有UI的函數控制項,以及WEB需求的元件,例如攝影機DVR之類。
關於ActiveX元件的小技巧,因為ActiveX算是控制項,首先在工具列滑鼠右鍵,按下"選擇項目..”會開啟"選擇工具箱項目"的視窗,選擇COM元件後選擇廠商提供的OCX即加入元件,.NET自動會幫你Reference並用AxHost包裝,就可以把它當一般.NET控制項使用。
而有時你不希望ActiveX元件在視窗出現,或是希望當使用的建立,則需要注意,ActiveX是必須存在於UI上的控制項,如果沒經初始化,一定會出現System.Windows.Forms.AxHost +InvalidActiveXStateException的錯誤訊息。
因此,你必須用AxHost的BeginInit與EndInit來加入控制項將之初始化後才能使用,範例方式如下;
- 11月 15 週一 201011:56
超重要~民國100年請休假建議
[技術性長假]
過年:2/2(三)~2/7(一),共6天連假,
只要提前請1/31和2/1,就! 可連放10天假期
[3天連假]
和平紀念日:2/26~2/28,3天連假
兒童節、清明節:4/2~4/5,4天連假
端午節:6/4~6/6,3天連假
中秋節:9/10~9/12,3天連假
國慶日:10/8~10/10,3天連假
[沒放到假]
元旦:1/1(六)
勞動節:5/1(日)
- 10月 29 週五 201015:57
ActiveX開發:錯誤代碼:0x80070002
開發ActiveX時候,原本程式執行好好的,註冊OCX/反註冊OCX都很正常,當照著MSDN步驟進行安全碼加註後,每次返註冊OCX都會出現DllUnregisterServer函數出錯,錯誤代碼:0x80070002 可能不敢相信,但以下是MSDN程式碼:
STDAPI DllUnregisterServer(void)
{
HRESULT hr; // HResult used by Safety Functions
AFX_MANAGE_STATE(_afxModuleAddrThis);
if (!AfxOleUnregisterTypeLib(_tlid))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
return ResultFromScode(SELFREG_E_CLASS);
// Remove entries from the registry.
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
if (FAILED(hr)) return hr;
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
if (FAILED(hr)) return hr;
return NOERROR;
}
錯誤代碼:0x80070002,錯誤描述爲:系統找不到指定的文件。但看看注冊表,其實反注冊是成功的,下面說一下錯誤的原因,安全組件其實是在注冊表中添加一些注冊,表明自己安全罷了,關于安全性的注冊是依賴與原組件的,所以上面函數反注冊的順序不正確,應該先反注冊掉安全組件,再反注冊掉原組件,修改後的代碼如下:
STDAPI DllUnregisterServer(void)
HRESULT hr; // HResult used by Safety Functions
{
AFX_MANAGE_STATE(_afxModuleAddrThis);
hr = UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
if (SUCCEEDED(hr))
hr = UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
return ResultFromScode(SELFREG_E_CLASS);
return hr;
}
- 9月 14 週二 201023:05
[錄影]小英吉他社練習
- 9月 13 週一 201010:10
肌肉的興奮劑:肌酸
對於經常上健身房或熱愛運動的人而言,如果到現在還沒有聽過肌酸,那您可真是遜斃了!因為這種二十世紀最ㄅ一尢ˋ、最炫、最搶手的「運動營養補充品」,其魅力正襲捲整個健身界及運動界。許多職業運動的明星–如打破美國職棒全壘打記錄的馬奎爾,或是NBA職籃明星卡爾.馬龍,都是肌酸眾多擁護者之一。究竟肌酸是何方神聖?它擁有什麼驚人的魅方呢?以下請看我們的檔案報導。
作者:陳乃維營養師
什麼是肌酸?
- 9月 09 週四 201000:58
蛋白質補充
蛋白質是合成肌肉最重要的原料,尤其對於 健身者來說,優質蛋白質的攝取更是左右完美體格的關鍵因素。 但是 面對市場上琳瑯滿目的品牌,你真的知道什麼才是對你最好的嗎?不用擔心,以下的文章將簡單地告訴您如何辨別優質的蛋白補充品。
◆ 蛋白質補充品的種類
目前市場上最常見的蛋白質來源是以雞蛋 (egg) 、大豆(soy)、 乳清(whey)及酪蛋白(casein)為主,而其中依不同的萃取形式又可細分成濃縮蛋白(concentrate)、分離蛋白(isolate)及水解蛋白(hydrolysate)等。濃縮蛋白是蛋白質最基本的萃取形式,符合一般大眾的基本需要。分離蛋白則是再進一步地以離子交換萃取方式精鍊,幾乎完全除去濃縮蛋白中多餘的脂肪、膽固醇、碳水化合物及乳糖等雜質。水解蛋白則是先將蛋白質經過初步分解步驟,形成易消化的小分子蛋白質,但口味會較差。若你仔細比較產品成分標示將不難發現不同萃取法在價格上的差異。
雞蛋蛋白 是早期健美人士及運動員最常使用的一種蛋白質來源,由於雞蛋含有很豐富的必須氨基酸,是一種完全蛋白質,所以早期運動人員常以生吞雞蛋來補充營養。但由於生吞雞蛋常有衛生問題(大腸桿菌),再加上蛋黃膽固醇很高,只吃蛋清又造成浪費,因此現在多以去除油脂及膽固醇的雞蛋蛋白補充品替代。研究發現,雞蛋蛋白會在攝取後約 1.5小時開始分解,3~5小時可完全消化,吸收速度相較於其他蛋白質來說不快不慢,因此又可歸類為 ” 中速蛋白質 ” 。(之後將做進一步的說明)
大豆蛋白 是目前最經濟實惠的一種蛋白質,由於取得容易,又沒有葷素及膽固醇等相關問題,因此在運動營養品市場上相當普遍。不過值得注意的是,大豆蛋白因為缺乏某些氨基酸(甲硫胺酸及胱胺酸),並不屬於一種完全蛋白質,再加上其支鏈氨基酸 BCAA含量及生物價BV值皆略低於乳清蛋白(BV=食物中可被人體吸收保留之氮的百分比),所以目前被認為是僅次於乳清的一種運動補充品。大豆蛋白在消化吸收速度上雖較乳清蛋白慢一些,但也被歸類成 ” 快速蛋白質 ” 。
乳清蛋白 及酪蛋白 都 是源自於牛奶中的蛋白質,其中乳清 (whey) 僅約佔牛奶中總蛋白量的 20% 。乳清蛋白 富含人體所需要的各種必須氨基酸,同時含有最高的支鏈氨基酸 BCAA成分 (將近 26%) 的一種蛋白質來源; 在運動的過程中, BCAA(白氨酸﹑異白氨酸和纈氨酸)能直接為骨骼肌提供能量,而不是像其它氨基酸需經過肝臟的新陳代謝。由於在運動中人體會對這三種氨基酸不斷消耗,因此想要保持肌肉塊形狀的運動員,就必須增加BCAA的攝取 ,而乳清蛋白恰能提供此項需求。此外,乳清蛋白也因其富含天然的抗自由基物質麩胱甘太 Glutathione及增強免疫力的免疫球蛋白,再加上有最高的蛋白質BV值,故很快就成為運動營養品市場上的主流產品。乳清蛋白會在攝取後30分鐘內分解,2~3小時 內就可完全消化吸收,故可分類為 ” 快速蛋白質 ” 。
酪蛋白是牛奶中除了乳清蛋白外另一種主要蛋白質,約佔了牛奶總蛋白的 80%。酪蛋白在萃取成本上較乳清便宜許多,但由於其分解吸收速率較慢,約7~8小時才可完全消化,因此被歸類為 ” 慢速蛋白質 ” 。
◆ 時間:建構肌肉的關鍵因素
讀到這裡,或許你會對前述許多蛋白質比較方法感到迷惑:到底是要比較氨基酸種類,還是 BV值,還是BCAA的含量,才是增長肌肉最優質的蛋白質?其實,對於運動健身者來說,吸收速度的快慢才是增長肌肉最關鍵的因素。
- 7月 27 週二 201006:11
Linux Driver基礎篇-編譯與掛載
先前介紹了一個簡單的字元範例,這個範例不需要任何硬體線路單純只使用printk函數輸出,一個標準的HELLO WORLD程式。那建立完範本該如何編譯? 如何掛載? 如何使用? 往後一一講解。
首先我的開發環境是使用ubuntu,核心版本是2.6.24,PC環境基本上用哪個版本的套件對以下步驟無多大影響,在這先以PC環境為主,往後在介紹ARM的cross compiler。而我們開發的是linux driver,因此編譯的時候linux核心src是不能缺少,所編譯的driver版本與核心版本必須是近似甚至相同的,反則會面臨雖然編譯程公卻無法掛載的命運,所幸PC環境上的套件都會有src,因此這部分無需擔心。
現在先將先開啟一新的資料夾,並將先前介紹的範本檔案建立存入該資料夾中。在開一個新檔案叫Makefile,對linux開發不熟的可能對此檔不清楚,這是make編譯程式的批次檔,方便開發使用,該檔案內容如下:
TARGET=demo
KDIR:=/lib/modules/$(shell uname -r)/build PWD:=$(shell pwd) obj-m:=$(TARGET).o default: make -C $(KDIR) M=$(PWD) modules clean: rm -rf *.o *.ko modules.* Modules.* *.mod.c
存檔即可,此批次檔TARGET設的參數將為該資料夾編譯後的檔名,在此設定為demo,編譯後產生demo.ko為我們所要掛載的driver module。之後在該資料夾下打入make即可編譯成功。
- 7月 26 週一 201011:52
Linux Driver 字元型基礎篇
在撰寫 driver 前必須先 include 一些標頭檔:
#include <linux/init.h>2. 撰寫控制元件的函式
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
struct file_operations 即為定義各個 function pointer 的 structure。
static ssize_t drv_read(struct file *filp, char *buf, size_t count, loff_t *ppos)3. 撰寫初始化、結束元件的函式
{
printk("device read\n");
return count;
}
static ssize_t drv_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
{
printk("device write\n");
return count;
}
static int drv_open(struct inode *inode, struct file *filp)
{
printk("device open\n");
return 0;
}
int drv_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
printk("device ioctl\n");
return 0;
}
static int drv_release(struct inode *inode, struct file *filp)
{
printk("device close\n");
return 0;
}
struct file_operations drv_fops =
{
read: drv_read,
write: drv_write,
ioctl: drv_ioctl,
open: drv_open,
release: drv_release,
};
#define MAJOR_NUM 60
#define MODULE_NAME "DEMO"
static int demo_init(void) {
if (register_chrdev(MAJOR_NUM, "demo", &drv_fops) < 0) {
printk("<1>%s: can't get major %d\n", MODULE_NAME, MAJOR_NUM);
return (-EBUSY);
}
printk("<1>%s: started\n", MODULE_NAME);
return 0;
}
static void demo_exit(void) {
unregister_chrdev(MAJOR_NUM, "demo");
printk("<1>%s: removed\n", MODULE_NAME);
}
module_init(demo_init);
module_exit(demo_exit);
其中 MAJOR_NUM 即為 driver 所對應的 device 的 major number
