http://github.com/dwelch67
โดยเฉพาะอย่างยิ่ง stm32f4 และ stm32vld แต่คนอื่น ๆ อาจเป็นประโยชน์กับคุณเช่นกัน mbed และไดเร็กทอรี mzero ภายใต้ mbed (cortex-m0)
ฉันชอบวิธีการที่เรียบง่ายแบบเรียบง่ายสคริปต์ตัวเชื่อมโยงขั้นต่ำรหัสเริ่มต้นขั้นต่ำ ฯลฯ การทำงานนั้นทำโดยรหัสไม่ใช่ toolchain ใด ๆ
รูปแบบส่วนใหญ่ของ gcc และ binutils (สามารถใช้นิ้วโป้งได้) จะทำงานกับตัวอย่างเหล่านี้เมื่อฉันใช้คอมไพเลอร์เพื่อคอมไพล์ไม่ใช่ทรัพยากรสำหรับการโทรในห้องสมุด ชิ้นส่วน thumb2 ที่ใหม่กว่าดังนั้นการเปลี่ยนแปลงบางอย่างอาจจำเป็น
ฉันสร้าง gcc, binutils และ llvm / clang ของตัวเองรวมทั้งใช้ codesourcery เช่นกัน (ตอนนี้เป็น mentor graphics แต่คุณยังสามารถรับเวอร์ชั่นฟรี / lite ได้)
Esp เมื่อเริ่มต้นรวบรวมโครงการสำหรับเป้าหมายใหม่ที่คุณต้องทำการถอดแยกชิ้นส่วน โดยเฉพาะอย่างยิ่งเพื่อให้แน่ใจว่ารายการอยู่ในตำแหน่งที่คุณต้องการตัวอย่างเช่นตารางเวกเตอร์
ดูตัวอย่าง stm32f4d / blinker02 มันเริ่มต้นด้วย vectors.s ตารางข้อยกเว้น / เวกเตอร์บวกรูทีนการสนับสนุน 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 มีเนื้อหาหลักของรหัส C ที่มีจุดเข้าใช้งาน C ที่ฉันเรียกว่า notmain () เพื่อหลีกเลี่ยงการเรียกมันว่า main (คอมไพเลอร์บางตัวเพิ่มขยะในไบนารีของคุณเมื่อคุณมี main ())
จะให้คุณตัดและวาง makefile บอกเล่าเรื่องราวเกี่ยวกับการรวบรวมและการเชื่อมโยง โปรดทราบว่าตัวอย่างจำนวนหนึ่งของฉันรวบรวมไบนารีสองตัวหรือมากกว่าจากรหัสเดียวกัน คอมไพเลอร์ gcc, คอมไพเลอร์เสียงดังกราวของ llvm, thumb only และ 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
linker, ld, ใช้ linker script ซึ่งผมเรียกว่า memmap ซึ่งอาจเจ็บปวดอย่างมากบางครั้งก็มีเหตุผลที่ดี ฉันชอบวิธีที่น้อยกว่าคือมีขนาดที่เหมาะกับทุกคนมากขึ้นทุกอย่างยกเว้นวิธีเข้าครัว
ฉันไม่ใช้. data โดยทั่วไป (แทบไม่เคย) และตัวอย่างนี้ไม่จำเป็นต้องมี. bbs ดังนั้นนี่คือสคริปต์ linker ซึ่งเพียงพอที่จะวางโปรแกรม (.text) ที่มันต้องการโปรเซสเซอร์สำหรับพวกเขาในแบบที่ฉันเป็น ใช้มัน
MEMORY
{
ram : ORIGIN = 0x08000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > ram
}
ฉันมีพื้นที่หน่วยความจำเพื่อกำหนดว่าไม่มีอะไรพิเศษเกี่ยวกับชื่อ ram ที่คุณสามารถเรียกได้ว่า foo หรือ bar หรือ bob หรือ ted ไม่สำคัญว่ามันจะเชื่อมโยงรายการหน่วยความจำไปยังส่วนต่างๆ ส่วนกำหนดสิ่งต่าง ๆ เช่น. 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 เว้นแต่ว่าคุณจะทำบางสิ่งในสคริปต์ linker รายการจะแสดง ขึ้นในไบนารีตามลำดับพวกเขาอยู่ในบรรทัดคำสั่ง 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 เริ่มการโทรไม่ได้หลัก ()
08000098 <notmain>:
8000098: b510 push {
ที่ดูดี (พวกเขาไม่แสดงที่อยู่เลขคี่ในการถอดแยกชิ้นส่วน)
ทั้งหมดเป็นอย่างดี.
ข้ามไปที่ตัวอย่าง blinker05 อันนี้รองรับอินเตอร์รัปต์ และต้องการ ram บางตัวดังนั้น. BSS จึงถูกกำหนด
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x100000
ram : ORIGIN = 0x20000000, LENGTH = 0x1C000
}
SECTIONS
{
.text : { *(.text*) } > rom
.bss : { *(.bss*) } > ram
}
จำ ram และ rom เป็นชื่อโดยพลการ, bob และ ted, foo และ bar ทำงานได้ดี
จะไม่แสดงเวกเตอร์ทั้งหมดเนื่องจาก cortex-m3 มีรายการ zillion ในตารางเวกเตอร์ถ้าคุณสร้างครบหนึ่งรายการ (แตกต่างกันไปจากแกนหนึ่งถึงแกนกลางและอาจอยู่ในแกนเดียวกันขึ้นอยู่กับตัวเลือกที่ผู้จำหน่ายชิปเลือก) ส่วนที่เกี่ยวข้องอยู่ที่นี่หลังจากถอดแยกชิ้นส่วน:
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
//-------------------------------------------------------------------
makefile สำหรับ blinker05 ควรคล้ายกับตัวอย่างของ blinker02 ซึ่งส่วนใหญ่จะถูกตัดและวางสำหรับส่วนใหญ่ เปลี่ยนไฟล์ต้นฉบับให้เป็นวัตถุแล้วเชื่อมโยง ฉันสร้างสำหรับ thumb, thumb2 โดยใช้ gcc และ clang คุณสามารถเปลี่ยนบรรทัด: ในเวลาที่จะรวมรายการ gcc เท่านั้นหากคุณไม่ต้องการ / ต้องการ clang (llvm) ที่เกี่ยวข้อง ฉันใช้ binutils เพื่อประกอบและเชื่อมโยงเอาท์พุทเสียงดังกราว btw
โครงการทั้งหมดเหล่านี้ใช้ฟรีปิดชั้นวางโอเพนซอร์ซเครื่องมือ ไม่มีของ IDE บรรทัดคำสั่งเท่านั้น ใช่ฉันแค่ยุ่งกับ Linux และไม่ใช่ Windows แต่เครื่องมือเหล่านี้พร้อมใช้งานสำหรับผู้ใช้ windows เช่นกันเปลี่ยนสิ่งต่าง ๆ เช่น rm -f เพื่อลบบางสิ่งบางอย่างใน makefile สิ่งต่าง ๆ เช่นเมื่อสร้างบน windows หรือเรียกใช้ linux บน vmware หรือ virtualbox หรือ qemu การไม่ใช้ IDE หมายความว่าคุณเลือกโปรแกรมแก้ไขข้อความของคุณเช่นกันฉันจะไม่เป็นเช่นนั้นฉันมีสิ่งที่ฉันชอบ โปรดทราบว่าคุณลักษณะที่น่ารำคาญอย่างยิ่งของโปรแกรมสร้าง gnu คือต้องใช้แท็บจริงใน makefile ฉันเกลียดแท็บที่มองไม่เห็นด้วยความหลงใหล ดังนั้นหนึ่งแก้ไขข้อความสำหรับ makefiles ที่ออกจากแท็บอื่น ๆ สำหรับซอร์สโค้ดที่ทำให้ช่องว่าง ฉันไม่รู้เกี่ยวกับ windows
ฉันหวังว่านี่จะช่วยได้ไม่ใช่ชิพ / บอร์ดที่แน่นอน แต่ cortex-m4 ก็ดี m4 ไม่ใช่ m3 ใกล้พอสำหรับการอภิปรายนี้ ดู mbed หรือ stm32vld dir สำหรับ cortex-m3 ที่เกิดขึ้นจริง (ความแตกต่างไม่เพียงพอจาก m4 สำหรับ makefiles และ boot code ฯลฯ ) แต่ไม่ได้ทำโดย st คอร์เท็กซ์ -m3 คอร์เท็กซ์ควรจะเหมือนกันในผู้ขายคอร์เทกซ์ -m3 และคอร์เท็กซ์ -m4 นั้นมีทั้ง ARMv7m และอยู่ใกล้กว่าต่างกัน cortex-m0 นั้นเป็น ARMv6m แทบจะไม่ได้มีคำสั่ง thumb2 เพียงพอที่จะรบกวนคอมไพเลอร์ยังไม่ทันกับมันดังนั้นเพียงแค่ใช้นิ้วโป้งเท่านั้น เครื่องจำลองนิ้วหัวแม่มือของฉันคือนิ้วหัวแม่มือเท่านั้นไม่มี thumb2 มันอาจเป็นประโยชน์กับคุณเช่นกันฉันคิดว่าฉันทำให้มันขัดจังหวะในบางรูปแบบหรือแฟชั่น