打印
[ZLG-ARM]

提问:ARM在中断程序中该如何关中断?

[复制链接]
4281|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
linjing|  楼主 | 2007-3-28 17:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
想要在SWI中断中访问管脚,同时FIQ中断中也需要访问这几个管脚,所以想在SWI中断中把FIQ中断禁止,该怎么做比较好?似乎不用先调用关中断例程,返回时再调用开中断例程这么麻烦吧,不知道如下面这么做可不可行?

int swi(0) PortAccess( void ){
    __asm {
        MSR CPSR_c, Mode_SVC + F_IRQ + I_IRQ
    }
    ...  // 读写与FIQ有冲突的管脚
    // SWI中断返回时是不是会自动将SPSR恢复到SPSR中从而重新恢复中断?
}

另外,按照ARM的建议,修改CPSR时应该用读-修改-写的方式,可在Keil的启动代码中Starts.s中就是用的立即数修改CPSR的,这么做有没有问题.

相关帖子

沙发
computer00| | 2007-3-28 18:12 | 只看该作者

晕~~~那是因为才刚刚启动,所以没必要保留以前的状态信息

MSR CPSR, #(Mode_SVC + F_IRQ + I_IRQ)

好象这里的CPSR需要指定修改哪个区的吧,光这样好象编译通不过的~~~~~

使用特权

评论回复
板凳
linjing|  楼主 | 2007-3-29 12:08 | 只看该作者

见笑了,我刚接触ARM,指令不太熟悉



我的意思是不用读-修改-写的方式,而直接用立即数改写CPRS,SWI中断返回时候自动恢复原来的状态,不需要手动恢复,请问二楼,这样可不可行?

使用特权

评论回复
地板
computer00| | 2007-3-29 13:00 | 只看该作者

最好不要直接修改,可能会不小心修改了其它标志位

读回来,放到一个寄存器,然后再修改某一个位,保留其它位不变,再写回去,也不是很麻烦啊。


要不你就把你的FIQ改到IRQ里面,这样就不用担心被打断了~~~~~~~

使用特权

评论回复
5
linjing|  楼主 | 2007-3-29 17:48 | 只看该作者

回computer00 ,其实我这样做是由具体情况决定的

我说的SWI中断访问的管脚实际上是想要模拟8位的外部总线

我说的FIQ中断是定时器中断,是我系统中的唯一的中断源,所以想用FIQ可能会简单些,定时中断用于生成系统时基,以及按键定时扫描(按键扫描是通过前面说的模拟8位总线进行的)

既然是模拟总线,所以希望能快点最好还是尽量快点,其实如果不追求速度的话,我完全可以将模拟总线包写成普通函数,再写两个SWI中断通过修改SPRS开/关中断,可相对来说那样多出许多指令。(我不喜欢用太高的晶振或者PLL,不希望一味通过提高主频来提速,纯粹个人习惯:)

其实如果实际做的话我也考虑过把FIQ改成向量IRQ,但我还是能希望探讨一些细节,也希望藉此来尽快熟悉ARM的体系结构

如果按照computer00 的说法,我不用立即数,改成下面的样子,可以吗
int swi(0) PortAccess( void ){
    __asm {
        MRS R0, CPSR
        ORR R0, RO, #F_IRQ + I_IRQ
        MSR CPSR_c, R0
    }
    ...  // 模拟总线
    // SWI中断返回时是不是会自动将SPSR恢复到SPSR中从而重新恢复中断?
}

使用特权

评论回复
6
computer00| | 2007-3-29 18:34 | 只看该作者

这样应该可以的.

为什么模拟总线要通过SWI啊? 关中断不如直接关中断控制寄存器来得快吧.这样就不用SWI来搞.

使用特权

评论回复
7
linjing|  楼主 | 2007-3-29 22:02 | 只看该作者

楼上的意思是不必禁止FIQ位和IRQ位,而是直接关中断控制器

暂时还没看懂LPC2104的那个中断系统,不过这个办法似乎不错,如果可行的话倒象是更简单,受教了!

使用特权

评论回复
8
computer00| | 2007-3-30 10:28 | 只看该作者

参看我以前写过的代码:

如果你只有一个中断,并且以后不会再扩展的话,你可以直接使用

VICIntEnClr=0xFFFFFFFF;
VICIntEnable=xxx; 

来控制中断.







/**********************************************************************************************
功能:进入临界段。
入口参数:无。
返回:无。
备注:该函数使用的是将中断分配寄存器清0的方法来关中断。比起用软中断,运行速度要快。
      如果要开某个中断,则应该先调用一次该函数,然后再修改中断备份变量CopyOfVICIntEnable
      的值,而不能直接修改VICIntEnable的值。否则会出错。
**********************************************************************************************/
void OSEnterCritical(void)
{
 if(OSEnCrCount==0)   //如果前面未关中断
  {
   VICIntEnClr=0xFFFFFFFF;           //将VICIntEnable清除,禁止中断
  }
 OSEnCrCount++;  //进入临界段次数加1
}
//////////////////////////////////End of function//////////////////////////////////////////////


/**********************************************************************************************
功能:退出临界段
入口参数:无。
返回:无。
备注:无。
**********************************************************************************************/
void OSExitCritical(void)
{
 if(OSEnCrCount>=1)  //如果进入临界段的次数大于等于1次
  {
   OSEnCrCount--;    //则次数减1
   if(OSEnCrCount==0)  //如果减次数减到0,则要开中断
    {
     VICIntEnable=CopyOfVICIntEnable;  //打开所需要开的中断
    }
  }
}
//////////////////////////////////End of function//////////////////////////////////////////////

使用特权

评论回复
9
linjing|  楼主 | 2007-3-30 11:58 | 只看该作者

先收藏,再分析,谢谢computer00

使用特权

评论回复
10
zlgARM| | 2007-3-30 17:37 | 只看该作者

linjing

    圈圈的关中断方法也可以。
    如果把中断看成是水龙头,那么如果想要关掉屋子里的水龙头,可以有两个办法。
    其一:关总阀。所有水龙头都没法再用,修改CPSR来关中断的方法属于此类;
    其二:逐个地把所有或部分水龙头关掉,修改VICIntEnClr的方法属此类。
    

使用特权

评论回复
11
linjing|  楼主 | 2007-3-31 10:27 | 只看该作者

用惯了Keil C51,在51中都是用的#pragma disable

Keil C51的#pragma disable有一个很重要的特点,进入子程序的时候保存中断允许位EA的状态,退出子程序的时候不是简单的开中断,而是“恢复”原来的中断允许EA的状态,逻辑上完整

使用特权

评论回复
12
有意思| | 2007-3-31 14:42 | 只看该作者

这样可不可以

__inline void enable_IRQ(void)
{
    __asm
    {
        MRS r1, CPSR
        BIC r1, r1, #0x80
        MSR CPSR_c, r1
    }
}

__inline void disable_IRQ(void)
{
    __asm
    {
        MRS r1, CPSR
        ORR r1, r1, #0x80
        MSR CPSR_c, r1
    }
}

使用特权

评论回复
13
linjing|  楼主 | 2007-3-31 21:30 | 只看该作者

百步笑一下五十步:)

“有意思”,五十步了吧:)

你的办法是可以,但必须放到特权模式下才行,就是前面提到的在用户模式下为什么要用SWI进管态关中断的问题,只有进入管态才能用你的程序。

使用特权

评论回复
14
有意思| | 2007-3-31 22:16 | 只看该作者

那这样呢

Maskmd       EQU     0x1f              
SVC32md      EQU     0x13
I_Bit        EQU     0x80


FRAME_R0     EQU     0X00
FRAME_R1     EQU     FRAME_R0 + 4
FRAME_R2     EQU     FRAME_R1 + 4
FRAME_R3     EQU     FRAME_R2 + 4
FRAME_R4     EQU     FRAME_R3 + 4
FRAME_R5     EQU     FRAME_R4 + 4
FRAME_R6     EQU     FRAME_R5 + 4
FRAME_R7     EQU     FRAME_R6 + 4
FRAME_R8     EQU     FRAME_R7 + 4
FRAME_R9     EQU     FRAME_R8 + 4
FRAME_R10    EQU     FRAME_R9 + 4
FRAME_R11    EQU     FRAME_R10 + 4
FRAME_R12    EQU     FRAME_R11 + 4
FRAME_PSR    EQU     FRAME_12 + 4
FRAME_LR     EQU     FRAME_PSR + 4
FRAME_PC     EQU     FRAME_LR + 4
FRAME_SIZE   EQU     FRAME_PC + 4

IRQ_Entry
    SUB      r14,r14,#4
    STMDB    r13,!{r0-r3,r12,r14}
    <服务中断>
    BL       read_RescheduleFlag
    CMP      r0,#0
    LDMNEIA  r13!,{r0-r13,r12,PC}^
    MRS      r2,spsr
    MOV      r0,r13
    ADD      r13,r13,#6*4
    MRS      r1,cpsr
    BIC      r1,r1,#Maskmd
    ORR      r1,r1,SVC32md
    MSR      cpsr_c,r1
    SUB      r13,r13,#FRAME_SIZE-FRAME_R4
    STMIA    r13,{r4-r11}
    LDMIA    r0,{r4-r9}
    BIC      r1,r1,#I_Bit
    MSR      cpsr_c,r1
    STMDB    r13!,{r4-r7}
    STR      r2,[r13,#FRAME_PSR]
    STR      r8,[r13,#FRAME_R12]
    STR      r9,[r13,#FRAME_PC]
    STR      r14,[r13,#FRAME_LR]
    
    <完成中断服务程序>
    LDMIA    r13!,{r0-r12,r14}
    MSR      spsr_cxsf,r14
    LDMIA    r13!,{r14,pc}^

使用特权

评论回复
15
linjing|  楼主 | 2007-3-31 22:29 | 只看该作者

百步只好向五十步说抱歉:(

百步最近刚接触ARM,根本看不懂ARM的汇编指令:{

自从知道ARM是什么东东之后,说实话,我根本就没打算去抠ARM的汇编,你想啊,现在有谁Windows编程的时候还去管x86的汇编指令的,不过现在看来汇编指令还是要学点的,不过您帖的程序只好懂我能看懂的时候再回了。

抱歉抱歉,不过本帖已收藏,回头我会看的

使用特权

评论回复
16
有意思| | 2007-4-1 10:12 | 只看该作者

你以为是我写的啊,没那本事

书上抄地,建议你看本书
ARM 嵌入式系统开发 ----软件设计与优化
ARM System Devcloper`s Guide:Designing and Optimizing System Software
[美] Andrew N.Sloss
[英] Dominic Sysmes
[美] Chis Wright
 沈建华译
北航出的,75块
里面详细介绍了可重入中断处理等
相关链接:http://www.dushu.com/book/11183297/

使用特权

评论回复
17
linjing|  楼主 | 2007-4-1 17:13 | 只看该作者

问 computer00

我如果令VICProtection=1, 你前面的 进出临界段 的代码还能直接用吗。

一般VICProtection的保护功能需要用吗

使用特权

评论回复
18
hotpower| | 2007-4-1 18:58 | 只看该作者

VICProtection只对用户级有作用~~~

使用特权

评论回复
19
linjing|  楼主 | 2007-4-6 19:47 | 只看该作者

追问一下,系统中只有一个中断的时候,用FIQ与IRQ会有什么

好像FIQ还有几个专用的寄存器,这是已知的不同

我的疑问是在只有一个中断源的时候,用FIQ响应和用IRQ开销是不是都一样,包括影响中断的时间,堆栈的占用,等等,还有其他的方面吗??

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

327

帖子

0

粉丝