Sunday, October 10, 2010

Interrupt Service Routines (ISRs) and its declaring in C language

About Interrupt Service Routines (ISRs) & Interrupt
對於Interrupt Service Routines(ISRs)各家有各種版本的解釋,但其實內容大同小異,例如,微軟在Windows CE 5.0的線上文件中對於ISRs有著這樣的說法,
An interrupt service routine (ISR) is a software routine that hardware invokes in response to an interrupt. ISRs examine an interrupt and determine how to handle it. ...... An ISR must perform very fast to avoid slowing down the operation of the device and the operation of all lower priority ISRs. [1]
由上面的最後一句話,我們可以知道ISRs的執行必須是快速的、有效率的,否則可能影響整個系統的運作。另外在Raj Kamal [2]的書上,對於ISR有這麼一段定義:
ISR is also called device driver in case of the devices and called exception or signal or trap handler in case of software interrupts.

Raj Kamal把ISR分成軟體及硬體的面相來說明。的確, Interrupt在我們修OS時,恐龍本OS [3]將Interrupt分成三類:
  1. External Interrupt: 由CPU外的週邊硬體所發出, 如: I/O complete...
  2. Internal Interrupt: CPU執行指令時發生, 如: Overflow, divide by zero...
  3. Software Interrupt: User Program在執行期間需要某項服務(如I/O request)而對OS發出Interrupt
當OS收到Interrupt,會保存目前process的執行狀態且暫停process,而去執行所對應的ISR。 


Declaring ISRs using C language
在C語言中,對於如何使用ISR,並沒有制定一個標準,因此不同的compiler會有不同的宣告方式,底下舉出各種compiler的宣告方式:
  • Borland C
/* Borland C */
void interrupt interrupt_handler(void)
{
    /* do something */
}
  • Watcom C/C++
/* Watcom C/C++ */
void _interrupt interrupt_handler(void)
{
    /* do something */
}
  • IAR
/* IAR declares an ISR like so: */
#pragma vector=TIMER0_OVF_vect
__interrupt void MotorPWMBottom()
{
    // code
}
  • AVR GCC
/* AVR GCC declares an ISR like so: */
ISR(PCINT1_vect)
{
  //code
}

其中, AVR GCC是以macro的方式呈現, 因此需要include底下這個header file
#include <avr/interrupt.h>

An ISR example
在筆者之前一篇文章「How to program the Pololu 3pi Robot using C language - "Motor Control"」中提到, ATmega328p有兩個8-bit timers: Timer0Timer2, 它們被用來控制電流, 因此時間的控制是很重要的, 假如某個timer發生了overflow就應該做出一些中斷措施, 底下的例子就是每當程式執行中, timer2發生overflow時, ISR的呼叫情形

// this ISR is called every time timer2 overflows
ISR(TIMER2_OVF_vect)
{
 us_times_10 += 1024;
 if (us_times_10 >= 10000)
 {
  timer0_millis++;
  us_times_10 -= 10000;
 }
}

Conclusion
本文收集了不同書本、網站對於Interrupt Service Routines的介紹, 並複習了OS課程中, 「恐龍本」所分類的幾種Interrupt情況, 分成了軟體及硬體兩個面相來描述。另外也介紹四種不同的編譯器對於ISR的使用方式, 最後舉出一個例子, 來介紹「AVR」單晶片在這方面的應用。


Reference
  1. http://msdn.microsoft.com/en-us/library/ms892408.aspx
  2. Embedded Systems: Architecture, Programming and Design, 2/e, by Raj Kamal, Tata McGraw-Hill, 2006
  3. Silberschatz, Galvin, and Gagne, “Operating System Concept,” Sixth Edition, John Wiley & Sons, Inc., 2002.
  4. http://wiki.osdev.org/Interrupt_Service_Routines
  5. AVR-Libc user manual (v1.6.6)

Thursday, October 7, 2010

[C++] convert int to string with the employment of STL / sstream


Abstract
在C語言中, 當「int」型別要轉換成「char *」型別時, 可以透過「sprintf()」來實作。而在C++中, 當「int」型別要轉換成「string」型別時,我們則可以透過stringstream來實作。本文目的是紀錄如何透過stringstream」來將int型別為「string型別



Example
/*
Author      : Trek
Description : Convert int to string with the employment of STL/sstream
Compiler    : g++

http://seeyababy.blogspot.com
*/

/* To use the stringstream, we must include the sstream header */
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main ()
{
    /* initialization */
    int a = 7207;
    string s;

    /* creates a stringstream that holds a copy of the string s */
    stringstream ss(s);

    /* auto formatting across an arithmetic type and a string type */
    ss << a;

    /* use the str member to obtain a copy of the string associated with the stringstream we just created. */
    s = ss.str();

    cout << s << endl;

    return 0;
}


Postscript
會有這麼一篇筆記的原因是, 筆者在coding時常常需要同時output許多圖片到某個資料夾, 此時如果將數字轉成字串, 那麼就可以"方便地append"在一些路徑下了 :)
 

Reference
  • C++ Primer, 4th Edition, S. B. Lippman, J. Lajoie and B. E. Moo

Friday, September 24, 2010

[Debug] error: stray ‘\xxx’ in program

「The key to eliminating bugs from your code is learning from your mistakes.」
~ by Jerry Jongerius


「人非聖賢,孰能無過」,再厲害的programmer也無法百分之百肯定自己的code是bug-free的 [Ref.1]。以目前Trek的等級,無法長篇大論只能先case by case的來舉出平常實作當中所遇到的小問題,小Bug」但初學者往往忽略了這些小細節而浪費了許多時間就像Jerry在本文開頭所言,至少我們需要記住這隻臭蟲,那麼,它將不再出現



這篇文章目的要紀錄一個例子
  • 試想,當我們在coding時,可能使用了不同的Editor,不同的compiler,甚至是在不同的OS底下執行的由於不同系統採用了不同的編碼方式,導致compilercompile無法辨認某一種編碼規格此時便會產生錯誤


  • 案例:友人在windows底下用msn傳了份code給筆者, 而筆者此時是在使用Linux系統, 當筆者利用g++編譯時, 問題產生了,如底下截圖:


  • 問題及解決方法:會產生這個error的原因是, 筆者直接從msn的對話框中複製了該份code, 並直接使用, 而它的編碼方式與g++所認定的方法不一樣, 因此Bug產生。但我們code明明沒有寫錯, 再怎麼trace code也無法找出Bug。了解原因後, 解決方法就變簡單了, 您可以使用常用的Editor, 親自寫出code, 而不是直接從某個您不知道它編碼方式的文件複製/貼上code

  • 另外, 這種情況也常發生在直接複製網頁上的code, 例如:直接複製簡體中文的網頁, 往往會因為編碼問題而產生錯誤


  • 更多Bug方面的深入探討請見Reference. 1


Reference
  1. http://blog.joycode.com/jiangsheng/archive/2006/02/05/71101.aspx
  2. http://s428.photobucket.com/home/rbrovillos

Saturday, September 4, 2010

[C++] 函式,如何傳遞一個C++物件

Introduction
不論在C或C++中,當函式要傳遞一個「傳回值」時,通常可以透過「暫存器」來傳遞,也就是:函式把將要回傳的值,暫存在某個暫存器中,接下來呼叫方就可以去讀取該暫存器,也就達到傳遞的效果,以上作法的前提是,該「暫存器」容納得下該「傳回值」;然而,在C++中,當函式的「傳回值」不再是一般小尺寸的型態,而是大尺寸的物件時,會發生什麼事?編譯器會如何來處理這種情況?本篇文章即要討論這個情況。



Return Value — 「object」
當傳回值是個C++的「物件」,且程式沒有設定傳回值最佳化時(Return Value Optimization),則需要透過兩次的物件複製來達到傳遞目的:
  1. 將該物件複製堆疊上的臨時空間
  2. 將存放在臨時空間中的物件複製儲存函式回傳值的物件
然而,根據不同的compiler及不同的calling convention,甚至不同的平台,在傳遞物件上皆會有不同的實作方式。

接下來在實驗的地方,我將比較在「VC9(WITH Windows XP)及「g++(WITH Ubuntu 10.04 64bit)這兩種不同的compiler及不同的平台下,執行物件回傳的異同,以及Return Value Optimization的設定對於執行結果的影響。




Experiment
實驗一實驗二的地方,我將在VC9g++底下分別執行測試的程式碼,並將執行結果的截圖貼上來。而由於前面兩個實驗產生了不同的執行結果,我將在short summary的地方進一步分析原因,並透過實驗三來做驗證
 
  • Source Code

#include <iostream>

using namespace std;

struct cpp_obj
{
 cpp_obj()
 {
  cout << "ctor\n";
 }
 cpp_obj(const cpp_obj& c)
 {
  cout << "copy ctor\n";
 }
 cpp_obj& operator=(const cpp_obj& rhs)
 {
  cout << "operator=\n";
  return *this;
 }
 ~cpp_obj()
 {
  cout << "dtor\n";
 }
};

cpp_obj return_test()
{
 cpp_obj b;
    cout << "before return\n";
 return b;
}

int main()
{
 cpp_obj n;
 n = return_test();
}

  • Exp.1
          實驗一是在windows XP下使用VC9,底下是執行結果的截圖



  • Exp.2
          實驗二是在Ubuntu下使用g++,底下是執行結果的截圖




  • short summary of Exp.1 & Exp.2
實驗一當中,我們發現物件被複製了兩次,分別是
  1. 呼叫「copy constructor」來將物件複製到堆疊上的臨時空間
  2. 呼叫「operator=」來將存放在臨時空間中的物件複製到儲存函式回傳值的物件上
實驗二,我們發現減少了copy constructor的呼叫,原因是因為g++ compiler在執行程式時自動做了最佳化(Return Value Optimization),將物件直接建構在臨時空間上,因此物件少了一次的複製。


因此,在實驗三,我們要做的就是將VC9的程式最佳化打開,我們可以預料得到的是: 最佳化打開後,物件勢必會減少一次的複製。


  • Exp.3
實驗三是在windows XP下使用VC9,且打開程式的最佳化(Return Value Optimization),底下是執行結果的截圖




Conclusion
本篇文章介紹了函式是如何傳遞一個C++物件,且透過實驗來說明不同的compiler會有不同的設定,根據不同的compiler及不同的calling convention,甚至不同的平台,在傳遞物件上皆會有不同的實作方式。

筆者是在VC9(WITH Windows XP)及g++(WITH Ubuntu 10.04 64bit)這兩種compiler下編譯程式的,而我們發現Return Value Optimization提升了程式執行時的效能,深深影響著實驗的結果,更多討論可以詳見Reference 2。

回傳一個物件是一件非常繁雜的工作,也因此,我們應該盡量避免回傳「物件」


Reference 
  1. 程式設計師的自我修養 — 連結、載入、程式庫,俞甲子、石凡、潘愛民 
  2. MSDN, http://msdn.microsoft.com/en-us/library/ms364057%28VS.80%29.aspx

Saturday, August 21, 2010

Learning English via movie — Shutter Island (隔離島)





如果說是衝著哪位演員來選擇看哪一部電影的話,李奧納多一定是本人的TOP3! 即便是在「鐵達尼號」前,甚至是羅密歐與茱麗葉前的赤子本色記得小時候是跟堂哥在HBO看這部電影的,直到近幾年的血鑽石,讓我完全愛上了「李先生」XD

看完隔離島,真的只有可以形容,因為這部片子實在太懸疑了本人就不做影評了,這篇文章的目的純粹是要紀錄我在看隔離島」時學到的實用、日常、生活」英文 XD

  •  We will casting off again as soon as you two are ashore
   ◎ 船長的意思是,當Teddy與Chuck上岸後會馬上調頭走掉

  •  warden
   ◎ 典獄長


  •  Your boys seem a little on edge Mr. McPherson
   ◎ Teddy對典獄長說,你的手下看起來好像有點緊張


  •  All right, you gentelman will be accorded all the help we can offer.
   ◎ 典獄長對Teddy與Chuck說獄方會盡可能來協助他們


  •  Admittance to ward C is forbidden without the written consent and physical presence of both myself and Dr. Cawly
   ◎ 要進入ward C必須要有書面的批准,並且要有我本人及醫生Cawly的陪同


  •  You act like insanity is catching
   ◎ 你看起來像是也被精神病感染了


  •  Executive order 319 of the Federal Code of Penitentiaries states that when stays at Penitentiaries the office head of institutions has the final authority.
   ◎ 監獄的聯邦法令第319條規定,在監獄裡面典獄長擁有最高權利


  •  Correctional officers at a mental institution that's a weird sight, if you don't mind me saying
   ◎ 精神病院裡有獄警看起來很奇怪


  •  To sustain the illusion that her children never died she created an elaborate fictional structure
   ◎ 為了維持她的孩子還活著的錯覺,她創造了複雜的虛擬場景


  •  Your poison, gentlemen?
   ◎ 要喝什麼酒? (這裡是特殊用法而不是問別人要什麼毒藥XD)


  •  You don't indulge in alcohol?
   ◎ 你不喜歡喝酒?


  •  psychiatry
   ◎ 精神病學


  •  You're bunking in the orderlies quarter
   ◎ 你們會睡在勤務人員的宿舍


  •  The greatest obstacle to her recovery was her refusal to face what she had done
   ◎ 她能否康復的最大障礙就是她拒絕去面對她之前所做的事


  •  I'm gonna go back and blow the lid off this place.
   ◎ 我會回去揭露這地方的真相


  •  civil war
   ◎ a war between groups of people in the same country; 內戰


  •  ma'am
   ◎ 女士;夫人 (尊稱)


  •  no hard feelings
   ◎ 別再生氣了啦 :)


  •  I was a esteemed psychiatrist, from a respected family.
   ◎ 我來自一個受敬仰的家庭, 且曾經是個受人敬重的精神科醫生


  •  Any past trauma in your life?
   ◎ 你曾有過精神創傷嗎?


  •  For god's sake dry off...
   ◎ 天啊...把衣服弄乾吧 (註: 因為李奧納多全身濕透了, 醫生要他把衣服脫下來以便晾乾)


  •  known proclivity for violence
   ◎ 有暴力傾向

  •  You were committed here by court order 24 months ago.
   ◎ 兩年前你被法院判刑到這裡來

  •  you've uncovered a conspiracy
   ◎ 你揭露了一樁陰謀

  •  Permanent measures will be taken to ensure you can't hurt anyone ever again.
   ◎ 我們將會採取永久性的措施來確定你不再傷害任何人

  •  We're running out of time here, Andrew.
   ◎ Andrew我們已經沒時間了

  •  which would be worse? To live as a monster...or to die as a good man.
   ◎ 這句話是李奧納多在劇中的最後一句話,聽起來挺悲傷的




Coming soon...
INCEPTION (全面啟動)



Reference
  1.  Google線上字典, http://www.google.com.tw/dictionary?hl=zh-TW

Sunday, July 18, 2010

Linkage Directives: extern "C"


◎Abstract
在C++程式中,有時會呼叫其它程式語言所寫的函式,本文將會以: 如何在C++程式中呼叫「C」語言的函式為例子來說明Linkage Directives — extern的使用方法時機,以及一些使用上該注意的事項。

◎Declaring a Non-C++ Function
有兩種方式可以在C++中宣告C函式「single「compound。如果單獨宣告某個函式或變數則使用single的用法;反之,當宣告兩個以上的函式或變數時,則使用compound的用法。使用方法分別如下:
  • single
// single statement linkage directive
extern "C" int func(int);

  • compound
// compound statement linkage directive
extern "C" {
    int func(int);
    double var;
}



Compatibility between C/C++ compiler
為了讓C++的compiler可以引用C語言的一些函式並且不影響原本C語言compiler的處理,也就是,使C與C++的compiler能夠相容我們常常可以在C語言的系統標頭檔、函式庫看到以下這種用法

#ifdef __cplusplus 
extern "C" {
#endif

int func(int);

#ifdef __cplusplus
}
#endif

它代表的是,如果編譯的是C++程式碼,則函式func」會使用extern "C"」來宣告; 如果是C程式碼,則直接宣告

※ 當我們使用C++編譯時,__cplusplus會被自動定義


Overloaded Functions
我們都知道,C++支援Function Overloaded,而C語言並不支持。因此,在C++ Primer(Ref.1)中有底下這麼一題練習題
Exercise18.34:
Explain these declarations and indicate whether they are legal:
extern "C" int compute(int *, int);
extern "C" double compute(double *, double);
答案是:
  • 如果其中一個宣告單獨出現,那麼會是沒問題的
  • 但是,當兩個宣告一起出現的話,就會因為C語言不支持Function Overloaded」而產生錯誤
這是在使用extern "C"」上必須注意的地方

◎Reference
  1. C++ Primer, 4th Edition, S. B. Lippman, J. Lajoie and B. E. Moo
  2. 程式設計師的自我修養 — 連結、載入、程式庫,俞甲子、石凡、潘愛民
  3. http://en.wikipedia.org/wiki/Name_mangling

Friday, July 16, 2010

汽車保養 — 五油三水

前題
因為最近在軍中的高裝檢被分配在輪車組,而對保養進度中的「五油三水」感到好奇,well,反正以後開車也會遇到這些問題,就索性好好來認識這些保養知識 (當兵,還是可以學習很多東西滴)五油三水是汽車的基礎保養,目的就是要讓你的愛車保持健健康康的,如此也可增加行車安全 (行車安全是目前軍中除了救災外,另一項極度注重任務 XD)。雖然現今大部份的車子都擁有電腦噴射引擎系統,可以用來監控各項設施並反應在汽車內的儀表板上,但我們還是得認識一下各項設施所賦予的功能,才有辦法在故障的第一時間做出正確的解決判斷

五油
  • 引擎機油
    老舊的車子可能導致吃機油的現象
    ,我們可以利用油尺來檢察機油是否足夠
  • 汽油
    ...略!!!
    (開車必須要有汽油 XD)
  • 變速箱油(自排油)
    一樣利用油尺來檢查
    ,並且經由其顏色的鮮艷程度可以判斷該油是乾淨或是髒的;甚至如果它的味道聞起來具有焦味,則表示離合器片有不當摩擦現象
  • 煞車油
    打開引擎蓋即可觀察其數量
    ,但需要在規定的時間做更換的動作,如此可以避免因為吸入太多水氣,使沸點降低,而提高煞車失靈機率
  • 方向機油
    參考資料指出許多人會拿機油來代替方向機油
    ,但為了避免方向機受損,盡量使用方向機專用油。此外,也應該避免所謂的Understeer」及Oversteer如下圖:

  •  Understeer
  •  Oversteer


三水 
  • 引擎冷卻水(水箱水)
    水箱水
    的功能就在於散熱,又名引擎冷卻水,因此我們可以瞭解它目的就是要散引擎所產生的熱。有些人會添加水箱精,它主要可以提高沸點降低凝固點,副加價值是防銹省油
  • 雨刷水
    略!!!
    (建議直接用自來水因為參考資料說玻璃清潔劑會有副作用)
  • 電瓶水
    略!!!
    (目前多為免加水電瓶else, 就加個蒸餾水吧)

參考資料
  1. http://www.carbibles.com/
  2. http://car.cool3c.com/article/7483