精华内容
下载资源
问答
  • 1.6. 异常中断处理 摘要 1.6.1. macros stmia /* ************************************************************************* * * Interrupt handling * *****************...

    1.6. 异常中断处理

    摘要

    1.6.1. macros stmia

    /*
     *************************************************************************
     *
     * Interrupt handling
     *
     *************************************************************************
     */
    
    @
    @ IRQ stack frame.
    @
    #define S_FRAME_SIZE	72
    
    #define S_OLD_R0	68
    #define S_PSR		64
    #define S_PC		60
    #define S_LR		56
    #define S_SP		52
    
    #define S_IP		48
    #define S_FP		44
    #define S_R10		40
    #define S_R9		36
    #define S_R8		32
    #define S_R7		28
    #define S_R6		24
    #define S_R5		20
    #define S_R4		16
    #define S_R3		12
    #define S_R2		8
    #define S_R1		4
    #define S_R0		0
    
    #define MODE_SVC 0x13
    #define I_BIT	 0x80
    
    /*
     * use bad_save_user_regs for abort/prefetch/undef/swi ...
     * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
     */
    	.macro	bad_save_user_regs
    
    	sub	sp, sp, #S_FRAME_SIZE
    	stmia	sp, {r0 - r12}			@ Calling r0-r12
    	ldr	r2, _armboot_start    
            

    1

    此处很简单,只是一些宏定义而已。

    后面用到的时候再解释。

    2

    .macro和后面的.endm相对应,其语法是:

    图 1.12. macro的语法

    macro的语法

    所以,此处就相当于一个无参数的宏bad_save_user_regs,也就相当于一个函数了。

    3

    sp

    = sp- S_FRAME_SIZE

    = sp - 72

    4

    stmia的语法为:

    图 1.13. LDM/STM的语法

    LDM/STM的语法

    其中,条件域的具体含义如下:

    图 1.14. 条件码的含义

    条件码的含义

    更具体的含义:

    六、批量数据加载/存储指令ARM微处理器所支持批量数据加载/存储指令可以一次在一片连续的存储器单元和多个寄存器之间传送数据,批量加载指令用于将一片连续的存储器中的数据传送到多个寄存器,批量数据存储指令则完成相反的操作。常用的加载存储指令如下:

    LDM(或STM)指令

    LDM(或STM)指令的格式为:

    LDM(或STM){条件}{类型} 基址寄存器{!},寄存器列表{∧}

    LDM(或STM)指令用于从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入栈或出栈。

    其中,{类型}为以下几种情况:

    IA 每次传送后地址加1;

    IB 每次传送前地址加1;

    DA 每次传送后地址减1;

    DB 每次传送前地址减1;

    FD 满递减堆栈;

    ED 空递减堆栈;

    FA 满递增堆栈;

    EA 空递增堆栈;

    {!}为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。

    基址寄存器不允许为R15,寄存器列表可以为R0~R15的任意组合。

    {∧}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。

    指令示例:

    STMFD R13!,{R0,R4-R12,LR} ;将寄存器列表中的寄存器(R0,R4到

    R12,LR)存入堆栈。

    LDMFD R13!,{R0,R4-R12,PC} ;将堆栈内容恢复到寄存器(R0,R4到

    R12,LR)。

    所以,此行的含义是,

    将r0到r12的值,一个个地传送到对应的地址上,基地址是sp的值,传完一个,sp的值加4,一直到传送完为止。

    此处,可见,前面那行代码:

    sp = sp - 72

    就是为此处传送r0到r12,共13个寄存器,地址空间需要13*4=72个字节,

    即前面sp减去72,就是为了腾出空间,留此处将r0到r12的值,放到对应的位置的。

    5

    此处的含义就是,将_armboot_start中的值,参考前面内容,即为_start,

    而_start的值:

    从 Nor Flash启动时:_stat=0

    relocate代码之后为:_start=TEXT_BASE=0x33D00000

    此处是已经relocate代码了,所以应该理解为后者,即_start=0x33D00000

    所以:

    r2=0x33D00000

    1.6.2. cal reg value and store

    	sub	r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
    	sub	r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
    	ldmia	r2, {r2 - r3}			@ get pc, cpsr
    	add	r0, sp, #S_FRAME_SIZE		@ restore sp_SVC
    	add	r5, sp, #S_SP
    	mov	r1, lr
    	stmia	r5, {r0 - r3}			@ save sp_SVC, lr_SVC, pc, cpsr
    	mov	r0, sp
    	.endm
            

    1

    此处:

    r2

    = r2 - ( CONFIG_STACKSIZE+CFG_MALLOC_LEN)

    = r2 – (128*1024 + 256*1024)

    = 0x33D00000 - 384KB

    = 0x33CA0000

    2

    此处:

    r2

    = r2 - (CFG_GBL_DATA_SIZE + 8)

    = 0x33CA0000 – (128 + 8)

    = 0x33C9FF78

    3

    分别将地址为r2和r2+4的内容,即地址为0x33C9FF780x33C9FF7C中的内容,load载入给r2和r3寄存器。

    4

    将sp的值,加上72,送给r0

    5

    前面的定义是:

    #define S_SP		52

    所以此处就是将sp的值,加上52,送给r5

    6

    将lr给r1

    7

    然后将r0到r3中的内容,存储到地址为r5-r5+12中的位置去。

    8

    将sp再赋值给r0

    9

    结束宏bad_save_user_regs

    此处虽然每行代码基本看懂了,但是到底此bad_save_user_regs函数是做什么的,还是不太清楚,有待以后慢慢深入理解。

    1.6.3. irq_save_user_regs irq_restore_user_regs

    	.macro	irq_save_user_regs
    	sub	sp, sp, #S_FRAME_SIZE
    	stmia	sp, {r0 - r12}			@ Calling r0-r12
    	add     r8, sp, #S_PC
    	stmdb   r8, {sp, lr}^                   @ Calling SP, LR
    	str     lr, [r8, #0]                    @ Save calling PC
    	mrs     r6, spsr
    	str     r6, [r8, #4]                    @ Save CPSR
    	str     r0, [r8, #8]                    @ Save OLD_R0
    	mov	r0, sp
    	.endm
    
    	.macro	irq_restore_user_regs
    	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
    	mov	r0, r0
    	ldr	lr, [sp, #S_PC]			@ Get PC
    	add	sp, sp, #S_FRAME_SIZE
    	subs	pc, lr, #4			@ return & move spsr_svc into cpsr
    	.endm
    
    	.macro get_bad_stack
    	ldr	r13, _armboot_start		@ setup our mode stack
    	sub	r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
    	sub	r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
    	str	lr, [r13]			@ save caller lr / spsr
    	mrs	lr, spsr
    	str     lr, [r13, #4] 
    	mov	r13, #MODE_SVC			@ prepare SVC-Mode
    	@ msr	spsr_c, r13
    	msr	spsr, r13
    	mov	lr, pc
    	movs	pc, lr
    	.endm
    
    	.macro get_irq_stack			@ setup IRQ stack
    	ldr	sp, IRQ_STACK_START
    	.endm
    
    	.macro get_fiq_stack			@ setup FIQ stack
    	ldr	sp, FIQ_STACK_START
    	.endm
    
            

    1

    上面两段代码,基本上和前面很类似,虽然每一行都容易懂,但是整个两个函数的意思,除了看其宏的名字irq_save_user_regs和irq_restore_user_regs,分别对应着中断中,保存和恢复用户模式寄存器,之外,其他的,个人目前还是没有太多了解。

    2

    此处的get_bad_stack被后面undefined_instruction,software_interrupt等处调用,目前能理解的意思是,在出错的时候,获得对应的堆栈的值。

    3

    此处的含义很好理解,就是把地址为IRQ_STACK_START中的值赋值给sp。

    即获得IRQ的堆栈的起始地址。

    而对于IRQ_STACK_START,是前面就提到过的cpu_init源码

    而此处,就是用到了,前面已经在cpu_init()中重新计算正确的值了。

    即算出IRQ堆栈的起始地址,其算法很简单,就是:

    	IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;

    即,先减去malloc预留的空间,和global data,即在

    u-boot-1.1.6_20100601\opt\EmbedSky\u-boot-1.1.6\board\EmbedSky\board.c

    中定义的全局变量:

    DECLARE_GLOBAL_DATA_PTR;

    而此宏对应的值在:

    u-boot-1.1.6_20100601\opt\EmbedSky\u-boot-1.1.6\include\asm-arm\global_data.h

    中:

    #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

    即,用一个固定的寄存器r8来存放此结构体的指针。

    [提示] 提示

    这也对应着编译uboot的时候,你所看到的编译参数-ffixed-r8

    此gd_t的结构体,不同体系结构,用的不一样。

    而此处arm的平台中,gd_t的定义在同一文件中:

    typedef	struct	global_data {
    	bd_t		*bd;
    	unsigned long	flags;
    	unsigned long	baudrate;
    	unsigned long	have_console;	/* serial_init() was called */
    	unsigned long	reloc_off;	/* Relocation Offset */
    	unsigned long	env_addr;	/* Address  of Environment struct */
    	unsigned long	env_valid;	/* Checksum of Environment valid? */
    	unsigned long	fb_base;	/* base address of frame buffer */
    #ifdef CONFIG_VFD
    	unsigned char	vfd_type;	/* display type */
    #endif
    #if 0
    	unsigned long	cpu_clk;	/* CPU clock in Hz!		*/
    	unsigned long	bus_clk;
    	unsigned long	ram_size;	/* RAM size */
    	unsigned long	reset_status;	/* reset status register at boot */
    #endif
    	void		**jt;		/* jump table */
    } gd_t;
                    

    而此全局变量gd_t *gd会被其他很多文件所引用,详情自己去代码中找。

    4

    此处和上面类似,把地址为FIQ_STACK_START中的内容,给sp。

    其中:

    	FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;

    即FIQ的堆栈起始地址,是IRQ堆栈起始地址减去IRQ堆栈的大小。

    1.6.4. exception handlers

    /*
     * exception handlers
     */
    	.align  5
    undefined_instruction:
    	get_bad_stack
    	bad_save_user_regs
    	bl 	do_undefined_instruction
    	.align	5
        
    
    software_interrupt:
    	get_bad_stack
    	bad_save_user_regs
    	bl 	do_software_interrupt
    
    	.align	5
    prefetch_abort:
    	get_bad_stack
    	bad_save_user_regs
    	bl 	do_prefetch_abort
    
    	.align	5
    data_abort:
    	get_bad_stack
    	bad_save_user_regs
    	bl 	do_data_abort
    
    	.align	5
    not_used:
    	get_bad_stack
    	bad_save_user_regs
    	bl 	do_not_used
    
            

    1

    如果发生未定义指令异常,CPU会掉转到start.S开头中对应的位置:

    	ldr	pc, _undefined_instruction

    即把地址为_undefined_instruction中的内容给pc,即跳转到此处执行对应的代码。

    其做的事情依次是:

    获得出错时候的堆栈

    保存用户模式寄存器

    跳转到对应的函数:do_undefined_instruction

    而do_undefined_instruction函数是在:

    u-boot-1.1.6_20100601\opt\EmbedSky\u-boot-1.1.6\cpu\arm920t\interrupts.c

    中:

    void bad_mode (void)
    {
    	panic ("Resetting CPU ...\n");
    	reset_cpu (0);
    }
    
    void do_undefined_instruction (struct pt_regs *pt_regs)
    {
    	printf ("undefined instruction\n");
    	show_regs (pt_regs);
    	bad_mode ();
    }
                    

    可以看到,此处起始啥事没错,只是打印一下出错时候的寄存器的值,然后跳转到bad_mode中取reset CPU,直接重启系统了。

    2

    以上几个宏,和前面的do_undefined_instruction是类似的,就不多说了。

    1.6.5. Launch

    @ HJ
    .globl Launch
        .align	4
    Launch:    
        mov r7, r0
        @ diable interrupt
    	@ disable watch dog timer
    	mov	r1, #0x53000000
    	mov	r2, #0x0
    	str	r2, [r1]
    
        ldr r1,=INTMSK
        ldr r2,=0xffffffff  @ all interrupt disable
        str r2,[r1]
    
        ldr r1,=INTSUBMSK
        ldr r2,=0x7ff       @ all sub interrupt disable
        str r2,[r1]
    
        ldr     r1, = INTMOD
        mov r2, #0x0        @ set all interrupt as IRQ (not FIQ)
        str     r2, [r1]
    
        @ 
    	mov	ip, #0
    	mcr	p15, 0, ip, c13, c0, 0      @	/* zero PID */
    	mcr	p15, 0, ip, c7, c7, 0       @	/* invalidate I,D caches */
    	mcr	p15, 0, ip, c7, c10, 4      @	/* drain write buffer */
    	mcr	p15, 0, ip, c8, c7, 0       @	/* invalidate I,D TLBs */
    	mrc	p15, 0, ip, c1, c0, 0       @	/* get control register */
    	bic	ip, ip, #0x0001             @	/* disable MMU */
    	mcr	p15, 0, ip, c1, c0, 0       @	/* write control register */
    
        @ MMU_EnableICache
        @mrc p15,0,r1,c1,c0,0
        @orr r1,r1,#(1<<12)
        @mcr p15,0,r1,c1,c0,0
    
    #ifdef CONFIG_SURPORT_WINCE
        bl Wince_Port_Init
    #endif
    
        @ clear SDRAM: the end of free mem(has wince on it now) to the end of SDRAM
        ldr     r3, FREE_RAM_END
        ldr     r4, =PHYS_SDRAM_1+PHYS_SDRAM_1_SIZE    @ must clear all the memory unused to zero
        mov     r5, #0
    
        ldr     r1, _armboot_start
        ldr     r2, =On_Steppingstone
        sub     r2, r2, r1
        mov     pc, r2
    On_Steppingstone:
    2:  stmia   r3!, {r5}
        cmp     r3, r4
        bne     2b
    
        @ set sp = 0 on sys mode
        mov sp, #0
    
        @ add by HJ, switch to SVC mode
    	msr	cpsr_c,	#0xdf	@ set the I-bit = 1, diable the IRQ interrupt
    	msr	cpsr_c,	#0xd3	@ set the I-bit = 1, diable the IRQ interrupt
        ldr sp, =0x31ff5800	
        
        nop
    	nop
        nop
    	nop
    
    	mov     pc, r7  @ Jump to PhysicalAddress
    	nop
        mov pc, lr
            

    1

    此处相当于一个叫做Launch的函数,做了也是类似的系统初始化的动作。

    但是没找到此函数在哪里被调用的。具体不太清楚。

    1.6.6. int_return

    
    #ifdef CONFIG_USE_IRQ
    	.align	5
    irq:
    /* add by www.embedsky.net to use IRQ for USB and DMA */
    	sub	lr, lr, #4			        @ the return address
    	ldr	sp, IRQ_STACK_START	        @ the stack for irq
    	stmdb	sp!, 	{ r0-r12,lr }	@ save registers
    	
    	ldr	lr,	=int_return		        @ set the return addr
    	ldr	pc, =IRQ_Handle		        @ call the isr
    int_return:
    	ldmia	sp!, 	{ r0-r12,pc }^	@ return from interrupt
    	.align	5
    fiq:
    	get_fiq_stack
    	/* someone ought to write a more effiction fiq_save_user_regs */
    	irq_save_user_regs
    	bl 	do_fiq
    	irq_restore_user_regs
    #else
    
    	.align	5
    irq:
    	get_bad_stack
    	bad_save_user_regs
    	bl 	do_irq
    
    	.align	5
    fiq:
    	get_bad_stack
    	bad_save_user_regs
    	bl 	do_fiq
    
    #endif
            

    1

    此处,做的事情,很容易看懂,就是中断发生后,掉转到这里,然后保存对应寄存器,然后跳转到对应irq函数IRQ_Handle中去。

    但是前面为何sp为何去减去4,原因不太懂。

    2

    关于IRQ_Handle,是在:

    u-boot-1.1.6_20100601\opt\EmbedSky\u-boot-1.1.6\cpu\arm920t\s3c24x0\interrupts.c

    中:

    void IRQ_Handle(void)
    {
    	unsigned long oft = intregs->INTOFFSET;
    	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
    
    //	printk("IRQ_Handle: %d\n", oft);
    
    	//清中断
    	if( oft == 4 ) gpio->EINTPEND = 1<<7;	
    	intregs->SRCPND = 1<<oft;
    	intregs->INTPND	= intregs->INTPND;
    
    	/* run the isr */
    	isr_handle_array[oft]();
    }
                    

    此处细节就不多解释了,大体含义是,找到对应的中断源,然后调用对应的之前已经注册的中断服务函数ISR。

    3

    此处也很简单,就是发生了快速中断FIQ的时候,保存IRQ的用户模式寄存器,然后调用函数do_fiq,调用完毕后,再恢复IRQ的用户模式寄存器。

    4

    do_fiq()是在:

    u-boot-1.1.6_20100601\opt\EmbedSky\u-boot-1.1.6\cpu\arm920t\interrupts.c

    中:

    void do_fiq (struct pt_regs *pt_regs)
    {
    	printf ("fast interrupt request\n");
    	show_regs (pt_regs);
    	bad_mode ();
    }
                    

    和前面提到过的do_undefined_instruction的一样,就是打印寄存器信息,然后跳转到bad_mode()去重启CPU而已。

    5

    此处就是,如果没有定义CONFIG_USE_IRQ,那么就用这段代码,可以看到,都只是直接调用do_irq和do_fiq,也没做什么实际工作。


    原文链接 http://www.crifan.com/files/doc/docbook/uboot_starts_analysis/release/htmls/ch01s6_handle_exception.html
    展开全文
  • 大家都知道51单片机有的寄存器R0-R7共有四组。很多朋友对寄存器组的使用时经常出现问题。虽然这并不是多难的问题,但如果出现错误,也会造成很严重的后果。
  • 外部中断使用指南(寄存器设置)

    千次阅读 2016-09-11 21:51:01
    实验板子:tiny210(芯片:s5pv210) ...实验目的:通过外部中断操作两个按键实现对LED灯亮灭控制 步骤:①初始化GPIO端口,使GPIO为外部中断状态;(寄存器:GPxxCON)  例:    ②配置

    http://www.bubuko.com/infodetail-694078.html


    实验板子:tiny210(芯片:s5pv210)

    实验目的:通过外部中断操作两个按键实现对LED灯的亮灭控制

    步骤:①初始化GPIO端口,使GPIO为外部中断状态;(寄存器:GPxxCON)

                 例:

                    技术分享

       ②配置外部中断触发模式,上升沿触发,下降沿触发,双边触发,高电平触发,低电平触发(寄存器:EXT_INT_x_CON)

                例:

                    技术分享

             ③取消屏蔽外部中断(寄存器:EXT_INT_x_MASK)

                 例:

                    技术分享

             ④通过向量中断控制器(VIC)使能中断(寄存器:VIC0INTENABLE,VIC1INTENABLE,VIC2INTENABLE,VIC3INTENABLE)(注:几乎每一个中断都有其对应的VIC)

             技术分享

             VICINTENABLE寄存器分别包括VIC0,IVC1,VIC2,VIC3四个,每一个中断控制器有32位,每一位对应一个中断源(假如你要使能外部中断1,那么首先要先找到外部中断1对应哪一个中断控制器,然后找到这个中断控制器的相应位为设置)

            ⑤设置中断程序入口(寄存器:VICxVECTADDRx)

               例:*(VICxVECTADDRx) = 函数名(函数名就是一个地址)

    技术分享

           ⑥开总中断         

    1 __asm__( 2 /*开中断*/ 3 "mrs r0,cpsr\n" 4 "bic r0, r0, #0x80\n" 5 "msr cpsr_c, r0\n" 6  : 7  : 8 );

           ⑦编写中断处理程序(清除中断寄存器:EXT_INT_x_PEND)

     

     1 void 函数名()  2  {  3 //1. 保存环境  4  5 //2. 中断处理  6  7 //3. 清除中断  8 *(EXT_INT_x_PEND) = ~0x0;//写1清除中断标志   9 *(VICxADDRESS) = 0; 10 //4. 恢复环境  11 }

     

    中断编写思维导图(仅供参考流程思路):

    技术分享

     

    总结:由中断编写思维导图应该有的思路是:1. 对相应GPIO以及中断源的初始化

                                                            2. 当中断发生,中断源对应的PEND寄存器会被置1,所以在中断处理程序里应该清除中断标志(注:写1清除中断)

                                                            3. 当中断发生,如果MASK寄存器没有取消屏蔽,则中断不被允许,所以在编写中断程序时应首先取消相应中断的屏蔽

                                                            4. 别忘了VIC的初始化,包括用VICINTENABLE对相应中断进行使能,用VICVECTADDR寄存器设置中断处理程序入口

     s3c2440示例代码(仅供参考思路步骤,与s5pv210不对应)

     1 void key_init()  2 {  3 rGPGCON &= ~(0x3 << 0); //设置GPGO—EINT[8]   4 rGPGCON |= (0x2 << 0); //设置GPGO—EINT[8]   5 rEXTINT1 &= ~(0xf << 0); //触发方式为低电平有效   6 rEINTPEND |= (1 << 8); //清中断   7 rEINTMASK &= ~(1 << 8); //允许外部中断  8 pISR_EINT8_23 = (U32)Key_handler; //中断服务程序  9 EnableIrq(BIT_EINT8_23); //允许中断(INTMSK) 10 } 11 12 static void __irq key_handler() 13 { 14 if (rINTPND == BIT_EINT8_23) //INTPND同时只能有一位为1 15 ClearPending(BIT_EINT8_23); //清SRCPND、INTPND          #define BIT_EINT8_23 (0x1 << 5) 16 if (rEINTPEND & (1 << 8)) //清外部中断EINTPEND 17 rEINTPEND |= 1 << 8; 18  ............ 19 }

     

    其他外部中断编程参考资料:

    1.中断源的相关寄存器:

             当需要开启中断时,则需要对中断源进行相应的配置,这里主要记录常用的外部中断的配置。外部中断的配置主要是对引脚的配置,涉及的寄存器主要分为两组。

             一组是EINT0~16,涉及的寄存器主要是EXT_INT_x_CON,EXT_INT_xMASK,EXT_INT_PEND。EXT_INT_x_CON是外部中断的的配置寄存器,主要配置中断的触发方式;EXT_INT_xMASK是外部中断的屏蔽寄存器,配置引脚的中断是否屏蔽;EXT_INT_PEND是外部中断的中断未决寄存器,中断结束时必须清楚相应位,否则会持续引发中断。

             另一组的则是其余的GPIO的中断,他们复用一个中断线路,涉及的寄存器主要是GPxx_INT_CON,GPxx_INT_MASK,GPxx_INT_PEND。各寄存器功能跟第一组的类似。

     

    2.中断控制器的相关寄存器:

           VICxINTSELECT——中断类型选择寄存器,通过此寄存器选择是IRQ还是FIQ。

           VICxINTENABLE——中断使能寄存器,通过此寄存器使能相应的中断线路。

           VICxINTENCLEAR——中断使能清除寄存器(即失能),在控制器禁止某路中断在该寄存器设置。

           VICxIRQSTATUS——普通中断请求状态寄存器,记录了经VICxINTENABLE和VICxINTSELECT过滤后的IRQ中断请求状态。

           VICxFIQSTATUS——普通中断请求状态寄存器,记录了经VICxINTENABLE和VICxINTSELECT过滤后的FIQ中断请求状态。

           VICxRAMINTR——原始中断请求寄存器,记录了未经VICxINTENABLE和VICxINTSELECT过滤后的中断请求状态。

           VICxSOFINT——软件中断寄存器,通过该寄存器可使控制器产生相应线路的中断信号,该信号未经过优先级,VICxINTENABLE和VICxINTSELECT等寄存器的过滤。

           VICxSOFINTCLEAR——软中断清除寄存器,在ISR(中断服务程序)结束时要清除该寄存器相应位来清除中断,否则该中断会持续触发。

            VICxVECTADDRx——向量地址寄存器,该寄存器保存的是相应线路的ISR的地址。

            VICxVECTPRIORITYx——保存相应相应线路的优先级,有16个优先级,0的优先级最高,当多个相同优先级的线路同时请求中断时,按硬件优先级排序,同一组中断,中断好越低优先级越高,如VIC0中,EINT0优先级;如正在执行某ISR时,又一同软件优先级的但硬件优先级高的线路请求中断,此时该中断被屏蔽,要当前ISR执行完毕才可受理。

            VICxSWPRIORITYMASK——软件优先级屏蔽,可设置屏蔽相应的优先级,屏蔽后则相应优先级的中断被屏蔽。

            VICxADDRESS——保存当前活跃的中断线路的ISR地址,读取一次该寄存器意味着当前活跃的中断请求已被标志为已服务,此操作只能在进入中断处理时执行;向该寄存器写如任意值表示清楚控制器中该路中断状态,此操作只能在ISR结尾处执行。

            VICxPROTECTION——控制器保护模式配置寄存器,配置为保护模式时,中断控制器的寄存器只能在特权模式下被访问;非保护模式时,用户模式和特权模式都可以访问中断控制器的寄存器。VICxPROTECTION只能在特权模式下访问。

     

    3.处理器内核配置主要是配置CPSR寄存器,配置相应中断控制位为允许中断。

    展开全文
  • DEBUG提供单步中断的中断处理程序,显示所有寄存器的内容后等待输入命令 使用-T命令,debug将TF标志设为1,使CPU工作在单步中断的方式下 自定义单步中断处理程序,实现特殊功能 单步中断的处理与过程 TF陷阱...

    debug利用CPU提供的单步中断功能

    • 程序的正常执行
    1. 取指令
    2. 改变CS:IP
    3. 执行指令
    4. 取指令
    • DEBUG提供单步中断的中断处理程序,显示所有寄存器的内容后等待输入命令

    使用-T命令,debug将TF标志设为1,使CPU工作在单步中断的方式下

    • 自定义单步中断处理程序,实现特殊功能

    单步中断的处理与过程

      • TF陷阱标志(trap flag):用于调试的单步方式操作
      • TF = 1时每条指令执行后产生陷阱,由系统控制计算机
      • TF = 0时CPU正常工作
      • IF中断标志(interrupt flag)
      • IF = 1允许CPU响应可屏蔽中断请求
      • IF = 0关闭中断
    • CPU在执行完一条指令后,如果检测到标志寄存器的TF位为1,则产生单步中断(中断类型码为1),引发中断过程,执行中断处理程序
    1. 取得标志类型码1
    2. 标志寄存器入栈TF和IF设置0

    设置TF = 0很重要,否则不停产生单步中断不断循环,TF置为0不允许单步中断了

    1. CS和IP入栈
    2. (IP) = (1 * 4) (CS) = (1 * 4 + 2)

    • 中断不响应的情况
    • 执行向SS寄存器发送数据,即使产生中断,CPU不响应
    • SS和SP同步完成
      在这里插入图片描述

    SS和SP联合指向栈顶,设置要同时完成

    • 强行插入指令把ss和sp割裂开,自动执行了下一条指令
      在这里插入图片描述
    展开全文
  • 参考: Cortex M3权威指南(中文).pdf STM32F4xx中文参考手册.pdf STM32F4开发指南-寄存器版本_V1.1.pdf ...首先stm32的中断有240个,中断优先级分两级抢占和响应。两种级别,规则如下,需要记住 高...

    参考:

    Cortex M3权威指南(中文).pdf

    STM32F4xx中文参考手册.pdf

    STM32F4开发指南-寄存器版本_V1.1.pdf

    https://blog.csdn.net/rng_uzi_/article/details/90762767

    记住:抢占和响应的值越小级别越高。

    首先stm32的中断有240个,中断优先级分两级抢占和响应。两种级别,规则如下,需要记住

    高抢占可以打断低抢占

    高响应不能打断低响应(同一抢占级,处理内部的优先级)

    中断7:抢占:2响应:0

    中断3:抢占:2响应:1

    同抢占级别,同时发生中断,响应级别的高先执行,(不是打断)

    中断6:抢占:3:响应0

    上面例子中的中断 3 和中断 7 都可以打断中断 6 的中断。而中断 7 和中断 3 却不可以相互
    打断!

     

    设置抢占和响应级别

     

     SCB->AIRCR 寄存器和IP寄存器

    首先两者联系,SCB->AIRCR 寄存器的10:8位bit,决定了,IP寄存器4:7bit的高四位的抢占与响应位的分配

    读一读关于IP寄存器的描述,子优先级就是响应优先级

     

    那么SCB->AIRCR 寄存器的10:8位bit怎么决定这个分配呢?

    AIRCR 寄存器的10:8位,设置几位抢占,几位响应。举例如下

    AIRCR寄存器8:10与IP寄存器4:7
      AIRCR寄存器8:10 IP寄存器4:7  
    0 111 抢占:0bit,响应:4bit  
    1 110 抢占:1bit,响应:3bit  
    2 101 抢占:2bit,响应:2bit  
    3 100 抢占:3bit,响应:1bit  
    4 011 抢占:4bit,响应:0bit  

     怎么理解这个表呢?

    AIRCR寄存器8:10是111,表示7,即ip寄存器的第四位到第七位为止是响应级(从0开始),本来就ip寄存器的4:7bit,那4,5,6,7bit,都表示响应级。

    AIRCR寄存器8:10是100,表示4,ip寄存器的第四位到第四位表示响应级。即一位表示响应级

    实例代码  0x05FA0000 看上面图片表D13

     

      SCB->AIRCR = 0x05FA0000 | 0x400;  //  04h=0100b  中断优先级分组 抢占:响应=3:1

     

    那么最多就是0:15级抢占,就是15个中断可相互打断,即011,没有响应级  ,4组

    如果全是响应,那么哪个高,那个先发生,先执行哪个。即111,第七位以内都是响应级,4:7bit都表示,0组

    举例:这是正点原子外部中断实验的优先级设置代码,两位的优先级,4,5,即101,第五位以内都是响应级

    	MY_NVIC_Init(3,2,EXTI2_IRQn,2);		//抢占3,子优先级2,组2
    	MY_NVIC_Init(2,2,EXTI3_IRQn,2);		//抢占2,子优先级2,组2	   
    	MY_NVIC_Init(1,2,EXTI4_IRQn,2);		//抢占1,子优先级2,组2	   
    	MY_NVIC_Init(0,2,EXTI0_IRQn,2);		//抢占0,子优先级2,组2	

    这里设置为组2,即:AIRCR寄存器的8:10bit,101。则IP寄存器4:7bit,第6,7bit为设置抢占优先级,4,5bit设置响应优先级

    那么就是,4级抢断,4种响应。所以所有中断的级别都没有超过2^2=4。只有0,1,2,3级。

     

    应用:

      SCB->AIRCR = 0x05FA0000 | 0x400;  //中断优先级分组 抢占:响应=3:1

    8,9,10bit,为100,ip寄存器高四位的4位是响应,5,6,7位是抢占

    ip寄存器,8bit寄存器,只用了高四位,111抢占,1响应。

    2^3=8级抢断,2级响应
        
      NVIC->IP[39] = 0xf0; //最低抢占优先级,最低响应优先级1111

    39号中断,最高级中断,没有中断的能打断。

    参考手册表49,查相应中断的位置。


     NVIC->ISER[1] |= (1<<(39-32)); //使能中断线39,也就是usart3中断

    256个中断,每个ISER,32位寄存器,控制32个中断。需要8个ISER,即ISER[8]寄存器组。

    39号中断,在ISER[1],32,33,34,335,36,37,38,39。第七位置一

    39-32=7

     

     

     

     

     

     

    展开全文
  • 有关中断的相关寄存器 PICTL(Port input communication trigger level)——端口输入信号 P1IFG (Port 1 interrupt flag group)——P1端口状态标志寄存器 P1IEN (Port 1 interrupt enable)——P1端口中断使能 IEN0...
  • ARM中断嵌套寄存器NVIC使用说明

    千次阅读 2016-11-03 16:07:03
    在ARM9系列中,针对某种具体芯片如stm23f103zet6,...在ARM9中,中断与内核紧密联系,要实现某一外设的中断功能就必须对内部控制系统(NVIC)进行设定。  转自:秦工博客http://www.arm32.com/post/304.html  1)
  • 大家晚上好,我分享内容大体是先介绍中断,各寄存器使用(可能这里有点啰嗦),然后就简单写一下定时器,然后PWM原理,以及它配置和使用。大概今晚就这样了,如果有什么错,或有什么疑问,请大家马上提出来,...
  • 在很多应用中需要暂时屏蔽所有的中断进行一些对时序要求较高任务,不然容易发生bug,例如I2C通讯。此时可以使用PRIMASK寄存器。PRIMASK可以屏蔽除NMI和HardFalut外所有异常和中断。修改PRIMASK寄存器的方法有...
  • 如果某些代码段不允许被中断打断,那么这段代码就必须用关中断的方式给保护起来,在UCOS中可以看到,一般保护方式有3种: (1)关闭中断(总中断或者指定几个中断),执行临界段,开启中断(总中断或者指定几个...
  • 使用key_init()就能得到按键按下值,所以中断函数在key)_init里 key_init()分析 初始化io口对应按键 使能io口 使能RCC寄存器里 AHB1 外设时钟使能寄存器 (RCC_AHB1ENR) 使能io口时钟 设置连接高电压按键 ...
  • 喜欢用寄存器的方式来敲代码, 很爽的感觉;...为了方便查阅, 工作过程中顺便把各个外设的寄存器整理成表格了; 分享给也喜欢使用寄存器操作的朋友! 你可以下载整个表格的完整包喔,我会不断完善的 : ...
  • 题目:有关TI DSP一些东西(整理一些网络资源及手册资料)--外设寄存器和CPU控制寄存器、数据类型、中断的使用 原文:http://blog.csdn.net/jbb0523/article/details/7799919 ===========================...
  • STM32 F429 USART发送寄存器原理及TXE,TC中断的使用 先来看USART 字符发送的基本步骤 :...5.波特率寄存器USART_BRR选择使用的波特率 6.将CR1的 TE 位置 1,首次发送前发送一个空闲帧。 7.向DR寄存器写入数据。(会清零
  • 基础知识一、单片机下C语法的使用技巧(1)位操作(2)define 宏定义(3)ifdef 条件编译(4)extern 引用外部变量申明(5)typedef 类型别名(6)结构体 struct二、STM32F407总线架构三、STM32F407时钟系统(1) ...
  • 在 ISR 中调用其它函数,必须和中断使用相同的寄存器组。当没用 NOAREGS 命令做明确的声明,编译器将使用绝对寄存器寻址方式访问函数选定(即用 using 或 REGISTERBANK 指定)的寄存器组,当函数假定的和实际所选...
  • 介绍RTX51_TINY: 在偶然情况下看到了有人在51上运用一款实时操作系统...首先要使用这个操作系统需要做一些前期准备:keil4 C51,一块51开发板。在keil C51上需要做些配置,在魔术棒中Target中operating System中设置
  • 但是,最开始想当然的使用HAL库中HAL_UART_Receive_IT() 和HAL_UART_Receive(),调用函数发现怎么也不对,总是有bug。网上查了一堆,博客很多,解决不了我问题啊,按照他们方法我还是不能接收到数据。 后来...
  • 问题背景 项目使用STM32F030,需要通过IAP进行固件升级,在FLASH里面要烧录两份代码:一个Boot loader,一个用户应用...但在STM32F0xx系列以Cortex-M0为内核的单片机中却怎么也找不到这个设置中断向量表的寄存器,用
  •  STM8L 系列单片机是 ST公司推出的低功耗单片机,与STM8S系列相比功耗降低了很多,但内部结构也...在外部中断中这一点很不同, STM8S自动清除外部中断,而STM8L是需要软件清除, 清除标志位的寄存器根据设置而不同...
  • 一:寄存器的使用:1、wince内部对物理地址访问:可以有3个途径。1:直接使用g_oalAddressTable(oemaddrtab_cfg.inc)已经定义好,物理地址对应虚拟地址。如:DCD 0x80000000, 0x30000000, 128 ;访问虚拟...
  • 题目:有关TI DSP一些东西(整理一些网络资源及手册资料)--外设寄存器和CPU控制寄存器、数据类型、中断的使用 =================================================================== IER 和 IFR 你知道如何去...
  • 内部寄存器的值 Uint16 ior ( Uint16 IOADDR ){ DELAY_US ( 20 ); * ADDR_POINT = IOADDR ; DELAY_US ( 20 ); return (* DATA_POINT ); } //-------------------------------------------------------------------...
  • 一般串口发送函数由于等待UDR里数据被发送出去会耗费太多时间去等待,使用UDR空中断减少CPU等待UDR里数据被发送时间。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,820
精华内容 1,128
关键字:

中断使用的寄存器