บทนำสู่ Device Tree ใน Embedded Linux: คู่มือการใช้งานจริง

เรียนรู้ Linux Device Tree ตั้งแต่พื้นฐานถึง Overlays ขั้นสูง ครอบคลุมไวยากรณ์ DTS โครงสร้างโหนด Bindings และการกำหนดค่าบอร์ดฮาร์ดแวร์ที่ออกแบบเอง

บทนำสู่ Device Tree ใน Embedded Linux: คู่มือการใช้งานจริง

Device Tree (DT) คือโครงสร้างข้อมูลและภาษาที่ใช้ในระบบ Linux แบบฝังตัว เพื่ออธิบายโครงสร้างฮาร์ดแวร์ของระบบให้กับเคอร์เนลในระหว่างการบูต โดยแทนที่วิธีการเดิมที่เขียนข้อมูลเฉพาะบอร์ดลงในซอร์สโค้ดของเคอร์เนลโดยตรง Device Tree เขียนในรูปแบบ Device Tree Source (DTS) และคอมไพล์เป็นรูปแบบไบนารี Device Tree Blob (DTB) โดย Device Tree Compiler (dtc) โดยจะอธิบายถึงโปรเซสเซอร์ หน่วยความจำ บัส อุปกรณ์ต่อพ่วง ตัวควบคุมการขัดจังหวะ นาฬิกา GPIO และการเชื่อมต่อระหว่างกันในโครงสร้างแบบลำดับชั้น บูตโหลดเดอร์ (เช่น U-Boot) จะส่ง DTB ไปยังเคอร์เนล Linux ในระหว่างการบูต ทำให้ไบนารีเคอร์เนลเดียวสามารถรองรับแพลตฟอร์มฮาร์ดแวร์หลายแพลตฟอร์มได้ง่ายๆ เพียงแค่เปลี่ยนไฟล์ DTB Device Tree เป็นสิ่งจำเป็นสำหรับแพลตฟอร์ม Linux ARM และ ARM64 และยังใช้โดย Zephyr RTOS ด้วย การเข้าใจโครงสร้าง Device Tree นั้นจำเป็นอย่างยิ่งสำหรับวิศวกร Linux ฝังตัวทุกคนที่พัฒนาแพ็คเกจสนับสนุนบอร์ดแบบกำหนดเอง (BSP) เพิ่มการสนับสนุนอุปกรณ์ต่อพ่วง หรือกำหนดค่าการมัลติเพล็กซ์พินและโดเมนพลังงานบนแพลตฟอร์ม System-on-Chip (SoC)

โครงสร้างของไฟล์ซอร์สโค้ด Device Tree คืออะไร?

/* Basic Device Tree Source (DTS) structure */
/dts-v1/;

/ {  /* Root node */
    model = "Custom IoT Board";
    compatible = "mycompany,iot-board", "ti,am335x";
    
    #address-cells = <1>;
    #size-cells = <1>;
    
    chosen {
        bootargs = "console=ttyS0,115200 root=/dev/mmcblk0p2";
        stdout-path = &uart0;
    };
    
    memory@80000000 {
        device_type = "memory";
        reg = <0x80000000 0x20000000>; /* 512MB DDR */
    };
    
    /* I2C bus with sensor */
    &i2c1 {
        status = "okay";
        clock-frequency = <400000>;
        
        temperature-sensor@48 {
            compatible = "ti,tmp102";
            reg = <0x48>;
            interrupt-parent = <&gpio1>;
            interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
        };
    };
    
    /* SPI bus with flash */
    &spi0 {
        status = "okay";
        
        flash@0 {
            compatible = "jedec,spi-nor";
            reg = <0>;
            spi-max-frequency = <40000000>;
            #address-cells = <1>;
            #size-cells = <1>;
            
            partition@0 {
                label = "bootloader";
                reg = <0x0 0x80000>;
            };
        };
    };
};

การเชื่อมต่อ Device Tree ทำงานอย่างไร?

การกำหนดค่า Device Tree Bindings กำหนดกฎสำหรับการอธิบายฮาร์ดแวร์ประเภทใดประเภทหนึ่งใน Device Tree แต่ละ Binding จะระบุคุณสมบัติที่จำเป็นและคุณสมบัติเสริมสำหรับโหนดอุปกรณ์ รวมถึงสตริง "compatible" ที่จับคู่อุปกรณ์กับไดรเวอร์เคอร์เนล Bindings มีเอกสารอยู่ในเคอร์เนล Linux ภายใต้ Documentation/devicetree/bindings/ ในรูปแบบ YAML (dt-schema) เมื่อคุณเขียนโหนด Device Tree สำหรับเซ็นเซอร์ ตัวควบคุม LED หรืออุปกรณ์ต่อพ่วงใดๆ คุณต้องปฏิบัติตามข้อกำหนด Binding สำหรับอุปกรณ์นั้น คุณสมบัติ "compatible" มีความสำคัญที่สุด เพราะจะบอกเคอร์เนลว่าควรโหลดไดรเวอร์ใด สตริง compatible หลายรายการช่วยให้สามารถใช้ตัวเลือกสำรองได้: compatible = "myvendor,sensor-v2", "generic-sensor" หมายความว่าเคอร์เนลจะค้นหาไดรเวอร์ที่ตรงกับ "myvendor,sensor-v2" ก่อน และจะใช้ "generic-sensor" เป็นตัวเลือกสำรองหากไม่พบ

Device Tree Overlays คืออะไร และควรใช้เมื่อใด?

Device Tree Overlays (DTO) ช่วยให้สามารถแก้ไขโครงสร้างพื้นฐานของอุปกรณ์ (Device Tree) ได้ในขณะทำงานโดยไม่ต้องคอมไพล์ใหม่ Overlays จะถูกคอมไพล์เป็นไฟล์ DTBO และนำไปใช้โดยบูตโหลดเดอร์หรือในขณะทำงาน (บนแพลตฟอร์มที่รองรับ ConfigFS) กรณีการใช้งานทั่วไป ได้แก่ การเปิดหรือปิดใช้งานอุปกรณ์ต่อพ่วง การกำหนดค่าบอร์ดขยาย (เช่น Raspberry Pi HAT หรือ BeagleBone capes) และการเปลี่ยนแปลงการมัลติเพล็กซ์พินสำหรับฮาร์ดแวร์รูปแบบต่างๆ ในการใช้งานจริง Overlays ช่วยให้ DTB พื้นฐานเพียงไฟล์เดียวรองรับฮาร์ดแวร์หลายรุ่น ลดจำนวนอิมเมจเฟิร์มแวร์ที่ต้องดูแลและทดสอบ

/* Device Tree Overlay example - enable SPI display */
/dts-v1/;
/plugin/;

&spi1 {
    status = "okay";
    #address-cells = <1>;
    #size-cells = <0>;
    
    display@0 {
        compatible = "sitronix,st7789v";
        reg = <0>;
        spi-max-frequency = <32000000>;
        dc-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
        reset-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
        width = <240>;
        height = <320>;
        rotation = <90>;
    };
};

เทคนิคการดีบัก Device Tree ที่ใช้กันทั่วไปมีอะไรบ้าง?

เครื่องมือและเทคนิคที่จำเป็นสำหรับการแก้ไขปัญหาเกี่ยวกับโครงสร้างข้อมูลอุปกรณ์:

  • dtc -I fs /proc/device-tree: ถอดรหัส device tree ที่กำลังทำงานอยู่เพื่อตรวจสอบว่าเคอร์เนลได้รับอะไรมาบ้าง
  • ls /proc/device-tree/: เรียกดูโหนดในโครงสร้างอุปกรณ์แบบเรียลไทม์ในรูปแบบระบบไฟล์ เพื่อตรวจสอบว่าโหนดนั้นมีอยู่จริงและดูคุณสมบัติของโหนดได้หรือไม่
  • dmesg | grep -i "device tree": ตรวจสอบบันทึกเคอร์เนลเพื่อดูข้อผิดพลาดและคำเตือนในการวิเคราะห์โครงสร้างอุปกรณ์
  • dt-validate: ตรวจสอบความถูกต้องของไฟล์ DTS กับรูปแบบการผูกข้อมูล YAML ก่อนทำการคอมไพล์ ช่วยตรวจจับข้อผิดพลาดในการผูกข้อมูลตั้งแต่เนิ่นๆ
  • fdtdump <dtb-file>: แปลงไฟล์ DTB ที่คอมไพล์แล้วให้อยู่ในรูปแบบที่อ่านง่ายสำหรับการตรวจสอบ
  • CONFIG_OF_UNITTEST: เปิดใช้งานการทดสอบหน่วยโครงสร้างอุปกรณ์เคอร์เนลเพื่อตรวจสอบความถูกต้องของการประยุกต์ใช้งานโอเวอร์เลย์และการแยกวิเคราะห์คุณสมบัติ

วิธีการเขียน Device Tree สำหรับบอร์ดแบบกำหนดเองทำอย่างไร?

การสร้าง Device Tree (DTS) สำหรับบอร์ดแบบกำหนดเองเริ่มต้นด้วยการระบุ SoC และรวมไฟล์ DTSI พื้นฐาน ซึ่งกำหนดคอร์ของโปรเซสเซอร์ บัสภายใน และอุปกรณ์ต่อพ่วงบนชิป จากนั้น DTS ของบอร์ดของคุณจะเปิดใช้งานอุปกรณ์ต่อพ่วงเฉพาะ กำหนดการมัลติเพล็กซ์พินผ่านระบบย่อย pinctrl อธิบายอุปกรณ์ภายนอกที่เชื่อมต่อผ่านบัส I2C, SPI และ UART กำหนดค่าตัวควบคุมพลังงานและแหล่งสัญญาณนาฬิกา และตั้งค่าแผนที่หน่วยความจำ ขั้นตอนการทำงานโดยทั่วไปคือ: ศึกษาคู่มืออ้างอิง SoC ตรวจสอบไฟล์ DTS ของบอร์ดที่คล้ายกันใน Kernel Tree สร้าง DTS ของบอร์ดของคุณด้วยการรวมที่เหมาะสม คอมไพล์ด้วย dtc และทดสอบและปรับปรุงอย่างต่อเนื่อง ให้ความสนใจเป็นพิเศษกับความขัดแย้งในการมัลติเพล็กซ์พิน พินทางกายภาพเดียวกันอาจสามารถกำหนดเส้นทางไปยังฟังก์ชันอุปกรณ์ต่อพ่วงหลายฟังก์ชันได้ และการกำหนดค่าที่ไม่ถูกต้องจะทำให้เกิดความล้มเหลวโดยไม่แสดงข้อผิดพลาด

ประเด็นสำคัญ: Device Tree คือโครงสร้างข้อมูลแบบลำดับชั้นที่อธิบายโครงสร้างฮาร์ดแวร์ให้กับเคอร์เนล Linux ในระหว่างการบูต โดยแทนที่โค้ดเฉพาะบอร์ดที่เขียนแบบตายตัว Device Tree เขียนในรูปแบบ DTS และคอมไพล์เป็นไบนารี DTB ทำให้ไบนารีเคอร์เนลเดียวสามารถรองรับแพลตฟอร์มฮาร์ดแวร์ได้หลายแพลตฟอร์ม Overlay ช่วยให้สามารถเปลี่ยนแปลงการกำหนดค่าฮาร์ดแวร์ในขณะทำงานได้โดยไม่ต้องคอมไพล์ใหม่

เราสร้าง BSP โดยใช้ Device Tree สำหรับบอร์ดแบบกำหนดเองได้อย่างไร?

ที่ EmbedCrest เราได้พัฒนาแพ็คเกจสนับสนุนบอร์ด (Board Support Package) แบบครบวงจรสำหรับบอร์ดเกตเวย์อุตสาหกรรมแบบกำหนดเอง โดยใช้ชิป NXP i.MX8M Mini SoC บอร์ดนี้ประกอบด้วยพอร์ตอีเธอร์เน็ต 3 พอร์ต (2x RGMII ผ่าน AR8035 PHYs + 1x USB-Ethernet ผ่าน LAN9514), ตัวรับส่งสัญญาณ RS-485 บน UART3, โมเด็ม Quectel EC25 LTE บน USB, ตัวรักษาความปลอดภัย ATECC608B บน I2C2 และ FPGA แบบกำหนดเอง (Lattice MachXO3) บน SPI1 สำหรับการประมวลผลโปรโตคอลอุตสาหกรรม การสร้าง Device Tree ต้องใช้เวลาพัฒนาแบบวนซ้ำ 3 สัปดาห์ เราเริ่มต้นจาก NXP EVK DTS (imx8mm-evk.dts) สร้าง DTS เฉพาะบอร์ดของเราด้วยการกำหนดค่า pinmux ที่ถูกต้องโดยใช้ i.MX Pins Tool อธิบายอุปกรณ์ต่อพ่วงแต่ละตัวด้วยสตริงที่เข้ากันได้และที่อยู่รีจิสเตอร์ที่เหมาะสม และตรวจสอบแต่ละโหนดทีละตัวโดยใช้การตรวจสอบ dtc และการทดสอบการบูต ส่วนที่ท้าทายที่สุดคือการกำหนดค่าการหน่วงเวลา RGMII สำหรับ PHY AR8035 อย่างถูกต้อง ซึ่งต้องปรับแต่งคุณสมบัติ rgmii-rxc-dly-en และ rgmii-txc-dly-en ผ่านการทดสอบแบบวนซ้ำด้วยการวัดปริมาณงาน iperf3 ที่การตั้งค่าการหน่วงเวลาสัญญาณนาฬิกาที่แตกต่างกัน

ข้อผิดพลาดที่พบบ่อยที่สุดในการเขียน Device Tree คืออะไร?

ข้อผิดพลาดที่พบบ่อยที่สุดในไฟล์ Device Tree คือความขัดแย้งในการกำหนดพินมัลติเพล็กซ์: การกำหนดพินทางกายภาพเดียวกันให้กับอุปกรณ์ต่อพ่วงสองตัวที่แตกต่างกัน SoC จะเลือกใช้อุปกรณ์ต่อพ่วงที่กำหนดค่าล่าสุดโดยไม่แจ้งให้ทราบล่วงหน้า ทำให้อุปกรณ์ต่อพ่วงตัวแรกทำงานล้มเหลวโดยไม่มีข้อความแสดงข้อผิดพลาดที่ชัดเจน ใช้เครื่องมือวางแผนพินของผู้ผลิต SoC (NXP Pins Tool, TI SysConfig, STM32CubeMX) เพื่อตรวจจับความขัดแย้งก่อนที่จะเขียนไฟล์ DTS ประการที่สอง คุณสมบัติ interrupt-parent และ interrupts ที่ไม่ถูกต้องทำให้การตรวจสอบอุปกรณ์สำเร็จ แต่ไม่สร้างการขัดจังหวะ ตรวจสอบการกำหนดค่าการขัดจังหวะด้วยคำสั่ง cat /proc/interrupts และทดสอบด้วยการเรียกใช้การขัดจังหวะด้วยตนเอง ประการที่สาม ข้อผิดพลาดในการกำหนดค่าสัญญาณนาฬิกาจะแสดงออกมาในรูปของอุปกรณ์ต่อพ่วงที่ทำงานที่ความถี่ไม่ถูกต้องหรือไม่ทำงานเลย ตรวจสอบ assigned-clocks และ assigned-clock-rates กับไฟล์ clock tree ในคู่มืออ้างอิงของ SoC ประการที่สี่ การลืมตั้งค่า status = "okay" ทำให้อุปกรณ์ต่อพ่วงที่อธิบายไว้อย่างถูกต้องถูกปิดใช้งาน ตามธรรมเนียมแล้ว ไฟล์ DTSI ของ SoC จะอธิบายอุปกรณ์ต่อพ่วงทั้งหมดด้วย status = "disabled" และไฟล์ DTS ของบอร์ดจะเปิดใช้งานอุปกรณ์ต่อพ่วงที่ใช้งานอยู่บางส่วน

คุณใช้ Device Tree Overlays เพื่อเพิ่มความยืดหยุ่นในการใช้งานจริงอย่างไร?

การใช้ Device Tree Overlay ช่วยให้ภาพเฟิร์มแวร์พื้นฐานเพียงภาพเดียวสามารถรองรับฮาร์ดแวร์หลายรุ่นได้ ลดความซับซ้อนในการผลิตและการบำรุงรักษา ในสถานการณ์การผลิต ลองพิจารณาผลิตภัณฑ์ตระกูลหนึ่งที่มีสามรุ่น ได้แก่ รุ่นพื้นฐานที่มีเฉพาะ RS-485 รุ่นระดับกลางที่เพิ่ม BLE ผ่านโมดูลที่เชื่อมต่อผ่าน UART และรุ่นพรีเมียมที่เพิ่ม LTE ผ่านโมเด็ม USB สร้าง DTS พื้นฐานโดยปิดใช้งานอุปกรณ์ต่อพ่วงเฉพาะรุ่นทั้งหมด จากนั้นสร้างไฟล์ DTBO โอเวอร์เลย์สามไฟล์ที่เปิดใช้งานอุปกรณ์ต่อพ่วงที่เหมาะสมสำหรับแต่ละรุ่น ในระหว่างการผลิต ให้เขียนตัวระบุรุ่นลงใน EEPROM หรือฟิวส์ OTP และกำหนดค่า U-Boot ให้เลือกโอเวอร์เลย์ที่เกี่ยวข้องในเวลาบูตโดยใช้คำสั่ง fdt apply วิธีการนี้ช่วยลดจำนวนภาพเฟิร์มแวร์จาก 3 เหลือเพียง 1 ภาพพื้นฐาน + 3 โอเวอร์เลย์ขนาดเล็ก ทำให้ไปป์ไลน์ CI/CD ระบบอัปเดต OTA และการทดสอบการผลิตง่ายขึ้น Zephyr RTOS ใช้กลไกโอเวอร์เลย์เดียวกัน (ไฟล์ app.overlay) ดังนั้นวิธีการนี้จึงใช้ได้กับโครงการ MCU ที่กำหนดเป้าหมายบอร์ดที่มีฮาร์ดแวร์หลายรุ่นเช่นกัน

บทความที่เกี่ยวข้อง

บทนำสู่ Device Tree ใน Embedded Linux: คู่มือการใช้งานจริง

เรียนรู้ Linux Device Tree ตั้งแต่พื้นฐานถึง Overlays ขั้นสูง ครอบคลุมไวยากรณ์ DTS โครงสร้างโหนด Bindings และการกำหนดค่าบอร์ดฮาร์ดแวร์ที่ออกแบบเอง

นักเขียนบทความ
by 
นักเขียนบทความ
บทนำสู่ Device Tree ใน Embedded Linux: คู่มือการใช้งานจริง

บทนำสู่ Device Tree ใน Embedded Linux: คู่มือการใช้งานจริง

เรียนรู้ Linux Device Tree ตั้งแต่พื้นฐานถึง Overlays ขั้นสูง ครอบคลุมไวยากรณ์ DTS โครงสร้างโหนด Bindings และการกำหนดค่าบอร์ดฮาร์ดแวร์ที่ออกแบบเอง

Device Tree (DT) คือโครงสร้างข้อมูลและภาษาที่ใช้ในระบบ Linux แบบฝังตัว เพื่ออธิบายโครงสร้างฮาร์ดแวร์ของระบบให้กับเคอร์เนลในระหว่างการบูต โดยแทนที่วิธีการเดิมที่เขียนข้อมูลเฉพาะบอร์ดลงในซอร์สโค้ดของเคอร์เนลโดยตรง Device Tree เขียนในรูปแบบ Device Tree Source (DTS) และคอมไพล์เป็นรูปแบบไบนารี Device Tree Blob (DTB) โดย Device Tree Compiler (dtc) โดยจะอธิบายถึงโปรเซสเซอร์ หน่วยความจำ บัส อุปกรณ์ต่อพ่วง ตัวควบคุมการขัดจังหวะ นาฬิกา GPIO และการเชื่อมต่อระหว่างกันในโครงสร้างแบบลำดับชั้น บูตโหลดเดอร์ (เช่น U-Boot) จะส่ง DTB ไปยังเคอร์เนล Linux ในระหว่างการบูต ทำให้ไบนารีเคอร์เนลเดียวสามารถรองรับแพลตฟอร์มฮาร์ดแวร์หลายแพลตฟอร์มได้ง่ายๆ เพียงแค่เปลี่ยนไฟล์ DTB Device Tree เป็นสิ่งจำเป็นสำหรับแพลตฟอร์ม Linux ARM และ ARM64 และยังใช้โดย Zephyr RTOS ด้วย การเข้าใจโครงสร้าง Device Tree นั้นจำเป็นอย่างยิ่งสำหรับวิศวกร Linux ฝังตัวทุกคนที่พัฒนาแพ็คเกจสนับสนุนบอร์ดแบบกำหนดเอง (BSP) เพิ่มการสนับสนุนอุปกรณ์ต่อพ่วง หรือกำหนดค่าการมัลติเพล็กซ์พินและโดเมนพลังงานบนแพลตฟอร์ม System-on-Chip (SoC)

โครงสร้างของไฟล์ซอร์สโค้ด Device Tree คืออะไร?

/* Basic Device Tree Source (DTS) structure */
/dts-v1/;

/ {  /* Root node */
    model = "Custom IoT Board";
    compatible = "mycompany,iot-board", "ti,am335x";
    
    #address-cells = <1>;
    #size-cells = <1>;
    
    chosen {
        bootargs = "console=ttyS0,115200 root=/dev/mmcblk0p2";
        stdout-path = &uart0;
    };
    
    memory@80000000 {
        device_type = "memory";
        reg = <0x80000000 0x20000000>; /* 512MB DDR */
    };
    
    /* I2C bus with sensor */
    &i2c1 {
        status = "okay";
        clock-frequency = <400000>;
        
        temperature-sensor@48 {
            compatible = "ti,tmp102";
            reg = <0x48>;
            interrupt-parent = <&gpio1>;
            interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
        };
    };
    
    /* SPI bus with flash */
    &spi0 {
        status = "okay";
        
        flash@0 {
            compatible = "jedec,spi-nor";
            reg = <0>;
            spi-max-frequency = <40000000>;
            #address-cells = <1>;
            #size-cells = <1>;
            
            partition@0 {
                label = "bootloader";
                reg = <0x0 0x80000>;
            };
        };
    };
};

การเชื่อมต่อ Device Tree ทำงานอย่างไร?

การกำหนดค่า Device Tree Bindings กำหนดกฎสำหรับการอธิบายฮาร์ดแวร์ประเภทใดประเภทหนึ่งใน Device Tree แต่ละ Binding จะระบุคุณสมบัติที่จำเป็นและคุณสมบัติเสริมสำหรับโหนดอุปกรณ์ รวมถึงสตริง "compatible" ที่จับคู่อุปกรณ์กับไดรเวอร์เคอร์เนล Bindings มีเอกสารอยู่ในเคอร์เนล Linux ภายใต้ Documentation/devicetree/bindings/ ในรูปแบบ YAML (dt-schema) เมื่อคุณเขียนโหนด Device Tree สำหรับเซ็นเซอร์ ตัวควบคุม LED หรืออุปกรณ์ต่อพ่วงใดๆ คุณต้องปฏิบัติตามข้อกำหนด Binding สำหรับอุปกรณ์นั้น คุณสมบัติ "compatible" มีความสำคัญที่สุด เพราะจะบอกเคอร์เนลว่าควรโหลดไดรเวอร์ใด สตริง compatible หลายรายการช่วยให้สามารถใช้ตัวเลือกสำรองได้: compatible = "myvendor,sensor-v2", "generic-sensor" หมายความว่าเคอร์เนลจะค้นหาไดรเวอร์ที่ตรงกับ "myvendor,sensor-v2" ก่อน และจะใช้ "generic-sensor" เป็นตัวเลือกสำรองหากไม่พบ

Device Tree Overlays คืออะไร และควรใช้เมื่อใด?

Device Tree Overlays (DTO) ช่วยให้สามารถแก้ไขโครงสร้างพื้นฐานของอุปกรณ์ (Device Tree) ได้ในขณะทำงานโดยไม่ต้องคอมไพล์ใหม่ Overlays จะถูกคอมไพล์เป็นไฟล์ DTBO และนำไปใช้โดยบูตโหลดเดอร์หรือในขณะทำงาน (บนแพลตฟอร์มที่รองรับ ConfigFS) กรณีการใช้งานทั่วไป ได้แก่ การเปิดหรือปิดใช้งานอุปกรณ์ต่อพ่วง การกำหนดค่าบอร์ดขยาย (เช่น Raspberry Pi HAT หรือ BeagleBone capes) และการเปลี่ยนแปลงการมัลติเพล็กซ์พินสำหรับฮาร์ดแวร์รูปแบบต่างๆ ในการใช้งานจริง Overlays ช่วยให้ DTB พื้นฐานเพียงไฟล์เดียวรองรับฮาร์ดแวร์หลายรุ่น ลดจำนวนอิมเมจเฟิร์มแวร์ที่ต้องดูแลและทดสอบ

/* Device Tree Overlay example - enable SPI display */
/dts-v1/;
/plugin/;

&spi1 {
    status = "okay";
    #address-cells = <1>;
    #size-cells = <0>;
    
    display@0 {
        compatible = "sitronix,st7789v";
        reg = <0>;
        spi-max-frequency = <32000000>;
        dc-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
        reset-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
        width = <240>;
        height = <320>;
        rotation = <90>;
    };
};

เทคนิคการดีบัก Device Tree ที่ใช้กันทั่วไปมีอะไรบ้าง?

เครื่องมือและเทคนิคที่จำเป็นสำหรับการแก้ไขปัญหาเกี่ยวกับโครงสร้างข้อมูลอุปกรณ์:

  • dtc -I fs /proc/device-tree: ถอดรหัส device tree ที่กำลังทำงานอยู่เพื่อตรวจสอบว่าเคอร์เนลได้รับอะไรมาบ้าง
  • ls /proc/device-tree/: เรียกดูโหนดในโครงสร้างอุปกรณ์แบบเรียลไทม์ในรูปแบบระบบไฟล์ เพื่อตรวจสอบว่าโหนดนั้นมีอยู่จริงและดูคุณสมบัติของโหนดได้หรือไม่
  • dmesg | grep -i "device tree": ตรวจสอบบันทึกเคอร์เนลเพื่อดูข้อผิดพลาดและคำเตือนในการวิเคราะห์โครงสร้างอุปกรณ์
  • dt-validate: ตรวจสอบความถูกต้องของไฟล์ DTS กับรูปแบบการผูกข้อมูล YAML ก่อนทำการคอมไพล์ ช่วยตรวจจับข้อผิดพลาดในการผูกข้อมูลตั้งแต่เนิ่นๆ
  • fdtdump <dtb-file>: แปลงไฟล์ DTB ที่คอมไพล์แล้วให้อยู่ในรูปแบบที่อ่านง่ายสำหรับการตรวจสอบ
  • CONFIG_OF_UNITTEST: เปิดใช้งานการทดสอบหน่วยโครงสร้างอุปกรณ์เคอร์เนลเพื่อตรวจสอบความถูกต้องของการประยุกต์ใช้งานโอเวอร์เลย์และการแยกวิเคราะห์คุณสมบัติ

วิธีการเขียน Device Tree สำหรับบอร์ดแบบกำหนดเองทำอย่างไร?

การสร้าง Device Tree (DTS) สำหรับบอร์ดแบบกำหนดเองเริ่มต้นด้วยการระบุ SoC และรวมไฟล์ DTSI พื้นฐาน ซึ่งกำหนดคอร์ของโปรเซสเซอร์ บัสภายใน และอุปกรณ์ต่อพ่วงบนชิป จากนั้น DTS ของบอร์ดของคุณจะเปิดใช้งานอุปกรณ์ต่อพ่วงเฉพาะ กำหนดการมัลติเพล็กซ์พินผ่านระบบย่อย pinctrl อธิบายอุปกรณ์ภายนอกที่เชื่อมต่อผ่านบัส I2C, SPI และ UART กำหนดค่าตัวควบคุมพลังงานและแหล่งสัญญาณนาฬิกา และตั้งค่าแผนที่หน่วยความจำ ขั้นตอนการทำงานโดยทั่วไปคือ: ศึกษาคู่มืออ้างอิง SoC ตรวจสอบไฟล์ DTS ของบอร์ดที่คล้ายกันใน Kernel Tree สร้าง DTS ของบอร์ดของคุณด้วยการรวมที่เหมาะสม คอมไพล์ด้วย dtc และทดสอบและปรับปรุงอย่างต่อเนื่อง ให้ความสนใจเป็นพิเศษกับความขัดแย้งในการมัลติเพล็กซ์พิน พินทางกายภาพเดียวกันอาจสามารถกำหนดเส้นทางไปยังฟังก์ชันอุปกรณ์ต่อพ่วงหลายฟังก์ชันได้ และการกำหนดค่าที่ไม่ถูกต้องจะทำให้เกิดความล้มเหลวโดยไม่แสดงข้อผิดพลาด

ประเด็นสำคัญ: Device Tree คือโครงสร้างข้อมูลแบบลำดับชั้นที่อธิบายโครงสร้างฮาร์ดแวร์ให้กับเคอร์เนล Linux ในระหว่างการบูต โดยแทนที่โค้ดเฉพาะบอร์ดที่เขียนแบบตายตัว Device Tree เขียนในรูปแบบ DTS และคอมไพล์เป็นไบนารี DTB ทำให้ไบนารีเคอร์เนลเดียวสามารถรองรับแพลตฟอร์มฮาร์ดแวร์ได้หลายแพลตฟอร์ม Overlay ช่วยให้สามารถเปลี่ยนแปลงการกำหนดค่าฮาร์ดแวร์ในขณะทำงานได้โดยไม่ต้องคอมไพล์ใหม่

เราสร้าง BSP โดยใช้ Device Tree สำหรับบอร์ดแบบกำหนดเองได้อย่างไร?

ที่ EmbedCrest เราได้พัฒนาแพ็คเกจสนับสนุนบอร์ด (Board Support Package) แบบครบวงจรสำหรับบอร์ดเกตเวย์อุตสาหกรรมแบบกำหนดเอง โดยใช้ชิป NXP i.MX8M Mini SoC บอร์ดนี้ประกอบด้วยพอร์ตอีเธอร์เน็ต 3 พอร์ต (2x RGMII ผ่าน AR8035 PHYs + 1x USB-Ethernet ผ่าน LAN9514), ตัวรับส่งสัญญาณ RS-485 บน UART3, โมเด็ม Quectel EC25 LTE บน USB, ตัวรักษาความปลอดภัย ATECC608B บน I2C2 และ FPGA แบบกำหนดเอง (Lattice MachXO3) บน SPI1 สำหรับการประมวลผลโปรโตคอลอุตสาหกรรม การสร้าง Device Tree ต้องใช้เวลาพัฒนาแบบวนซ้ำ 3 สัปดาห์ เราเริ่มต้นจาก NXP EVK DTS (imx8mm-evk.dts) สร้าง DTS เฉพาะบอร์ดของเราด้วยการกำหนดค่า pinmux ที่ถูกต้องโดยใช้ i.MX Pins Tool อธิบายอุปกรณ์ต่อพ่วงแต่ละตัวด้วยสตริงที่เข้ากันได้และที่อยู่รีจิสเตอร์ที่เหมาะสม และตรวจสอบแต่ละโหนดทีละตัวโดยใช้การตรวจสอบ dtc และการทดสอบการบูต ส่วนที่ท้าทายที่สุดคือการกำหนดค่าการหน่วงเวลา RGMII สำหรับ PHY AR8035 อย่างถูกต้อง ซึ่งต้องปรับแต่งคุณสมบัติ rgmii-rxc-dly-en และ rgmii-txc-dly-en ผ่านการทดสอบแบบวนซ้ำด้วยการวัดปริมาณงาน iperf3 ที่การตั้งค่าการหน่วงเวลาสัญญาณนาฬิกาที่แตกต่างกัน

ข้อผิดพลาดที่พบบ่อยที่สุดในการเขียน Device Tree คืออะไร?

ข้อผิดพลาดที่พบบ่อยที่สุดในไฟล์ Device Tree คือความขัดแย้งในการกำหนดพินมัลติเพล็กซ์: การกำหนดพินทางกายภาพเดียวกันให้กับอุปกรณ์ต่อพ่วงสองตัวที่แตกต่างกัน SoC จะเลือกใช้อุปกรณ์ต่อพ่วงที่กำหนดค่าล่าสุดโดยไม่แจ้งให้ทราบล่วงหน้า ทำให้อุปกรณ์ต่อพ่วงตัวแรกทำงานล้มเหลวโดยไม่มีข้อความแสดงข้อผิดพลาดที่ชัดเจน ใช้เครื่องมือวางแผนพินของผู้ผลิต SoC (NXP Pins Tool, TI SysConfig, STM32CubeMX) เพื่อตรวจจับความขัดแย้งก่อนที่จะเขียนไฟล์ DTS ประการที่สอง คุณสมบัติ interrupt-parent และ interrupts ที่ไม่ถูกต้องทำให้การตรวจสอบอุปกรณ์สำเร็จ แต่ไม่สร้างการขัดจังหวะ ตรวจสอบการกำหนดค่าการขัดจังหวะด้วยคำสั่ง cat /proc/interrupts และทดสอบด้วยการเรียกใช้การขัดจังหวะด้วยตนเอง ประการที่สาม ข้อผิดพลาดในการกำหนดค่าสัญญาณนาฬิกาจะแสดงออกมาในรูปของอุปกรณ์ต่อพ่วงที่ทำงานที่ความถี่ไม่ถูกต้องหรือไม่ทำงานเลย ตรวจสอบ assigned-clocks และ assigned-clock-rates กับไฟล์ clock tree ในคู่มืออ้างอิงของ SoC ประการที่สี่ การลืมตั้งค่า status = "okay" ทำให้อุปกรณ์ต่อพ่วงที่อธิบายไว้อย่างถูกต้องถูกปิดใช้งาน ตามธรรมเนียมแล้ว ไฟล์ DTSI ของ SoC จะอธิบายอุปกรณ์ต่อพ่วงทั้งหมดด้วย status = "disabled" และไฟล์ DTS ของบอร์ดจะเปิดใช้งานอุปกรณ์ต่อพ่วงที่ใช้งานอยู่บางส่วน

คุณใช้ Device Tree Overlays เพื่อเพิ่มความยืดหยุ่นในการใช้งานจริงอย่างไร?

การใช้ Device Tree Overlay ช่วยให้ภาพเฟิร์มแวร์พื้นฐานเพียงภาพเดียวสามารถรองรับฮาร์ดแวร์หลายรุ่นได้ ลดความซับซ้อนในการผลิตและการบำรุงรักษา ในสถานการณ์การผลิต ลองพิจารณาผลิตภัณฑ์ตระกูลหนึ่งที่มีสามรุ่น ได้แก่ รุ่นพื้นฐานที่มีเฉพาะ RS-485 รุ่นระดับกลางที่เพิ่ม BLE ผ่านโมดูลที่เชื่อมต่อผ่าน UART และรุ่นพรีเมียมที่เพิ่ม LTE ผ่านโมเด็ม USB สร้าง DTS พื้นฐานโดยปิดใช้งานอุปกรณ์ต่อพ่วงเฉพาะรุ่นทั้งหมด จากนั้นสร้างไฟล์ DTBO โอเวอร์เลย์สามไฟล์ที่เปิดใช้งานอุปกรณ์ต่อพ่วงที่เหมาะสมสำหรับแต่ละรุ่น ในระหว่างการผลิต ให้เขียนตัวระบุรุ่นลงใน EEPROM หรือฟิวส์ OTP และกำหนดค่า U-Boot ให้เลือกโอเวอร์เลย์ที่เกี่ยวข้องในเวลาบูตโดยใช้คำสั่ง fdt apply วิธีการนี้ช่วยลดจำนวนภาพเฟิร์มแวร์จาก 3 เหลือเพียง 1 ภาพพื้นฐาน + 3 โอเวอร์เลย์ขนาดเล็ก ทำให้ไปป์ไลน์ CI/CD ระบบอัปเดต OTA และการทดสอบการผลิตง่ายขึ้น Zephyr RTOS ใช้กลไกโอเวอร์เลย์เดียวกัน (ไฟล์ app.overlay) ดังนั้นวิธีการนี้จึงใช้ได้กับโครงการ MCU ที่กำหนดเป้าหมายบอร์ดที่มีฮาร์ดแวร์หลายรุ่นเช่นกัน

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

บทนำสู่ Device Tree ใน Embedded Linux: คู่มือการใช้งานจริง

บทนำสู่ Device Tree ใน Embedded Linux: คู่มือการใช้งานจริง

เรียนรู้ Linux Device Tree ตั้งแต่พื้นฐานถึง Overlays ขั้นสูง ครอบคลุมไวยากรณ์ DTS โครงสร้างโหนด Bindings และการกำหนดค่าบอร์ดฮาร์ดแวร์ที่ออกแบบเอง

Lorem ipsum dolor amet consectetur adipiscing elit tortor massa arcu non.

Device Tree (DT) คือโครงสร้างข้อมูลและภาษาที่ใช้ในระบบ Linux แบบฝังตัว เพื่ออธิบายโครงสร้างฮาร์ดแวร์ของระบบให้กับเคอร์เนลในระหว่างการบูต โดยแทนที่วิธีการเดิมที่เขียนข้อมูลเฉพาะบอร์ดลงในซอร์สโค้ดของเคอร์เนลโดยตรง Device Tree เขียนในรูปแบบ Device Tree Source (DTS) และคอมไพล์เป็นรูปแบบไบนารี Device Tree Blob (DTB) โดย Device Tree Compiler (dtc) โดยจะอธิบายถึงโปรเซสเซอร์ หน่วยความจำ บัส อุปกรณ์ต่อพ่วง ตัวควบคุมการขัดจังหวะ นาฬิกา GPIO และการเชื่อมต่อระหว่างกันในโครงสร้างแบบลำดับชั้น บูตโหลดเดอร์ (เช่น U-Boot) จะส่ง DTB ไปยังเคอร์เนล Linux ในระหว่างการบูต ทำให้ไบนารีเคอร์เนลเดียวสามารถรองรับแพลตฟอร์มฮาร์ดแวร์หลายแพลตฟอร์มได้ง่ายๆ เพียงแค่เปลี่ยนไฟล์ DTB Device Tree เป็นสิ่งจำเป็นสำหรับแพลตฟอร์ม Linux ARM และ ARM64 และยังใช้โดย Zephyr RTOS ด้วย การเข้าใจโครงสร้าง Device Tree นั้นจำเป็นอย่างยิ่งสำหรับวิศวกร Linux ฝังตัวทุกคนที่พัฒนาแพ็คเกจสนับสนุนบอร์ดแบบกำหนดเอง (BSP) เพิ่มการสนับสนุนอุปกรณ์ต่อพ่วง หรือกำหนดค่าการมัลติเพล็กซ์พินและโดเมนพลังงานบนแพลตฟอร์ม System-on-Chip (SoC)

โครงสร้างของไฟล์ซอร์สโค้ด Device Tree คืออะไร?

/* Basic Device Tree Source (DTS) structure */
/dts-v1/;

/ {  /* Root node */
    model = "Custom IoT Board";
    compatible = "mycompany,iot-board", "ti,am335x";
    
    #address-cells = <1>;
    #size-cells = <1>;
    
    chosen {
        bootargs = "console=ttyS0,115200 root=/dev/mmcblk0p2";
        stdout-path = &uart0;
    };
    
    memory@80000000 {
        device_type = "memory";
        reg = <0x80000000 0x20000000>; /* 512MB DDR */
    };
    
    /* I2C bus with sensor */
    &i2c1 {
        status = "okay";
        clock-frequency = <400000>;
        
        temperature-sensor@48 {
            compatible = "ti,tmp102";
            reg = <0x48>;
            interrupt-parent = <&gpio1>;
            interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
        };
    };
    
    /* SPI bus with flash */
    &spi0 {
        status = "okay";
        
        flash@0 {
            compatible = "jedec,spi-nor";
            reg = <0>;
            spi-max-frequency = <40000000>;
            #address-cells = <1>;
            #size-cells = <1>;
            
            partition@0 {
                label = "bootloader";
                reg = <0x0 0x80000>;
            };
        };
    };
};

การเชื่อมต่อ Device Tree ทำงานอย่างไร?

การกำหนดค่า Device Tree Bindings กำหนดกฎสำหรับการอธิบายฮาร์ดแวร์ประเภทใดประเภทหนึ่งใน Device Tree แต่ละ Binding จะระบุคุณสมบัติที่จำเป็นและคุณสมบัติเสริมสำหรับโหนดอุปกรณ์ รวมถึงสตริง "compatible" ที่จับคู่อุปกรณ์กับไดรเวอร์เคอร์เนล Bindings มีเอกสารอยู่ในเคอร์เนล Linux ภายใต้ Documentation/devicetree/bindings/ ในรูปแบบ YAML (dt-schema) เมื่อคุณเขียนโหนด Device Tree สำหรับเซ็นเซอร์ ตัวควบคุม LED หรืออุปกรณ์ต่อพ่วงใดๆ คุณต้องปฏิบัติตามข้อกำหนด Binding สำหรับอุปกรณ์นั้น คุณสมบัติ "compatible" มีความสำคัญที่สุด เพราะจะบอกเคอร์เนลว่าควรโหลดไดรเวอร์ใด สตริง compatible หลายรายการช่วยให้สามารถใช้ตัวเลือกสำรองได้: compatible = "myvendor,sensor-v2", "generic-sensor" หมายความว่าเคอร์เนลจะค้นหาไดรเวอร์ที่ตรงกับ "myvendor,sensor-v2" ก่อน และจะใช้ "generic-sensor" เป็นตัวเลือกสำรองหากไม่พบ

Device Tree Overlays คืออะไร และควรใช้เมื่อใด?

Device Tree Overlays (DTO) ช่วยให้สามารถแก้ไขโครงสร้างพื้นฐานของอุปกรณ์ (Device Tree) ได้ในขณะทำงานโดยไม่ต้องคอมไพล์ใหม่ Overlays จะถูกคอมไพล์เป็นไฟล์ DTBO และนำไปใช้โดยบูตโหลดเดอร์หรือในขณะทำงาน (บนแพลตฟอร์มที่รองรับ ConfigFS) กรณีการใช้งานทั่วไป ได้แก่ การเปิดหรือปิดใช้งานอุปกรณ์ต่อพ่วง การกำหนดค่าบอร์ดขยาย (เช่น Raspberry Pi HAT หรือ BeagleBone capes) และการเปลี่ยนแปลงการมัลติเพล็กซ์พินสำหรับฮาร์ดแวร์รูปแบบต่างๆ ในการใช้งานจริง Overlays ช่วยให้ DTB พื้นฐานเพียงไฟล์เดียวรองรับฮาร์ดแวร์หลายรุ่น ลดจำนวนอิมเมจเฟิร์มแวร์ที่ต้องดูแลและทดสอบ

/* Device Tree Overlay example - enable SPI display */
/dts-v1/;
/plugin/;

&spi1 {
    status = "okay";
    #address-cells = <1>;
    #size-cells = <0>;
    
    display@0 {
        compatible = "sitronix,st7789v";
        reg = <0>;
        spi-max-frequency = <32000000>;
        dc-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
        reset-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
        width = <240>;
        height = <320>;
        rotation = <90>;
    };
};

เทคนิคการดีบัก Device Tree ที่ใช้กันทั่วไปมีอะไรบ้าง?

เครื่องมือและเทคนิคที่จำเป็นสำหรับการแก้ไขปัญหาเกี่ยวกับโครงสร้างข้อมูลอุปกรณ์:

  • dtc -I fs /proc/device-tree: ถอดรหัส device tree ที่กำลังทำงานอยู่เพื่อตรวจสอบว่าเคอร์เนลได้รับอะไรมาบ้าง
  • ls /proc/device-tree/: เรียกดูโหนดในโครงสร้างอุปกรณ์แบบเรียลไทม์ในรูปแบบระบบไฟล์ เพื่อตรวจสอบว่าโหนดนั้นมีอยู่จริงและดูคุณสมบัติของโหนดได้หรือไม่
  • dmesg | grep -i "device tree": ตรวจสอบบันทึกเคอร์เนลเพื่อดูข้อผิดพลาดและคำเตือนในการวิเคราะห์โครงสร้างอุปกรณ์
  • dt-validate: ตรวจสอบความถูกต้องของไฟล์ DTS กับรูปแบบการผูกข้อมูล YAML ก่อนทำการคอมไพล์ ช่วยตรวจจับข้อผิดพลาดในการผูกข้อมูลตั้งแต่เนิ่นๆ
  • fdtdump <dtb-file>: แปลงไฟล์ DTB ที่คอมไพล์แล้วให้อยู่ในรูปแบบที่อ่านง่ายสำหรับการตรวจสอบ
  • CONFIG_OF_UNITTEST: เปิดใช้งานการทดสอบหน่วยโครงสร้างอุปกรณ์เคอร์เนลเพื่อตรวจสอบความถูกต้องของการประยุกต์ใช้งานโอเวอร์เลย์และการแยกวิเคราะห์คุณสมบัติ

วิธีการเขียน Device Tree สำหรับบอร์ดแบบกำหนดเองทำอย่างไร?

การสร้าง Device Tree (DTS) สำหรับบอร์ดแบบกำหนดเองเริ่มต้นด้วยการระบุ SoC และรวมไฟล์ DTSI พื้นฐาน ซึ่งกำหนดคอร์ของโปรเซสเซอร์ บัสภายใน และอุปกรณ์ต่อพ่วงบนชิป จากนั้น DTS ของบอร์ดของคุณจะเปิดใช้งานอุปกรณ์ต่อพ่วงเฉพาะ กำหนดการมัลติเพล็กซ์พินผ่านระบบย่อย pinctrl อธิบายอุปกรณ์ภายนอกที่เชื่อมต่อผ่านบัส I2C, SPI และ UART กำหนดค่าตัวควบคุมพลังงานและแหล่งสัญญาณนาฬิกา และตั้งค่าแผนที่หน่วยความจำ ขั้นตอนการทำงานโดยทั่วไปคือ: ศึกษาคู่มืออ้างอิง SoC ตรวจสอบไฟล์ DTS ของบอร์ดที่คล้ายกันใน Kernel Tree สร้าง DTS ของบอร์ดของคุณด้วยการรวมที่เหมาะสม คอมไพล์ด้วย dtc และทดสอบและปรับปรุงอย่างต่อเนื่อง ให้ความสนใจเป็นพิเศษกับความขัดแย้งในการมัลติเพล็กซ์พิน พินทางกายภาพเดียวกันอาจสามารถกำหนดเส้นทางไปยังฟังก์ชันอุปกรณ์ต่อพ่วงหลายฟังก์ชันได้ และการกำหนดค่าที่ไม่ถูกต้องจะทำให้เกิดความล้มเหลวโดยไม่แสดงข้อผิดพลาด

ประเด็นสำคัญ: Device Tree คือโครงสร้างข้อมูลแบบลำดับชั้นที่อธิบายโครงสร้างฮาร์ดแวร์ให้กับเคอร์เนล Linux ในระหว่างการบูต โดยแทนที่โค้ดเฉพาะบอร์ดที่เขียนแบบตายตัว Device Tree เขียนในรูปแบบ DTS และคอมไพล์เป็นไบนารี DTB ทำให้ไบนารีเคอร์เนลเดียวสามารถรองรับแพลตฟอร์มฮาร์ดแวร์ได้หลายแพลตฟอร์ม Overlay ช่วยให้สามารถเปลี่ยนแปลงการกำหนดค่าฮาร์ดแวร์ในขณะทำงานได้โดยไม่ต้องคอมไพล์ใหม่

เราสร้าง BSP โดยใช้ Device Tree สำหรับบอร์ดแบบกำหนดเองได้อย่างไร?

ที่ EmbedCrest เราได้พัฒนาแพ็คเกจสนับสนุนบอร์ด (Board Support Package) แบบครบวงจรสำหรับบอร์ดเกตเวย์อุตสาหกรรมแบบกำหนดเอง โดยใช้ชิป NXP i.MX8M Mini SoC บอร์ดนี้ประกอบด้วยพอร์ตอีเธอร์เน็ต 3 พอร์ต (2x RGMII ผ่าน AR8035 PHYs + 1x USB-Ethernet ผ่าน LAN9514), ตัวรับส่งสัญญาณ RS-485 บน UART3, โมเด็ม Quectel EC25 LTE บน USB, ตัวรักษาความปลอดภัย ATECC608B บน I2C2 และ FPGA แบบกำหนดเอง (Lattice MachXO3) บน SPI1 สำหรับการประมวลผลโปรโตคอลอุตสาหกรรม การสร้าง Device Tree ต้องใช้เวลาพัฒนาแบบวนซ้ำ 3 สัปดาห์ เราเริ่มต้นจาก NXP EVK DTS (imx8mm-evk.dts) สร้าง DTS เฉพาะบอร์ดของเราด้วยการกำหนดค่า pinmux ที่ถูกต้องโดยใช้ i.MX Pins Tool อธิบายอุปกรณ์ต่อพ่วงแต่ละตัวด้วยสตริงที่เข้ากันได้และที่อยู่รีจิสเตอร์ที่เหมาะสม และตรวจสอบแต่ละโหนดทีละตัวโดยใช้การตรวจสอบ dtc และการทดสอบการบูต ส่วนที่ท้าทายที่สุดคือการกำหนดค่าการหน่วงเวลา RGMII สำหรับ PHY AR8035 อย่างถูกต้อง ซึ่งต้องปรับแต่งคุณสมบัติ rgmii-rxc-dly-en และ rgmii-txc-dly-en ผ่านการทดสอบแบบวนซ้ำด้วยการวัดปริมาณงาน iperf3 ที่การตั้งค่าการหน่วงเวลาสัญญาณนาฬิกาที่แตกต่างกัน

ข้อผิดพลาดที่พบบ่อยที่สุดในการเขียน Device Tree คืออะไร?

ข้อผิดพลาดที่พบบ่อยที่สุดในไฟล์ Device Tree คือความขัดแย้งในการกำหนดพินมัลติเพล็กซ์: การกำหนดพินทางกายภาพเดียวกันให้กับอุปกรณ์ต่อพ่วงสองตัวที่แตกต่างกัน SoC จะเลือกใช้อุปกรณ์ต่อพ่วงที่กำหนดค่าล่าสุดโดยไม่แจ้งให้ทราบล่วงหน้า ทำให้อุปกรณ์ต่อพ่วงตัวแรกทำงานล้มเหลวโดยไม่มีข้อความแสดงข้อผิดพลาดที่ชัดเจน ใช้เครื่องมือวางแผนพินของผู้ผลิต SoC (NXP Pins Tool, TI SysConfig, STM32CubeMX) เพื่อตรวจจับความขัดแย้งก่อนที่จะเขียนไฟล์ DTS ประการที่สอง คุณสมบัติ interrupt-parent และ interrupts ที่ไม่ถูกต้องทำให้การตรวจสอบอุปกรณ์สำเร็จ แต่ไม่สร้างการขัดจังหวะ ตรวจสอบการกำหนดค่าการขัดจังหวะด้วยคำสั่ง cat /proc/interrupts และทดสอบด้วยการเรียกใช้การขัดจังหวะด้วยตนเอง ประการที่สาม ข้อผิดพลาดในการกำหนดค่าสัญญาณนาฬิกาจะแสดงออกมาในรูปของอุปกรณ์ต่อพ่วงที่ทำงานที่ความถี่ไม่ถูกต้องหรือไม่ทำงานเลย ตรวจสอบ assigned-clocks และ assigned-clock-rates กับไฟล์ clock tree ในคู่มืออ้างอิงของ SoC ประการที่สี่ การลืมตั้งค่า status = "okay" ทำให้อุปกรณ์ต่อพ่วงที่อธิบายไว้อย่างถูกต้องถูกปิดใช้งาน ตามธรรมเนียมแล้ว ไฟล์ DTSI ของ SoC จะอธิบายอุปกรณ์ต่อพ่วงทั้งหมดด้วย status = "disabled" และไฟล์ DTS ของบอร์ดจะเปิดใช้งานอุปกรณ์ต่อพ่วงที่ใช้งานอยู่บางส่วน

คุณใช้ Device Tree Overlays เพื่อเพิ่มความยืดหยุ่นในการใช้งานจริงอย่างไร?

การใช้ Device Tree Overlay ช่วยให้ภาพเฟิร์มแวร์พื้นฐานเพียงภาพเดียวสามารถรองรับฮาร์ดแวร์หลายรุ่นได้ ลดความซับซ้อนในการผลิตและการบำรุงรักษา ในสถานการณ์การผลิต ลองพิจารณาผลิตภัณฑ์ตระกูลหนึ่งที่มีสามรุ่น ได้แก่ รุ่นพื้นฐานที่มีเฉพาะ RS-485 รุ่นระดับกลางที่เพิ่ม BLE ผ่านโมดูลที่เชื่อมต่อผ่าน UART และรุ่นพรีเมียมที่เพิ่ม LTE ผ่านโมเด็ม USB สร้าง DTS พื้นฐานโดยปิดใช้งานอุปกรณ์ต่อพ่วงเฉพาะรุ่นทั้งหมด จากนั้นสร้างไฟล์ DTBO โอเวอร์เลย์สามไฟล์ที่เปิดใช้งานอุปกรณ์ต่อพ่วงที่เหมาะสมสำหรับแต่ละรุ่น ในระหว่างการผลิต ให้เขียนตัวระบุรุ่นลงใน EEPROM หรือฟิวส์ OTP และกำหนดค่า U-Boot ให้เลือกโอเวอร์เลย์ที่เกี่ยวข้องในเวลาบูตโดยใช้คำสั่ง fdt apply วิธีการนี้ช่วยลดจำนวนภาพเฟิร์มแวร์จาก 3 เหลือเพียง 1 ภาพพื้นฐาน + 3 โอเวอร์เลย์ขนาดเล็ก ทำให้ไปป์ไลน์ CI/CD ระบบอัปเดต OTA และการทดสอบการผลิตง่ายขึ้น Zephyr RTOS ใช้กลไกโอเวอร์เลย์เดียวกัน (ไฟล์ app.overlay) ดังนั้นวิธีการนี้จึงใช้ได้กับโครงการ MCU ที่กำหนดเป้าหมายบอร์ดที่มีฮาร์ดแวร์หลายรุ่นเช่นกัน

Related articles