ARM处理器基础知识ing


1 ARM处理器模式


  ARM处理器共有7种工作模式:用户模式系统模式外部中断模式快速中断模式管理模式数据访问中止模式未定义指令中止模式

  除了用户模式以外,后6种处理器模式可以称为特权模式;除了用户模式和系统模式,后5种称为异常处理模式

处理器工作模式

特权模式

异常模式

说明

用户模式(User, usr)

 ---

---

正常程序执行的模式

系统模式(System, sys)

特权模式

可访问任意系统资源

---

用于运行特权级的操作系统任务

管理模式(Supervisor, sve)

异常模式

通常由系统异常状态切换进来

供操作系统使用的一种保护模式

外部中断模式(IRQ, irq)

用户通常的中断使用

快速中断模式(FIQ, fiq)

用于高速数据传输和通道处理

数据访问中止模式(Abort, abt)

用于虚拟存储及存储保护

未定义指令中止模式(Undefin- ed, und)

用于支持通过软件仿真硬件的协处理器


1.1 ARM工作模式



  (1)用户模式:用户程序的工作模式,运行在操作系统的用户态,没有权限操作其它硬件资源,只能执行处理自己的数据,也不能直接切换到其它模式,要想访问硬件资源或切换到其它模式,只能通过软中断或产生异常。在Linux操作系统中,用户空间进程就是在这种模式下运行;


  (2) 系统模式:特权模式,和用户模式共用一套寄存器(包括R15-PC,程序计数器),该模式下可访问用户模式的寄存器,且操作系统的一些特权任务可用此模式访问受控的资源,系统模式不能由任何异常进入;


----------     ARM进入以下几种模式后,都要给R15-PC寄存器重新赋值,开始执行新的指令     ----------


  (3)管理模式:操作系统使用的保护模式,该模式主要用于系统的初始化软中断处理。当ARM刚上电或复位时,进入该模式,并强制PC从0x0000 0000处取指令;当系统软中断(如系统调用,调用ARM的SWI汇编指令)时,进入该模式,并强制PC从0x0000 0008处取指令 —— 这也是ARM从用户模式主动切入管理模式(Linux从用户态主动进入内核态)的唯一方法在Linux操作系统中,内核空间在这种模式下运行;


----------     当出现异常状况时,Linux还有可能在如下几种ARM模式下运行,如硬件中断、程序问题导致的异常等     ----------


  (4) 外部中断模式:特权模式和异常处理模式,用于处理一般的中断请求,通常在硬件产生中断信号之后自动进入该模式,可访问任意硬件资源。 进入该模式后、ARM强制PC从0x0000 0018处取指令


  (5) 快速中断模式:快速中断模式是相对一般中断模式而言的,它是用来处理对时间要求比较紧急的中断请求,主要用于高速数据传输及通道处理中。进入该模式后,ARM强制PC从0x0000 001C处取指令


  (6) 数据访问中止模式用于支持虚拟内存或存储器保护,当用户程序访问非法地址,没有权限读取的内存地址时,会进入该模式,linux下编程时经常出现的segment fault通常都是在该模式下抛出返回的。指令取终止时,进入该模式,并强制PC从0x0000 000C处取指令;当数据取终止时,进入该模式,并强制PC从0x0000 0010处取指令


  (7) 未定义指令中止模式:用于支持硬件协处理器的软件仿真,CPU在指令的译码阶段不能识别该指令操作时,会进入未定义模式。当程序中出现未定义的指令时,进入该模式,并强制PC从0x0000 0004处取指令



1.2 Linux操作系统与ARM工作模式



  首先,ARM开发板在刚上电或复位后都会首先进入SVC管理模式,此时,程序计数器R15-PC值会被赋为0x0000 0000。bootloader就是在此模式下,位于0x0000 0000的NOR FLASH或SRAM中装载的。因此,开机或重启后bootloader会被首先执行。


  接着,bootloader引导Linux内核,此时,Linux内核一样运行在ARM的SVC即管理模式下。当内核启动完毕,准备进入用户态init进程时,内核将ARM的当前程序状态寄存器CPSRM[4:0]设置为0x10000,进而用户态程序运行在ARM的用户模式由于用户模式下对资源的访问受限,因此可以达到保护Linux操作系统内核的目的。



1.3 ARM寄存器与ARM工作模式



  ARM有37个32-Bits长的寄存器,各工作模式下的通用寄存器和状态寄存器如下表。

 > 通用寄存器:30个;
 > 程序计数器 (PC):1个;
 > 状态寄存器:6个,1个当前程序状态寄存器 (current program status register,CPSR),5个备份程序状态寄存器 (saved program status register,SPSR);



1.3.1 通用寄存器



  R0~R7未分组的寄存器,对于任何处理器模式,这些寄存器都对应于相同的32位物理寄存器;

  R8~R14分组寄存器,它们所对应的物理寄存器,取决于当前的处理器模式,几乎所有允许使用通用寄存器的指令都允许使用分组寄存器;

  R13堆栈指针(SP),在ARM指令集当中,没有以特殊方式使用R13的指令或其它功能,只是习惯上都这样使用,但是在Thumb指令集中存在使用R13的指令;

  R14链接寄存器(LR),在结构上有两个特殊功能:

a. 在每种模式下,模式自身的R14版本用于保存子程序返回地址

b. 当发生异常时,将异常模式的对应R14设置为异常返回地址(有些异常有一个小的固定偏移量)。



1.3.2 状态寄存器



  aa



2 Linux中断机制



  Linux中断时进入中断处理例程执行程序时,处理器所处的模式还是SVC模式,即管理模式。实际上,在中断到来时,程序上做了处理,以使得进入SVC模式而不是中断模式。如下面Linux内核汇编代码linux/arch/arm/kernel/entry-armv.S中的代码片段,确实内核代码使得中断时进入的还是SVC模式

/*
 * Vector stubs.
 *
 * This code is copied to 0xffff1000 so we can use branches in the
 * vectors, rather than ldr's.  Note that this code must not exceed
 * a page size.
 *
 * Common stub entry macro:
 *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
 *
 * SP points to a minimal amount of processor-private memory, the address
 * of which is copied into r0 for the mode specific abort handler.
 */
	.macro	vector_stub, name, mode, correction=0
	.align	5

vector_\name:
	.if \correction
	sub	lr, lr, #\correction
	.endif

	@
	@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
	@ (parent CPSR)
	@
	stmia	sp, {r0, lr}		@ save r0, lr
	mrs	lr, spsr
	str	lr, [sp, #8]		@ save spsr	// 以上3句是将spsr中的模式位改为svc,注意这里只是修改了irq的spsr,还未切换状态

	@
	@ Prepare for SVC32 mode.  IRQs remain disabled.
	@
	mrs	r0, cpsr
	eor	r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
	msr	spsr_cxsf, r0

	@
	@ the branch table must immediately follow this code
	@
	and	lr, lr, #0x0f				// 取出spsr中的[M3:M0],因M4表示26位还是32位寻址,如果只想要模式,取[M3:M0]就行
 THUMB(	adr	r0, 1f			)
 THUMB(	ldr	lr, [r0, lr, lsl #2]	)
	mov	r0, sp						// 将irq模式的栈基地址填到r0,以后在svc_entry中可以通过r0去读取irq的栈
 ARM(	ldr	lr, [pc, lr, lsl #2]	)		// 将[M3:M0]乘4再加pc,计算出入口(一个entry占4字节),结果usr还是svc要看中断之前的模式
	movs	pc, lr			@ branch to handler in SVC mode	//跳转入口(__irq_usr或__irq_svc),mov带了s,用spsr去填cpsr
ENDPROC(vector_\name)

	.align	2
	@ handler addresses follow this label
1:
	.endm

	.section .stubs, "ax", %progbits
__stubs_start:
	@ This must be the first word
	.word	vector_swi

vector_rst:
 ARM(	swi	SYS_ERROR0	)
 THUMB(	svc	#0		)
 THUMB(	nop			)
	b	vector_und

/*
 * Interrupt dispatcher
 */
	vector_stub	irq, IRQ_MODE, 4		// 宏vector_\name展开,展开后,上述ARM(ldr lr,[pc,lr,lsl #2])处PC值为下面__irq_usr的地址

	.long	__irq_usr			@  0  (USR_26 / USR_32)
	.long	__irq_invalid			@  1  (FIQ_26 / FIQ_32)
	.long	__irq_invalid			@  2  (IRQ_26 / IRQ_32)
	.long	__irq_svc			@  3  (SVC_26 / SVC_32)
	.long	__irq_invalid			@  4
	.long	__irq_invalid			@  5
	.long	__irq_invalid			@  6
	.long	__irq_invalid			@  7
	.long	__irq_invalid			@  8
	.long	__irq_invalid			@  9
	.long	__irq_invalid			@  a
	.long	__irq_invalid			@  b
	.long	__irq_invalid			@  c
	.long	__irq_invalid			@  d
	.long	__irq_invalid			@  e
	.long	__irq_invalid			@  f

	// 其中一些是占位符,这里刚好16个,对应了[M3:M0]的所有可能取值,所以entry的地址就可以用[M3:M0]很快的算出来,之所以弄16个entry,是因为[M3:M0]在各种模式的取值中并不是连续的














  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值