2009年11月4日 星期三

一個8051 的系統應用問題

我們來講一個8051 很基本,卻很容易發生問題的系統應用問題,

而這個問題有時一開始時,您也不容易察覺的。

其實,這個問題對許多單晶片微處理器來說,也是常見的。

這個問題是系統中斷問題。....

中斷處理程序幾乎是標準的處理器的重要關鍵技術,而一般所謂的多核心多重處理器,

也是借重這種中斷處理程序所延伸的,我想這一種中斷觀念也是業界所公認的標準作法。

以前我之前有提過一棵所謂的多核心處理器,他也是利用硬體來做分時多工,

所以基本上他也是一種隱性之中斷處理方式的...基本精神都是沒變的!

當然啊...因為現在所謂的IC 設計與周邊電路的成熟應用來看,這種觀念會更發揮的淋漓盡致的,

下圖是一個變種8051的中斷向量表:從表中我們可以很清楚的看到許多過去標準8051 所沒有

看到的一些硬體中斷功能...有些甚至還在某一個中斷向量之下再進一步細分的,

如圖中所沒有標示的USB 中斷...因為USB 中斷還要分Control Token...Out Token ... In Token.等等。

所以,您會發現:如果像我之前提過的那一種試圖用硬體分時多工做成的號稱多核心處理器,

在這一方面的擴充性就會顯得比較沒彈性一點了...因為畢竟他還是共用同一組系統Clock Source 。

系統資源是有限的...而唯一能夠提高系統性能的方法:就是提高系統Clock 頻率!

這也是所有單晶片微處理器所強調或追求的方向。

所以,我們就會看到所謂的25MHz...48MHz...96Mhz ...甚至操到2~300 MHz以上的。

以現在IC設計與IC 製程技術來說:都已經不成問題了。

----

好了,講我們這一次的主題:系統韌體的中斷處理程序。

中斷處理程序會對我們寫韌體會造成什麼影響?!主要就是:Interrupt Latency(中斷延遲時間)

及所謂堆疊區(Stack)的影響,而Stack 的主要還是來自於一般變數的儲存(當然還包括硬體

本身的中斷向量位置的存入與回取的動作!)

我常開玩笑說:您再快的微處理器也是會發生中斷『打架』的事情的啦!...

而我們並不擔心中斷系統打架,因為本中斷就有所謂的優先順序的...

這本來就是延伸我們人類的基本觀念:我們大腦也是單向處理能力的,

一次一時也只能處理一件事,一心多用是很容易出事的啦!

所以以8051 的標準C 的中斷處理程序是如何寫的呢?!

          extern bit alarm;
           int alarm_count;
   
   
          void falarm (void) interrupt 1 using 3  {
              alarm_count *= 2;
              alarm = 1;
         }

----上式中的 interrupt 1 所代表的就是:中斷向量位置。

(您可以查上表中的那個Timer 0中的priority order 就是 1)

這一點我們就很清楚的瞭解到的啦!但另外一個 using 2 ...就比較沒有標準用法了,

一般人也很容易忽略到...而往往系統有時會因此發生問題的,

而這種問題對一些比較沒經驗的工程師來說:有時會被稱所謂的靈異現象!

是真的靈異現象嗎?!非也...其實都是自己在系統規劃與韌體編寫上發生問題所造成的。

我們先來看這個 using 2 是拿來幹啥用的?!...他就是拿來指定中斷處理程序要拿哪一組

Register Bank 來用?!...這對於Keil C 這種編譯組譯器來說是很重要的!

我們都知道一般 8051 有四組通用Register Bank ,一般高階C 組譯成組合語言時,

他們會大量使用這些Registers (R0..R7),這是我們用C 在寫程式時,不容易察覺的!

我們來看上式程式組譯後的結果:

      ; FUNCTION falarm (BEGIN)
0000 C0E0       PUSH  ACC
0002 C0D0       PUSH  PSW
                      ; SOURCE LINE # 5
                      ; SOURCE LINE # 6
0004 E500   R   MOV   A,alarm_count+01H
0006 25E0       ADD   A,ACC
0008 F500   R   MOV   alarm_count+01H,A
000A E500   R   MOV   A,alarm_count
000C 33         RLC   A
000D F500   R   MOV   alarm_count,A
                      ; SOURCE LINE # 7
000F D200   E   SETB   alarm
                      ; SOURCE LINE # 8
0011 D0D0       POP   PSW
0013 D0E0       POP   ACC
0015 32         RETI
      ; FUNCTION falarm (END)
----

 我們可以看到兩個指令:PUSH ACC 及PUSH PSW..(有的甚至還有PUSH DPH/PUSH DPL)。

而從一般程式跳入中斷程式到完成這一個PUSH 的動作時間,就是我們常說的Interrupt Latency !

...其實,以現在高速的微處理器來說:這一點時間都已經不算什麼了。

倒是您把記憶體中的變數或堆疊區給搞亂了,那才真的會造成捉問題累死人的事啊!

我們來看PUSH PSW 是做什麼?!

PSW Register (all 8051 and 251 variants)

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
CYACFORS1RS0OVUDP

The following table describes the status bits in the PSW:

RS1 RS0 Working Register Bank and Address
0 0 Bank0 (D:0x00 - D:0x07)
0 1 Bank1 (D:0x08 - D:0x0F)
1 0 Bank2 (D:0x10 - D:0x17)
1 1 Bank3 (D:0x18H - D:0x1F)

Symbol Function
CYCarry flag
ACAuxiliary Carry flag (For BCD Operations)
F0Flag 0 (Available to the user for General Purpose)
RS1,
RS0
Register bank select:
RS1 RS0 Working Register Bank and Address
0 0 Bank0 (D:0x00 - D:0x07)
0 1 Bank1 (D:0x08 - D:0x0F)
1 0 Bank2 (D:0x10 - D:0x17)
1 1 Bank3 (D:0x18H - D:0x1F)
0VOverflow flag
UDUser definable flag
PParity flag
Reserved for future use (251 Only)
ZZero flag (251 Only)
NNegative flag (251 Only)

------------------------------------------------------------------------------------

就是拿來切不同的Register Bank 的!....所以一般人都會容易犯這一個錯誤的!

不去明確的要求組譯器指定不同的Bank...這本來就是我們在系統規劃裡的一個重要事項。

沒有稍微搞過硬體或韌體的純軟體工程師就很容易犯這個錯誤,而往往這個錯誤會

讓一些比較沒經驗的工程師,一時會捉不到問題點...搞了老半天,就會怪IC 有問題。

尤其像現在這種變種的8051 來說:他的中斷向量變得比較多了,

但他的Register Bank 還是只是維持四組,處理這種問題就要變得更小心了。

所以事前的系統規劃或是在韌體撰寫與系統完成後的系統驗證工作,

就顯得非常重要...而不是一上機,就批哩趴啦的把程式寫完就交差了事...

而沒有詳細的去分析與驗證系統...往往這種中斷程序打架造成Register Bank錯亂之事,

真的很難抓問題...因為可能連ICE 的Debug 功能也無法精準的掌握...這本來就是人為疏失啊!

我記得以前我們在大公司裡也曾經發生這種問題,而造成硬體設計工程師與軟體工程師們之間,

互不信任與造成許多不必要的紛擾...

---

我要說明一下的是:不是只有中斷向量程式可以加註這一段 using 2 而已,

其實,一般標準副程式也是可以加這一句話的,

如此一來能更能夠掌握每一段副程式之間的變數交換與資料傳遞的:

void Example_Subroutine(unsigned char Variables) using 1{

....

...

}

瞭解嗎?!...

希望這一篇簡單的系統應用資訊也可以提供一些有用的資訊給您!

謝謝!

 

 

5 則留言:

  1. 看不是很懂, 沒用過變種8051, 8051工作上也只用過一次, 也許我只用assembly就沒這問題

    回覆刪除
    回覆
    1. 如果您寫的8051 都是小程式...或是比較少用到多重中斷.....
      那您也可以不用理這一篇文章,此篇文章僅供參考。
      至於,用Assembly 寫?!...應該會比較容易留意到這個問題吧。
      所以,如果您有防範未然,那也不必理這一篇文章。
      對您來說,或許就是僅供參考! /:)

      刪除
  2. http://www.eettaiwan.com/ART_8800427460_676964_NP_d1862aaf.HTM
    請問版主怎麼看這個新聞?


    Luminary Micro是ARM的Cortex-M3處理器合作夥伴,先前已公佈了6款Stellaris微控制器,其中包括定價為1.00美元的入門級 LM3S101微控制器。Luminary Micro的Stellaris系列微控制器是少數以晶片形式實現Cortex-M3的產品,適合建築與家庭自動化、工廠自動化與控制、工業控制電源設 備、步進馬達、有刷和無刷直流馬達以及交流感應電機之類的應用。
    這些元件還擁有單週期嵌入式Flash和SRAM、低壓差穩壓器、整合的掉電重置(BOR)和上電重置功能、類比比較器(Analog Comparator)、取樣速度達每秒100萬個樣本、多達8通道的10位元ADC、SSI、通用輸入/輸出(GPIO)、看門狗定時器(WDT)、數 量可達7個的通用定時器、最多可以有2個通用非同步收發器(UART)、I2C和最多可達6個用於運動控制的PWM波形發生器以及QEI,所有這些功能都 可以直接通過其接腳實現,而不需要借助多工技術。

    回覆刪除
    回覆
    1. 很努力的用一篇文章回答您了:
      http://tw.myblog.yahoo.com/chamberplus-taiwan/article?mid=1693

      刪除
  3. 你好,這篇文章的觀念真的很好
    我想請教,8051MCU初始堆疊起始位址是0x07+1=0x08,
    那麼 Bank1 (0x08 - 0x0F)是否不要拿來宣告使用(using)會比較好??
    來防止Bank1會被其他中斷副程式覆蓋堆疊資料,
    這樣觀念是否正確嗎??
    謝謝 email: LMF16882001@yahoo.com.tw

    回覆刪除