4928|11

18

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

末尾连锁 [复制链接]

请问下中断中的末尾连锁有和作用

最新回复

对,是我说错了,是 Key1 所在 GPIO 的次优先级要比 Key2 所在 GPIO 的次优先级高,数值低的优先级高。 按照楼主设计的实验,应该是在 Key2 所在GPIO的中断完成后才能去执行 Key1 所在中断,也就是应该实现末尾连锁,不应该发生中断嵌套,但为什么此刻却偏偏发生了呢? 但现在却发生了抢占,这确实和理论不一样。这一点可见《Cortex-M3 权威指南第二版~英文原版》的 120 页。 还有一个比较困扰我的问题是,我记得默认优先级分组值是0,也就是复位后所有的优先级不存在分组的问题,而 Stellaris MCU 用三个位来表示优先级,也就是做多是 8 级嵌套。 [ 本帖最后由 Study_Stellaris 于 2011-10-1 23:52 编辑 ]  详情 回复 发表于 2011-10-1 23:16
 
点赞 关注

回复
举报

1729

帖子

0

TA的资源

五彩晶圆(初级)

沙发
 
第一次听过这个名词,希望有高手来解决一下。
 
 

回复

8

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
原理就是在某些时候可以省去没必要的出栈入栈,具体的芯片手册上有讲,简单来说就是中断更快,周期更少
 
 
 

回复

18

帖子

0

TA的资源

一粒金砂(中级)

4
 
但是我调试周立功程序单步运行末尾连锁正常,直接运行就出现a(key1)会抢断b(key2)的怪现象,谁能帮我解释下:
/****************************************Copyright (c)****************************************************
**                            Guangzhou ZHIYUAN electronics Co.,LTD.
**                                      
**                                 http://www.embedtools.com
**
**--------------File Info---------------------------------------------------------------------------------
** File name:               IntDome1.c
** Latest modified Date:    2007.11.23
** Latest Version:          V1.0
** Descriptions:            中断优先级实验
**
**--------------------------------------------------------------------------------------------------------
** Created by:              Kang qinhua
** Created date:            2007.11.23
** Version:                 V1.0
** Descriptions:            The original version
**
**--------------------------------------------------------------------------------------------------------
** Modified by:            
** Modified date:           
** Version:                 
** Descriptions:            
**
*********************************************************************************************************/
#include "hw_types.h"
#include "hw_memmap.h"
#include "hw_ints.h"
#include "hw_nvic.h"
#include "interrupt.h"
#include "sysctl.h"
#include "gpio.h"

#define KEY1   GPIO_PIN_4                                                                                                /*  设置PA4口为KEY1                    */
#define KEY2   GPIO_PIN_4                                                                                                /*  设置PB4口为KEY2                    */
#define KEY3   GPIO_PIN_4                                               /*  设置PC4口为KEY3                    */

#define LED3   GPIO_PIN_6                                                                                                /*  设置PB6口为LED3                    */
#define LED4   GPIO_PIN_5                                                                                                /*  设置PA5口为LED4                    */
#define LED5   GPIO_PIN_5                                                                                                /*  设置PB5口为LED5                    */
#define LED6   GPIO_PIN_5                                                                                                /*  设置PC5口为LED6                    */

/*********************************************************************************************************
** Function name:         delay
** Descriptions:          延时函数
** input parameters:      t,延时时间常数
** output parameters:     无
** Returned value:        无
*********************************************************************************************************/
void delay (int  t)
{
    for ( ; t; --t);
}

/*********************************************************************************************************
** Function name:         GPIO_Port_A_ISR
** Descriptions:          GPIOA中断函数
**                        用KEIL软件时,在Startup.S中添加该中断函数名
** input parameters:      无
** output parameters:     无
** Returned value:        无
*********************************************************************************************************/
void GPIO_Port_A_ISR (void)
{
    unsigned long i = 0;
    GPIOPinIntClear(GPIO_PORTA_BASE, KEY1);                             /*  清除中断标志                */
        for ( i = 100; i > 0; i--) {
                GPIOPinWrite(GPIO_PORTA_BASE, LED4, ~GPIOPinRead(GPIO_PORTA_BASE, LED4));
                delay(200000);
        }
}

/*********************************************************************************************************
** Function name:         GPIO_Port_B_ISR
** Descriptions:          GPIOB中断函数
**                        用KEIL软件时,在Startup.S中添加该中断函数名
** input parameters:      无
** output parameters:     无
** Returned value:        无
*********************************************************************************************************/
void GPIO_Port_B_ISR (void)
{
    unsigned long i = 0;
    GPIOPinIntClear(GPIO_PORTB_BASE, KEY2);                             /*  清除中断标志                */
        for ( i = 100; i > 0; i--) {
            GPIOPinWrite(GPIO_PORTB_BASE, LED5, ~GPIOPinRead(GPIO_PORTB_BASE, LED5));
                delay(200000);
        }
}

/*********************************************************************************************************
** Function name:         GPIO_Port_C_ISR
** Descriptions:          GPIOC中断函数
**                        用KEIL软件时,在Startup.S中添加该中断函数名
** input parameters:      无
** output parameters:     无
** Returned value:        无
*********************************************************************************************************/
void GPIO_Port_C_ISR (void)
{
    unsigned long i = 0;
    GPIOPinIntClear(GPIO_PORTC_BASE, KEY3);                             /*  清除中断标志                */
        for ( i = 100; i > 0; i--) {
            GPIOPinWrite(GPIO_PORTC_BASE, LED6, ~GPIOPinRead(GPIO_PORTC_BASE, LED6));
                delay(200000);
        }
}

/*********************************************************************************************************
** Function name:         main          
** Descriptions:          主函数
**                        运行时LED3闪烁
**                        KEY1--GPIOA中断 ,对应于LED4,设置成组优先级为2,次优先级为0
**                        KEY2--GPIOB中断 ,对应于LED5,设置成组优先级为2,次优先级为1
**                        KEY3--GPIOC中断 ,对应于LED6,设置成组优先级为1,次优先级为1
**                        按下KEY1,LED4闪烁;按下KEY2,LED5闪烁;按下KEY3,LED6闪烁;
**                        KEY1与KEY2产生末尾连锁,KEY3可抢断KEY1、KEY2,通过LED可以观测结果
** input parameters:      无
** output parameters:     无      
** Returned value:        无         
*********************************************************************************************************/
int main (void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);                        /*  使能GPIO PA口               */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);                        /*  使能GPIO PB口               */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);                        /*  使能GPIO PC口               */

/*********************************************************************************************************
  设置KEY1、KEY2、KEY3为输入
*********************************************************************************************************/
/*  GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, KEY1);         
        GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, KEY2);
        GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, KEY3); */

    GPIODirModeSet(GPIO_PORTA_BASE, KEY1, GPIO_DIR_MODE_IN);
        GPIODirModeSet(GPIO_PORTB_BASE, KEY2, GPIO_DIR_MODE_IN);
        GPIODirModeSet(GPIO_PORTC_BASE, KEY3, GPIO_DIR_MODE_IN);

/*********************************************************************************************************
  设置LED3、LED4、LED5、LED6为输出
*********************************************************************************************************/
/*  GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, LED3);
    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, LED4);
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, LED5);
        GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, LED6);         */

        GPIODirModeSet(GPIO_PORTB_BASE, LED3, GPIO_DIR_MODE_OUT);
    GPIODirModeSet(GPIO_PORTA_BASE, LED4, GPIO_DIR_MODE_OUT);
        GPIODirModeSet(GPIO_PORTB_BASE, LED5, GPIO_DIR_MODE_OUT);
        GPIODirModeSet(GPIO_PORTC_BASE, LED6, GPIO_DIR_MODE_OUT);

    GPIOPadConfigSet(GPIO_PORTA_BASE, KEY1 | LED4,                                    /*  设置KEY1的驱动强度和类型    */
                     GPIO_STRENGTH_4MA,                                                    /*  4mA的输出驱动强度           */
                     GPIO_PIN_TYPE_STD);                                                /*  设置为推挽管脚              */

    GPIOPadConfigSet(GPIO_PORTB_BASE, KEY2 | LED5 | LED3,                            /*  设置KEY2的驱动强度和类型    */
                     GPIO_STRENGTH_4MA,                                                    /*  4mA的输出驱动强度           */
                     GPIO_PIN_TYPE_STD);                                                /*  设置为推挽管脚              */

    GPIOPadConfigSet(GPIO_PORTC_BASE, KEY3 | LED6,                                    /*  设置KEY3的驱动强度和类型    */
                     GPIO_STRENGTH_4MA,                                                    /*  4mA的输出驱动强度           */
                     GPIO_PIN_TYPE_STD);                                                /*  设置为推挽管脚              */

    GPIOIntTypeSet(GPIO_PORTA_BASE, KEY1, GPIO_RISING_EDGE);            /*  设置KEY1中断的触发方式为
                                                                                上升沿触发                  */
        GPIOIntTypeSet(GPIO_PORTB_BASE, KEY2, GPIO_RISING_EDGE);            /*  设置KEY2中断的触发方式为
                                                                                上升沿触发                  */
        GPIOIntTypeSet(GPIO_PORTC_BASE, KEY3, GPIO_RISING_EDGE);            /*  设置KEY3中断的触发方式为
                                                                                上升沿触发                  */

    IntMasterEnable();                                                  /*  使能总中断         */

    GPIOPinIntEnable(GPIO_PORTA_BASE, KEY1);                                        /*  使能KEY1中断                */
    GPIOPinIntEnable(GPIO_PORTB_BASE, KEY2);                                        /*  使能KEY2中断                */
    GPIOPinIntEnable(GPIO_PORTC_BASE, KEY3);                                        /*  使能KEY3中断                */       

    IntEnable(INT_GPIOA);                                               /*  使能GPIOA中断               */
    IntEnable(INT_GPIOB);                                               /*  使能GPIOB中断               */  
    IntEnable(INT_GPIOC);                                               /*  使能GPIOC中断               */       

    IntPrioritySet(INT_GPIOA, 2 << 6 | 0 << 5);                                /*  GPIOA组优先级为2,
                                                                                次优先级为0                 */
    IntPrioritySet(INT_GPIOB, 2 << 6 | 1 << 5);                         /*  GPIOB组优先级为2,
                                                                                次优先级为1                 */
    IntPrioritySet(INT_GPIOC, 1 << 6 | 1 << 5);                         /*  GPIOA组优先级为1,
                                                                                次优先级为1                 */

        IntPriorityGroupingSet(2);                                          /*  组优先级为4位,次优先级2位  */
                                                                                                   
    while (1) {
                GPIOPinWrite(GPIO_PORTB_BASE, LED3, ~GPIOPinRead(GPIO_PORTB_BASE, LED3));
                delay(200000);
        }
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/
 
 
 

回复

18

帖子

0

TA的资源

一粒金砂(中级)

5
 
程序中key1和key2应该实现末尾连锁功能,但是实际中key1中断却可以抢占key2的中断,这是为什么呀?
GPIOPinIntEnable(GPIO_PORTA_BASE, KEY1);                                        /*  使能KEY1中断                */
    GPIOPinIntEnable(GPIO_PORTB_BASE, KEY2);                                        /*  使能KEY2中断                */
    GPIOPinIntEnable(GPIO_PORTC_BASE, KEY3);                                        /*  使能KEY3中断                */       

    IntEnable(INT_GPIOA);                                               /*  使能GPIOA中断               */
    IntEnable(INT_GPIOB);                                               /*  使能GPIOB中断               */  
    IntEnable(INT_GPIOC);                                               /*  使能GPIOC中断               */       

    IntPrioritySet(INT_GPIOA, 2 << 6 | 0 << 5);                                /*  GPIOA组优先级为2,
                                                                                次优先级为0                 */
    IntPrioritySet(INT_GPIOB, 2 << 6 | 1 << 5);                         /*  GPIOB组优先级为2,
                                                                                次优先级为1                 */
    IntPrioritySet(INT_GPIOC, 1 << 6 | 1 << 5);                         /*  GPIOA组优先级为1,
                                                                                次优先级为1                 */

        IntPriorityGroupingSet(2);                                          /*  组优先级为4位
 
 
 

回复

1729

帖子

0

TA的资源

五彩晶圆(初级)

6
 

回复 板凳 yinliang21th 的帖子

是这样啊!谢谢指点。
 
 
 

回复

400

帖子

0

TA的资源

五彩晶圆(中级)

7
 

楼主的问题实际上是两个问题,

1. 尾链是什么用的?

2. M3的中断优先级机制?

3. 我先回答第一个问题

1) 在M3之前的MCU在处理中断时一般都采用如下的过程:

     中断1发生 -> 现场保护1 -> 中断1处理 -> 现场恢复

2) 如果在中断1发生之后,未处理结束之前,和中断1优先级相同的中断2也发生了,这个时候的处理过程如下:

     中断1发生 -> 现场保护1 -> 中断1处理 -> 现场恢复

          中断2发生.................................................................-> 现场保护2 -> 中断2处理 -> 现场恢复

    从上面的过程我们可以看出,实际上我们进行了2次同样的现场保护,即现场保护1和现场保护2, 也进行了2次同样的现场恢复。

    M3的内核对这个过程进行了优化,在中断1处理完后,并不急于恢复现场,而是判断是否由另外的中断2发生,如果有则不退出中断处理,而是直接进入中断2处理程序。

    处理流程如下:

     中断1发生 -> 现场保护1 -> 中断1处理 ->

          中断2发生...........................................中断2处理 -> 现场恢复

 

3) 总结一下,由上描述可知,尾链技术是为了简化两个相同优先级的中断的切换过程。

 注意: 这里讲的相同优先级是指两个中断不能互相打断,而不是绝对的相等。M3采用中断优先级编号和组号来管理中断的优先级。使用者需要了解这个机制才能正确的设置各个中断源的处理流程。

 

4. 关于第二个问题,请参见我对M3中断优先级的描述: https://bbs.eeworld.com.cn/viewthread.php?tid=301771&highlight=

[ 本帖最后由 Triton.zhang 于 2011-10-1 00:33 编辑 ]

赞赏

1

查看全部赞赏

 
 
 

回复

1803

帖子

0

TA的资源

五彩晶圆(高级)

8
 
1.
IntPriorityGroupingSet(2); /* 组优先级为4位

这个应该表示组优先级为 2 位
2.尾链连锁部分 Triton.Zhang 说的很清楚了。
3.可能楼主的疑问是:GPIOA 和 GPIOB 一个组,但是 A 的优先级比 B 要低,为什么 A 还会抢占 B 呢?这个和 Triton 之前的帖子里有点不一样。(楼主确定抢占了吗?)
这个问题请 Triton.Zhang 再详细解答一下。
[ 本帖最后由 Study_Stellaris 于 2011-10-1 12:11 编辑 ]
 
 
 

回复

18

帖子

0

TA的资源

一粒金砂(中级)

9
 
楼上理解有误,我是这个疑问。GPIOA 和 GPIOB 优先圾在同一个组,A 的次优先级比 B 要高,当处理b中断时,产生a中断,理论上应该是实现末尾连锁功能,但是实际上a中断却可以抢占了b中断,不知道为何原因?我是在lm3s811上调试的,单步运行正常,但是全速运行就出现这种怪现象。

[ 本帖最后由 uhhznb 于 2011-10-1 18:01 编辑 ]
 
 
 

回复

400

帖子

0

TA的资源

五彩晶圆(中级)

10
 
1.  按照理论,PA和PB在同一个优先组别,发生中断时谁先到就先处理谁,随后发生的中断是不能打断头一个中断的。
2. 简单的从程序上看,应该是没问题的,但也可能有隐含的BUG没注意看出来。
3. 楼主是如何判断同组优先级打断了头一个中断的。能详细描述下试验过程和现象么?
   按照我的理解,应该是先按下KEY1,LED4开始闪灯,未等闪到100次时,按下KEY2,LED5就开始闪灯了么?
 
 
 

回复

18

帖子

0

TA的资源

一粒金砂(中级)

11
 
因为key1的次优先级比key2高,我是先按key2,led5开始闪灯,未等到闪到100次,按下key1,led4就开始闪了。
 
 
 

回复

1803

帖子

0

TA的资源

五彩晶圆(高级)

12
 

回复 11楼 uhhznb 的帖子

对,是我说错了,是 Key1 所在 GPIO 的次优先级要比 Key2 所在 GPIO 的次优先级高,数值低的优先级高。
按照楼主设计的实验,应该是在 Key2 所在GPIO的中断完成后才能去执行 Key1 所在中断,也就是应该实现末尾连锁,不应该发生中断嵌套,但为什么此刻却偏偏发生了呢?
但现在却发生了抢占,这确实和理论不一样。这一点可见《Cortex-M3 权威指南第二版~英文原版》的 120 页。
还有一个比较困扰我的问题是,我记得默认优先级分组值是0,也就是复位后所有的优先级不存在分组的问题,而 Stellaris MCU 用三个位来表示优先级,也就是做多是 8 级嵌套。

[ 本帖最后由 Study_Stellaris 于 2011-10-1 23:52 编辑 ]
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表