STM32F2: Makefile, skrip linker dan kombinasi file start-up tanpa IDE komersial

16

Saya telah bekerja dengan STM32F2 (khususnya, STM32F217IGH6 pada papan pengembangan) selama sekitar dua bulan. Sejauh ini masalah terbesar saya berkaitan dengan "setup", yang meliputi makefile, skrip linker dan file start-up.

Secara khusus, saya tidak dapat mengatur dengan benar tabel vektor interrupt saya dan telah memanggil penangan interrupt. ST memang memberikan contoh yang disesuaikan dengan IDE komersial. Sebagai gantinya, saya menggunakan kompilasi Yagarto gratis dari toolchain GCC (dan OpenOCD untuk memuat gambar melalui JTAG).

Adakah contoh proyek untuk board saya (atau sepupu dekatnya) yang berisi makefile, script linker dan kombinasi file start-up yang sesuai untuk IDE non-komersial yang diatur untuk interrupt handler untuk dipanggil?

Randomblue
sumber
2
Anda harus mencari contoh Cortex M3, papan dan prosesor yang tepat tidak begitu penting untuk hal-hal yang Anda tanyakan. Anda mungkin perlu memodifikasi tata letak memori dalam skrip linker dan metode untuk mem-flash di makefile, tetapi itu saja.
starblue
1
Bisakah Anda menempatkan semua ini di repo git dan meletakkannya di github atau sesuatu?
AngryEE
1
Inilah alasan saya berhenti menggunakan STM segera setelah saya mencobanya. Jika mereka membuat hidup saya sulit dengan rantai alat jahat, maka saya akan pergi ke tempat lain. Ketika saya mencoba IDE untuk PSoC3 dan PSoC5, itu adalah dunia yang berbeda.
Rocketmagnet
Apakah Anda berkomitmen untuk Yagarto? Itu benar-benar baik dan membuat pertanyaan hebat, tapi saya akrab dengan toolchain CodeSourcery Lite . Sebuah jawaban untuk rantai alat yang berbeda mungkin bisa diadaptasi, tetapi tidak akan berhasil.
Kevin Vermeer

Jawaban:

20

http://github.com/dwelch67

stm32f4 dan stm32vld pada khususnya, tetapi yang lain mungkin berguna bagi Anda juga. mbed dan direktori mzero di bawah mbed (cortex-m0).

Saya suka pendekatan bodoh sederhana, skrip linker minimal, kode startup minimal, dll. Pekerjaan ini dilakukan oleh kode bukan oleh toolchain tertentu.

Sebagian besar bentuk gcc dan binutils (yang mampu diacungi jempol) akan bekerja agak dengan contoh-contoh ini karena saya menggunakan kompiler untuk mengkompilasi bukan sebagai sumber daya untuk panggilan perpustakaan, saya tidak menggunakan skrip penghubung stok, dll. Gcc dan binutils yang lebih tua tidak akan tahu tentang bagian thumb2 yang lebih baru sehingga beberapa perubahan mungkin diperlukan.

Saya membangun gcc, binutils dan llvm / clang saya sendiri dan juga menggunakan codesourcery misalnya (sekarang mentor grafik tetapi Anda masih bisa mendapatkan versi gratis / lite).

Terutama ketika mulai menyusun proyek untuk target baru yang perlu Anda lakukan beberapa pembongkaran. Khususnya untuk memastikan item berada di tempat yang Anda inginkan, tabel vektor misalnya.

Lihatlah stm32f4d / blinker02 misalnya. Itu dimulai dengan vektor.s tabel pengecualian / vektor ditambah beberapa rutinitas dukungan 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

Tidak ada interupsi pada contoh ini, tetapi hal-hal lain yang Anda butuhkan ada di sini.

blinker02.c berisi badan utama kode C dengan titik masuk C yang saya panggil notmain () untuk menghindari memanggilnya main (beberapa kompiler menambahkan sampah ke biner Anda ketika Anda memiliki main ()).

akan mengampuni Anda memotong dan menempel. makefile bercerita tentang kompilasi dan penautan. Perhatikan bahwa sejumlah contoh saya mengkompilasi dua atau lebih binari dari kode yang sama. gcc compiler, compiler clang llvm, ibu jari saja dan thumb2, optimasi berbeda, dll

Mulai dengan membuat file objek dari file sumber.

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, menggunakan skrip linker yang saya sebut memmap, ini bisa sangat menyakitkan, kadang-kadang karena alasan yang baik, kadang tidak. Saya lebih suka pendekatan yang lebih sedikit untuk satu ukuran cocok untuk semua, semuanya kecuali pendekatan wastafel dapur.

Saya tidak menggunakan data. Biasanya (well hampir tidak pernah) dan contoh ini tidak memiliki kebutuhan .bss jadi di sini adalah skrip linker, hanya cukup untuk menempatkan program (.text) di mana perlu untuk prosesor ini mereka seperti saya menggunakannya.

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

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

Saya memiliki wilayah memori untuk mendefinisikan bahwa, tidak ada yang istimewa tentang ram nama Anda dapat menyebutnya foo atau bar atau bob atau ted itu tidak masalah itu hanya menghubungkan item memori ke bagian. Bagian menentukan hal-hal seperti .text, .data, .bss, .rodata dan kemana mereka pergi di peta memori.

ketika Anda membangun ini, Anda melihat saya membongkar semuanya (objdump -D) Anda melihat ini

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}

Hal utama yang perlu diperhatikan adalah alamat di sebelah kiri adalah tempat kami menginginkannya, kode vectors.s adalah yang pertama dalam biner (Karena itu adalah yang pertama di baris perintah ld, kecuali jika Anda melakukan sesuatu pada skrip linker, item akan ditampilkan di biner dalam urutan mereka berada di baris perintah ld). Untuk mem-boot dengan benar, Anda harus memastikan tabel vektor Anda ada di tempat yang tepat. Item pertama adalah alamat stack saya, itu bagus. Item kedua adalah alamat untuk memulai dan itu harus berupa angka ganjil. penggunaan .thumb_func sebelum label menyebabkan hal ini terjadi sehingga Anda tidak perlu melakukan hal-hal buruk lainnya.

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

08000056 <hang>:
 8000056:       e7fe          

jadi 0x08000051 dan 0x08000057 adalah entri vektor yang tepat untuk _start dan hang. mulai panggilan notmain ()

08000098 <notmain>:
 8000098:       b510            push    {

Itu terlihat bagus (Mereka tidak menunjukkan alamat bernomor ganjil dalam pembongkaran).

Semua baik-baik saja.

Lewati ke contoh blinker05, yang ini memang mendukung interupsi. dan membutuhkan ram, jadi .bss didefinisikan.

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

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

ingat ram dan rom adalah nama arbitrer, bob dan ted, foo dan bar semuanya berfungsi dengan baik.

Tidak akan menampilkan seluruh vektor.s karena korteks-m3 memiliki miliaran entri dalam tabel vektor jika Anda membuat yang lengkap (bervariasi dari inti ke inti dan mungkin dalam inti yang sama tergantung pada opsi yang dipilih oleh vendor chip) Bagian yang relevan ada di sini setelah pembongkaran:

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}

mengambil beberapa trial and error untuk menempatkan handler itu tepat di tempat yang tepat, periksa dengan chip Anda di mana ia perlu itu belum tentu di tempat yang sama seperti ini, dan dengan begitu banyak interupsi Anda mungkin mencari interupsi yang berbeda pula. Prosesor korteks-m, tidak seperti lengan normal, membuatnya sehingga Anda TIDAK PERLU kode trampolin untuk gangguan, mereka mempertahankan sejumlah register dan mengelola beralih mode prosesor melalui isi register tautan. selama perangkat keras dan abi untuk kompiler cukup dekat semuanya berfungsi. Dalam hal ini saya melakukan handler di C, tidak seperti platform lain dan di masa lalu Anda tidak perlu melakukan sesuatu yang khusus dengan kompiler / sintaks hanya membuat fungsi (tapi jangan melakukan hal-hal bodoh dalam fungsi / handler)

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

Makefile untuk blinker05 harus menyerupai contoh blinker02, kebanyakan dipotong dan ditempelkan untuk sebagian besar. ubah masing-masing file sumber menjadi objek lalu tautkan. Saya membangun untuk ibu jari, ibu jari2 menggunakan gcc dan dentang. Anda dapat mengubah semua: pada saat itu hanya menyertakan item gcc jika Anda tidak memiliki / ingin dentang (llvm) terlibat. Saya menggunakan binutils untuk merakit dan menghubungkan btw output dentang.

Semua proyek ini menggunakan alat gratis, bebas, sumber terbuka, dan peralatan. tidak ada IDE, hanya baris perintah. Ya saya hanya main-main dengan Linux dan bukan Windows, tetapi alat ini tersedia untuk pengguna windows juga, mengubah hal-hal seperti rm -f sesuatu untuk del sesuatu di makefile, hal-hal seperti itu ketika membangun di windows. Itu atau jalankan linux di vmware atau virtualbox atau qemu. Tidak menggunakan IDE berarti Anda memilih editor teks Anda juga, saya tidak akan masuk ke dalamnya, saya punya favorit saya. Perhatikan bahwa fitur yang sangat menyebalkan dari program gnu make adalah membutuhkan tab yang sebenarnya di makefile, saya benci tab yang tak terlihat dengan penuh gairah. Jadi satu editor teks untuk file makefile yang meninggalkan tab, yang lain untuk kode sumber yang membuat spasi. Saya tidak tahu tentang windows,

Saya harap ini membantu, ini bukan chip / board yang tepat tetapi juga korteks-m4 m4 bukan m3, cukup dekat untuk diskusi ini. lihat mbed atau stm32vld dir untuk cortex-m3 aktual (tidak cukup perbedaan dari m4 untuk makefile dan kode boot, dll), tetapi tidak dibuat oleh st. Inti korteks-m3 harus sama di semua vendor, korteks-m3 dan korteks-m4 keduanya ARMv7m dan lebih dekat daripada berbeda. Korteks-m0 adalah ARMv6m, hampir tidak memiliki instruksi thumb2 yang cukup mengganggu, kompiler belum menyusul sehingga hanya menggunakan ibu jari saja (berpura-pura Anda sedang membangun ARMv4T (hanya ibu jari) jika perlu). Simulator thumbulator saya hanya ibu jari, tidak ada thumb2, mungkin berguna bagi Anda juga, saya pikir saya membuatnya melakukan interupsi dalam beberapa bentuk atau mode.

old_timer
sumber
Saya sedang membaca jawabannya dan saya kira pengarang untuk jawaban ini adalah ANDA. Jawaban Anda telah banyak membantu saya dan memotivasi saya untuk pindah ke prosesor ARM daripada menjadi AVR dan PIC Fanboy. Terima kasih
MaNyYaCk
Sama
2

Anda dapat melihat situs ini di mana ia mencoba menjelaskan dasar-dasar tautan dan low_level_init dalam kode.

Harap dicatat bahwa halaman ini difokuskan untuk menggambarkan masalah, sehingga vektor nvic agak minim.

Kemudian Anda memiliki contoh yang lebih lengkap di "STM32F2xx standard peripherals library", lihat saja di bagian gcc (karena Yagarto berbasis gcc). Dan ada contoh kode di sana yang akan membantu Anda dengan pengaturan yang benar dari nvic (tabel vektor interupsi).

Jadi, bahkan jika ini bukan jawaban yang lengkap, saya harap itu agak membantu.

Johan
sumber