2017-11-15 24 views
2

Tiva C 런치 패드에 대해 가장 간단한 프로그램을 작성하려고합니다. 스택 포인터 값과 프로그램 카운터 값은 처음 두 개의 32 비트 플래시 단어에서 자동으로 가져옵니다. 하지만, 어떻게 든 이유로, 내가 gdb로 디버깅 할 때, 스택 포인터는 0x0을 얻는다. 이로 인해 프로그램이 실패하게됩니다. 나는 디버깅이 지침을 사용하고 있습니다 : 어셈블리ARM Cortex M4 (Tiva C 시리즈 TM4C123GH6PM)의 시동시 스택 포인터가로드되지 않습니다.

(gdb) target extended-remote :3333 
(gdb) monitor reset halt 
(gdb) load 
(gdb) monitor reset init 

프로그램의 Startup.s입니다 :

 .syntax unified 

     .section .vector_interrupt, "x" 

    g_pfnVectors: 
     .word 0x20007FFF 
     .word _Reset 

     .text 
    .global _Reset 
    _Reset: 
     mov r0, #0 
     b stop 

    stop: 
     add r0, r0, #1 
     b stop 

링커 파일 Tiva.lds :

ENTRY(_Reset) 

MEMORY 
{ 
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 
} 

SECTIONS { 
     .vector_interrupt : { 
     KEEP(*(.vector_interrupt)); 
    } > FLASH 

    .text : { 
     . = 0x0000026c; 
     * (.text); 
    } > FLASH 

} 

및 메이크 :

gcc=arm-none-eabi-gcc 
objcopy=arm-none-eabi-objcopy 

FLAGS= -ggdb3 -nostdlib -std=c99 -mcpu=cortex-m4 \ 
     -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -Wall \ 
     -Werror -nostartfiles 

csum.bin: csum.elf 
    $(objcopy) -O binary csum.elf csum.bin 

csum.elf: startup.s 
    $(gcc) $(FLAGS) -T Tiva.lds -o csum.elf \ 
    startup.s 

openocd: 
    openocd -f ../openOCD/ek-tm4c123gxl.cfg 

무엇이 잘못 되었나요?

나는 예외 핸들러를 넣어 피하려고했다

실현. 그러나 이제 나는 그들을 넣었다. 문제는 내가 시작할 때 UsageFault를 얻고 있다는 것이다. 의 Startup.s :

.syntax unified 

     .section .vector_interrupt, "x" 
g_pfnVectors: 
     .word _stack_start 
     .word _Reset 
     .word NMI   /* NMI Handler */ 
     .word HardFault  /* Hard Fault Handler */ 
     .word MemManage  /* MPU Fault Handler */ 
     .word BusFault  /* Bus Fault Handler */ 
     .word UsageFault /* Usage Fault Handler */ 
     .word 0    /* Reserved */ 
     .word 0    /* Reserved */ 
     .word 0    /* Reserved */ 
     .word 0    /* Reserved */ 
     .word SVC   /* SVCall Handler */ 
     .word DebugMon  /* Debug Monitor Handler */ 
     .word 0    /* Reserved */ 
     .word PendSV  /* PendSV Handler */ 
     .word SysTick  /* SysTick Handler */ 

     .text 
.global _Reset 
_Reset: 
     mov r0, #0 
     b stop 

stop: 
     add r0, r0, #1 
     b stop    @ Infinite loop to stop execution 



     .align 1 
     .thumb_func 
     .weak Default_Handler 
     .type Default_Handler, %function 
Default_Handler: 
     b . 

/* Macro to define default handlers */ 
     .macro def_handler handler_name 
      .weak \handler_name 
      .set \handler_name, Default_Handler 
     .endm 

     def_handler NMI 
     def_handler HardFault 
     def_handler MemManage 
     def_handler BusFault 
     def_handler UsageFault 
     def_handler SVC 
     def_handler DebugMon 
     def_handler PendSV 
     def_handler SysTick 
     def_handler DEF_IRQHandler 

Tiva.lds :이 팔 - 없음 - EABI-objdump를 -d csum.elf

의 출력이

ENTRY(_Reset) 

MEMORY 
{ 
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 
} 

_stack_start = ORIGIN(SRAM)+LENGTH(SRAM); 

SECTIONS { 
     .text : { 
      KEEP(*(.vector_interrupt)); 
      * (.text); 
     } > FLASH 

} 

입니다

나는이 수정을했다 UsageFault에 대한
csum.elf:  file format elf32-littlearm 


Disassembly of section .text: 

00000000 <g_pfnVectors>: 
    0: 20008000 .word 0x20008000 
    4: 00000040 .word 0x00000040 
    8: 0000004d .word 0x0000004d 
    c: 0000004d .word 0x0000004d 
    10: 0000004d .word 0x0000004d 
    14: 0000004d .word 0x0000004d 
    18: 0000004d .word 0x0000004d 
    ... 
    2c: 0000004d .word 0x0000004d 
    30: 0000004d .word 0x0000004d 
    34: 00000000 .word 0x00000000 
    38: 0000004d .word 0x0000004d 
    3c: 0000004d .word 0x0000004d 

00000040 <_Reset>: 
    40: f04f 0000 mov.w r0, #0 
    44: e7ff  b.n 46 <stop> 

00000046 <stop>: 
    46: f100 0001 add.w r0, r0, #1 
    4a: e7fc  b.n 46 <stop> 

0000004c <BusFault>: 
    4c: f7ff bff8 b.w 4c <BusFault> 

이유가 될 수 있습니다

,691,363 (210)
  • 정의되지 않은 명령

- 명령 실행에 대한 잘못된 상태가

- - 예외 반환에 오류가

하지만 난 파악하지

가 잘못된 정렬되지 않은 액세스 이유는 무엇입니까?

+2

를 참조하십시오? –

+0

벡터 테이블의 두 번째 항목이 있어야 할 때 리셋 처리기 (_Reset은 0x0000026C 인 반면 벡터 테이블 항목은 0x0000026A 임)가 아니기 때문에 문제가 발생했는지 궁금합니다. 그 –

+0

당신은'.word _Reset'을 말할 수 있어야하고 링커가 올바른 주소를 고쳐 줄 수 있어야합니다. 그리고 벡터는 홀수이어야한다고 생각합니다 (왜냐하면 Thumb 엔트리 포인트이기 때문입니다). [그러나, "0으로 모든 플래시 메모리"는 더 심각한 문제처럼 들립니다!] – NickJH

답변

3

ARM 어셈블리로 작성하는 것은 까다 롭습니다. 이 코드에는 세 가지 문제점이있었습니다. 그것은 ALLOC 속성을 가지고 있지 않았기 때문에

  1. .vector_interrupt 섹션에서는 바이너리 파일을하지 않았다. objcopy은 ALLOC 특성이없는 섹션을 무시합니다. 결과적으로 초기 스택 포인터와 리셋 벡터는 0이었습니다. 이 문제를 해결하려면, 섹션의 속성은 "XA"를 읽어야

    .section .vector_interrupt, "xa" 
    
  2. 또 다른 문제 : 초기 스택 포인터가 정렬되지 않은 것입니다.

    .word 0x20008000 
    

이는 MCU가 적어도 32킬로바이트의 RAM을 가정 한 것입니다 :로 변경합니다.

  1. 분기 대상 주소에는 Thumb 모드를 나타내는 LSB 비트가 1로 설정되어야합니다. Cortex-M4는 Thumb 명령어 세트 만 지원하므로 짝수 주소로 점프하려고 할 때 오류가 발생합니다. 어셈블러가 올바른 주소 값을 생성하게하려면 .thumb_func은 분기 타겟을 식별 한 레이블 앞에 와야합니다.

생성 된 바이너리의 첫 8 바이트는 무엇입니까 https://sourceware.org/binutils/docs/as/ARM-Directives.html

+0

나는 그것을 넣었지만 어떤 변화도 보이지 않는다. : –

+0

bin 파일이 변경 되었습니까? 이제는 처음 두 단어에 0이 아닌 값이 있습니까? –

+0

예, 스택 포인터와 프로그램 카운터가 잘로드되었습니다 . –