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