SYSBIOS学习笔记---硬件中断(HWI)的创建

本文介绍了在SYSBIOS实时操作系统中配置硬件中断的方法,包括静态配置和动态配置两种方式,并详细解释了配置参数的意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       在进行嵌入式开发的时候,我们会根据不同的需求来决定是否使用操作系统,以及使用什么样的操作系统,在ARM嵌入式开发中大家常用Linux操作系统来进行系统的开发;而在DSP嵌入式开发中,尤其是TI的DSP,在早期的时候由于处理器的性能相对的弱一些,资源也相对较少,这时为了满足实时性的要求,一般是跑裸机程序。随着TI的DSP处理器的性能越来越强大,资源也越来越多,为了把开发人员从繁重的底层驱动开发解放出来,TI随即推出了SYSBIOS实时操作系统,该操作系统目前已经支持TI的全系列DSP。

       今天笔者就来和大家一起来分享一下关于SYSBIOS中硬件中断(HWI)的创建,硬件中断的创建有两种方式,一种是静态的创建,另一种是动态的创建。所谓静态的创建就是使用CCS下cfg图形配置界面进行配置,或者使用cfg Script脚本语言来进行配置,前者配置比较耗电脑系统资源,会出现卡顿的现象;后者占用的系统资源非常的少,不会出现卡顿的现象。当然一般情况我们使用前者就可以了。下面是一个典型的HWI图形配置界面。


其各项参数解释如下:

Handle:当前硬件中断的句柄,此项参数在这里没有具体的作用,但如果是软件中断的话,该参数会被用于发布一个具体的软件中断。

ISR function:中断服务函数,此项参数填写你要执行的中断函数的函数名。

Interrupt number:中断号,指定该硬件中断由哪个CPU可屏蔽硬件中断响应,该中断号的取值需要更具具体的器件来确定。我在这里用的是c6657,它的值是4到15。

Argument passed to ISR function:传递到中断服务函数的参数,如果没有就填写为0,在这里没有参数,所以填写为0。

Event Id:事件ID,即系统事件的的编号,这个得根据具体的要求查阅相关手册,我在这里响应的是外部按键的中断,查阅手册得知事件的ID是91,因此填写的是91。

Masking options:屏蔽选项,有MaskingOption_NONE、MaskingOption_ALL、MaskingOption_SELF、MaskingOption_BITMASK、MaskingOption_LOWER。这里选择的是MaskingOption_SELF,也就是在响应中断是时候自身的中断事件又来了这时不会去响应。


所谓的动态配置是指在程序中调用相应的API函数来配置,这样就可以在程序的运行中有选择的进行配置,这样可以减少系统的资源消耗,下面是一个典型的配置程序代码:

 // 动态创建硬件中断
    Hwi_Handle hwi0;
    Hwi_Params hwiParams;
    Error_Block eb;

    // 初始化错误块
    Error_init(&eb);

    // 使用默认值初始化参数
    Hwi_Params_init(&hwiParams);
    // 中断事件
	hwiParams.eventId = 91;
    // 传递到中断服务函数的参数
    hwiParams.arg = 0;
    // 不允许该中断自身嵌套
    hwiParams.maskSetting = Hwi_MaskingOption_SELF;
    // 使能中断
    hwiParams.enableInt = TRUE;
    // 可屏蔽中断 4
    hwi0 = Hwi_create(4, USER0KEYIsr, &hwiParams, &eb);
    /**/
    if(hwi0 == NULL)
    {
    	System_abort("Hwi1 create failed");
    }
该程序实现的功能和上述使用静态的方式是一样的。










<think>我们正在讨论F280049C芯片的EPWM中断函数声明问题。用户询问如果省略`__interrupt`关键字会有什么影响。 在C2000系列芯片的C/C++编程中,`__interrupt`关键字用于声明一个函数为中断服务程序(ISR)。这个关键字告诉编译器: 1. 在进入该函数时,自动保存上下文(包括寄存器等) 2. 在退出该函数时,自动恢复上下文 3. 使用特殊的返回指令(通常是`IRET`)而不是普通的`RET` 如果省略`__interrupt`关键字,那么该函数就会被当作普通函数处理。这样,当发生中断时,CPU跳转到这个函数,但编译器不会生成保存和恢复上下文的代码,也不会使用中断返回指令。这将导致: - 进入中断函数时,不会自动保存关键寄存器(如ACC, P, ST0, ST1等) - 函数返回时使用普通的子程序返回指令(`LRET`或`RET`),而不是中断返回指令(`IRET`),这可能导致无法正确从中断返回 - 中断处理过程中可能会破坏主程序的上下文,导致程序运行错误 因此,省略`__interrupt`关键字会导致中断服务程序无法正常工作,并可能引起系统崩溃。 下面我们通过一个具体的代码示例来说明: **正确的中断函数声明:** ```c __interrupt void epwm1ISR(void) { // 中断处理代码 ... // 清除中断标志 EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE); ... } ``` **错误的中断函数声明(省略__interrupt):** ```c void epwm1ISR(void) { // 中断处理代码 ... // 清除中断标志 EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE); ... } ``` 在错误的情况下,当EPWM1中断发生时,程序会跳转到`epwm1ISR`,但因为没有保存上下文,中断服务程序中的代码可能会修改寄存器,而这些寄存器在中断返回后主程序继续执行时会被破坏。同时,由于没有使用`IRET`返回,中断返回地址和状态可能不正确。 **如何正确配置EPWM中断?** 1. **声明中断服务程序**:使用`__interrupt`关键字声明函数。 2. **注册中断服务程序**:使用`Interrupt_register`函数将中断服务程序与特定的中断号关联。 3. **启用中断**:使用`Interrupt_enable`函数启用特定的中断,并确保全局中断使能。 示例代码: ```c #include "driverlib.h" // 声明EPWM1中断服务程序 __interrupt void epwm1ISR(void) { // 处理中断 ... // 清除中断标志 EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE); // 确认中断(用于PIE中断组) Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); // EPWM1属于PIE组3 } int main(void) { Device_init(); // 初始化EPWM1 EPWM_setTimeBasePeriod(EPWM1_BASE, 1000); // ... 其他EPWM配置 // 配置EPWM中断 EPWM_enableInterrupt(EPWM1_BASE); // 使能EPWM中断事件 EPWM_setInterruptSource(EPWM1_BASE, EPWM_INT_TBCTR_U_CMP); // 设置中断源 EPWM_setInterruptEventCount(EPWM1_BASE, 1); // 每1次事件产生一次中断 // 注册中断服务程序 Interrupt_register(INT_EPWM1, &epwm1ISR); Interrupt_enable(INT_EPWM1); // 启用全局中断 EINT; ERTM; while(1); } ``` **总结**: - 必须使用`__interrupt`关键字声明中断服务程序,以确保编译器生成正确的上下文保存/恢复代码和中断返回指令。 - 省略该关键字会导致中断服务程序无法正确执行,并可能破坏系统运行环境。 §§相关问题§§ 1. 在C2000开发中,除了`__interrupt`,还有哪些重要的编译器关键字? 2. 如何调试中断服务程序中的问题? 3. 在中断服务程序中需要注意哪些编程规范? 4. 如何配置多个EPWM模块的中断? 5. 中断嵌套是如何实现的?</think>### F280049C EPWM中断函数省略`__interrupt`关键字的影响分析 在F280049C开发中,**EPWM中断函数声明前省略`__interrupt`关键字将导致中断无法正常工作**,具体影响如下: #### 1. 中断上下文保存失败 - **关键问题**:编译器不会生成自动保存/恢复CPU寄存器的代码 - **后果**: - 中断服务程序(ISR)会破坏主程序的寄存器状态 - 返回主程序后出现随机崩溃或数据损坏 - 无法正确处理关键寄存器如ACC、PCL、ST0等 #### 2. 中断返回机制失效 - 普通函数使用`LRET`返回,而中断必须使用`IRET` - 省略关键字会导致: ```nasm ; 错误代码示例 LRET ; 普通函数返回 ; 正确应为 IRET ; 中断返回(恢复状态寄存器) ``` - 导致CPU状态寄存器(ST0, ST1)无法恢复[^1] #### 3. 中断向量表关联失败 编译器无法将函数识别为ISR,导致: ```c // 错误声明(省略__interrupt) void epwm1ISR(void) { // 不会被链接到中断向量表 EPWM_clearInterrupt(EPWM1_BASE); } ``` #### 4. 中断嵌套控制失效 - 缺少自动的`INTM`位管理(全局中断屏蔽) - 可能导致: - 中断重入引发栈溢出 - 关键操作被意外打断 --- ### 正确的中断函数声明示例 ```c #include "F28x_Project.h" // 必须使用__interrupt关键字 __interrupt void epwm1ISR(void) { // 1. 清除中断标志 EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE); // 2. 处理中断任务 GpioDataRegs.GPATOGGLE.bit.GPIO0 = 1; // 示例:翻转GPIO // 3. 确认PIE中断(组3对应EPWM) PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; } ``` ### 关键配置步骤 1. **中断函数注册**: ```c Interrupt_register(INT_EPWM1, &epwm1ISR); ``` 2. **PIE配置**: ```c PieVectTable.EPWM1_INT = &epwm1ISR; // 关联中断向量 PieCtrlRegs.PIEIER3.bit.INTx1 = 1; // 使能PIE组3通道1 ``` 3. **启用中断**: ```c EPWM_enableInterrupt(EPWM1_BASE); // EPWM模块级使能 Interrupt_enable(INT_EPWM1); // CPU级使能 EINT; // 全局中断使能 ``` --- ### 调试建议 当省略`__interrupt`时,可通过以下现象诊断: 1. **CCS调试器观察**: - 中断触发后PC指针不跳转到ISR - PIEIFR寄存器标志位置位但无响应 2. **寄存器检查**: ```c if (PieCtrlRegs.PIEIFR3.bit.INTx1) { // 中断挂起但未执行 } ``` 3. **堆栈验证**: ```c // 在可疑函数内检查SP Uint16 sp = __get_SP(); ``` > 📌 **最佳实践**:始终使用`__interrupt`关键字声明中断函数,并通过`#pragma CODE_SECTION()`指定到正确内存段[^2]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_IRONMAN_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值