C6748_UART(4) - UART中斷


 

一、主函數man.c  

  UART的中斷部分函數內容在C6748_UART輪詢模式中已經介紹,這里不再贅述。這里主要介紹關於中斷部分的函數。UART中斷的主函數如下:

int main(void)
{
    // 外設使能配置
    PSCInit();
    // GPIO 管腳復用配置
    GPIOBankPinMuxSet();
    // DSP 中斷初始化
    InterruptInit();
    // UART 初始化
    UARTInit();
    // UART 中斷初始化
    UARTInterruptInit();
    // 主循環
    for(;;)
    {
    }
}

 

二、DSP中斷初始化函數InterruptInit() 

  前部分的內容參見C6748_UART輪詢模式,首先進行的是DSP中斷初始化,該函數主要包含了IntDSPINTCInit()和IntGlobalEnable()兩個函數。其中,IntDSPINTCInit()函數是初始化DSP的中斷控制器,包括初始化所有可屏蔽中斷標志位及使能不可屏蔽中斷;IntGlobalEnable()函數是使能DSP全局中斷具體的介紹如下:

 1 void IntDSPINTCInit (void)
 2 {
 3     unsigned int step = 0;
 4 
 5     /* Set ISRs to default "do-nothing" routine */
 6     while(step != C674X_INT_COUNT)
 7         c674xISRtbl[step++] = IntDefaultHandler;
 8 
 9     /* Set interrupt service table pointer to the vector table */
10 #ifdef __TI_EABI__
11     ISTP = (unsigned int)_intcVectorTable;
12 #else
13     ISTP = (unsigned int)intcVectorTable;
14 #endif
15 
16     /* Clear pending CPU maskable interrupts (if any) */
17     ICR = 0xFFF0;
18 
19     /* Enable NMIE bit to allow CPU maskable interrupts */
20     IER = (1 << C674X_NMI);
21 }
DSP中斷初始化函數IntDSPINTCInit

  其中,IntDefaultHandler是While(1)的空函數,c674xISRtbl為定義的一個函數指針數組,存放的函數指針指向參數列表為void,返回值為void的函數。其實c674xISRtbl就是存放中斷服務程序地址的指針數組,各指針分別指向對應INT4到INT15的中斷服務程序(interrupt service routine,而該函數的意思是先將16個c674xISRtbl[step++]函數指針均初始化為默認While(1)程序。ICR = 0xFFF0即將可屏蔽中斷INT15-INT4的所有中斷標志位IFR清除,IER = (1 << C674X_NMI)使能不可屏蔽中斷。

(CPU and Instruction手冊--P41)

(CPU and Instruction手冊--P42)

  而其中的c674xISRtbl[step++]函數指針所指向的函數如下所示,位於interrupt.c文件中。

  1 #ifdef __TI_EABI__
  2 interrupt void _c674x_nmi_isr (void)
  3 #else
  4 interrupt void c674x_nmi_isr (void)
  5 #endif
  6 {
  7     c674xISRtbl[1]();
  8 }
  9 
 10 #ifdef __TI_EABI__
 11 interrupt void _c674x_rsvd_int2_isr (void)
 12 #else
 13 interrupt void c674x_rsvd_int2_isr (void)
 14 #endif
 15 {
 16     c674xISRtbl[2]();
 17 }
 18 
 19 #ifdef __TI_EABI__
 20 interrupt void _c674x_rsvd_int3_isr (void)
 21 #else
 22 interrupt void c674x_rsvd_int3_isr (void)
 23 #endif
 24 {
 25     c674xISRtbl[3]();
 26 }
 27 
 28 #ifdef __TI_EABI__
 29 interrupt void _c674x_mask_int4_isr (void)
 30 #else
 31 interrupt void c674x_mask_int4_isr (void)
 32 #endif
 33 {
 34     c674xISRtbl[4]();
 35 }
 36 
 37 #ifdef __TI_EABI__
 38 interrupt void _c674x_mask_int5_isr (void)
 39 #else
 40 interrupt void c674x_mask_int5_isr (void)
 41 #endif
 42 {
 43     c674xISRtbl[5]();
 44 }
 45 
 46 #ifdef __TI_EABI__
 47 interrupt void _c674x_mask_int6_isr (void)
 48 #else
 49 interrupt void c674x_mask_int6_isr (void)
 50 #endif
 51 {
 52     c674xISRtbl[6]();
 53 }
 54 
 55 #ifdef __TI_EABI__
 56 interrupt void _c674x_mask_int7_isr (void)
 57 #else
 58 interrupt void c674x_mask_int7_isr (void)
 59 #endif
 60 {
 61     c674xISRtbl[7]();
 62 }
 63 
 64 #ifdef __TI_EABI__
 65 interrupt void _c674x_mask_int8_isr (void)
 66 #else
 67 interrupt void c674x_mask_int8_isr (void)
 68 #endif
 69 {
 70     c674xISRtbl[8]();
 71 }
 72 
 73 #ifdef __TI_EABI__
 74 interrupt void _c674x_mask_int9_isr (void)
 75 #else
 76 interrupt void c674x_mask_int9_isr (void)
 77 #endif
 78 {
 79     c674xISRtbl[9]();
 80 }
 81 
 82 #ifdef __TI_EABI__
 83 interrupt void _c674x_mask_int10_isr (void)
 84 #else
 85 interrupt void c674x_mask_int10_isr (void)
 86 #endif
 87 {
 88     c674xISRtbl[10]();
 89 }
 90 
 91 #ifdef __TI_EABI__
 92 interrupt void _c674x_mask_int11_isr (void)
 93 #else
 94 interrupt void c674x_mask_int11_isr (void)
 95 #endif
 96 {
 97     c674xISRtbl[11]();
 98 }
 99 
100 #ifdef __TI_EABI__
101 interrupt void _c674x_mask_int12_isr (void)
102 #else
103 interrupt void c674x_mask_int12_isr (void)
104 #endif
105 {
106     c674xISRtbl[12]();
107 }
108 
109 #ifdef __TI_EABI__
110 interrupt void _c674x_mask_int13_isr (void)
111 #else
112 interrupt void c674x_mask_int13_isr (void)
113 #endif
114 {
115     c674xISRtbl[13]();
116 }
117 
118 #ifdef __TI_EABI__
119 interrupt void _c674x_mask_int14_isr (void)
120 #else
121 interrupt void c674x_mask_int14_isr (void)
122 #endif
123 {
124     c674xISRtbl[14]();
125 }
126 
127 #ifdef __TI_EABI__
128 interrupt void _c674x_mask_int15_isr (void)
129 #else
130 interrupt void c674x_mask_int15_isr (void)
131 #endif
132 {
133     c674xISRtbl[15]();
134 }
c674xISRtbl[step++]函數

   函數將ISTP(Interrupt Service Table Pointer)指向intcVectorTable,intcVectorTable是一張向量表,記錄了CPU中斷服務程序的入口地址,各向量對應一個CPU中斷。該向量表在intvecs.asm文件中,路徑同interrupt.c文件一樣(\demo\StarterWare\Source\StarterWare\SystemConfig),內容如下,而intcVectorTable表所有向量的入口函數在interrupt.c文件中,

  1     .global _intcVectorTable
  2 
  3     .global _c_int00
  4 
  5     .global _c674x_nmi_isr
  6 
  7     .global _c674x_rsvd_int2_isr
  8 
  9     .global _c674x_rsvd_int3_isr
 10 
 11     .global _c674x_mask_int4_isr
 12 
 13     .global _c674x_mask_int5_isr
 14 
 15     .global _c674x_mask_int6_isr
 16 
 17     .global _c674x_mask_int7_isr
 18 
 19     .global _c674x_mask_int8_isr
 20 
 21     .global _c674x_mask_int9_isr
 22 
 23     .global _c674x_mask_int10_isr
 24 
 25     .global _c674x_mask_int11_isr
 26 
 27     .global _c674x_mask_int12_isr
 28 
 29     .global _c674x_mask_int13_isr
 30 
 31     .global _c674x_mask_int14_isr
 32 
 33     .global _c674x_mask_int15_isr
 34 
 35  
 36 
 37 ;**********************************************************
 38 
 39 ;               Interrupt Fetch Packet
 40 
 41 ;**********************************************************
 42 
 43 VEC_ENTRY .macro addr
 44 
 45     STW B0,*--B15
 46 
 47     MVKL addr,B0
 48 
 49     MVKH addr,B0
 50 
 51     B B0
 52 
 53     LDW *B15++,B0
 54 
 55     NOP 2
 56 
 57     NOP
 58 
 59     NOP
 60 
 61     .endm
 62 
 63  
 64 
 65 ;**********************************************************
 66 
 67 ;               Interrupt Vector Table
 68 
 69 ;**********************************************************
 70 
 71     .align 1024
 72 
 73 _intcVectorTable:
 74 
 75     VEC_ENTRY _c_int00
 76 
 77     VEC_ENTRY _c674x_nmi_isr
 78 
 79     VEC_ENTRY _c674x_rsvd_int2_isr
 80 
 81     VEC_ENTRY _c674x_rsvd_int3_isr
 82 
 83     VEC_ENTRY _c674x_mask_int4_isr
 84 
 85     VEC_ENTRY _c674x_mask_int5_isr
 86 
 87     VEC_ENTRY _c674x_mask_int6_isr
 88 
 89     VEC_ENTRY _c674x_mask_int7_isr
 90 
 91     VEC_ENTRY _c674x_mask_int8_isr
 92 
 93     VEC_ENTRY _c674x_mask_int9_isr
 94 
 95     VEC_ENTRY _c674x_mask_int10_isr
 96 
 97     VEC_ENTRY _c674x_mask_int11_isr
 98 
 99     VEC_ENTRY _c674x_mask_int12_isr
100 
101     VEC_ENTRY _c674x_mask_int13_isr
102 
103     VEC_ENTRY _c674x_mask_int14_isr
104 
105     VEC_ENTRY _c674x_mask_int15_isr
intvecs.asm

  在intvecs.asm文件如“_c_int00”代表中斷函數名,C語言中的函數在匯編中使用需要在前面加“_”,而這些中斷向量表是根據中斷優先級順序排列的。

_enable_interrupts函數為Intrinsic函數,函數使能全局中斷。Intrinsic函數為C/C++語言提供了一個調用匯編語言的接口機制,通過Intrinsic函數,C/C++函數中可以調用匯編函數。

 

三、UART 中斷初始化 UARTInterruptInit()

 1 void UARTInterruptInit(void)
 2 {
 3     IntRegister(C674X_MASK_INT4, UARTIsr);
 4     IntEventMap(C674X_MASK_INT4, SYS_INT_UART0_INT);
 5     IntEnable(C674X_MASK_INT4);
 6 
 7     // 使能中斷
 8     unsigned int intFlags = 0;
 9     intFlags |= (UART_INT_LINE_STAT  |  \
10                  UART_INT_TX_EMPTY |    \
11                  UART_INT_RXDATA_CTI);
12     UARTIntEnable(SOC_UART_0_REGS, intFlags);
13 }

  先是注冊4號CPU可屏蔽中斷的中斷服務函數(這里的可屏蔽中斷可在INT4到INT15中任意選擇,如下圖所示),IntRegister(C674X_MASK_INT4, UARTIsr)函數如下所示。

1 void IntRegister (unsigned int cpuINT, void (*userISR)(void))
2 {
3 /* Check the CPU maskable interrupt number */
4 ASSERT(((cpuINT >= 1) && (cpuINT <= 15)));
5 
6 /* Assign the user's ISR to the CPU maskable interrupt */
7 c674xISRtbl[cpuINT] = userISR;
8 }

  該函數首先核對可屏蔽中斷序號是否錯誤,接着由“c674xISRtbl[cpuINT] = userISR”函數將該c674xISRtbl函數指針數組的第4個指針指向了userISR(UARTIsr)程序。則當C674X_MASK_INT4中斷發生時,執行UARTIsr函數。

(見Magamodule手冊P161)

   其次,由IntEventMap(C674X_MASK_INT4, SYS_INT_UART0_INT)將128個系統中斷事件EVT中的UART0_INT事件與12個可屏蔽中斷INT中的INT4之間建立映射關系。由IntEnable使能可屏蔽中斷INT4。

1     unsigned int intFlags = 0;
2     intFlags |= (UART_INT_LINE_STAT  |  \
3                  UART_INT_TX_EMPTY |    \
4                  UART_INT_RXDATA_CTI);
5     UARTIntEnable(SOC_UART_0_REGS, intFlags);

  通過intFlags的值表示三種中斷觸發事件,任意一種發生則執行中斷INT4,UARTIntEnable(SOC_UART_0_REGS, intFlags)對UART的中斷使能寄存器IER(Interrupt Enable Register)寄存器進行設置。

(見指南P1448)

 

四、UART中斷服務函數UARTIsr()

 1 void UARTIsr()
 2 {
 3     static unsigned int length = sizeof(txArray);
 4     static unsigned int count = 0;
 5     unsigned char rxData = 0;
 6     unsigned int int_id = 0;
 7 
 8     // 確定中斷源
 9     int_id = UARTIntStatus(SOC_UART_0_REGS);
10 
11     // 清除 UART2 系統中斷
12     IntEventClear(SYS_INT_UART0_INT);
13 
14     // 發送中斷
15     if(UART_INTID_TX_EMPTY == int_id)
16     {
17         if(0 < length)
18         {
19             // 寫一個字節到 THR
20             UARTCharPutNonBlocking(SOC_UART_0_REGS, txArray[count]);
21             length--;
22             count++;
23         }
24         if(0 == length)
25         {
26             // 禁用發送中斷
27             UARTIntDisable(SOC_UART_0_REGS, UART_INT_TX_EMPTY);
28         }
29      }
30 
31     // 接收中斷
32     if(UART_INTID_RX_DATA == int_id)
33     {
34         rxData = UARTCharGetNonBlocking(SOC_UART_0_REGS);
35         UARTCharPutNonBlocking(SOC_UART_0_REGS, rxData);
36     }
37 
38     // 接收錯誤
39     if(UART_INTID_RX_LINE_STAT == int_id)
40     {
41         while(UARTRxErrorGet(SOC_UART_0_REGS))
42         {
43             // 從 RBR 讀一個字節
44             UARTCharGetNonBlocking(SOC_UART_0_REGS);
45         }
46     }
47 
48     return;
49 }
UARTIsr函數

 當中斷發生了,在IER中相應的中斷位也使能了,此時在IIR的IPEND位就會清零,代表UART中斷發生了,此時就會執行UART中斷服務程序UARTIsr()。首先通過“int_id = UARTIntStatus(SOC_UART_0_REGS)”清除中斷鑒別寄存器IIR的IPEND位,即清除IIR中的UART的中斷標志位,其次讀取IIR的INTID的值,得到中斷類型,其值的定義如下圖所示。按照UART中斷優先級的順序(發送中斷1>接收中斷2>接受錯誤3),依此判定“int_id”的值,執行相應的程序。

(見指南P1449)

  •  如果UART中斷是由發送中斷引起的,說明發送FIFO為空,就往THR寄存器(transmitter holding register)寫1字節。注意,在FIFO模式下,THR寄存器變成了1個16字節的FIFO。
  • 如果UART中斷是由接收中斷引起的,則檢查LSR寄存器(Line Status Register)的DR(Data-ready)字段,確定數據是否已經准備好,即接收器FIFO中是否有數據,如果有,則從RBR寄存器(Receiver Buffer Register)中讀取該數據。當UART處於FIFO模式時,RBR為16字節的FIFO。注意,RBR和THR,DLL共享同一地址,要讀RBR,需要確保LCR寄存器的DLAB位為0.
  • 若UART中斷是由接收錯誤引起的,則從RBR中把錯誤的字節都讀出來,並不斷檢測LSR的錯誤標志位,直到所有的錯誤字節都讀走了。

(指南P1432)

(指南P1431)

(指南P1442)

 

五、關於C6748的UART中斷說明

(見指南P1442)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM