STM32F2 : 상용 IDE없이 Makefile, 링커 스크립트 및 시작 파일 조합


16

약 2 개월 동안 STM32F2 (특히 개발 보드의 STM32F217IGH6)와 함께 작업했습니다. 지금까지 가장 큰 문제는 makefile, 링커 스크립트 및 시작 파일을 포함하는 "setup"과 관련이있었습니다.

특히, 인터럽트 벡터 테이블을 올바르게 설정할 수 없었고 인터럽트 핸들러를 호출했습니다. ST는 상용 IDE에 맞춘 예제를 제공합니다. 대신, GCC 툴체인 (및 JTAG를 통해 이미지를로드하기 위해 OpenOCD)의 무료 Yagarto 재 컴파일을 사용하고 있습니다.

인터럽트 핸들러가 호출되도록 설정된 비상업적 IDE에 대한 적절한 makefile, 링커 스크립트 및 시작 파일 조합을 포함하는 내 보드 (또는 가까운 사촌)를위한 예제 프로젝트가 있습니까?


2
Cortex M3 예제를 찾아봐야합니다. 정확한 보드와 프로세서는 요청한 사항에 중요하지 않습니다. 링커 스크립트에서 메모리 레이아웃과 makefile에서 깜박이는 방법을 수정해야 할 수도 있지만 그게 전부입니다.
starblue

1
이 모든 것을 git repo에 넣고 github 또는 다른 것에 넣을 수 있습니까?
AngryEE

1
이것이 바로 STM 사용을 중단 한 이유입니다. 그들이 불쾌한 툴체인으로 내 인생을 어렵게 만들면 다른 곳으로 가고 있습니다. PSoC3 및 PSoC5에 대한 IDE를 사용해 보았을 때 차이가났습니다.
Rocketmagnet

당신은 Yagarto에 최선을 다하고 있습니까? 그것은 완전히 괜찮고 좋은 질문을하지만 CodeSourcery Lite 툴 체인에 익숙합니다 . 다른 툴체인에 대한 대답은 아마도 적합 할 수도 있지만 기본적으로 작동하지는 않습니다.
케빈 베르메르

답변:


20

http://github.com/dwelch67

stm32f4 및 stm32vld, 특히 다른 것들도 유용 할 수 있습니다. mbed 아래의 mbed 및 mzero 디렉토리 (cortex-m0).

나는 간단한 바보 같은 접근 방식, 최소한의 링커 스크립트, 최소한의 시작 코드 등을 유지합니다. 작업은 특정 툴 체인이 아닌 코드로 수행됩니다.

컴파일러를 사용하여 라이브러리 호출에 대한 리소스로 컴파일하지 않고 주식 링커 스크립트 등을 사용하지 않기 때문에 대부분의 gcc 및 binutils (엄지 손가락을 사용할 수 있음)는 이러한 예제에서 다소 작동합니다. 이전 gcc 및 binutils는 최신 thumb2 부품이므로 일부 변경이 필요할 수 있습니다.

나는 내 자신의 gcc, binutils 및 llvm / clang을 빌드하고 예를 들어 코드 소스를 사용합니다 (현재 멘토 그래픽이지만 여전히 무료 / 라이트 버전을 얻을 수 있습니다).

Esp는 새로운 목표를 위해 프로젝트를 모으기 시작할 때 약간의 분해를해야합니다. 특히 항목이 원하는 위치에 있는지 확인하려면 벡터 테이블을 예로들 수 있습니다.

예를 들어 stm32f4d / blinker02를보십시오. 벡터는 예외 / 벡터 테이블과 일부 asm 지원 루틴으로 시작합니다.

/* vectors.s */
.cpu cortex-m3
.thumb

.word   0x20002000  /* stack top address */
.word   _start      /* 1 Reset */
.word   hang        /* 2 NMI */
.word   hang        /* 3 HardFault */
.word   hang        /* 4 MemManage */
.word   hang        /* 5 BusFault */
.word   hang        /* 6 UsageFault */
.word   hang        /* 7 RESERVED */
.word   hang        /* 8 RESERVED */
.word   hang        /* 9 RESERVED*/
.word   hang        /* 10 RESERVED */
.word   hang        /* 11 SVCall */
.word   hang        /* 12 Debug Monitor */
.word   hang        /* 13 RESERVED */
.word   hang        /* 14 PendSV */
.word   hang        /* 15 SysTick */
.word   hang        /* 16 External Interrupt(0) */
.word   hang        /* 17 External Interrupt(1) */
.word   hang        /* 18 External Interrupt(2) */
.word   hang        /* 19 ...   */

.thumb_func
.global _start
_start:
    /*ldr r0,stacktop */
    /*mov sp,r0*/
    bl notmain
    b hang

.thumb_func
hang:   b .

/*.align
stacktop: .word 0x20001000*/

;@-----------------------
.thumb_func
.globl PUT16
PUT16:
    strh r1,[r0]
    bx lr
;@-----------------------
.thumb_func
.globl PUT32
PUT32:
    str r1,[r0]
    bx lr
;@-----------------------
.thumb_func
.globl GET32
GET32:
    ldr r0,[r0]
    bx lr
;@-----------------------
.thumb_func
.globl GET16
GET16:
    ldrh r0,[r0]
    bx lr

.end

이 예제에서는 인터럽트가 없지만 필요한 다른 것들이 여기 있습니다.

blinker02.c에는 main 호출하지 않기 위해 notmain ()이라고 부르는 C 시작 점이있는 C 코드의 본문이 포함되어 있습니다 (일부 컴파일러는 main ()이있을 때 바이너리를 정크에 추가합니다).

잘라내어 붙여 넣습니다. makefile은 컴파일과 링크에 대한 이야기를 들려줍니다. 많은 예제가 동일한 코드에서 2 개 이상의 바이너리를 컴파일합니다. gcc 컴파일러, llvm의 clang 컴파일러, thumb 전용 및 thumb2, 다른 최적화 등

소스 파일에서 오브젝트 파일을 작성하여 시작하십시오.

vectors.o : vectors.s
    $(ARMGNU)-as vectors.s -o vectors.o

blinker02.gcc.thumb.o : blinker02.c
    $(ARMGNU)-gcc $(COPS) -mthumb -c blinker02.c -o blinker02.gcc.thumb.o

blinker02.gcc.thumb2.o : blinker02.c
    $(ARMGNU)-gcc $(COPS) -mthumb -mcpu=cortex-m3 -march=armv7-m -c blinker02.c -o blinker02.gcc.thumb2.o

blinker02.gcc.thumb.bin : memmap vectors.o blinker02.gcc.thumb.o
    $(ARMGNU)-ld -o blinker02.gcc.thumb.elf -T memmap vectors.o blinker02.gcc.thumb.o
    $(ARMGNU)-objdump -D blinker02.gcc.thumb.elf > blinker02.gcc.thumb.list
    $(ARMGNU)-objcopy blinker02.gcc.thumb.elf blinker02.gcc.thumb.bin -O binary

blinker02.gcc.thumb2.bin : memmap vectors.o blinker02.gcc.thumb2.o
    $(ARMGNU)-ld -o blinker02.gcc.thumb2.elf -T memmap vectors.o blinker02.gcc.thumb2.o
    $(ARMGNU)-objdump -D blinker02.gcc.thumb2.elf > blinker02.gcc.thumb2.list
    $(ARMGNU)-objcopy blinker02.gcc.thumb2.elf blinker02.gcc.thumb2.bin -O binary

링커 ld는 내가 memmap이라고 부르는 링커 스크립트를 사용합니다. 때로는 좋은 이유 때문에 때로는 고통 스럽습니다. 나는 하나의 크기에 대한 접근이 적을수록 부엌 싱크대 접근을 제외한 모든 것을 선호합니다.

나는 일반적으로 .data를 사용하지 않으며 (거의 전혀 사용하지 않음)이 예제에는 .bss가 필요하지 않으므로 링커 스크립트가 있습니다. 그것을 사용합니다.

MEMORY
{
    ram : ORIGIN = 0x08000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > ram
}

나는 그것을 정의 할 수있는 메모리 영역을 가지고있다. 이름 램에 대해 foo 또는 bar 또는 bob이라고 부를 수있는 특별한 것은 없으며 메모리 항목을 섹션에 연결하는 것만 중요하지 않습니다. 이 섹션에서는 .text, .data, .bss, .rodata 및 메모리 맵의 위치를 ​​정의합니다.

당신이 이것을 만들 때, 당신은 내가 모든 것을 분해하는 것을 보게됩니다 (objdump -D)

Disassembly of section .text:

08000000 <_start-0x50>:
 8000000:       20002000        andcs   r2, r0, r0
 8000004:       08000051        stmdaeq r0, {r0, r4, r6}
 8000008:       08000057        stmdaeq r0, {r0, r1, r2, r4, r6}
 800000c:       08000057        stmdaeq r0, {r0, r1, r2, r4, r6}
 8000010:       08000057        stmdaeq r0, {r0, r1, r2, r4, r6}

주목할 점은 왼쪽에있는 주소는 우리가 원하는 위치이며, vectors.s 코드는 바이너리에서 첫 번째입니다 (링커 ​​스크립트에서 무언가를하지 않으면 항목이 표시되지 않는 한 ld 명령 행에서 첫 번째이므로 ld 명령 행에있는 순서대로 바이너리에 올림). 제대로 부팅하려면 벡터 테이블이 올바른 위치에 있는지 확인해야합니다. 첫 번째 항목은 내 스택 주소입니다. 두 번째 항목은 _start의 주소이며 홀수 여야합니다. 레이블 앞에 .thumb_func를 사용하면이 문제가 발생하므로 다른보기 흉한 작업을 수행 할 필요가 없습니다.

08000050 <_start>:
 8000050:       f000 f822       bl      8000098 <notmain>
 8000054:       e7ff            b.n     8000056 <hang>

08000056 <hang>:
 8000056:       e7fe          

따라서 0x08000051 및 0x08000057은 _start 및 hang에 적합한 벡터 항목입니다. 시작 호출 notmain ()

08000098 <notmain>:
 8000098:       b510            push    {

괜찮아 보입니다 (분해에 홀수 번호를 표시하지 않습니다).

모든 것이 잘됩니다.

blinker05 예제로 건너 뛰십시오.이 인터럽트는 인터럽트를 지원합니다. 램이 필요하므로 .bss가 정의됩니다.

MEMORY
{
    rom : ORIGIN = 0x08000000, LENGTH = 0x100000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1C000
}

SECTIONS
{
    .text : { *(.text*) } > rom
    .bss  : { *(.bss*) } > ram
}

램과 롬은 임의의 이름, 밥과 테드, foo와 bar는 모두 잘 작동한다는 것을 기억하십시오.

완전한 벡터를 만들면 cortex-m3에 벡터 테이블에 치열한 항목이 있기 때문에 전체 벡터를 표시하지 않습니다 (칩 공급 업체가 선택한 옵션에 따라 코어마다 다를 수 있으며 같은 코어 내에있을 수 있음) 관련 부분은 분해 후 여기에 있습니다.

08000000 <_start-0x148>:
 8000000:       20020000        andcs   r0, r2, r0
 8000004:       08000149        stmdaeq r0, {r0, r3, r6, r8}
 8000008:       0800014f        stmdaeq r0, {r0, r1, r2, r3, r6, r8}
...
8000104:       0800014f        stmdaeq r0, {r0, r1, r2, r3, r6, r8}
 8000108:       08000179        stmdaeq r0, {r0, r3, r4, r5, r6, r8}
 800010c:       0800014f        stmdaeq r0, {r0, r1, r2, r3, r6, r8}

해당 처리기를 올바른 위치에 정확하게 배치하려면 시행 착오가 필요하며 칩과 반드시 ​​같은 위치에 있지 않아야하는 위치를 확인하십시오. 인터럽트가 너무 많으면 다른 인터럽트를 찾고있을 수 있습니다. cortex-m 프로세서는 일반 암과 달리 인터럽트에 대한 트램펄린 코드가 필요하지 않도록 특정 레지스터 수를 유지하고 링크 레지스터 내용을 통해 프로세서 모드 전환을 관리합니다. 컴파일러의 하드웨어와 abi가 충분히 가까이 있으면 모든 것이 작동합니다. 이 경우 다른 플랫폼과 달리 C에서 처리기를 수행했으며 과거에는 컴파일러 / 구문으로 특별한 작업을 수행하지 않아도 함수를 만들 수 있습니다 (그러나 함수 / 처리기에서 바보 같은 일을하지 마십시오)

//-------------------------------------------------------------------
volatile unsigned int intcounter;
//-------------------------------------------------------------------
// CAREFUL, THIS IS AN INTERRUPT HANDLER
void tim5_handler ( void )
{
    intcounter++;
    PUT32(TIM5BASE+0x10,0x00000000);
}
// CAREFUL, THIS IS AN INTERRUPT HANDLER
//-------------------------------------------------------------------

blinker05의 makefile은 blinker02 예제와 비슷해야하며 대부분의 경우 잘라서 붙여 넣기해야합니다. 개별 소스 파일을 객체로 변환 한 다음 링크하십시오. gcc와 clang을 사용하여 thumb, thumb2를 빌드합니다. clang (llvm)이 포함되지 않은 경우 gcc 항목 만 포함하도록 all : 행을 변경할 수 있습니다. binutils를 사용하여 clang 출력 btw를 어셈블하고 링크합니다.

이러한 모든 프로젝트는 무료이며 기성품 인 오픈 소스 도구를 사용합니다. IDE 없음, 명령 행 전용. 예, Windows가 아닌 Linux 만 엉망이지만이 도구는 Windows 사용자도 사용할 수 있습니다.이 파일은 rm -f와 같은 것을 makefile의 델타로 변경하고, Windows에서 빌드 할 때와 같은 것을 변경하십시오. vmware 또는 virtualbox 또는 qemu에서 Linux를 실행하십시오. IDE를 사용하지 않으면 텍스트 편집기도 선택한다는 것을 의미합니다. 나는 그것을 좋아하지 않습니다. gnu make 프로그램의 매우 성가신 기능은 makefile에 실제 탭이 필요하다는 것입니다. 열심히 보이지 않는 탭이 싫어요. 따라서 탭을 떠나는 makefile 용 텍스트 편집기와 공백을 만드는 소스 코드 용 텍스트 편집기가 있습니다. 나는 창문에 대해 모른다

이것이 도움이되기를 바랍니다. 정확한 칩 / 보드가 아니라 m3이 아닌 cortex-m4 well m4입니다.이 토론에 충분히 가깝습니다. 실제 cortex-m3에 대해서는 mbed 또는 stm32vld 디렉토리를 참조하십시오 (makefile 및 부트 코드 등에 대해서는 m4와 충분히 다르지 않음). cortex-m3 코어는 여러 공급 업체에서 동일해야하며 cortex-m3 및 cortex-m4는 ARMv7m이며 서로 다르지 않고 더 가깝습니다. cortex-m0은 ARMv6m이며, 방해 할만한 Thumb2 명령어는 거의 없으며, 컴파일러가이를 따라 잡지 않았으므로 Thumb 만 사용하십시오 (필요한 경우 ARMv4T 용으로 빌드하는 것처럼 가장하십시오). 내 썸뮬 레이터 시뮬레이터는 엄지 손가락이며 엄지 손가락이 없으며 유용 할 수 있습니다. 나는 어떤 형식이나 방식으로 인터럽트를 수행했다고 생각합니다.


나는 그 답을 읽고 있었고이 답의 저자는 당신 일 것이라고 생각합니다. 귀하의 답변은 AVR 및 PIC Fanboy보다 ARM 프로세서로 전환하는 데 많은 도움이되었습니다. 감사합니다
MaNyYaCk

천만
에요

2

코드에서 링커와 low_level_init의 기본 사항을 설명하려는이 사이트를 살펴볼 수 있습니다.

이 페이지는 문제 설명에 중점을 두므로 nvic 벡터는 최소화됩니다.

그런 다음 "STM32F2xx 표준 주변 장치 라이브러리"에보다 완전한 예제가 있습니다. Yaccato가 gcc 기반이므로 gcc 섹션 만 살펴보십시오. 그리고 nvic (인터럽트 벡터 테이블)을 올바르게 설정하는 데 도움이되는 예제 코드가 있습니다.

그래서 이것이 완전한 대답이 아니더라도 어쨌든 도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.