2017-05-21 11 views
1

에 도움이 필요합니다.ARM 모드를 변경하기위한 지침이 작동하지 않습니다. "msr cpsr_c XX"

Raspberry Pi2 (Cortex-A7) Baremetal Led의 깜박임 테스트 코드를 실행하려고합니다.

아래 코드는 완벽하게 작동합니다.

.extern __bss_start 
.extern __bss_end 

.extern FreeRTOS_IRQ_Handler 
.extern FreeRTOS_SVC_Handler 
.extern main 

.section .init 
.global _start 

.equ CPSR_MODE_USER,  0x10 
.equ CPSR_MODE_FIQ,  0x11 
.equ CPSR_MODE_IRQ,  0x12 
.equ CPSR_MODE_SVR,  0x13 
.equ CPSR_MODE_ABORT,  0x17 
.equ CPSR_MODE_UNDEFINED, 0x1B 
.equ CPSR_MDOE_SYSTEM,  0x1F 

.equ CPSR_IRQ_INHIBIT,  0x80 
.equ CPSR_FIQ_INHIBIT,  0x40 
.equ CPSR_THUMB,   0x20 

_start: 
    ldr pc, _reset_vector 
    ldr pc, _undefined_instruction_vector 
    ldr pc, _software_interrupt_vector 
    ldr pc, _prefetch_abort_vector 
    ldr pc, _data_abort_vector 
    ldr pc, _unused_vector 
    ldr pc, _interrupt_vector 
    ldr pc, _fast_interrupt_vector 

_reset_vector:     .word _reset 
_undefined_instruction_vector: .word _undefined_instruction 
_software_interrupt_vector:  .word _software_interrupt 
_prefetch_abort_vector:   .word _prefetch_abort 
_data_abort_vector:    .word _data_abort 
_unused_vector:     .word _unused 
_interrupt_vector:    .word _interrupt 
_fast_interrupt_vector:   .word _fast_interrupt 

_reset: 
    mov r0, #0x8000 
    mov r1, #0x0000 
    ldmia r0!,{r2, r3, r4, r5, r6, r7, r8, r9} 
    stmia r1!,{r2, r3, r4, r5, r6, r7, r8, r9} 
    ldmia r0!,{r2, r3, r4, r5, r6, r7, r8, r9} 
    stmia r1!,{r2, r3, r4, r5, r6, r7, r8, r9} 

//  mov r0, #(CPSR_MODE_SVR | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT) 
//  msr cpsr_c, r0 
    mov sp, #(64 * 1024 * 1024) 

    ldr r0, =__bss_start 
    ldr r1, =__bss_end 

    mov r2, #0 

_bss_init: 
    cmp  r0,r1 
    it  lt 
    strlt r2,[r0], #4 
    blt  _bss_init 

bl main 

_loop: 
    b _loop 


_undefined_instruction: 
    b _undefined_instruction 

_software_interrupt: 
    b _software_interrupt 

_prefetch_abort: 
    b _prefetch_abort 

_data_abort: 
    b _data_abort 

_unused: 
    b _unused 

_interrupt: 
    b _interrupt 

_fast_interrupt: 
    b _fast_interrupt 

그러나 코드의 중간에있는 주석을 제거하면.

mov r0, #(CPSR_MODE_SVR | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT) 
    msr cpsr_c, r0 

더 이상 주 기능으로 부팅되지 않습니다.

각 모드마다 스택 포인터를 설정할 수 있도록 모드를 변경해야합니다. 그러나 그것을하기를위한 지시는 작동하지 않는 것처럼 보인다.

아이디어가 있으십니까? 무슨 일이 일어나고 있는지 이해하는 데 도움이됩니다.

+0

수정하지 않고 cpsr을 검사 했습니까? 하이 모드 야? –

+0

와우, 감사합니다 old_timer. HYP 모드였습니다. HYP 모드는 cpsr 레지스터를 작성하여 모드를 변경할 수없는 것처럼 보입니다. – Harry

답변

3

우선, 감사합니다. "old_timer"이 (가) 내게 의견을 남겼습니다.

라즈베리 파이 2 이미지 릴리스의 특정 시점부터 HYP 모드 (SVC 모드 아님)로 부팅하기로 결정했습니다.

다음 검사 코드를 삽입하면 문제가 해결됩니다.

_reset: 
    cpsid if 

    /* Check if HYP mode */ 
    mrs r0, cpsr_all 
    and r0, r0, #0x1F 
    mov r8, #0x1A 
    cmp r0, r8 
    beq overHyped 
    b continueBoot 

overHyped: /* Get out of HYP mode */ 
    ldr r1, =continueBoot 
    msr ELR_hyp, r1 
    mrs r1, cpsr_all 
    and r1, r1, #0x1f ;@ CPSR_MODE_MASK 
    orr r1, r1, #0x13 ;@ CPSR_MODE_SUPERVISOR 
    msr SPSR_hyp, r1 
    eret 

continueBoot: