成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

寫中斷程序要注意哪些方面?

開發
當中央處理器正在處理內部數據時,外界發生了緊急情況,要求CPU暫停當前的工作轉去處理這個緊急事件。處理完畢后,再回到原來被中斷的地址,繼續原來的工作,這樣的過程稱為中斷。

[[374914]]

 與每類I/O設備相關的進程都有一個靠近內存底部的地址,稱作中斷向量。它包括中斷服務程序的入口地址。

當中央處理器正在處理內部數據時,外界發生了緊急情況,要求CPU暫停當前的工作轉去處理這個緊急事件。處理完畢后,再回到原來被中斷的地址,繼續原來的工作,這樣的過程稱為中斷。

中斷處理過程:

(1)保護被中斷進程現場。為了在中斷處理結束后能夠使進程準確地返回到中斷點,系統必須保存當前處理機程序狀態字PSW和程序計數器PC等的值。

(2)分析中斷原因,轉去執行相應的中斷處理程序。在多個中斷請求同時發生時,處理優先級最高的中斷源發出的中斷請求。

(3)恢復被中斷進程的現場,CPU繼續執行原來被中斷的進程。

三個大注意事項

1、中斷函數代碼應盡量簡潔。一般不宜在中斷函數內編寫大量復雜冗長的代碼;應盡量避免在中斷函數內調用其他自定義函數;

2、盡量避免在中斷內調用數學函數。因為某些數學函數涉及相關的庫函數調用和中間變量較多,可能出現交叉調用。在必須使用數學函數時,可考慮將復雜的數學函數運算任務交給主程序完成,中斷函數通過全局變量引用其結果;

3、宏的定義與調用。在中斷函數中調用宏,可減少在函數調用中壓棧與出棧的開銷。

九個小注意事項

1、中斷函數不能進行參數傳遞

2、中斷函數沒有返回值

3、在任何情況下都不能直接調用中斷函數

4、中斷函數使用浮點運算要保存浮點寄存器的狀態。

5、如果在中斷函數中調用了其它函數,則被調用函數所使用的寄存器必須與中斷函數相同,被調函數最好設置為可重入的。

6、(可忽略)C51編譯器對中斷函數編譯時會自動在程序開始和結束處加上相應的內容,具體如下:

在程序開始處對ACC、B、DPH、DPL和PSW入棧,結束時出棧。

中斷函數未加using n修飾符的,開始時還要將R0~R1入棧,結束時出棧。

如中斷函數加using n修飾符,則在開始將PSW入棧后還要修改PSW中的工作寄存器組選擇位。

C51編譯器從絕對地址8m 3處產生一個中斷向量,其中m為中斷號,也即interrupt后面的數字。該向量包含一個到中斷函數入口地址的絕對跳轉。

7、中斷函數最好寫在文件的尾部,并且禁止使用extern存儲類型說明。防止其它程序調用。

8、在設計中斷時,要注意的是哪些功能應該放在中斷程序中,哪些功能應該放在主程序中。一般來說中斷服務程序應該做最少量的工作,這樣做有很多好處。

首先系統對中斷的反應面更寬了,有些系統如果丟失中斷或對中斷反應太慢將產生十分嚴重的后果,這時有充足的時間等待中斷是十分重要的。

其次它可使中斷服務程序的結構簡單,不容易出錯。中斷程序中放入的東西越多,他們之間越容易起沖突。簡化中斷服務程序意味著軟件中將有更多的代碼段,但可把這些都放入主程序中。

9、中斷服務程序的設計對系統的成敗有至關重要的作用,要仔細考慮各中斷之間的關系和每個中斷執行的時間,特別要注意那些對同一個數據進行操作的中斷

舉例說明

中斷是嵌入式系統中重要的組成部分,這導致了很多編譯開發商提供一種擴展—讓標準C支持中斷。具代表事實是,產生了一個新的關鍵字 __interrupt。下面的代碼就使用了__interrupt關鍵字去定義了一個中斷服務子程序(ISR),請評論一下這段代碼的。

 

  1. __interrupt double compute_area (double radius)  
  2.     double area = PI * radius * radius; 
  3.     printf("\nArea = %f", area); 
  4.     return area; 

這個函數有太多的錯誤了:

1) ISR 不能返回一個值。如果你不懂這個,那么你不會被雇用的。

2) ISR 不能傳遞參數。如果你沒有看到這一點,你被雇用的機會等同第一項。

3) 在許多的處理器/編譯器中,浮點一般都是不可重入的。有些處理器/編譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做浮點運算。此外,ISR應該是短而有效率的,在ISR中做浮點運算是不明智的。

4) 與第三點一脈相承,printf()經常有重入和性能上的問題。如果你丟掉了第三和第四點,我不會太為難你的。不用說,如果你能得到后兩點,那么你的被雇用前景越來越光明了。

解釋重入:

printf()經常有重入解釋

不可重入函數不可以在它還沒有返回就再次被調用。例如printf,malloc,free等都是不可重入函數。因為中斷可能在任何時候發生,例如在printf執行過程中,因此不能在中斷處理函數里調用printf,否則printf將會被重入。

函數不可重入大多數是因為在函數中引用了全局變量。例如,printf會引用全局變量stdout,malloc,free會引用全局的內存分配表。

如果中斷發生的時候,當運行到printf的時候,假設發生了中斷嵌套,而此時stdout資源被占用,所以第二個中斷printf等待第一個中斷的stdout資源釋放,第一個中斷等待第二個中斷返回,造成了死鎖。

不可重入函數指的是該函數在被調用還沒有結束以前,再次被調用可能會產生錯誤。可重入函數不存在這樣的問題。

不可重入函數在實現時候通常使用了全局的資源,在多線程的環境下,如果沒有很好的處理數據保護和互斥訪問,就會發生錯誤。

常見的不可重入函數有:

  1. printf --------引用全局變量stdout 
  2. malloc --------全局內存分配表 
  3. free    --------全局內存分配表 

在unix里面通常都有加上_r后綴的同名可重入函數版本。如果實在沒有,不妨在可預見的發生錯誤的地方嘗試加上保護鎖同步機制等等。

下面引用一段別人的解釋:

這主要在多任務環境中使用,一個可重入的函數簡單來說,就是:可以被中斷的函數。就是說,你可以在這個函數執行的任何時候中斷他的運行,在OS的調度下去執行另外一段代碼而不會出現什么錯誤。而不可重入的函數由于使用了一些系統資源,比如全局變量區,中斷向量表等等,所以他如果被中斷的話,可能出現問題,所以這類函數是不能運行在多任務環境下的。

把一個不可重入函數變成可重入的唯一方法是用可重入規則來重寫他。

其實很簡單,只要遵守了幾條很容易理解的規則,那么寫出來的函數就是可重入的:

第一,不要使用全局變量。因為別的代碼很可能覆蓋這些變量值。

第二,在和硬件發生交互的時候,切記執行類似disinterrupt()之類的操作,就是關閉硬件中斷。完成交互記得打開中斷,在有些系列上,這叫做“進入/退出核心”或者用OS_ENTER_KERNAL/OS_EXIT_KERNAL來描述。

第三,不能調用任何不可重入的函數。

第四,謹慎使用堆棧。最好先在使用前先OS_ENTER_KERNAL。

還有一些規則,都是很好理解的,總之,時刻記住一句話:保證中斷是安全的!

通俗的來講吧:由于中斷是可能隨時發生的,斷點位置也是無法預期的。所以必須保證每個函數都具有不被中斷發生,壓棧,轉向ISR,彈棧后繼續執行影響的穩定性。也就是說具有不會被中斷影響的能力。既然有這個要求,你提供和編寫的每個函數就不能拿公共的資源或者是變量來使用,因為該函數使用的同時,ISR(中斷服務程序)也可那會去修改或者是獲取這個資源,從而有可能使中斷返回之后,這部分公用的資源已經面目全非。

滿足下列條件的函數多數是不可重入的:

  1. (1)函數體內使用了靜態的數據結構; 
  2.  
  3. (2)函數體內調用了malloc()或者free()函數; 
  4.  
  5. (3)函數體內調用了標準I/O函數。 

下面舉例加以說明。

可重入函數

  1. void strcpy(char* lpszDest, char* lpszSrc) 
  2.   while(*lpszDest++ = *lpszSrc++); 
  3.   *dest=0; 

非可重入函數1

  1. char cTemp; // 全局變量 
  2. void SwapChar1(char* lpcX, char* lpcY) 
  3.   cTemp = *lpcX;  
  4.   *lpcX = *lpcY;  
  5.   lpcY = cTemp; // 訪問了全局變量,在分享內存的多個線程中可能造成問題 

非可重入函數2

  1. void SwapChar2(char* lpcX, char* lpcY) 
  2.   static char cTemp; // 靜態局部變量 
  3.   cTemp = *lpcX;  
  4.   *lpcX = *lpcY;  
  5.   lpcY = cTemp; // 使用了靜態局部變量,在分享內存的多個線程中可能造成問題 

如何寫出可重入的函數?在函數體內不訪問那些全局變量,不使用靜態局部變量,堅持只使用局部變量,寫出的函數就將是可重入的。如果必須訪問全局變量,記住利用互斥信號量來保護全局變量。

 

責任編輯:姜華 來源: 嵌入式Linux系統開發
相關推薦

2019-05-15 10:38:17

微服務架構監控

2014-01-26 14:24:25

開源項目

2025-05-06 06:37:40

2011-04-29 12:54:00

筆記本

2013-03-20 10:57:04

2010-09-25 17:57:48

項目管理

2020-11-26 15:30:05

VueReac前端

2024-06-26 08:32:13

2010-08-11 11:12:46

IT公司面試問題

2015-09-16 13:19:11

2017-03-08 15:37:23

商用電腦初創企業

2011-06-28 15:06:09

ASP.NET網站優化

2013-10-16 09:42:53

虛擬桌面

2021-06-30 17:21:23

CPUMySQL性能

2013-10-21 10:51:01

認證管理VDI部署

2009-10-27 20:53:15

企業網絡架構網絡規劃

2015-05-28 11:41:17

綜合布線系統

2009-08-10 15:56:35

802局域網網橋兼容性

2011-10-25 10:28:55

數據中心基礎架構服務器

2015-07-29 16:11:51

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 激情一区二区三区 | 欧美a级成人淫片免费看 | 日韩欧美亚洲 | 国产一区二区三区精品久久久 | www.色午夜.com | 欧美成人精品激情在线观看 | 激情亚洲 | 成人亚洲性情网站www在线观看 | 免费国产一区 | 天天干天天干 | 久久久久久亚洲 | 91毛片网| 999久久久久久久久6666 | 久久精品小视频 | 欧美性久久| 国产激情一区二区三区 | 日韩在线播放av | 黄色一级毛片 | 国产一区亚洲 | 成人精品在线视频 | 免费视频久久 | 久久精品一区二区三区四区 | 中文字幕av在线播放 | 精品国产一区二区在线 | 91视频91| 成人欧美一区二区三区黑人孕妇 | 精品欧美一区二区在线观看 | 亚洲精品一区在线观看 | 国产精品久久精品 | 成人高潮片免费视频欧美 | 日韩一区二区av | www久| 日韩三级在线 | 成人性视频免费网站 | 精品视频一区二区在线观看 | 久久天堂| 国产欧美精品区一区二区三区 | 日韩精品免费在线观看 | 国产成人jvid在线播放 | h视频在线播放 | 亚洲高清在线观看 |