STM32F2: Ticari IDE'siz Makefile, bağlayıcı komut dosyası ve başlangıç ​​dosyası kombinasyonu


16

Yaklaşık iki aydır bir STM32F2 (özellikle bir geliştirme kartında STM32F217IGH6) ile çalışıyorum. Şimdiye kadar benim en büyük sorunum makefile, linker komut dosyası ve başlangıç ​​dosyası içeren "kurulum" ile ilgiliydi.

Özellikle, kesinti vektör tablomu düzgün bir şekilde ayarlayamadım ve kesinti işleyicileri çağırdım. ST, ticari IDE'lere uyarlanmış örnekler sunmaktadır. Bunun yerine, GCC araç zincirinin (ve JTAG aracılığıyla görüntüyü yüklemek için OpenOCD) ücretsiz Yagarto yeniden derlemesini kullanıyorum.

Kartım için (veya yakın bir kuzeni), kesinti işleyicileri için ayarlanmış ticari olmayan IDE'ler için uygun makefile, linker betiği ve başlangıç ​​dosyası kombinasyonunu içeren örnek projeler var mı?


2
Cortex M3 örneklerini aramalısınız, tam kart ve işlemci sorduğunuz şeyler için o kadar önemli değil. Muhtemelen linker betiğindeki bellek düzenini ve makefile içinde yanıp sönme yöntemini değiştirmeniz gerekir, ancak hepsi bu olmalıdır.
starblue

1
Tüm bunları bir git deposuna koyabilir ve github'a koyabilir misiniz?
AngryEE

1
Tam olarak denediğimde STM'yi kullanmayı bırakmamın nedeni budur. Kötü alet zinciriyle hayatımı zorlaştıracaklarsa, başka bir yere gidiyorum. PSoC3 ve PSoC5 için IDE'yi denediğimde, bu bir fark dünyasıydı.
Rocketmagnet

Yagarto'ya bağlı mısın? Bu tamamen iyi ve harika bir soru getiriyor, ancak CodeSourcery Lite araç zincirine aşinayım . Farklı bir araç zinciri için bir cevap muhtemelen uyarlanabilir, ancak kutudan çıkar çıkmaz.
Kevin Vermeer

Yanıtlar:


20

http://github.com/dwelch67

özellikle stm32f4 ve stm32vld, ancak diğerleri sizin için de yararlı olabilir. mbed ve mzero dizini mbed altında (cortex-m0).

Basit aptal yaklaşımı, minimal linker komut dosyalarını, minimum başlangıç ​​kodunu vb.Gibi seviyorum. İş, herhangi bir belirli araç zinciri tarafından değil kodla yapılır.

Çoğu gcc ve binutils biçimi (başparmak yeteneğine sahip) bu örneklerle biraz çalışacak, çünkü derleyici kütüphane çağrıları için bir kaynak olarak değil derlemek için kullanıyorum, stok bağlayıcı komut dosyalarını vb. Kullanmıyorum. Eski gcc ve binutils yeni başparmak2 bölümleri, bu nedenle bazı değişiklikler gerekli olabilir.

Kendi gcc, binutils ve llvm / clang'ımı oluşturmanın yanı sıra örneğin codeurcery kullanıyorum (şimdi akıl hocası grafikleri ama yine de ücretsiz / lite sürümünü alabilirsiniz).

Esp yeni bir hedef için bir proje oluşturmaya başlarken bazı sökme yapmanız gerekir. Özellikle, öğelerin istediğiniz yerde olduğundan emin olmak için, örneğin vektör tablosu.

Örneğin stm32f4d / blinker02 öğesine bakın. Vektörlerle başlar. S istisna / vektör tablosu artı bazı asm destek rutinleri:

/* 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

Bu örnekte kesinti yok, ancak ihtiyacınız olan diğer şeyler burada.

blinker02.c, ana kodu çağırmamak için notmain () olarak adlandırdığım C giriş noktasıyla birlikte C kodunun ana gövdesini içerir (bir main () olduğunda bazı derleyiciler ikilinize önemsiz ekler).

size kesip yapıştıracak. thefilefile derleme ve bağlama hakkında bir hikaye anlatır. Bazı örneklerimin aynı koddan iki veya daha fazla ikili dosya derlediğini unutmayın. gcc derleyici, llvm'nin clang derleyicisi, yalnızca başparmak ve başparmak2, farklı optimizasyonlar, vb.

Kaynak dosyalardan nesne dosyaları yaparak başlayın.

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

linker, ld, memmap olarak adlandırdığım bir linker betiği kullanır, bunlar son derece acı verici olabilir, bazen iyi bir nedenden dolayı, bazen değil. Ben daha az tek beden herkese uyar daha fazla yaklaşım, mutfak lavabo yaklaşım dışında her şeyi tercih ederim.

Ben tipik olarak .data kullanmıyorum (neredeyse hiç asla) ve bu örnek .bss için bir ihtiyaç yok bu yüzden burada linker komut dosyası, sadece bu işlemci için olması gereken yere program (.text) yerleştirmek için yeterli konum kullanarak.

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

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

Ben tanımlamak için bir bellek bölgesi var, adı ram hakkında foo veya bar veya bob diyebilirsiniz özel bir şey yok ya da sadece bellek öğeleri bölümlere bağlar önemli değil ted. Bölümler .text, .data, .bss, .rodata ve bellek haritasında nereye gittiklerini tanımlar.

Bunu inşa ettiğinde, her şeyi söktüğümü görüyorsun (objdump -D) bunu görüyorsun

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}

Dikkat edilmesi gereken en önemli şey, soldaki adresin istediğimiz yer olmasıdır, vectors.s kodu ilk olarak ikiliktir (çünkü ld komut satırında ilk olduğu için, linker komut dosyasında bir şey yapmazsanız öğeler gösterecektir ld komut satırındaki sırayla ikili dosyada). Düzgün önyükleme için vektör tablonuzun doğru yerde olduğundan emin olmalısınız. İlk öğe benim yığın adresim, bu iyi. İkinci öğe _start adresidir ve tek bir sayı olmalıdır. bir etiketten önce .thumb_func kullanımı bunun olmasına neden olur, bu yüzden başka çirkin görünümlü şeyler yapmak zorunda kalmazsınız.

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

08000056 <hang>:
 8000056:       e7fe          

0x08000051 ve 0x08000057 _start ve hang için uygun vektör girişleridir. çağrıları başlat notmain ()

08000098 <notmain>:
 8000098:       b510            push    {

Bu iyi görünüyor (Demontajda tek numaralı adresi göstermiyorlar).

Herşey iyi.

Örnek blinker05'e atlayın, bu kesintileri destekler. ve bazı koçlara ihtiyaç duyar, bu nedenle .bss tanımlanır.

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

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

koç ve rom'un rastgele isimler olduğunu unutmayın, bob ve ted, foo ve bar iyi çalışır.

Tüm vektörleri göstermeyecektir. Çünkü tam bir tane yaparsanız korteks-m3 vektör tablosunda bir milyon girişe sahiptir (çip satıcısı tarafından seçilen seçeneklere bağlı olarak çekirdekten çekirdeğe ve belki aynı çekirdek içinde değişir) İlgili bölümler sökme işleminden sonra buradadır:

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}

bu işleyiciyi tam olarak doğru noktaya yerleştirmek için biraz deneme yanılma alır, çipinize ihtiyaç duyduğu yerde kontrol edin, mutlaka bununla aynı yerde değildir ve çok fazla kesinti ile yine de farklı bir kesme arıyor olabilirsiniz. korteks-m işlemcileri, normal kollardan farklı olarak, kesmeler için trambolin kodu GEREKMEZ, böylece belirli sayıda kaydı korurlar ve bağlantı kayıt içeriği aracılığıyla işlemci modlarının değiştirilmesini yönetirler. derleyici için donanım ve abi yeterince yakın olduğu sürece hepsi işe yarıyor. Bu durumda işleyiciyi C'de yaptım, diğer platformların aksine ve geçmişin aksine derleyici / sözdizimi ile özel bir şey yapmanıza gerek yok sadece bir işlev yapın (ancak işlev / işleyicide aptalca şeyler yapmayın)

//-------------------------------------------------------------------
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 için makefile blinker02 örneğine benzemelidir, çoğunlukla bunların çoğu için kes ve yapıştır. tek tek kaynak dosyaları nesnelere dönüştürün ve bağlayın. Ben başparmak, gcc ve clang kullanarak thumb2 için inşa. all: satırını, glang öğelerini yalnızca clang (llvm) içermiyorsa / istemiyorsanız değiştirebilirsiniz. Ben clang çıkış btw birleştirmek ve bağlamak için binutils kullanın.

Tüm bu projeler ücretsiz, rafta, açık kaynak, araçlar kullanıyor. IDE yok, sadece komut satırı. Evet, sadece Windows ile değil Linux ile uğraşıyorum, ancak bu araçlar Windows kullanıcıları için de mevcut, rm gibi şeyleri değiştir - makefile'da bir şey yapmak için bir şey, pencereler üzerinde inşa ederken böyle şeyler. Bu veya linux'u vmware, virtualbox veya qemu üzerinde çalıştırın. IDE kullanmamak, metin düzenleyicinizi de seçtiğiniz anlamına gelir, buna girmeyeceğim, favorilerim var. GNU make programının son derece can sıkıcı bir özelliği, makefile gerçek sekmeler gerektirdiğini unutmayın, görünmez sekmelerden bir tutkuyla nefret ediyorum. Yani sekmelerden ayrılan makefiles için bir metin düzenleyicisi, boşluk oluşturan kaynak kodu için diğeri. Pencereleri bilmiyorum,

Umarım bu yardımcı olur, tam yonga / tahta değil, bu tartışma için yeterince yakın bir korteks-m4 kuyusu m4 m3 değildir. gerçek bir korteks-m3 için mbed veya stm32vld dir'e bakın (makefiles ve boot kodu vb. için m4'ten yeterli fark yok), ancak st. Korteks-m3 çekirdeği satıcılar arasında aynı olmalıdır, korteks-m3 ve korteks-m4'ün ikisi de ARMv7m'dir ve farklı olmaktan çok daha yakındır. Korteks-m0 bir ARMv6m, rahatsız etmek için yeterince başparmak2 talimatı yok, derleyiciler onunla yakalanmadı, bu yüzden sadece başparmak kullanın (gerekirse bir ARMv4T (sadece başparmak) için inşa ediyormuş gibi yapın). Benim simülatör simülatör sadece başparmak, hiçbir başparmak2, sizin için de yararlı olabilir, sanırım bazı şekillerde veya moda kesmeler yaptım.


Cevabı okuyordum ve sanırım bu cevap için yazar SEN olabilirsin. Verdiğiniz yanıtlar bana çok yardımcı oldu ve AVR ve PIC Fanboy olmaktan çok ARM işlemcilere geçmemi sağladı. Teşekkürler
MaNyYaCk


2

Bu siteye linker ve low_level_init ile ilgili temel bilgileri açıklamaya çalışabilirsiniz.

Sayfanın sorunu tanımlamaya odaklandığını lütfen unutmayın, bu nedenle nvic vektörü çok azdır.

Daha sonra "STM32F2xx standart çevre birimleri kütüphanesinde" daha eksiksiz örneklere sahipsiniz, sadece gcc bölümlerine bakın (Yagarto gcc tabanlı olduğundan). Ve burada nvic'in (interrupt vector table) doğru kurulumunda size yardımcı olacak örnek kod var.

Yani bu tam bir cevap olmasa bile, yine de biraz yardımcı olacağını umuyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.