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 용으로 빌드하는 것처럼 가장하십시오). 내 썸뮬 레이터 시뮬레이터는 엄지 손가락이며 엄지 손가락이 없으며 유용 할 수 있습니다. 나는 어떤 형식이나 방식으로 인터럽트를 수행했다고 생각합니다.