2013-03-19 7 views
4

texane gdb server과 함께 Sourcery CodeBench Lite 2012.03-56 컴파일러 및 gdb 슈트를 사용하고 있습니다.Cortex m3 첫 번째 명령어 실행

오늘 나는 값싼 STM32VLDISCOVERY 보드에 대해 FreeRTOS 데모 예제를 시험해보고 싶었지만 필요한 모든 소스 파일을 복사하고 오류없이 컴파일했지만 예제가 작동하지 않았습니다. 디버거를 시작하고 GPIO 레지스터에 대한 포인터를 역 참조하려고 할 때 예제가 실패한 것으로 나타났습니다. GPIO에 대한 포인터를 포함 글로벌 배열 변수는 등록 :

GPIO_TypeDef* GPIO_PORT[LEDn] = {LED3_GPIO_PORT, LED4_GPIO_PORT}; 

가 제대로 초기화되지 않았으며 어떤 임의의 값으로 채워졌다. 나는 전처리 기가 LED3_GPIO_PORT와 LED3_GPIO_PORT를 정의했는지 확인했다.

문제가 발생한 부분을 조사한 후 CMSIS lib에있는 trueSTUDIO에 제공된 시작 파일을 살펴 보았습니다. 원래 startup_stm32f10x_md_vl.S 파일 :

.section .text.Reset_Handler 
    .weak Reset_Handler 
    .type Reset_Handler, %function 
Reset_Handler: 

/* Copy the data segment initializers from flash to SRAM */ 
    movs r1, #0 
    b LoopCopyDataInit 

CopyDataInit: 
    ldr r3, =_sidata 
    ldr r3, [r3, r1] 
    str r3, [r0, r1] 
    adds r1, r1, #4 

LoopCopyDataInit: 
    ldr r0, =_sdata 
    ldr r3, =_edata 
    adds r2, r0, r1 
    cmp r2, r3 
    bcc CopyDataInit 
    ldr r2, =_sbss 
    b LoopFillZerobss 
... 

디버깅하는 동안 나는 레지스터 (R1)가 먼저 명령에 의해 제로로 MOVS의 R1, # 0 초기화되지 않습니다 것으로 나타났습니다. 레지스터 r1은 루프의 카운터로 사용되므로 실행 루프 LoopCopyDataInit에 도달하면 레지스터 r1에 이전 실행의 일부 가비지 데이터가로드되므로 루프에 들어 가지 않습니다. 이 의 결과로 시작 코드는 .data 섹션을 초기화하지 않습니다. 내가 MOVS r1을하기 전에 두 개의 NOP 명령을 배치

, # 0 명령은 다음 R1은 0으로 초기화 된 레지스터 및 예제가 작동하기 시작

startup_stm32f10x_md_vl.S 파일의 수정 된 부분 :

/* Copy the data segment initializers from flash to SRAM */ 
    nop 
    nop 
    movs r1, #0 
    b LoopCopyDataInit 
당신은 ISR 벡터 TABL을 볼 수 있듯이

Disassembly of section .isr_vector: 

08000000 <g_pfnVectors>: 
8000000:  20002000  andcs r2, r0, r0 
8000004:  08000961  stmdaeq r0, {r0, r5, r6, r8, fp} 
... 

Disassembly of section .text: 

... 
8000960 <Reset_Handler>: 
8000960: 2100   movs r1, #0 
8000962: f000 b804  b.w  800096e <LoopCopyDataInit> 

08000966 <CopyDataInit>: 
8000966: 4b0d   ldr  r3, [pc, #52] ; (800099c <LoopFillZerobss+0x16>) 
8000968: 585b   ldr  r3, [r3, r1] 
800096a: 5043   str  r3, [r0, r1] 
800096c: 3104   adds r1, #4 

:

이 최종 코드의 관련 부분의 분해이다 e가 Reset_Handler 주소를 제대로 가리키고 있습니다. 그래서, 무슨 일이 일어나고있는거야? 왜 첫 번째 명령 movs r1, # 0 원래 시작 코드에서 실행 된 적이 있습니까?

편집 : 나는 다시 보드 다시 전원을 전원을 끌 때

원래의 코드가 작동합니다. MCU를 여러 번 리셋 할 수 있습니다. gdb-server를 시작하면 리셋 후에도 코드가 작동하지 않습니다. 다시 작동 시키려면 전원을 켜야합니다. 디버거가 이상하게 여기는 것 같아요.

참고 :

나는 시작 코드는이 MCU와 함께 사용하는 다른 사람들이 무엇을보고 있었다 중복 두 경우 모두에있는 링커 정의 된 값들은 하나 인터럽트를 비활성화 또는 부하 SP 레지스터. 그들이이 이상한 행동에 부딪치게되면 그들은 그것을 알아 채지 못할 것입니다.

+0

해서는 안'08000960'로'g_pfnVectors' 포인트 리셋 벡터가 아닌'08000961'? –

+0

_ ARM 코어 텍스 -M3, Joseph Yiu_, 3.7 리셋 시퀀스 : "Reset vector (프로그램 실행의 시작 주소, LSB는 Thumb 상태를 나타 내기 위해 1로 설정되어야 함)." 이는 8000961이 실제로 08000960 주소임을 나타냅니다. – BlueSky

+0

그건 의미가 있습니다. 분명히 잘못된 것을 볼 수는 없으며 아마도 디버거와의 이상한 상호 작용 일 것입니다. –

답변

3

소리가 디버거의 버그와 같습니다. 아마도 첫 번째 명령에 중단 점을 설정하고 완전히 건너 뛰거나 다시 실행하면 제대로 작동하지 않습니다. 이 문제는 벡터를 재설정했기 때문에 복잡 할 수 있습니다. 첫 번째 명령에서 안정적으로 멈추는 것은 불가능할 수도 있습니다. NOP가 도움이되기 때문에 프로그램을 개발하는 동안 NOP가 그대로 유지되는 것이 좋습니다.

그러나 대안이 있습니다. 배열을 수정할 필요가 없으므로 쓰기 가능한 섹션에 실제로 배열이 필요하지 않습니다. 플래시의 배열을 넣어 컴파일러를 가지려면, 보통은 const를로 선언하는 충분 :

GPIO_TypeDef* const GPIO_PORT[LEDn] = {LED3_GPIO_PORT, LED4_GPIO_PORT}; 
+0

네, 거기서 NOP를 남겼습니다. 어쨌든, 이것은 freeRTOS 패키지에서 가져온 예제 프로젝트 일뿐입니다. 나는 코드 작성자가 아니지만, 거기에 'const'가 필요하다는 데 동의한다. 감사. – BlueSky

1

거기에 무엇이 잘못 될 수 있는지에 관해서는 아무 것도 알려지지 않았습니다. 먼저이 코드를 어떻게 디버깅하고 있습니까? 디버거를 연결 한 다음 JTAG를 통해 프로세서에 재설정을 실행합니까?나는 당신의 Reset_Handler: 레이블을 첫 번째 명령어로 사용하고, 플래시를 켜고, 보드를 켠 다음 JTAG를 연결하기 때문에 디버거에서 발생할 수있는 기이함을 최소화 할 수 있도록 b Reset_Handler을 넣으려고합니다. 그런 다음 PC를 mov 명령어로 설정하고 작동하는지 확인하십시오. 부트 로더 또는 부트 ROM이이 코드를 실행합니까? 그것은 명령이나 데이터 캐시에서 이상한 일이 될 수 있습니다.

+0

texane gdb server (usb to swd)를 사용하여 이미지를 다운로드하고 디버깅하고 있습니다. 'b ResetHandler'를 실행하면 PC가 이미 '8000962'를 가리키고 있으므로 첫 번째 명령어가 바로 건너 뜁니다. – BlueSky

관련 문제