การพัฒนาเฟิร์มแวร์สำหรับไมโครคอนโทรลเลอร์
วิกินี้อธิบายถึงขั้นตอนและตัวอย่างการพัฒนาเฟิร์มแวร์ลงบนบอร์ดไมโครคอนโทรลเลอร์ที่เราได้ประกอบขึ้นมา โดยเนื้อหาครอบคลุมเฉพาะสภาพแวดล้อมการพัฒนาโปรแกรมบนลินุกซ์เท่านั้น
เนื้อหา
ติดตั้งซอฟท์แวร์ที่เกี่ยวข้อง
- ครอสคอมไพเลอร์ (cross compiler) สำหรับไมโครคอนโทรลเลอร์ตระกูล AVR รวมถึงไลบรารีที่เกี่ยวข้อง
sudo apt-get install avr-gcc avr-libc
- AVR toolchain
sudo apt-get install binutils-avr
- AVRDUDE (AVR Downloader/UploaDEr) ใช้สำหรับโหลดรหัสภาษาเครื่องลงบนหน่วยความจำแฟลชของไมโครคอนโทรลเลอร์ผ่านพอร์ต USB
sudo apt-get install avrdude
โปรแกรมตัวอย่าง
ทดลองพิมพ์โปรแกรมตัวอย่างต่อไปนี้ และบันทึกไว้ในชื่อ first.c
#define F_CPU 16000000UL // บอกไลบรารีว่า MCU ทำงานที่ 16MHz #include <avr/io.h> #include <util/delay.h> int main(void) { PORTD = 0b00000000; // กำหนดลอจิกขา PD7..0 เป็น 0 DDRD = 0b00001000; // กำหนดให้ขา PD3 ทำหน้าที่เอาท์พุท while (1) { PORTD = 0b00001000; // ส่งลอจิก 1 ไปที่ขา PD3 _delay_ms(1000); PORTD = 0b00001000; // ส่งลอจิก 0 ไปที่ขา PD3 _delay_ms(1000); } return 0; }
โปรแกรมข้างต้นเรียกใช้ค่าคงที่สำหรับ I/O รีจีสเตอร์จากไฟล์เฮดเดอร์ avr/io.h
และฟังก์ชันหน่วงเวลาจากไฟล์เฮดเดอร์ util/delay.h
การคอมไพล์และสร้างรหัสภาษาเครื่อง
คอมไพล์โปรแกรมโดยเรียกใช้คำสั่ง avr-gcc
ซึ่งเป็นครอสคอมไพเลอร์ที่ทำหน้าที่แปลโปรแกรมให้เป็นรหัสภาษาเครื่องสำหรับสถาปัตยกรรม AVR
avr-gcc -mmcu=atmega168 -O -o first.elf first.c
อ็อพชันต่าง ๆ ที่ระบุในคำสั่งข้างต้นมีหน้าที่ดังนี้
-mmcu=atmega168
เป็นตัวบอกคอมไพเลอร์ว่าไมโครคอนโทรลเลอร์ที่ใช้เป็นเบอร์ ATMega168-O
ระบุว่าให้คอมไพเลอร์ทำ code optimization ซึ่งจำเป็นต้องใช้เพื่อให้ฟังก์ชัน_delay_ms()
ทำงานได้ถูกต้อง-o first.elf
ระบุว่าให้เอาท์พุทถูกเก็บลงในไฟล์first.elf
หากไม่ระบุโปรแกรมจะสร้างไฟล์ชื่อa.out
แทน
ผลลัพธ์ที่ได้จะอยู่ในรูปของไฟล์ฟอร์แมต ELF (Excutable and Linkable Format) ซึ่งประกอบไปด้วยเฮดเดอร์และข้อมูลเสริมอื่น ๆ อีกมากมาย อย่างไรก็ตามเราต้องการเพียงแค่ส่วนที่เป็นรหัสภาษาเครื่องของโปรแกรม ซึ่งสกัดออกมาได้โดยใช้คำสั่ง avr-objcopy
ดังนี้
avr-objcopy -j .text -O ihex first.elf first.hex
อ็อพชันต่าง ๆ ที่ระบุในคำสั่งข้างต้นมีหน้าที่ดังนี้
-j .text
สกัดข้อมูลจากเซคชัน .text ซึ่งเป็นเซคชันที่เก็บโค้ดโปรแกรมในไฟล์ ELF-O ihex
ส่งเอาท์พุทในรูปแบบ Intel HEX
ผลลัพธ์ที่ได้จะถูกเก็บไว้ในไฟล์ first.hex
ซึ่งเป็นไฟล์ ASCII โดยภายในไฟล์จะมีข้อมูลคล้ายคลึงกับที่แสดงในตัวอย่าง
$ cat first.hex :100000000C9434000C9451000C9451000C94510049 :100010000C9451000C9451000C9451000C9451001C :100020000C9451000C9451000C9451000C9451000C :100030000C9451000C9451000C9451000C945100FC :100040000C9451000C9451000C9451000C945100EC :100050000C9451000C9451000C9451000C945100DC :100060000C9451000C94510011241FBECFEFD4E02A :10007000DEBFCDBF11E0A0E0B1E0E4EEF0E002C0F1 :1000800005900D92A030B107D9F711E0A0E0B1E0E2 :1000900001C01D92A030B107E1F70E9453000C94FB :1000A00071000C940000CFEFD4E0DEBFCDBF1BB8D1 :1000B00088E08AB988E08BB928EE33E080E991E0E6 :1000C0000197F1F721503040C9F788E08BB928EE4D :1000D00033E080E991E00197F1F721503040C9F712 :0400E000E9CFFFCF96 :00000001FF
การเขียนโปรแกรมลงบนหน่วยความจำแฟลชของไมโครคอนโทรลเลอร์
ดูรูป
ใช้คำสั่ง avrdude
avrdude -p atmega168 -c usbasp -u -U flash:w:first.hex