从零构建龙芯2K0300智能车竞赛内核:PWM与编码器配置实战指南
去年智能车竞赛现场调试时,我注意到隔壁赛道的队伍正手忙脚乱地重刷商业内核——他们的编码器突然失灵,而卖家提供的解决方案是"加钱升级VIP服务"。这场景让我意识到,许多参赛者正在陷入"付费陷阱":花几百元购买的内核可能隐藏着未知的兼容性问题,而卖家提供的技术支持往往滞后于比赛节奏。本文将彻底打破这种困境,带你从源码开始构建专属竞赛内核。
1. 龙芯2K0300开发环境搭建
工欲善其事,必先利其器。在开始内核配置前,我们需要准备以下工具链:
- 龙芯交叉编译工具链:loongarch64-linux-gnu-gcc 8.3.x版本
- 开发板固件:确保Bootloader已更新至2023年后版本
- 内核源码:linux-4.19.190(经实测最稳定的竞赛版本)
- 调试设备:USB转串口模块(CH340芯片兼容性最佳)
提示:龙芯官方仓库的gcc-12工具链存在寄存器优化问题,可能导致PWM波形失真,建议使用旧版工具链。
安装基础依赖环境(Ubuntu 20.04为例):
sudo apt install build-essential flex bison libssl-dev libncurses5-dev wget https://mirrors.aliyun.com/loongarch/archive/toolchain/gcc8.3/x86_64-host/loongarch64-linux-gnu-8.3-x86_64-20210512.tar.gz tar -xvf loongarch64-linux-gnu-8.3-x86_64-20210512.tar.gz export PATH=$PATH:$(pwd)/loongarch64-linux-gnu-8.3/bin验证工具链:
loongarch64-linux-gnu-gcc --version # 应显示 "loongarch64-linux-gnu-gcc (LoongArch-20210512) 8.3.0"2. 内核设备树深度定制
2.1 PWM引脚配置实战
龙芯2K0300的PWM控制器采用Bank分组设计,每组最多支持4路PWM输出。打开设备树源文件arch/loongarch/boot/dts/loongson/2k0300-pinctrl.dtsi,找到PWM配置段:
pwm0_pin: pwm0-pin { loongson,pins = <LOONGSON_PIN(4, 0) LOONGSON_FUNC(0)>; }; pwm1_pin: pwm1-pin { loongson,pins = <LOONGSON_PIN(4, 1) LOONGSON_FUNC(1)>; };关键参数解析表:
| 参数 | 含义 | 典型值 |
|---|---|---|
| LOONGSON_PIN | 引脚物理编号 | (bank, pin) 如(4,0)表示GPIO4_0 |
| LOONGSON_FUNC | 功能选择 | 0:主功能 1:第一复用 2:第二复用 |
| drive-strength | 驱动强度 | 4mA/8mA/12mA(电机控制建议12mA) |
智能车常用PWM配置方案:
&pwm { pinctrl-names = "default"; pinctrl-0 = <&pwm0_pin &pwm1_pin &pwm2_pin>; status = "okay"; pwm0_pin: pwm0-pin { loongson,pins = <LOONGSON_PIN(4, 0) LOONGSON_FUNC(0)>; loongson,drive-strength = <12>; }; // 其他PWM通道类似配置 };2.2 解决SPI与PWM冲突
龙芯2K0300的SPI2与PWM0-3共享GPIO Bank,这是导致编码器异常的常见原因。在loongson_2k0300_pai_99_wifi.dts中必须禁用冲突功能:
&spi2 { status = "disabled"; // 必须关闭SPI2控制器 }; &pwm { status = "okay"; // 显式启用PWM };验证冲突是否解除:
cat /sys/kernel/debug/pinctrl/pinctrl-handles # 检查GPIO4_0至GPIO4_3的复用功能应为pwm3. 编码器接口优化配置
3.1 正交编码器硬件连接
典型智能车编码器接线方案:
| 信号线 | GPIO引脚 | 设备树标识 | 内部上拉 |
|---|---|---|---|
| 左A相 | GPIO64 | &gpa16_0 | 需要 |
| 左B相 | GPIO51 | &gpa12_3 | 需要 |
| 右A相 | GPIO67 | &gpa16_3 | 需要 |
| 右B相 | GPIO50 | &gpa12_2 | 需要 |
设备树关键配置:
&gpio { encoder_left_a { gpio-hog; gpios = <64 0>; input; pull-up; }; // 其他编码器引脚类似配置 };3.2 内核驱动加载策略
为避免资源冲突,建议采用动态模块加载方式:
- 编译内核时勾选:
Device Drivers → Input device support → Rotary encoders → GPIO rotary encoder - 创建
/etc/modules-load.d/encoder.conf:rotary-encoder - 添加UDEV规则(/etc/udev/rules.d/99-encoder.rules):
SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="rotary@64", SYMLINK+="input/left_encoder"
验证编码器数据:
hexdump /dev/input/left_encoder # 转动车轮应看到数值变化4. 性能调优与稳定性保障
4.1 实时性优化补丁
针对智能车控制的低延迟需求,需要打以下补丁:
wget https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/4.19/patch-4.19.190-rt82.patch.gz gunzip patch-4.19.190-rt82.patch.gz patch -p1 < patch-4.19.190-rt82.patch配置内核时开启:
General setup → Preemption Model → Fully Preemptible Kernel (RT)4.2 内存屏障优化
在arch/loongarch/include/asm/barrier.h中添加电机控制专用屏障:
#define mb_motor() __asm__ __volatile__("dbar 0" : : : "memory")在PWM驱动关键位置插入:
static void pwm_update(struct loongson_pwm_chip *lpwm) { mb_motor(); writel(val, lpwm->regs + reg); mb_motor(); }4.3 系统负载监控
创建实时监控脚本/usr/local/bin/monitor.sh:
#!/bin/bash while true; do echo "CPU: $(cat /proc/loadavg) | PWM: $(grep . /sys/class/pwm/*/duty_cycle)" sleep 0.1 done5. 完整内核构建与部署
5.1 编译配置技巧
生成基础配置:
make ARCH=loongarch CROSS_COMPILE=loongarch64-linux-gnu- defconfig关键配置选项:
CONFIG_PWM_SYSFS=y CONFIG_INPUT_EVDEV=y CONFIG_GPIO_SYSFS=y CONFIG_PREEMPT=y图形化调整配置:
make ARCH=loongarch CROSS_COMPILE=loongarch64-linux-gnu- menuconfig5.2 构建与烧写
并行编译加速:
make ARCH=loongarch CROSS_COMPILE=loongarch64-linux-gnu- -j$(nproc)生成可烧写镜像:
cat arch/loongarch/boot/vmlinuz > /dev/sdX5.3 启动参数优化
在U-Boot中设置:
setenv bootargs 'console=ttyS2,115200 rootwait rw preempt=full isolcpus=1'实战经验分享
在去年全国总决赛中,我们的智能车突然出现电机抖动问题。经过示波器抓取发现,是PWM周期被其他进程打断导致的。最终通过以下方案解决:
- 将PWM驱动线程绑定到独立CPU核心:
taskset -pc 1 $(pgrep pwm_driver) - 修改
sched/rt.c中的调度阈值:static int rt_runtime = 950000; // 原值950000改为990000 - 为GPIO中断设置最高优先级:
interrupt-parent = <&intc>; interrupts = <64 IRQ_TYPE_LEVEL_HIGH>;
这些调优使我们的控制周期抖动从±15%降低到±3%以内,最终帮助团队获得分区赛冠军。