지난 글에서 ARM 코어는 전원 인가시 가장 먼저 0x00에 위치한 리셋 익셉션 핸들러를 호출한다고 했던거 같은데

리셋 익셉션 핸들러는 메모리 맵을 우선 설정해줘야 한다고 한다.

동작 모드별 메모리맵 설정이 끝난 후 C 언어 main으로 진입

 

https://ggamji.tistory.com/113

 

navilos - 3. 메모리맵

방학 하는 동안 노느라 너무 오랜만이라 잘 생각나지않는데 이번에는 부팅 과정을 다룬다. 부팅 하드웨어 초기화 과정 정도로 이해하고 있었는데 리셋 익셉션 핸들러 처리 후 C언어로 넘어가기

ggamji.tistory.com

 

 

위 글에서 ARM의 7개의 동작 모드와 메모리 맵을 그렸는데 

리셋 익셉션 핸들러에서 각 동작 모드를 돌아가며 스택을 초기화 시키도록 코드를 구현하자

 

#define	INST_ADDR_START		0
#define	USRSYS_STACK_START	0x00100000
#define	SVC_STACK_START		0x00300000
#define	IRQ_STACK_START		0x00400000
#define	FIQ_STACK_START		0x00500000
#define	ABT_STACK_START		0x00600000
#define	UND_STACK_START		0x00700000
#define	TASK_STACK_START	0x00800000
#define	GLOBAL_ADDR_START	0x04800000
#define	DALLOC_ADDR_START	0x04900000

#define	INST_MEM_SIZE		(USRSYS_STACK_START - INST_ADDR_START)
#define	USRSYS_STACK_SIZE	(SVC_STACK_START - USRSYS_STACK_START)
#define SVC_STACK_SIZE		(IRQ_STACK_START - SVC_STACK_START)
#define	IRQ_STACK_SIZE		(FIQ_STACK_START - IRQ_STACK_START)
#define	FIQ_STACK_SIZE		(ABT_STACK_START - FIQ_STACK_START)
#define	ABT_STACK_SIZE		(UND_STACK_START - ABT_STACK_START)
#define UND_STACK_SIZE		(TASK_STACK_START - UND_STACK_START)
#define	TASK_STACK_SIZE		(GLOBAL_ADDR_START - TASK_START_START)
#define DALLOC_MEM_SIZE		(55 * 1024 * 1024)

#define	USRSYS_STACK_TOP	(USRSYS_STACK_START + USRSYS_STACK_SIZE - 4)
#define	SVC_STACK_TOP		(SVC_STACK_START + SVC_STACK_SIZE - 4)
#define	IRQ_STACK_TOP		(IRQ_STACK_START + IRQ_STACK_SIZE - 4)
#define FIQ_STACK_TOP		(FIQ_STACK_START + FIQ_STACK_SIZE - 4)
#define ABT_STACK_TOP		(ABT_STACK_START + ABT_STACK_SIZE - 4)
#define UND_STACK_TOP		(UND_STACK_START + UND_STACK_SIZE - 4)

include/MemoryMap.h 헤더 파일 구현하고

 

#define ARM_MODE_BIT_USR 0X10
#define	ARM_MODE_BIT_FIQ 0X11
#define	ARM_MODE_BIT_IRQ 0X12
#define	ARM_MODE_BIT_SVC 0X13
#define ARM_MODE_BIT_ABT 0X17
#define ARM_MODE_BIT_UND 0X1B
#define	ARM_MODE_BIT_SYS 0X1F
#define ARM_MODE_BIT_MON 0X16

include/ARMv7AR.h 도 구현

 

 

각 동작 모드별로 비트가 다른데

프로그램 상태 레지스터 PSR에서 이런 상태를 보관하는데

현재 상태를 저장하는 레지스터로 CPSR(Current PSR)

상태를 저장하는 레지스터로 SPSR(Saved PSR)이 존재한다.

 

아래 그림은 cortex-a8의 PSR로

여기서 M[4:0]이 모드비트인데

위 ARMv7AR.h 헤더에 구현한데로 저 자리에 다음의 값이 들어갈때 동작모드가 변경되며,

익셉션이 발생 시 하드웨어가 알아서 바꾼다.

10000 : USR

10001 :FIQ

....

11011 : UND

11111 : SYS

 

 

ARM 동작 모드

- 익셉션과 관련된 동작모드와 관련되지 않은 동작모드가 있음

- User 모드 USR : ARM 상태나 Thumb 상태로 동작하며 일반적으로 이 모드로 동작

- Fast Interrupt 모드 FIQ : FIQ 익셉션 발생시 전환. 이 모드는 ARM 상태서만 동작. 뱅크드 레지스터가짐

- 인터럽트 모드 IRQ : IRQ 익셉션 발생시 전환. ARM 상태와 Thumb 상태 둘다 동작 

- Supervisor 모드 SVC : 운영체제가 시스템 콜 호출하기 위한 보호모드. 호출시 SVC 모드로 변경후 수행. 

- Abort 모드 ABT : 어보트가 발생시 동작

- System 모드 SYS : 사용자 프로세스가 커널 모드가 필요할때 사용. 소프트웨어로 전환 가능

- Undefined 모드 und : 정의되지 않은 명령어 발생시 진입

* 뱅크드 레지스터 : 빠른 처리를 위한 별도 레지스터

 

 

 

 

ARM 레지스터

- 각 동작마다 고유의 뱅크드 레지스터와 공유되는 레지스터가 존재

- 공유되는 레지스터 = 범용 레지스터(R0 ~ R12) + R15(PC) + CPSR

- 모드 별 뱅크드 레지스터는 아래 그림 참조

- R13 : 스택 포인터

- R14 : 링크 레지스터로 서브 루틴 호출시 리턴어드레스 보관

- R15 : 프로그램 카운터

+ Recent posts