---
# System prepended metadata

title: F2812的中斷系統
tags: [F2812]

---

[TOC]


# 整體中斷架構
- 見 <手把手教你DSP> 第11章
- F2812的中斷向量有32個，其中有12個中斷向量是用戶可使用也用得最多的，INT1 ~ INT12，以下僅介紹這12個中斷向量形成的架構
- 當一個中斷事件發生，要讓CPU去響應這個事件然後執行ISR需要經過重重關卡，基本上分為3級，可以想像成每一級都有好多開關，為了確認是否真的要響應這個中斷。如果希望某個中斷線路能進入到CPU的話，那以下線路的每個部份都要確保有開啟
    - ![image](https://hackmd.io/_uploads/BkKdflwCR.png)
- 下圖可以看到，整個中斷有多條線路，使用了兩個多工器去做選擇
    - 在IFR前有12條線路，INT1~12
    - 下方的INTx即代表著INT1 ~ 12，而且每個INTx都再分出去INTx.1 ~ INTx.8，所以總共可以有96條不同的中斷線路
    - ![image](https://hackmd.io/_uploads/By2pPHdCC.png)

    

# CPU級中斷
- 從架構圖來看，INTx 中斷信號進入CPU前需要經過重重關卡，這些" 開關 "有一個未被啟用，CPU就不會響應這個中斷信號
- CPU級中斷向量的優先級可以見[F2812中斷查詢](https://hackmd.io/-naxV-upSE6WgtpQUBUrKw)

## IFR (中斷旗標暫存器)
- 暫存器的每一位對應了INT1~INT12
- 當INTx的中斷信號進入，IFR對應的bit就會立起(置1)
- 如果CPU最後成功響應了對應的中斷信號，那IFR的那個bit會<font color="red">自動清0</font>
- 
## IER (中斷使能暫存器)
- 暫存器的每一位對應了INT1~INT12
- 當有偵測到IFR的旗標立起，CPU會檢查IER對應的bit是否使能，有被置1才算啟用該中斷線路

## INTM(中斷屏蔽)
- 這是一個總開關的概念，中斷信號的最後一道關卡
- 如果置1，則中斷信號可以通過


# PIE級中斷
- 上面架構提到每個INTx都有8個PIE級線路，所以整個PIE級中斷系統要控制96個中斷線路是否可以通過
- 每個INTx雖然有多個子線路，但每次只會有一個中斷信號進入CPU級中斷
- 對每個INTx來說，外設中斷給出的中斷信號同樣要經過層層關卡才能確定這個中斷信號是否可以進入CPU級中斷
- PIE級中斷向量表與優先級可見[F2812中斷查詢](https://hackmd.io/-naxV-upSE6WgtpQUBUrKw)

## PIEIFRx (PIE級 IFR)
- x 對應 INTx
- 與CPU級的IFR類似，對應的bit有對應的子線路 INTx.1 ~ INTx.8
- 當INTx.y的中斷信號到來時，對應的旗標會升起。如果CPU成功響應這個中斷，該旗標會<font color="red">自動清0</font>

## PIEIERx (PIE級 IER)
- x 對應 INTx
- 同樣的，各bit對應 INTx.1 ~ INTx.8
- 當有偵測到PIEIFRx的某個旗標立起，CPU會檢查PIRIER對應的bit是否使能，有被置1才算啟用該中斷線路

## PIEACK (PIE級 應答暫存器)
- 在PIE級中斷信號進入CPU級之前，可以看到還需要一個AND邏輯閘與PIEACKx共同作用，這個PIEACKx也是一個開關的概念，決定INTx的子線路可不可以進入CPU級中斷
- 對這個暫存器x位元寫入1相當於允許PIE級x組中斷信號進入CPU級
    - 對某位寫入1會清0
    - 架構圖中可以看到PIEACKx進入AND邏輯閘有一個反向符號，所以清0反而是允許通過
- 當CPU響應了INTx的中斷，PIEACKx位元會自動被置1，這邊置1反而是關閉這條信號，所以執行完ISR後要<font color="red">手動對PIEACKx寫入1才會清0</font>使通過

# 中斷優先級
- 當有多個中斷信號同時產生，但中斷線路只允許一條通過時，就有中斷優先級的考量。
- 架構圖中可以看到兩個MUX多工器，這就是依據優先級從多條線路中選擇一條通過
- 既然有兩個多工器，那就會有兩種優先級。一個是PIE級的，一個是CPU級的。PIE級內的是INTx.1 ~ INTx.8的優先順序，CPU級內的是INT1~INT12的優先順序
- [F2812中斷查詢](https://hackmd.io/-naxV-upSE6WgtpQUBUrKw)的中斷向量表可以看到每個中斷有CPU級和PIE級的優先級


# 外設中斷
- F2812片內結構。右側的那些外設大多都能產生中斷信號，該中斷信號會送進上面提及的PIE級和CPU級中斷，最後才被CPU響應
    ![image](https://hackmd.io/_uploads/SksqjfKC0.png)
    
# 中斷向量表
- 已知總共有96個外設中斷，當CPU響應一個中斷訊號後會執行對應的ISR，那麼應該要有96個確切的ISR程式的位置，CPU才知道要跳去哪裡
-  中斷向量表就是儲存每個中斷對應的ISR位址用的
-  預設程式庫已經建立好一些ISR並且在[中斷向量表](https://hackmd.io/-naxV-upSE6WgtpQUBUrKw)中了，用戶可以選擇修改原有ISR，或是將中斷向量表內的ISR位址改成自己建立的函式位址，見下面範例程式
    
# 程式範例 : 初始化
- 以下都可以在[DSP的初始化](https://hackmd.io/vGiH_bLMTEC1baO3HxS5NA)範例中看到

## CPU級常用操作

``` c++=
DINT;  // Disable Global interrupt INTM
EINT;  // Enable Global interrupt INTM

IER = 0x0000; // Disable all INTx interrupt
IER |= (M_INT2 | M_INT3); // Enable INT2 and INT3 interrupt

// Clear all INTx interrupt flag
IFR = 0x0000;
```
## PIE級常用操作

``` c++=
// found in the DSP281x_PieCtrl.c file.
InitPieCtrl(); // Disable all PIE interrupt

PieCtrlRegs.PIEIER2.all = M_INT4 // Enable INT2.4 interrupt
PieCtrlRegs.PIEIER3.all = (M_INT2 | MINT3)// Enable INT3.2, INT3.3 interrupt

// found in DSP281x_PieVect.c.
// This function must be executed after boot time.
InitPieVectTable();

// 自定義ISR
interrupt void eva_timer1_isr(void);

// 把T1PINT (對應INT2.4) 中斷ISR改成自己的函式
EALLOW;	//This is needed to write to EALLOW protected registers
    PieVectTable.T1PINT = &eva_timer1_isr;	// Timer1 ISR
EDIS;
```

