星期三, 4月 22, 2009

BeagleBoard

農曆年後拿到的板子,到手後作了基本的測試就因為其他的事情而停頓...

左邊是 Type A 轉 mini B 的 USB 線,可以供電給 Beagleboard,下方白色接頭的線則是 USB OTG,有了它,板子可以變成 USB Host 的角色,這時就需要外接電源了(左二),另外,一張 4GB SD 卡是用來儲存 rootfs,最右邊則是 HDMI2DVI cable,有了它才能外接電腦螢幕。



自己花錢買的東西當然要好好珍惜(手上還有一片 JTAG Port 有問題的 QT2410),為了預防使用中板子被靜電打死,所以在購買時順便加買了壓克力外殼避免外力直接去接觸到硬體,開孔處也處理的很好,整體質感不錯,不會給人很粗糙的隨便感 ;)





板子上的 JTAG 是 14 PIN 的,但是我手上的 JTAGKey 是標準的 20 PIN,所以我先跑去光華商場買了一個接頭,順便做了一條線,看過電路圖後,我猜測只要把一些 PIN 接地後應該就可以用了,等有空的時候再試。



整個接好就像這樣,透過 USB Hub 外接鍵盤、滑鼠,功能的擴展性是很夠的,要有網路或無線網路也不會是問題。



最後,這是前幾天把 QT-Embedded 4.5 放到板子上的跑 Demo 程式的執行畫面,應該很熟悉吧,但是好像收不到鍵盤或滑鼠的 event,rootfs 是 based on Angstrom。(我已經把 Configure / Build Qt-Embedded 4.5 的 Scipt 及 Log 放上去,有興趣的人可以參考)

星期一, 4月 13, 2009

園藝樂

上星期一因為心情不爽上班,ㄟ,我是說身體不舒服,莫名地得了星期一症候群,請了一天假一大早就跑到附近的內湖花市裡閒晃,第一次逛花市,即便我已經生活在內湖三年了。

老實說,這種別人在上班,我卻在外面蹓達又有錢領的感覺比大家都放假的感覺還開心。

很快買好東西後,就開始我的園藝樂,不知道有多少人聽過倒地鈴這植物,我在台北的山區晃了幾次沒看過,中南部很常見,所以趁著回南部掃墓順便摘了幾株,準備種在窗台邊希望能移植成功。



我覺得最好玩的地方在於它的種子,成熟的種子是黑色,中間會有一個白色的小愛心,很特別,就像小孩子收集星砂送給喜歡的人,有人也會收集種子,裝在小玻璃瓶裡當作禮物 ;)



因為瓶罐蟋蟀一書,特地買了幾個玻璃瓶回來建立自己的瓶中世界,植物就從老姐送的銅錢草移植過去,至於將蟋蟀養在瓶子裡就不必了 ;)







就像在水族箱種水草一樣,會有分前景、中景及後景,根據植物的高低來種植,使用箝子可以幫助更容易的將植物植入,以之前種水草的經驗,因為水族箱比較大的關係,這個難多了,比較難控制。



一個早上的成果,我連吃不完的地瓜都拿去種了 ;)

Complex C Declarations

因為 olv 丟了一個複雜的 C 語言宣告給我:
 void (*glXGetProcAddressARB(const GLubyte *procName))( void )
勾起學生時代的回憶,所以把這篇 1991 年出現在 comp.lang.c 的文章挖出來,這裡可以下載完整的內容。

The "right-left" rule is a completely regular rule for deciphering C declarations. It can also be useful in creating them.

First, symbols. Read

* -- as "pointer to" ----------- always on the left side --- 指標, 指向...
[ ] - as "array of" -------------- always on the right side - 陣列, 其陣列元素為...
( ) - as "function returning" - always on the right side - 函式, 回傳值為...

as you encounter them in the declaration.

利用 "right-left rule" 可以幫助我們正確地解讀 C 語言的宣告,不論是多麼複雜,即便是不合法的宣告。在解讀的過程中,若是遇到了上述表格裡的 * [ ] ( ) 符號,則將它們視為其後相對應的解釋。

STEP 1
------
Find the identifier. This is your starting point. Then say to yourself, "identifier is." You've started your declaration.

步驟一、先把識別子(變數名或函式名稱)找出來,這時候你可以說:xxx 是一個 ...,例如 int *p[ ]

識別子是 p,翻成「p 是一個...」

STEP 2
------
Look at the symbols on the right of the identifier. If, say, you find "( )" there, then you know that this is the declaration for a function. So you would then have "identifier is function returning". Or if you found a "[ ]" there, you would say "identifier is array of". Continue right until you run out of symbols *OR* hit a *right* parenthesis ")". (If you hit a left parenthesis, that's the beginning of a ( ) symbol, even if there
is stuff in between the parentheses. More on that below.)

步驟二、檢查識別子右邊出現的符號,如果有的話,例如看到 [ ] 我們可以說「xxx 是一個陣列,它的陣列元素是 ...」,若是看到 ( ) 則翻成「xxx 是一個函式,回傳值是 ...」,接著繼續地往識別子的右邊尋找其他符號,直到識別子右邊已經沒有符號或是遇到了 ")",跳到步驟三。

int *p[ ],往識別子 p 右邊遇到了符號 [ ],右邊也沒有其他符號,翻成「p 是一個陣列,其陣列元素是...」

另外,如果遇到的是 [N],也就是帶有陣列大小的陣列宣告,我們可以這樣翻「 xxx 是一個大小為 N 的陣列,它的陣列元素是...」,若是遇到的是 (yyy),我們可以翻成「xxx 是一個參數為 yyy 的函式,其回傳值為...」

STEP 3
------
Look at the symbols to the left of the identifier. If it is not one of our symbols above (say, something like "int"), just say it. Otherwise, translate it into English using that table above. Keep going left until you run out of symbols *OR* hit a *left* parenthesis "(".

步驟三、檢查識別子左邊的符號,如果出現的是 * [ ] ( ) 就照表翻譯,若出現的並不屬於上述的符號,那麼看到甚麼就說甚麼,不需要額外的翻譯,例如看到 int 就直接翻成 int,繼續地往識別子的左邊尋找,直到識別子左邊已經沒有其他符號或是遇到了 "(",接著回到步驟二(若是識別子左右兩邊已經沒有其他符號)

int *p[ ],往識別子左邊先找到了 *,所以翻成「p 是一個陣列,其陣列元素是指標,指向...」,繼續往左邊看,遇到了 int,由於識別子左右兩邊都沒有符號了,所以完整的解讀是「p 是一個陣列,其陣列元素是指標,指向 int」

「p 是一個陣列,其陣列元素是指向 int 的指標」

Now repeat steps 2 and 3 until you've formed your declaration.

重複地套用步驟二、三,直到完成整個宣告的解讀。

我相信剛接觸 C 語言的人很難分辨上述的 int *p[ ] 與 int (*p)[10] 的差別,試著套用 ”right-left-rule” 解讀:

1. int (*p)[10],識別子是 p,翻成「p 是一個」

2. 往p 的右邊看到的符號是 ”)”,根據步驟二的說明,我們跳到步驟三檢查識別子 p 的左邊

3. 往 p 的左邊看到的符號是 ”*”,翻成「p 是一個指標,指向...」

4. 繼續往 p 的左邊檢查,遇到的符號是 ”(”,根據步驟三的說明,我們回到步驟二檢查識別子 p 右邊的其他符號

5. 繼續往 p 右邊我們遇到了 [10],翻成「p 是一個指標,指向大小為10的陣列,其陣列元素是...」

6. 繼續往 p 右邊檢查,已經沒有其他符號了,根據步驟二的說明,接著繼續講查識別子 p 左邊的符號

7. 接著往 p 左邊我們遇到了 int,因為不屬於 * [ ] ( ) 中的一個,所以翻成「p 是一個指標,指向大小為10的陣列,其陣列元素是 int」

8. 識別子左右兩邊已經沒有符號,結束

知道了 p 的宣告,在寫程式的時候,就可以避免 assign 錯誤型態的變數給它的錯誤
int main(void) {
int array[10];
int (*p)[10] = &array;
array[2] = 111;
(*p)[2] = 222;
printf("%d\n", array[2]);
return 0;
}

回頭看 void (*glXGetProcAddressARB(const GLubyte *procName))( void ),套用 ”right-left-rule”:

1. 先把識別子找出來, glXGetProcAddressARB 是識別子,翻成「glXGetProcAddressARB 是一個」

2. 往識別子右邊看到的符號是 (const GLubyte *procName),翻成「glXGetProcAddressARB 是一個參數為 const GLubyte *procName 的函式,其回傳值為...」

3. 再往右邊看下去,我們遇到了 ”)”,根據步驟二的說明,我們跳到步驟三

4. 往識別子的左邊看到的符號是 ”*”,翻成「glXGetProcAddressARB 是一個參數為 const GLubyte *procName 的函式,其回傳值為指標,指向...」

5. 繼續往左邊看,我們遇到了符號 ”(“,根據步驟三,我們跳回步驟二

6. 回到步驟二,我們繼續往識別子右邊找其他的符號,這時出現的是 “( void )”,所以翻成「glXGetProcAddressARB 是一個參數為 const GLubyte *procName 的函式,其回傳值為指標,指向一個參數為 void的函式,其回傳值為...」

7. 再往右邊找,已經沒有任何符號,跳到步驟三

8. 往左邊找到了 void,直接翻,「glXGetProcAddressARB 是一個參數為 const GLubyte *procName 的函式,其回傳值為指標,指向一個參數為 void的函式,其回傳值為 void」

9. 識別子左右兩邊已經沒有符號了,完成
「glXGetProcAddressARB 是一個參數為 const GLubyte *procName 的函式,其回傳值為指標,指向一個參數為 void的函式,其回傳值為 void」再稍微修飾一下,改成「glXGetProcAddressARB 是一個參數為 const GLubyte *procName 的函式,其回傳值為函式指標,指向一個參數為 void的函式,其回傳值為 void」

void helloworld(void) { return; }

void (*glXGetProcAddressARB(char *procName))( void ) {
return helloworld;
}

int main(void) {
glXGetProcAddressARB("ARB");
return 0;
}