Tổng quan về quy trình Porting Embedded Linux cho người mới

 

Porting (chuyển đổi) Linux lên một bo mạch (board) mới là một tác vụ nền tảng và quan trọng trong phát triển hệ thống nhúng. Tuy nhiên, quy trình tổng thể có thể gây nhầm lẫn cho các kỹ sư mới tiếp cận.

Bài viết này sẽ cung cấp một cái nhìn tổng quan, chính xác và đủ đơn giản để giúp người mới hình dung rõ ràng về công việc porting.

1. Yếu tố đầu vào: SoC (System on Chip)

Đầu vào của quá trình porting là một SoC (System on Chip).

Về cơ bản, SoC là một vi mạch tích hợp (IC) phức tạp. Các nhà sản xuất chip lấy một lõi CPU (ví dụ: ARM, PowerPC…) và thiết kế các ngoại vi (peripherals) xung quanh nó, ví dụ như bộ điều khiển DRAM, Ethernet, UART, I2C, CAN… Sau đó, tất cả các thành phần này được đóng gói lại thành một con chip duy nhất. Con chip SoC này sẽ kết nối ra thế giới bên ngoài thông qua các chân (pins).

2. Sản phẩm đầu ra: BSP (Board Support Package)

Sản phẩm cuối cùng của quá trình porting là một bộ BSP (Board Support Package).

Một bộ BSP bao gồm hai thành phần chính:

  1. Con chip SoC (phần cứng).
  2. Một bộ source code (mã nguồn) hoàn chỉnh dùng để build ra Bootloader và một Hệ điều hành Linux (bao gồm Kernel và Root File System) có thể chạy được trên con SoC đó.

Bộ BSP này sẽ được bán cho các khách hàng (các công ty phát triển sản phẩm). Các công ty này sẽ phát triển thêm các ứng dụng (applications) chạy trên nền tảng BSP mà chúng ta đã cung cấp.

Ví dụ thực tế: Router WiFi

Để hình dung rõ hơn, hãy xem xét quy trình tạo ra một router WiFi:

  1. Mua BSP: Bên làm router (ví dụ: TP-Link, Linksys) sẽ mua một bộ BSP từ một nhà cung cấp chip (ví dụ: Qualcomm, MediaTek).
  2. Thiết kế phần cứng: Họ tự thiết kế bo mạch (PCB) cho router và gắn con chip SoC vào giữa.
  3. Cài đặt OS: Họ build hệ điều hành Linux từ bộ source code của BSP và cài đặt lên router.
  4. Phát triển Ứng dụng: Lúc này, router có thể khởi động lên, nhưng mới chỉ có các chức năng phần cứng cơ bản (ví dụ: giao tiếp qua UART). Để router có thể phát WiFi, bên làm router phải tự viết ứng dụng (application) cho phép người dùng truy cập vào từ trình duyệt web, cấu hình tên/mật khẩu WiFi, và truyền các giá trị cấu hình đó xuống phần cứng.

Ngoài ra, họ còn phải phát triển rất nhiều ứng dụng khác như Firewall, xem TV qua WiFi (IPTV), quản lý mạng… Như vậy, công việc porting (tạo ra BSP) là để xây dựng nền tảng, còn công việc phát triển sản phẩm là viết ứng dụng trên nền tảng đó.

3. Ba Giai đoạn chính của quy trình Porting

Mấu chốt của việc porting là làm ra bộ source code dùng để build BootloaderOS (Kernel + Root File System).

Vì vậy, công việc porting cũng được chia làm 3 giai đoạn chính:

A. Giai đoạn 1: Porting Bootloader

Bootloader là một chương trình nhỏ, được chạy trước cả hệ điều hành. Ngay sau khi nhấn nút nguồn, hệ thống sẽ chạy ROM code (được nạp sẵn trong CPU), và ROM code sẽ chạy chương trình bootloader.

  • Nhiệm vụ: Bootloader phải khởi tạo các thành phần phần cứng tối quan trọng để chuẩn bị cho việc load OS.
    • Khởi tạo DRAM (để có RAM cho OS chạy).
    • Khởi tạo UART (để giao tiếp console, debug).
    • Khởi tạo trình điều khiển cho thiết bị lưu trữ OS (ví dụ: thẻ nhớ, flash, hoặc Ethernet nếu boot qua mạng).
  • Sau khi khởi tạo xong, nó sẽ load OS image (ảnh của hệ điều hành) và giải nén vào RAM. Cuối cùng, nó sẽ thực hiện lệnh nhảy (jump) để bắt đầu thực thi kernel của OS.
  • Công việc porting:
    1. Tải source code của một bootloader phổ biến (ví dụ: U-Boot, Grub).
    2. Tiến hành cấu hình (config) để lựa chọn các file source code cần thiết, các chức năng sẽ được build.
    3. Viết các driver còn thiếu cho bootloader (ví dụ: UART driver, Ethernet driver…).
B. Giai đoạn 2: Porting Linux Kernel

Quy trình cũng tương tự như bootloader:

  1. Tải source Linux kernel từ trên mạng về.
  2. Cấu hình (config) các chức năng, lựa chọn các module/driver sẽ được build.
  3. Tiến hành build thử.
  4. Sau khi build thành công, công việc chính là viết các driver cho kernel. Bo mạch có module phần cứng nào, chúng ta phải viết driver cho module đó.

Một tác vụ cực kỳ quan trọng khi porting kernel là viết Device Tree (DTB). Device Tree là một file dữ liệu dùng để mô tả lại toàn bộ cấu trúc phần cứng của bo mạch (SoC dùng chip gì, các ngoại vi được kết nối vào chân nào, địa chỉ thanh ghi ra sao…). Sau đó, các driver trong kernel sẽ đọc thông tin từ Device Tree này để tự cấu hình và hoạt động.

Đến đây, bo mạch đã có kernel, nhưng vẫn chưa thể sử dụng được các chức năng cơ bản (như login, hay gõ lệnh ls, cp…). Nguyên nhân là nó chưa có Root File System.

C. Giai đoạn 3: Porting Root File System (rootfs)

Ở bước này, chúng ta phải build ra được một hệ thống file hoàn chỉnh (giống như hệ thống file trong máy tính Ubuntu/Debian vậy). Đây được gọi là Root File System (rootfs).

Trong rootfs sẽ chứa tất cả các ứng dụng và thư viện mà người dùng sẽ sử dụng (ví dụ: /bin/ls, /bin/cp, /bin/cd, /sbin/ifconfig, thư viện C…).

Lưu ý, công việc ở bước này không phải là viết code mới cho các ứng dụng đó. Chúng ta chỉ cần cấu hình để build chúng từ source code có sẵn. Thông thường, các kỹ sư sẽ sử dụng một hệ thống build tự động như Yocto hoặc Buildroot để thực hiện công việc này.

4. Kết luận

Sau khi hoàn thành 3 giai đoạn trên, chúng ta sẽ có một bộ source code BSP hoàn chỉnh. Từ bộ source này, chúng ta có thể build ra bootloader và OS.

Khi nạp (flash) các file binary này vào thẻ nhớ của bo mạch, nó có thể khởi động lên, người dùng có thể đăng nhập (log in) và sử dụng các chức năng cơ bản của hệ điều hành một cách bình thường. Công việc porting của chúng ta đến đây là kết thúc.

 

 

 

 

 

 

 

 

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top