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