Skip to content

BSP 定制开发

BSP 概述

BSP(Board Support Package,板级支持包)是针对特定硬件平台的底层软件包,包含引导程序、内核驱动、设备树等。

BSP 组成

移远 Android BSP 组成:
  ├── Bootloader(引导程序)
  │   ├── XBL(eXtensible Bootloader):高通一级引导
  │   └── ABL(Android Bootloader):Android 引导
  ├── Linux Kernel(内核)
  │   ├── 设备树(Device Tree)
  │   └── 驱动程序
  ├── Android 系统
  │   ├── AOSP(Android Open Source Project)
  │   └── 移远定制层(HAL、系统 App)
  └── 文件系统
      ├── system.img
      ├── vendor.img
      └── userdata.img

开发环境搭建

编译环境要求

bash
# Ubuntu 20.04 LTS(推荐)
# 安装依赖
sudo apt-get install -y \
    git-core gnupg flex bison build-essential \
    zip curl zlib1g-dev gcc-multilib g++-multilib \
    libc6-dev-i386 libncurses5 lib32ncurses5-dev \
    x11proto-core-dev libx11-dev lib32z1-dev \
    libgl1-mesa-dev libxml2-utils xsltproc unzip \
    fontconfig python3 python3-pip

# 安装 repo 工具
mkdir -p ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH

获取 BSP 源码

bash
# 从移远开发者中心下载 BSP 包
# 或通过 repo 同步(需要移远账号)

# 解压 BSP 包
tar -xzf SC200E_Android11_BSP_v1.0.tar.gz
cd SC200E_Android11_BSP

# 初始化编译环境
source build/envsetup.sh
lunch sc200e-userdebug  # 选择编译目标

编译

bash
# 完整编译(首次,耗时 2-4 小时)
make -j$(nproc)

# 编译特定模块
make kernel -j$(nproc)          # 只编译内核
make bootimage -j$(nproc)       # 编译 boot.img
make systemimage -j$(nproc)     # 编译 system.img

# 编译输出目录
ls out/target/product/sc200e/
# boot.img, system.img, vendor.img, userdata.img

设备树定制

设备树(Device Tree)描述硬件配置,是 BSP 定制的核心。

设备树文件位置

kernel/arch/arm64/boot/dts/
└── qcom/
    ├── sc200e.dts          # 主设备树
    ├── sc200e-pinctrl.dtsi # 引脚配置
    └── sc200e-regulator.dtsi # 电源配置

添加 I2C 设备

c
// 在设备树中添加 I2C 传感器(如温湿度传感器 SHT30)
&i2c_2 {
    status = "okay";
    clock-frequency = <400000>;  // 400kHz Fast Mode
    
    sht30@44 {
        compatible = "sensirion,sht3x";
        reg = <0x44>;  // I2C 地址
        status = "okay";
    };
};

添加 UART 设备

c
// 配置 UART2 为用户串口
&uart_2 {
    status = "okay";
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&uart2_active>;
    pinctrl-1 = <&uart2_sleep>;
};

// 引脚配置
&tlmm {
    uart2_active: uart2_active {
        mux {
            pins = "gpio4", "gpio5";  // TX, RX
            function = "blsp_uart2";
        };
        config {
            pins = "gpio4", "gpio5";
            drive-strength = <2>;
            bias-disable;
        };
    };
};

配置 GPIO

c
// 在设备树中定义 GPIO
/ {
    custom_gpio {
        compatible = "quectel,custom-gpio";
        
        // 定义 GPIO 引脚
        gpio-led = <&tlmm 10 GPIO_ACTIVE_HIGH>;
        gpio-button = <&tlmm 11 GPIO_ACTIVE_LOW>;
        
        // 中断配置
        interrupt-parent = <&tlmm>;
        interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
    };
};

驱动开发

字符设备驱动示例

c
// 简单字符设备驱动(用于控制 GPIO)
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "custom_gpio"
#define GPIO_LED 10

static int major_number;
static struct class *device_class;
static struct device *device;

static ssize_t device_write(struct file *file, 
                             const char __user *buf,
                             size_t len, loff_t *offset)
{
    char value;
    if (copy_from_user(&value, buf, 1))
        return -EFAULT;
    
    gpio_set_value(GPIO_LED, value - '0');
    return len;
}

static struct file_operations fops = {
    .write = device_write,
};

static int __init gpio_driver_init(void)
{
    // 申请 GPIO
    gpio_request(GPIO_LED, "led");
    gpio_direction_output(GPIO_LED, 0);
    
    // 注册字符设备
    major_number = register_chrdev(0, DEVICE_NAME, &fops);
    device_class = class_create(THIS_MODULE, DEVICE_NAME);
    device = device_create(device_class, NULL, 
                           MKDEV(major_number, 0), NULL, DEVICE_NAME);
    
    pr_info("GPIO driver loaded\n");
    return 0;
}

static void __exit gpio_driver_exit(void)
{
    device_destroy(device_class, MKDEV(major_number, 0));
    class_destroy(device_class);
    unregister_chrdev(major_number, DEVICE_NAME);
    gpio_free(GPIO_LED);
}

module_init(gpio_driver_init);
module_exit(gpio_driver_exit);
MODULE_LICENSE("GPL");

固件烧录

使用 QFIL 烧录(Windows)

1. 安装高通 USB 驱动和 QFIL 工具
2. 模组进入 EDL(Emergency Download)模式:
   - 按住 BOOT_CONFIG 引脚,同时上电
   - 或通过 ADB:adb reboot edl
3. 打开 QFIL,选择 Flat Build
4. 加载 rawprogram0.xml 和 patch0.xml
5. 点击 Download 开始烧录

使用 fastboot 烧录(Linux)

bash
# 进入 fastboot 模式
adb reboot bootloader

# 查看设备
fastboot devices

# 烧录各分区
fastboot flash boot boot.img
fastboot flash system system.img
fastboot flash vendor vendor.img
fastboot flash userdata userdata.img

# 重启
fastboot reboot

褚成志的笔记