
ยกระดับการพัฒนาเฟิร์มแวร์ด้วย OTA พร้อมเรียนรู้หลักการทำงานและแนวทางการนำไปใช้
การอัปเดตเฟิร์มแวร์แบบไร้สาย (OTA) ช่วยให้สามารถแก้ไขซอฟต์แวร์ของอุปกรณ์ฝังตัวจากระยะไกลได้โดยไม่ต้องเข้าถึงตัวอุปกรณ์ และกลายเป็นสิ่งจำเป็นสำหรับการรักษาความปลอดภัย แก้ไขข้อผิดพลาด และเพิ่มคุณสมบัติใหม่ให้กับอุปกรณ์ IoT ที่ใช้งานอยู่ตลอดอายุการใช้งาน ระบบ OTA ประกอบด้วยส่วนประกอบหลายอย่าง ได้แก่ กระบวนการสร้างและลงนามเฟิร์มแวร์ เซิร์ฟเวอร์กระจายหรือ CDN ตัวแทนการอัปเดตฝั่งอุปกรณ์ บูตโหลดเดอร์ที่สามารถจัดการช่องเฟิร์มแวร์หลายช่อง และกลไกการรายงานสถานะการอัปเดต สถาปัตยกรรมที่พบมากที่สุดคือการแบ่งพาร์ติชันแบบ A/B (dual-bank) โดยเฟิร์มแวร์ใหม่จะถูกดาวน์โหลดไปยังช่องที่ไม่ได้ใช้งานในขณะที่เฟิร์มแวร์ปัจจุบันยังคงทำงานอยู่ จากนั้นบูตโหลดเดอร์จะสลับไปยังช่องที่ใช้งานอยู่เมื่อรีบูตหลังจากตรวจสอบลายเซ็นการเข้ารหัสของอิมเมจใหม่แล้ว วิธีนี้ช่วยให้มั่นใจได้ว่าอุปกรณ์จะมีระบบสำรองที่ใช้งานได้ดีเสมอหากการอัปเดตล้มเหลว การอัปเดตแบบเดลต้า (differential) ช่วยลดขนาดการดาวน์โหลดโดยการส่งเฉพาะส่วนต่างของไบนารีระหว่างเวอร์ชันเฟิร์มแวร์ ซึ่งมีความสำคัญอย่างยิ่งสำหรับอุปกรณ์ที่มีแบนด์วิดท์จำกัดที่ใช้ LoRaWAN หรือ NB-IoT ซึ่งการถ่ายโอนอิมเมจแบบเต็มจะใช้เวลาหลายชั่วโมง
ในระบบแบ่งพาร์ติชั่นแบบ A/B หน่วยความจำแฟลชของอุปกรณ์จะถูกแบ่งออกเป็นพื้นที่บูตโหลดเดอร์ สล็อต 0 (หลัก/ใช้งาน) และสล็อต 1 (รอง/เตรียมการ) เมื่อมีการอัปเดต โปรแกรมอัปเดตจะดาวน์โหลดอิมเมจเฟิร์มแวร์ที่ลงนามแล้วใหม่ลงในสล็อต 1 ในขณะที่แอปพลิเคชันในสล็อต 0 ยังคงทำงานตามปกติ เมื่อการดาวน์โหลดเสร็จสมบูรณ์และตรวจสอบความถูกต้องของส่วนหัวของอิมเมจแล้ว อุปกรณ์จะตั้งค่าสถานะสล็อต 1 เป็นรอการดำเนินการและรีบูต บูตโหลดเดอร์ (โดยทั่วไปคือ MCUboot) จะอ่านสถานะรอการดำเนินการ ตรวจสอบลายเซ็นการเข้ารหัสของอิมเมจในสล็อต 1 และสลับสล็อตทั้งสองหรือบูตจากสล็อตใหม่โดยตรง หลังจากบูตครั้งแรก แอปพลิเคชันจะต้องยืนยันการอัปเดตโดยการตั้งค่าสถานะ "ยืนยันแล้ว" มิฉะนั้น บูตโหลดเดอร์จะย้อนกลับไปใช้อิมเมจก่อนหน้าในการรีบูตครั้งถัดไป ซึ่งเป็นการป้องกันการย้อนกลับอัตโนมัติ
/* MCUboot swap states and OTA flow */
// Device flash layout
// ┌──────────────────┐ 0x00000
// │ MCUboot │ (32 KB)
// ├──────────────────┤ 0x08000
// │ Slot 0 (Active) │ (384 KB)
// ├──────────────────┤ 0x68000
// │ Slot 1 (Staging)│ (384 KB)
// ├──────────────────┤ 0xC8000
// │ Scratch Area │ (16 KB)
// └──────────────────┘
// OTA update agent pseudocode
void ota_update_task(void) {
fw_image_t *image = ota_check_for_update();
if (image == NULL) return;
// Download to Slot 1
ota_download_to_slot1(image->url, image->size);
// Verify checksum before requesting swap
if (verify_sha256(SLOT1_ADDR, image->size, image->hash)) {
boot_request_upgrade();
NVIC_SystemReset();
}
}
// After boot, confirm update succeeded
void app_init(void) {
if (boot_is_img_confirmed() == false) {
if (self_test_passed()) {
boot_write_img_confirmed();
}
// If not confirmed, MCUboot will revert on next reboot
}
}การอัปเดตแบบเดลต้า (ดิฟเฟอเรนเชียล) จะส่งเฉพาะส่วนต่างของไบนารีระหว่างเวอร์ชันเฟิร์มแวร์ปัจจุบันและเวอร์ชันเป้าหมาย ซึ่งช่วยลดขนาดการดาวน์โหลดได้อย่างมาก เครื่องมืออย่าง jdiff, bsdiff หรือโมดูลการอัปเดตแบบเดลต้าของ Mender สามารถบีบอัดส่วนต่างของเฟิร์มแวร์ให้เหลือเพียง 10-30% ของขนาดอิมเมจเต็ม ซึ่งมีความสำคัญอย่างยิ่งสำหรับอุปกรณ์ที่เชื่อมต่อ LPWAN เนื่องจากอิมเมจเฟิร์มแวร์ขนาด 256 KB ที่อัตราการส่งข้อมูล LoRaWAN อาจใช้เวลาดาวน์โหลดมากกว่า 30 นาทีหากเป็นอิมเมจเต็ม แต่ใช้เวลาน้อยกว่า 5 นาทีหากเป็นการอัปเดตแบบเดลต้า ข้อเสียคือการอัปเดตแบบเดลต้าต้องการให้อุปกรณ์มี RAM หรือแฟลชชั่วคราวเพียงพอในการสร้างอิมเมจเต็มขึ้นมาใหม่ และต้องสร้างการอัปเดตแบบเดลต้าสำหรับแต่ละการเปลี่ยนจากเวอร์ชันต้นทางไปยังเวอร์ชันเป้าหมายโดยเฉพาะ
แพลตฟอร์มการอัปเดต OTA หลักๆ และจุดแข็งของแต่ละแพลตฟอร์ม:
ความน่าเชื่อถือของการอัปเดตแบบไร้สาย (OTA) ต้องอาศัยการออกแบบทางวิศวกรรมที่รอบคอบ ควรใช้การตรวจสอบความถูกต้องของข้อมูล (checksum) ในหลายระดับ ได้แก่ ความสมบูรณ์ของเลเยอร์การขนส่ง (TLS), แฮช SHA-256 ระดับอิมเมจ และการตรวจสอบลายเซ็น ใช้ตัวจับเวลาเฝ้าระวัง (watchdog timer) เพื่อตรวจจับการวนลูปการบูตและเรียกใช้การย้อนกลับอัตโนมัติ ทดสอบการอัปเดตกับฮาร์ดแวร์ทุกเวอร์ชันในอุปกรณ์ของคุณก่อนที่จะใช้งานในวงกว้าง ดำเนินการทดสอบแบบเป็นขั้นตอน (canary deployments) โดยเริ่มจากการอัปเดต 1%, 10% และ 100% ของอุปกรณ์ และตรวจสอบอัตราข้อผิดพลาดในแต่ละขั้นตอน เก็บรักษาบันทึกสถานะการอัปเดตอย่างถาวรเพื่อให้ระบบคลาวด์สามารถติดตามได้ว่าอุปกรณ์ใดอัปเดตสำเร็จ อุปกรณ์ใดล้มเหลว และเพราะเหตุใด สำหรับอุปกรณ์ที่ใช้แบตเตอรี่ ควรตรวจสอบระดับแบตเตอรี่ก่อนเริ่มการอัปเดต การอัปเดตที่ล้มเหลวระหว่างการเขียนเนื่องจากการสูญเสียพลังงานอาจทำให้อุปกรณ์เสียหายได้
ประเด็นสำคัญ: การอัปเดตเฟิร์มแวร์แบบ OTA จำเป็นต้องมีการแบ่งพาร์ติชั่นแฟลชแบบ A/B เพื่อการย้อนกลับที่ปลอดภัย การตรวจสอบลายเซ็นเข้ารหัสลับ (ECDSA P-256 หรือ Ed25519) เพื่อป้องกันการเรียกใช้โค้ดโดยไม่ได้รับอนุญาต ตัวนับเวอร์ชันแบบโมโนโทนิกเพื่อป้องกันการย้อนกลับ และการติดตั้งใช้งานในกลุ่มอุปกรณ์แบบเป็นขั้นตอน การอัปเดตแบบเดลต้าช่วยลดขนาดการดาวน์โหลดลง 70-90% สำหรับอุปกรณ์ LPWAN ที่มีแบนด์วิดท์จำกัด
ที่ EmbedCrest เราได้ออกแบบและติดตั้งโครงสร้างพื้นฐาน OTA สำหรับบริษัทมิเตอร์อัจฉริยะที่มีมิเตอร์น้ำเชื่อมต่อ LoRaWAN จำนวน 10,000 เครื่องทั่วพื้นที่เมืองใหญ่ มิเตอร์แต่ละเครื่องใช้ไมโครคอนโทรลเลอร์ STM32L4 ที่มีหน่วยความจำแฟลช 1 MB แบ่งเป็น MCUboot ขนาด 32 KB, Slot 0 (ใช้งานอยู่) ขนาด 448 KB, Slot 1 (เตรียมการ) ขนาด 448 KB และพื้นที่ชั่วคราวขนาด 16 KB เนื่องจากข้อจำกัดด้านแบนด์วิดท์ของ LoRaWAN (ประมาณ 50 ไบต์ต่อลิงก์อัปที่ SF10) การถ่ายโอนภาพเฟิร์มแวร์ขนาด 200 KB เต็มรูปแบบจะใช้แพ็กเก็ตมากกว่า 4,000 แพ็กเก็ตและใช้เวลานานกว่า 40 ชั่วโมง เราจึงนำการอัปเดตแบบเดลต้าโดยใช้ bsdiff มาใช้ ซึ่งบีบอัดการเปลี่ยนแปลงเฟิร์มแวร์ทั่วไปให้เหลือเพียง 15-30 KB ลดเวลาการถ่ายโอนเหลือ 3-6 ชั่วโมงต่ออุปกรณ์ กระบวนการอัปเดตใช้โหมดมัลติแคสต์คลาส C: มิเตอร์จะเปลี่ยนจากคลาส A (พลังงานต่ำสุด) ไปเป็นคลาส C (รับฟังอย่างต่อเนื่อง) ชั่วคราวในช่วงเวลาการบำรุงรักษาตามกำหนดการ รับข้อมูลส่วนต่างผ่านลิงก์ดาวน์ลิงก์มัลติแคสต์ และเปลี่ยนกลับไปเป็นคลาส A หลังจากได้รับการยืนยัน เราดำเนินการติดตั้งใน 5 ขั้นตอน: กลุ่มทดสอบ 1%, 10%, 25%, 50% และ 100% โดยตรวจสอบอัตราความสำเร็จ การตรวจจับลูปการบูต และความผิดปกติของการใช้พลังงานในแต่ละขั้นตอน
โหมดความล้มเหลว OTA ที่ร้ายแรงที่สุดคืออุปกรณ์เสียหายจนไม่สามารถกู้คืนได้หากไม่มีการเข้าถึงทางกายภาพ ปัญหานี้เกิดขึ้นเมื่อบูตโหลดเดอร์เสียหายหรือเมื่อช่องเสียบเฟิร์มแวร์ทั้งสองช่องมีอิมเมจที่ไม่ถูกต้อง วิธีแก้ไขคือทำให้บูตโหลดเดอร์ไม่สามารถเปลี่ยนแปลงได้ (วางไว้ในพื้นที่แฟลชที่ป้องกันการเขียน) ใช้พาร์ติชั่นกู้คืนอิมเมจต้นแบบ (เฟิร์มแวร์ขนาดเล็กในพื้นที่แฟลชที่ป้องกันแยกต่างหาก ซึ่งบูตโหลดเดอร์ ROM จะใช้เป็นตัวสำรอง) และตรวจสอบระดับแบตเตอรี่ก่อนเริ่มกระบวนการอัปเดต สำหรับอุปกรณ์ STM32 ให้กำหนดค่า Option Bytes เพื่อป้องกันการเขียนพื้นที่แฟลชบูตโหลดเดอร์โดยใช้บิต WRP (Write Protection) ความล้มเหลวที่อันตรายอีกอย่างคือการอัปเดตสำเร็จแต่มีข้อบกพร่องเล็กน้อยที่ตรวจพบได้หลังจากนั้นหลายสัปดาห์ หลังจากที่อัปเดตอุปกรณ์ทั้งหมดแล้ว วิธีแก้ไขคือใช้การตรวจสอบสถานะอัตโนมัติ: เฟิร์มแวร์ที่อัปเดตแล้วต้องยืนยันตัวเองภายในระยะเวลาที่กำหนดได้ (30-300 วินาที) โดยการเรียกใช้ boot_write_img_confirmed() มิฉะนั้นบูตโหลดเดอร์จะกลับไปสู่สถานะเดิมโดยอัตโนมัติ ควรเพิ่มการทดสอบตัวเองเชิงฟังก์ชัน (การตรวจสอบความถูกต้องของการอ่านค่าเซ็นเซอร์ การวนรอบการสื่อสาร การตรวจสอบการทำงานของระบบเฝ้าระวัง) เข้าไปในตรรกะการยืนยัน ไม่ใช่แค่การใช้ตัวจับเวลาแบบง่ายๆ เท่านั้น
การอัปเดตอิมเมจแบบเต็มจะส่งไบนารีเฟิร์มแวร์ทั้งหมดที่ได้รับการตรวจสอบโดยแฮช SHA-256 และลายเซ็น ECDSA การอัปเดตแบบนี้ทำได้ง่ายกว่า ไม่ต้องใช้ตรรกะการสร้างใหม่ฝั่งไคลเอ็นต์ และสามารถอัปเดตจากเวอร์ชันใดก็ได้ไปยังเวอร์ชันใดก็ได้ อย่างไรก็ตาม การอัปเดตแบบนี้ใช้แบนด์วิดท์และเวลาในการถ่ายโอนสูงสุด ส่วนการอัปเดตแบบเดลต้าจะส่งเฉพาะส่วนต่างของไบนารีระหว่างเวอร์ชันปัจจุบันและเวอร์ชันเป้าหมาย ซึ่งสร้างขึ้นโดยใช้อัลกอริทึม เช่น bsdiff, xdelta3 หรือ mender-binary-delta ของ Mender แพทช์เดลต้าโดยทั่วไปจะมีขนาด 10-30% ของขนาดอิมเมจแบบเต็มสำหรับการอัปเดตเล็กน้อย และ 40-60% สำหรับการปรับโครงสร้างครั้งใหญ่ ข้อเสียของการอัปเดตแบบเดลต้ามีมากมาย: การอัปเดตแบบเดลต้าต้องการให้เครื่องมี RAM หรือแฟลชชั่วคราวเพียงพอในการใช้แพทช์ (bsdiff ต้องการหน่วยความจำทำงานประมาณ 2 เท่าของขนาดแพทช์) ต้องสร้างแพทช์สำหรับแต่ละชุดเวอร์ชันต้นทางถึงเป้าหมาย (N เวอร์ชันสร้าง N-1 แพทช์สำหรับการอัปเดตตามลำดับ หรือ N*(N-1)/2 สำหรับการข้ามเวอร์ชันแบบสุ่ม) และอิมเมจปัจจุบันที่เสียหายจะป้องกันการใช้แพทช์ สำหรับอุปกรณ์ที่เชื่อมต่อผ่าน LPWAN ซึ่งมีข้อจำกัดด้านแบนด์วิดท์สูง การอัปเดตแบบเดลต้าจึงเป็นสิ่งจำเป็น ส่วนอุปกรณ์ที่เชื่อมต่อผ่าน Wi-Fi ซึ่งมีแบนด์วิดท์เหลือเฟือ การอัปเดตภาพเต็มรูปแบบนั้นง่ายกว่าและมีประสิทธิภาพมากกว่า