ผลต่างระหว่างรุ่นของ "กลไกบูทโหลดเดอร์และการโปรแกรมไมโครคอนโทรลเลอร์ผ่าน UART"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
 
(ไม่แสดง 10 รุ่นระหว่างกลางโดยผู้ใช้คนเดียวกัน)
แถว 1: แถว 1:
 
ชิปไมโครคอนโทรลเลอร์ที่นำมาใช้นั้นต้องอาศัยการโปรแกรมผ่านเครื่องโปรแกรมชิป วิกินี้จะอธิบายถึงการเตรียมและบรรจุบูทโหลดเดอร์ลงไปในชิปเพื่อให้ตัวชิปสามารถโหลดโปรแกรมผ่านทางพอร์ทอนุกรมของคอมพิวเตอร์โดยไม่ต้องอาศัยเครื่องโปรแกรมชิปอีกต่อไป
 
ชิปไมโครคอนโทรลเลอร์ที่นำมาใช้นั้นต้องอาศัยการโปรแกรมผ่านเครื่องโปรแกรมชิป วิกินี้จะอธิบายถึงการเตรียมและบรรจุบูทโหลดเดอร์ลงไปในชิปเพื่อให้ตัวชิปสามารถโหลดโปรแกรมผ่านทางพอร์ทอนุกรมของคอมพิวเตอร์โดยไม่ต้องอาศัยเครื่องโปรแกรมชิปอีกต่อไป
  
=== บูทโหลดเดอร์สำหรับชิป AVR ===
+
== บูทโหลดเดอร์สำหรับชิป AVR ==
 
ศึกษาเอกสารเกี่ยวกับ Self-Programming บนชิป AVR และดาวน์โหลดโปรแกรมตัวอย่างจากลิ้งค์ต่อไปนี้
 
ศึกษาเอกสารเกี่ยวกับ Self-Programming บนชิป AVR และดาวน์โหลดโปรแกรมตัวอย่างจากลิ้งค์ต่อไปนี้
 
* [http://www.atmel.com/images/doc1644.pdf เอกสาร AVR109 Application Notes ของ Atmel]
 
* [http://www.atmel.com/images/doc1644.pdf เอกสาร AVR109 Application Notes ของ Atmel]
 
* [http://www.atmel.com/Images/AVR109.zip ซอร์สโค้ดตัวอย่างตามเอกสาร AVR109]
 
* [http://www.atmel.com/Images/AVR109.zip ซอร์สโค้ดตัวอย่างตามเอกสาร AVR109]
  
== ปรับแก้ไขโปรแกรมตัวอย่าง ==
+
== ปรับแก้ไขการตั้งค่าของบูทโหลดเดอร์ ==
โปรแกรมจาก Atmel ต้องถูกแก้ไขให้สอดรับกับวงจรที่ออกแบบขึ้น รวมถึงแก้ไขโค้ดบางอย่างที่ให้โปรแกรมคอมไพล์ได้อย่างถูกต้องสำหรับชิป ATMega168
+
โค้ดตัวอย่างจาก Atmel มาพร้อมกับเชลล์สคริปต์ <tt>preprocessor.sh</tt> (กรณีที่ใช้ยูนิกซ์) และไฟล์ Microsoft Excel <tt>preprocessor.xls</tt> (กรณีที่มีโปรแกรม Excel) ที่ใช้สำหรับสร้างไฟล์ <tt>defines.h</tt> ขึ้นมาเพื่อควบคุมการสร้างบูทโหลดเดอร์ให้สอดคล้องกับวงจรที่ออกแบบขึ้น เมื่อได้ไฟล์ <tt>defines.h</tt> แล้วให้เพิ่มคำสั่งสองบรรทัดนี้เข้าไปที่ท้ายสุดของไฟล์ เนื่องจากชิป ATMega168 ใช้ชื่อบิตสำหรับควบคุมการเขียน EEPROM ที่แตกต่างไปจากชิปตระกูล AVR เบอร์อื่น ๆ
  
=== ทำให้โค้ดคอมไพล์ได้ ===
+
#define EEMWE EEMPE
ให้เปิดไฟล์ <tt>defines.h</tt> และแก้ไขบรรทัดที่นิยามมาโครเกี่ยวกับ UART ให้เป็นดังนี้
+
#define EEWE  EEPE
  
#define BAUD_RATE_LOW_REG UBRR0
+
== แก้ไขฟิวส์ของชิปไมโครคอนโทรลเลอร์ ==
#define UART_CONTROL_REG UCSR0B
+
ชิป ATmega168 ต้องมีการปรับการตั้งค่าเพื่อให้ตัวชิปเริ่มต้นทำงานในพื้นที่บูทโหลดเดอร์แทนที่จะเริ่มทำงานในพื้นที่แอพลิเคชัน การตั้งค่าทำได้โดยการกำหนดค่าฟิวส์ในตัวชิปตามแผนผังด้านล่าง
#define ENABLE_TRANSMITTER_BIT TXEN0
 
#define ENABLE_RECEIVER_BIT RXEN0
 
#define UART_STATUS_REG UCSR0A
 
#define TRANSMIT_COMPLETE_BIT TXC0
 
#define RECEIVE_COMPLETE_BIT RXC0
 
#define UART_DATA_REG UDR0
 
  
จากนั้นเพิ่มคำสั่งสองบรรทัดนี้เข้าไปที่ท้ายสุดของไฟล์ <tt>defines.h</tt> เนื่องจากชิป ATMega168 ใช้ชื่อบิตสำหรับควบคุมการเขียน EEPROM ที่แตกต่างไปจากชิปตระกูล AVR เบอร์อื่น ๆ
+
---------------------------------------------------------------------
 +
  ATMega88, ATMega168
 +
---------------------------------------------------------------------
 +
  Fuse extended byte:
 +
  0x00 = 0 0 0 0  0 0 0 0 <-- BOOTRST (boot reset vector at 0x1800)
 +
                    \+/
 +
                      +------- BOOTSZ (00 = 2k bytes)
 +
  Fuse high byte:
 +
  0xd6 = 1 1 0 1  0 1 1 0
 +
        ^ ^ ^ ^  ^ \-+-/
 +
        | | | |  |  +------ BODLEVEL 0..2 (110 = 1.8 V)
 +
        | | | |  + --------- EESAVE (preserve EEPROM over chip erase)
 +
        | | | +-------------- WDTON (if 0: watchdog always on)
 +
        | | +---------------- SPIEN (allow serial programming)
 +
        | +------------------ DWEN (debug wire enable)
 +
        +-------------------- RSTDISBL (reset pin is enabled)
 +
  Fuse low byte:
 +
  0xdf = 1 1 0 1  1 1 1 1
 +
        ^ ^ \ /  \--+--/
 +
        | |  |      +------- CKSEL 3..0 (external >8M crystal)
 +
        | |  +--------------- SUT 1..0 (crystal osc, BOD enabled)
 +
        | +------------------ CKOUT (if 0: Clock output enabled)
 +
        +-------------------- CKDIV8 (if 0: divide by 8)
 +
---------------------------------------------------------------------
  
  #define EEMWE EEMPE
+
บรรจุการตั้งค่าเหล่านี้ลงใน <tt>Makefile</tt> ที่มาพร้อมกับซอร์สโค้ด AVR109 โดยเพิ่มเติมบรรทัดที่ระบุว่า
  #define EEWE EEPE
+
 
 +
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
 +
 
 +
ให้เป็น
 +
 
 +
  AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex -U hfuse:w:0xd6:m -U lfuse:w:0xdf:m -U efuse:w:0x00:m
 +
 
 +
<tt>Makefile</tt> ที่ให้มานั้นระบุโพรโทคอลสำหรับเครื่องโปรแกรมชิปไว้เป็น STK500 กรณีที่ใช้เครื่องโปรแกรมชิปแบบอื่นให้แก้ไขการตั้งค่าตัวแปร <tt>AVRDUDE_PROGRAMMER</tt> ให้ถูกต้อง
 +
 
 +
== ดัดแปลงบูทโหลดเดอร์ให้แสดงผลบน LED ==
 +
 
 +
ซอร์สโค้ดบูทโหลดเดอร์ต้นฉบับนั้นไม่มีการสั่งให้แสดงผลใด ๆ เพื่อแสดงสถานะของบูทโหลดเดอร์ ให้ดัดแปลงไฟล์ <tt>main.c</tt> ดังแสดง
 +
 
 +
    if( !(PROGPIN & (1<<PROG_NO)) ) // If PROGPIN is pulled low, enter programmingmode.
 +
    {
 +
        // เพิ่มโค้ดให้แสดงสถานะการเข้าสู่บูทโหลดเดอร์บน LED
 +
        :
 +
 
 +
 
 +
 
 +
== คอมไพล์บูทโหลดเดอร์และบรรจุลงชิป ==
 +
คอมไพล์บูทโหลดเดอร์ด้วยคำสั่ง <tt>make</tt>
 +
 
 +
  make
 +
 
 +
จากนั้นต่อบอร์ดเข้ากับเครื่องโปรแกรมชิป แล้วสั่งอัพโหลดบูทโหลดเดอร์ลงชิปด้วยคำสั่ง
 +
 
 +
  make program
  
=== ตรวจสอบขาอินพุทสำหรับควบคุมการเข้าบูทโหลดเดอร์ ===
+
== ใช้งานบูทโหลดเดอร์ ==
พิจารณามาโครที่ระบุเงื่อนไขการเข้าบูทโหลดเดอร์ในไฟล์ <tt>defines.h</tt>
+
เมื่อชิปไมโครคอนโทรลเลอร์บรรจุบูทโหลดเดอร์เอาไว้แล้วจะสามารถสั่งให้เข้าสู่บูทโหลดเดอร์เพื่อโปรแกรมตัวเองได้โดยไม่ต้องอาศัยเครื่องโปรแกรมชิปโดยการทำให้ชิปอยู่ในสถานะที่ตรงกับเงื่อนไขที่กำหนดเอาไว้ใน <tt>defines.h</tt> (เช่นกดสวิตช์หรือเสียบจั๊มเปอร์ค้างไว้) ในระหว่างที่กดรีเซ็ท บูทโหลดเดอร์จะสื่อสารกับคอมพิวเตอร์ด้วยอักขระคำสั่งผ่านพอร์ทอนุกรม เราจึงสามารถเขียนโปรแกรมที่อ่านรหัสภาษาเครื่องจากไฟล์ .hex เพื่อส่งไปเขียนบนหน่วยความจำแฟลชของไมโครคอนโทรลเลอร์ได้โดยง่าย
  
#define PROGPORT PORTD
+
อย่างไรก็ตามเนื่องจากซอฟต์แวร์ avrdude มีความสามารถในการสื่อสารกับบูทโหลดเดอร์ตามเอกสาร AVR109 อยู่แล้ว จึงสามารถใช้ avrdude โปรแกรมชิปได้ทันทีโดยระบุโพรโทคอลการสื่อสารเป็น avr109 ดังตัวอย่าง
#define PROGPIN PIND
 
#define PROG_NO PD4
 
  
แก้ไขนิยามให้สอดคล้องกับวงจรที่ออกแบบไว้ โดยเงื่อนไขการเข้าบูทโหลดเดอร์คือสวิตช์ USER ต้องถูกกดค้างเอาไว้หลังจากรีเซ็ท
+
avrdude -p atmega168 -c avr109 -P /dev/ttyUSB0 -U flash:w:first.hex:i

รุ่นแก้ไขปัจจุบันเมื่อ 09:44, 20 กรกฎาคม 2559

ชิปไมโครคอนโทรลเลอร์ที่นำมาใช้นั้นต้องอาศัยการโปรแกรมผ่านเครื่องโปรแกรมชิป วิกินี้จะอธิบายถึงการเตรียมและบรรจุบูทโหลดเดอร์ลงไปในชิปเพื่อให้ตัวชิปสามารถโหลดโปรแกรมผ่านทางพอร์ทอนุกรมของคอมพิวเตอร์โดยไม่ต้องอาศัยเครื่องโปรแกรมชิปอีกต่อไป

บูทโหลดเดอร์สำหรับชิป AVR

ศึกษาเอกสารเกี่ยวกับ Self-Programming บนชิป AVR และดาวน์โหลดโปรแกรมตัวอย่างจากลิ้งค์ต่อไปนี้

ปรับแก้ไขการตั้งค่าของบูทโหลดเดอร์

โค้ดตัวอย่างจาก Atmel มาพร้อมกับเชลล์สคริปต์ preprocessor.sh (กรณีที่ใช้ยูนิกซ์) และไฟล์ Microsoft Excel preprocessor.xls (กรณีที่มีโปรแกรม Excel) ที่ใช้สำหรับสร้างไฟล์ defines.h ขึ้นมาเพื่อควบคุมการสร้างบูทโหลดเดอร์ให้สอดคล้องกับวงจรที่ออกแบบขึ้น เมื่อได้ไฟล์ defines.h แล้วให้เพิ่มคำสั่งสองบรรทัดนี้เข้าไปที่ท้ายสุดของไฟล์ เนื่องจากชิป ATMega168 ใช้ชื่อบิตสำหรับควบคุมการเขียน EEPROM ที่แตกต่างไปจากชิปตระกูล AVR เบอร์อื่น ๆ

#define EEMWE EEMPE
#define EEWE  EEPE

แก้ไขฟิวส์ของชิปไมโครคอนโทรลเลอร์

ชิป ATmega168 ต้องมีการปรับการตั้งค่าเพื่อให้ตัวชิปเริ่มต้นทำงานในพื้นที่บูทโหลดเดอร์แทนที่จะเริ่มทำงานในพื้นที่แอพลิเคชัน การตั้งค่าทำได้โดยการกำหนดค่าฟิวส์ในตัวชิปตามแผนผังด้านล่าง

---------------------------------------------------------------------
 ATMega88, ATMega168
---------------------------------------------------------------------
 Fuse extended byte:
 0x00 = 0 0 0 0   0 0 0 0 <-- BOOTRST (boot reset vector at 0x1800)
                    \+/
                     +------- BOOTSZ (00 = 2k bytes)
 Fuse high byte:
 0xd6 = 1 1 0 1   0 1 1 0
        ^ ^ ^ ^   ^ \-+-/
        | | | |   |   +------ BODLEVEL 0..2 (110 = 1.8 V)
        | | | |   + --------- EESAVE (preserve EEPROM over chip erase)
        | | | +-------------- WDTON (if 0: watchdog always on)
        | | +---------------- SPIEN (allow serial programming)
        | +------------------ DWEN (debug wire enable)
        +-------------------- RSTDISBL (reset pin is enabled)
 Fuse low byte:
 0xdf = 1 1 0 1   1 1 1 1
        ^ ^ \ /   \--+--/
        | |  |       +------- CKSEL 3..0 (external >8M crystal)
        | |  +--------------- SUT 1..0 (crystal osc, BOD enabled)
        | +------------------ CKOUT (if 0: Clock output enabled)
        +-------------------- CKDIV8 (if 0: divide by 8)
---------------------------------------------------------------------

บรรจุการตั้งค่าเหล่านี้ลงใน Makefile ที่มาพร้อมกับซอร์สโค้ด AVR109 โดยเพิ่มเติมบรรทัดที่ระบุว่า

AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex

ให้เป็น

AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex -U hfuse:w:0xd6:m -U lfuse:w:0xdf:m -U efuse:w:0x00:m

Makefile ที่ให้มานั้นระบุโพรโทคอลสำหรับเครื่องโปรแกรมชิปไว้เป็น STK500 กรณีที่ใช้เครื่องโปรแกรมชิปแบบอื่นให้แก้ไขการตั้งค่าตัวแปร AVRDUDE_PROGRAMMER ให้ถูกต้อง

ดัดแปลงบูทโหลดเดอร์ให้แสดงผลบน LED

ซอร์สโค้ดบูทโหลดเดอร์ต้นฉบับนั้นไม่มีการสั่งให้แสดงผลใด ๆ เพื่อแสดงสถานะของบูทโหลดเดอร์ ให้ดัดแปลงไฟล์ main.c ดังแสดง

   if( !(PROGPIN & (1<<PROG_NO)) ) // If PROGPIN is pulled low, enter programmingmode.
   {
       // เพิ่มโค้ดให้แสดงสถานะการเข้าสู่บูทโหลดเดอร์บน LED
       :


คอมไพล์บูทโหลดเดอร์และบรรจุลงชิป

คอมไพล์บูทโหลดเดอร์ด้วยคำสั่ง make

make

จากนั้นต่อบอร์ดเข้ากับเครื่องโปรแกรมชิป แล้วสั่งอัพโหลดบูทโหลดเดอร์ลงชิปด้วยคำสั่ง

make program

ใช้งานบูทโหลดเดอร์

เมื่อชิปไมโครคอนโทรลเลอร์บรรจุบูทโหลดเดอร์เอาไว้แล้วจะสามารถสั่งให้เข้าสู่บูทโหลดเดอร์เพื่อโปรแกรมตัวเองได้โดยไม่ต้องอาศัยเครื่องโปรแกรมชิปโดยการทำให้ชิปอยู่ในสถานะที่ตรงกับเงื่อนไขที่กำหนดเอาไว้ใน defines.h (เช่นกดสวิตช์หรือเสียบจั๊มเปอร์ค้างไว้) ในระหว่างที่กดรีเซ็ท บูทโหลดเดอร์จะสื่อสารกับคอมพิวเตอร์ด้วยอักขระคำสั่งผ่านพอร์ทอนุกรม เราจึงสามารถเขียนโปรแกรมที่อ่านรหัสภาษาเครื่องจากไฟล์ .hex เพื่อส่งไปเขียนบนหน่วยความจำแฟลชของไมโครคอนโทรลเลอร์ได้โดยง่าย

อย่างไรก็ตามเนื่องจากซอฟต์แวร์ avrdude มีความสามารถในการสื่อสารกับบูทโหลดเดอร์ตามเอกสาร AVR109 อยู่แล้ว จึงสามารถใช้ avrdude โปรแกรมชิปได้ทันทีโดยระบุโพรโทคอลการสื่อสารเป็น avr109 ดังตัวอย่าง

avrdude -p atmega168 -c avr109 -P /dev/ttyUSB0 -U flash:w:first.hex:i