ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

海思平台TW2868视频解码芯片Linux驱动开发全解析

2026/9/5 23:52:00 拓冰建站 浏览量
海思平台TW2868视频解码芯片Linux驱动开发全解析 简介本资源是面向嵌入式Linux驱动开发者的海思平台TW2868视频处理芯片底层驱动源码包适用于安防监控、数字电视接收器等音视频终端设备的系统集成与定制开发。资源共7个文件含2个C源文件TW2868.c、gpio_rw.c、3个头文件tw2868.h、tw2868_def.h、gpio_rw.h、1个已编译的内核模块tw2868.ko及1个标准Makefile总大小仅17KB结构精炼覆盖设备初始化、GPIO控制、寄存器读写、中断响应等关键驱动逻辑。已有216人学习下载适合具备Linux内核模块编译经验、熟悉海思SDK环境的中高级开发者。读者可直接加载ko模块验证硬件功能亦可基于源码修改适配不同PCB引脚定义或优化DMA传输流程Makefile与头文件组织规范便于快速融入海思Hi35xx系列SDK内核树进行二次构建。1. 项目概述解码TW2868在Linux海思平台上的驱动之旅最近在折腾一个老项目手头有几块基于海思HiSilicon芯片的嵌入式板子需要接入TW2868这款多路视频解码芯片。TW2868这玩意儿在安防监控、多画面分割显示的领域里算是个“老熟人”了尤其是在一些DVR、NVR的板卡上很常见。它的核心功能就是把多路模拟摄像头比如CVBS信号的数字视频流解码出来然后通过并口或者类似接口吐给主处理器。而我这次的任务就是在海思的Linux SDK环境下为它编写一个稳定、高效的底层驱动。这听起来像是个标准的“芯片驱动适配”工作但实际踩进去才发现从海思SDK那略显特殊的框架到TW2868寄存器操作的时序拿捏再到多路视频数据流的稳定搬运每一步都有不少门道。如果你也在为类似的视频解码芯片做Linux驱动适配或者对海思平台下的外设驱动开发感兴趣那这篇从零到一的踩坑实录或许能给你省下不少折腾的时间。2. 核心需求与方案选型解析2.1 项目核心需求拆解这个驱动项目的目标非常明确让海思主芯片比如常见的Hi3516、Hi3518系列能够通过TW2868芯片稳定地采集并处理多路模拟摄像头的视频数据。拆解开来主要有以下几个硬性要求视频流接入TW2868通常支持4路或8路CVBS输入驱动需要能正确初始化芯片并将指定通道的视频数据解码为YUV或RGB格式的数字信号。数据接口对接TW2868解码后的数据通过并行的数字视频接口如BT.656输出。驱动需要配置海思芯片对应的视频输入VI模块正确接收这些数据并处理好时序如行场同步信号。海思平台集成必须完全融入海思提供的媒体处理软件框架MPP。这意味着驱动产出的视频数据要能无缝对接后续的VPSS视频前处理、VENC视频编码等模块最终形成完整的视频采集、处理、编码链路。稳定与效率作为安防监控类应用驱动必须保证长时间运行的稳定性不能出现丢帧、花屏、死锁等问题。同时数据搬运效率要高尽量减少CPU占用为编码等后续任务留出资源。2.2 为什么选择海思Linux SDK框架在海思平台上做开发尤其是多媒体相关几乎无法绕开其官方的MPPMedia Process Platform框架。这不是一个可以随意选择的“方案”而是必须遵循的“路径”。海思芯片的许多硬件加速模块如VI、VPSS、VENC、VDEC的寄存器操作和内存管理都被MPP框架封装好了。如果你试图绕过MPP直接去操作这些硬件的底层寄存器不仅会异常复杂而且极易导致系统不稳定或性能无法发挥。因此我们的TW2868驱动本质上是一个“海思VI模块的传感器SENSOR驱动”。我们需要按照海思定义的HI_MPI_VI接口规范实现一个SENSOR对象在其中完成TW2868的初始化、参数设置分辨率、帧率、以及使能/关闭等操作。数据流由海思的VI控制器通过BT.656接口直接“拉取”驱动层主要负责配置TW2868输出符合VI控制器预期的信号格式。注意这里有一个关键理解点。TW2868驱动不直接负责DMA搬运视频数据到内存。这个工作是由海思VI模块的硬件FIFO和DMA控制器完成的。驱动的工作是告诉TW2868“请以1080P30fps、BT.656格式输出数据”同时告诉海思VI模块“请准备接收这个格式的数据”。两者配置匹配后数据流就自动建立了。2.3 TW2868硬件控制方式选择TW2868通常通过I2C总线进行配置。这是最普遍和标准的方式。我们需要在海思的Linux内核中确保I2C控制器驱动正常工作并将TW2868作为其上的一个从设备Slave Device进行注册和访问。为什么不直接用GPIO模拟时序虽然理论上可以用GPIO模拟I2C时序即所谓的“bit-banging”但在海思这种复杂系统中绝对不推荐。原因有三第一海思的I2C控制器驱动成熟稳定直接使用可以保证时序精确性和可靠性第二内核的I2C子系统提供了设备树Device Tree支持配置管理更清晰第三使用标准I2C框架可以方便地利用内核的调试工具如i2cdetect来排查问题。所以方案很清晰基于海思Linux SDK和MPP框架编写一个符合SENSOR驱动模型的TW2868 I2C设备驱动。3. 海思Linux开发环境搭建与核心概念3.1 SDK获取与交叉编译环境搭建海思会为其芯片提供完整的Linux SDK包通常包含U-Boot、内核、根文件系统以及最重要的MPP库和样例代码。第一步就是获取与你手中芯片型号完全匹配的SDK。搭建交叉编译工具链SDK里会提供或指定一个交叉编译工具链比如arm-hisiv300-linux-或arm-hisiv400-linux-。你需要将其路径加入到系统的PATH环境变量中。export PATH/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin:$PATH然后通过arm-hisiv300-linux-gcc -v验证是否安装成功。理解SDK目录结构SDK通常有类似以下的目录osdrv/: 包含内核、U-Boot源码和编译脚本。mpp/: 媒体处理平台包含头文件、库文件、样例源码。这是我们驱动开发的核心参考。package/: 一些第三方软件包。tools/: 一些PC端工具如烧录工具。编译内核与模块首先需要根据你的板级硬件配置内核。海思SDK的内核通常已经打好了相关补丁。重点在于配置Device Tree和驱动。cd osdrv/opensource/kernel/linux-3.18.y make ARCHarm CROSS_COMPILEarm-hisiv300-linux- hi3516ev200_defconfig # 使用你的板子对应配置 make ARCHarm CROSS_COMPILEarm-hisiv300-linux- menuconfig # 确保 I2C, Video capture, 以及海思的VI、VPSS等支持已编译进内核或编为模块 make ARCHarm CROSS_COMPILEarm-hisiv300-linux- uImage -j8 make ARCHarm CROSS_COMPILEarm-hisiv300-linux- modules3.2 海思MPP框架与VI模块关键概念在动手写驱动前必须吃透MPP框架中关于视频输入VI的部分。关键数据结构在mpp/include/hi_comm_vi.h和hi_comm_video.h中定义。VI通道VI Pipe VI Channel这是海思视频输入的核心抽象。一个Pipe可以理解为一个物理的输入接口如BT.656接口一个Channel是这个接口上的一个逻辑数据流。一个Pipe下可以有多个Channel用于实现多画面分割。对于TW2868我们通常使用一个Pipe对应其BT.656输出并在这个Pipe下创建多个Channel来对应TW2868的多个物理输入通道。SENSOR驱动模型海思期望你为每个图像传感器或像TW2868这样的解码芯片实现一个sensor对象。这个对象是一个包含了一系列函数指针的结构体ISP_SENSOR_EXP_FUNC_S主要函数有pfn_sensor_init: 传感器初始化上电、复位、I2C配置。pfn_sensor_exit: 传感器退出。pfn_sensor_set_info: 设置传感器工作模式分辨率、帧率等。pfn_sensor_get_info: 获取传感器信息。 我们的TW2868驱动就是要填充这个结构体。数据流绑定Bind配置好VI Channel和SENSOR后需要通过HI_MPI_VI_SetDevBindPipe和HI_MPI_VI_SetChnBindPipe等API将SENSOR与具体的VI Dev/Chn绑定起来数据通路才算建立。实操心得刚开始看海思的MPP文档和样例时容易被一堆VI_DEV、VI_PIPE、VI_CHN搞晕。一个简单的记忆方法是DEV对应一个物理芯片如TW2868PIPE对应这个芯片的一个数据输出口通常就一个CHN对应你想从这个输出口里提取的某一路视频比如TW2868的CH1画面。配置顺序一般是创建DEV - 创建PIPE - 配置PIPE属性绑定SENSOR- 创建CHN - 启动CHN。4. TW2868驱动核心实现详解4.1 I2C设备注册与设备树配置要让内核识别TW2868首先需要在设备树.dts文件中声明它。假设TW2868连接在I2C总线0上从机地址为0x44具体地址需查TW2868手册通常由引脚电平决定。// 在板级.dts文件的i2c0节点内添加 i2c0 { status okay; clock-frequency 400000; // I2C速率TW2868支持400KHz tw2868: video-decoder44 { compatible techwell,tw2868; // 用于匹配驱动 reg 0x44; // I2C从机地址 reset-gpios gpio_chip 8 GPIO_ACTIVE_LOW; // 复位引脚可选 power-gpios gpio_chip 9 GPIO_ACTIVE_HIGH; // 电源使能引脚可选 // 可能还需要配置时钟、电源等具体看硬件设计 }; };compatible属性是关键驱动中会通过它来匹配设备。接下来在驱动代码中我们需要定义一个i2c_driverstatic const struct i2c_device_id tw2868_id[] { { tw2868, 0 }, { } }; MODULE_DEVICE_TABLE(i2c, tw2868_id); static const struct of_device_id tw2868_of_match[] { { .compatible techwell,tw2868 }, { } }; MODULE_DEVICE_TABLE(of, tw2868_of_match); static struct i2c_driver tw2868_i2c_driver { .driver { .name tw2868, .of_match_table of_match_ptr(tw2868_of_match), }, .probe tw2868_probe, .remove tw2868_remove, .id_table tw2868_id, }; module_i2c_driver(tw2868_i2c_driver);在tw2868_probe函数中我们将完成驱动的核心初始化。4.2 实现海思SENSOR驱动接口这是驱动与海思MPP对接的核心。我们需要定义一个全局的sensor对象。#include hi_comm_vi.h #include hi_sns_ctrl.h // 定义TW2868的上下文结构体存放芯片状态、I2C client等 typedef struct { struct i2c_client *i2c_client; HI_BOOL power_on; HI_BOOL initialized; // 可以添加当前分辨率、帧率等状态信息 } TW2868_CTX_S; static TW2868_CTX_S g_tw2868_ctx; // SENSOR初始化函数 static HI_S32 TW2868_Init(HI_VOID) { HI_S32 ret HI_SUCCESS; struct i2c_client *client g_tw2868_ctx.i2c_client; if (g_tw2868_ctx.initialized) { return HI_SUCCESS; } // 1. 硬件上电/复位序列 (如果设备树中定义了gpio) // gpiod_set_value(g_tw2868_ctx.reset_gpio, 0); // msleep(10); // gpiod_set_value(g_tw2868_ctx.reset_gpio, 1); // msleep(50); // 2. 通过I2C写入TW2868初始化寄存器序列 ret tw2868_write_regs(client, tw2868_init_reg_table, TABLE_SIZE); if (ret ! HI_SUCCESS) { printk(KERN_ERR TW2868 init failed!\n); return HI_FAILURE; } g_tw2868_ctx.initialized HI_TRUE; g_tw2868_ctx.power_on HI_TRUE; printk(KERN_INFO TW2868 initialized.\n); return HI_SUCCESS; } // SENSOR退出函数 static HI_VOID TW2868_Exit(HI_VOID) { // 写入休眠或关断寄存器 // tw2868_write_reg(g_tw2868_ctx.i2c_client, POWER_CTL_REG, 0x00); g_tw2868_ctx.initialized HI_FALSE; g_tw2868_ctx.power_on HI_FALSE; } // 设置SENSOR工作模式分辨率、帧率 static HI_S32 TW2868_SetInfo(const HI_MPI_VI_SENSOR_INFO_S *pstSensorInfo) { HI_U32 width pstSensorInfo-width; HI_U32 height pstSensorInfo-height; HI_FLOAT framerate pstSensorInfo-framerate; // 根据传入的参数配置TW2868输出相应的视频格式 // 例如判断是720P30fps还是1080P25fps然后写入不同的寄存器组 HI_S32 ret HI_SUCCESS; if ((width 1920) (height 1080) (framerate 25.0)) { ret tw2868_write_regs(g_tw2868_ctx.i2c_client, tw2868_1080p25_regs, ...); } else if ((width 1280) (height 720) (framerate 30.0)) { ret tw2868_write_regs(g_tw2868_ctx.i2c_client, tw2868_720p30_regs, ...); } else { printk(KERN_ERR Unsupported mode: %dx%d%f\n, width, height, framerate); return HI_FAILURE; } return ret; } // 填充SENSOR能力结构体告诉MPP本驱动支持的格式 static HI_S32 TW2868_GetInfo(HI_MPI_VI_SENSOR_INFO_S *pstSensorInfo) { // 这里填充TW2868支持的分辨率、帧率列表 pstSensorInfo-num 2; // 支持两种模式 pstSensorInfo-sensor_info[0].width 1920; pstSensorInfo-sensor_info[0].height 1080; pstSensorInfo-sensor_info[0].framerate 25; pstSensorInfo-sensor_info[0].sensor_type VI_SENSOR_TYPE_BT656; pstSensorInfo-sensor_info[1].width 1280; pstSensorInfo-sensor_info[1].height 720; pstSensorInfo-sensor_info[1].framerate 30; pstSensorInfo-sensor_info[1].sensor_type VI_SENSOR_TYPE_BT656; return HI_SUCCESS; } // 最关键的一步定义并导出SENSOR对象 static ISP_SENSOR_EXP_FUNC_S g_stTW2868ExpFunc { .pfn_sensor_init TW2868_Init, .pfn_sensor_exit TW2868_Exit, .pfn_sensor_set_info TW2868_SetInfo, .pfn_sensor_get_info TW2868_GetInfo, // 可能还有其他函数如控制增益、曝光等TW2868若不支持可置NULL }; // 这个导出符号会被海思的VI模块调用 EXPORT_SYMBOL(g_stTW2868ExpFunc);4.3 TW2868寄存器配置详解TW2868的驱动核心就是那一张张的寄存器配置表。这些值需要严格参照TW2868的数据手册Datasheet和官方应用笔记Application Note。以下是一个简化的示例展示如何组织这些配置// 定义一个寄存器-值对的结构体 typedef struct { HI_U8 reg_addr; HI_U8 reg_value; } tw2868_reg_val_t; // 初始化寄存器序列示例非完整 static const tw2868_reg_val_t tw2868_init_reg_table[] { {0x00, 0x01}, // 软件复位 {0x01, 0x40}, // 配置时钟、PLL等 {0x02, 0x1A}, // 输入通道选择、格式控制 {0x03, 0x0F}, // 使能所有4个通道的输出 {0x04, 0x80}, // 配置输出为YUV422BT.656格式 {0x05, 0x00}, // 亮度、对比度等图像参数 // ... 更多寄存器 }; // 1080P25模式寄存器序列 static const tw2868_reg_val_t tw2868_1080p25_regs[] { {0x10, 0xXX}, // 设置水平总像素 {0x11, 0xXX}, // 设置垂直总行数 {0x12, 0xXX}, // 设置行同步宽度等 // ... 时序相关寄存器 }; // I2C写入辅助函数 static HI_S32 tw2868_write_reg(struct i2c_client *client, HI_U8 reg, HI_U8 val) { HI_U8 buf[2] {reg, val}; struct i2c_msg msg { .addr client-addr, .flags 0, .len 2, .buf buf, }; int ret i2c_transfer(client-adapter, msg, 1); if (ret ! 1) { dev_err(client-dev, I2C write failed at reg 0x%02x\n, reg); return HI_FAILURE; } return HI_SUCCESS; }踩坑实录寄存器配置的时序TW2868有些寄存器配置有先后顺序要求。例如必须先配置PLL和时钟相关寄存器稳定后再配置视频格式寄存器。在编写初始化序列时最好严格按照数据手册中“Power-Up Sequence”或“Initialization Flow”的步骤来并在关键步骤后增加适当的延时msleep。我曾因为少了一个5ms的延时导致输出图像始终不稳定排查了很久。5. 驱动集成、测试与问题排查5.1 驱动编译与内核模块加载将写好的驱动文件如tw2868_drv.c放到海思SDK内核的drivers/media/i2c/目录下是一个常见做法。需要修改该目录的Kconfig和Makefile文件将TW2868驱动添加为编译选项。# 在 drivers/media/i2c/Makefile 中添加 obj-$(CONFIG_VIDEO_TW2868) tw2868.o# 在 drivers/media/i2c/Kconfig 中添加 config VIDEO_TW2868 tristate Techwell TW2868 video decoder support depends on I2C VIDEO_V4L2 MEDIA_CONTROLLER help Support for the Techwell TW2868 4/8 channel video decoder.配置内核时选中VIDEO_TW2868可以编译进内核*或编为模块M。编为模块便于调试。编译内核和模块后将生成的tw2868.ko文件拷贝到开发板根文件系统使用insmod tw2868.ko加载。使用dmesg | grep tw2868查看驱动打印的日志确认probe函数是否成功执行。5.2 与海思MPP样例程序对接测试海思MPP SDK中通常会提供sample_vio视频输入输出样例这样的测试程序。我们需要修改样例代码将其中的sensor_type配置为我们驱动对应的类型。在MPP的sensor初始化部分通常有一个sensor注册表。我们需要在这里添加对TW2868的支持。例如在sample_vio的源码中找到类似SENSOR_TYPE_XXX的定义和g_pastSensor数组添加一项#ifdef TW2868_SUPPORT {TW2868_NAME, TW2868_I2C_ADDR, g_stTW2868ExpFunc}, #endif然后在sample_vio的配置文件或命令行参数中指定sensor名为TW2868_NAME如“tw2868”。运行测试程序如果配置正确MPP会调用我们导出的g_stTW2868ExpFunc中的函数完成初始化并开始采集图像。你可以通过MPP的HI_MPI_VPSS_GetChnFrame等API获取到视频帧数据并保存为文件或通过网络发送来验证图像是否正确。5.3 常见问题与排查技巧实录驱动开发过程就是不断踩坑和填坑。以下是我遇到的一些典型问题及解决方法问题现象可能原因排查步骤与解决方法I2C通信失败1. 设备树配置错误地址、兼容性2. I2C总线未使能3. 硬件连接问题上拉电阻、电压1. 在系统启动后进入/sys/bus/i2c/devices/查看是否有对应的I2C总线设备。2. 使用i2cdetect -y 0假设总线0扫描设备看能否看到0x44地址。3. 检查内核启动日志dmesg看I2C控制器驱动是否加载成功设备树节点是否被正确解析。驱动probe失败1.of_match_table不匹配2.probe函数中资源申请失败如GPIO3. 初始化序列中某步出错导致返回失败1. 在驱动probe函数开头加printk看是否被调用。2. 逐步检查probe函数确认GPIO申请、内存分配等是否成功。3. 在TW2868初始化函数TW2868_Init中增加更详细的调试打印定位到具体出错的寄存器写入步骤。MPP报错“无法绑定SENSOR”1. 导出的g_stTW2868ExpFunc符号未正确被MPP找到2. SENSOR名称不匹配3.GetInfo返回的格式MPP不支持1. 使用cat /proc/kallsyms | grep tw2868检查驱动符号是否成功加载到内核符号表。2. 确保在MPP配置中填写的SENSOR名称与驱动中定义的完全一致大小写敏感。3. 检查TW2868_GetInfo函数返回的sensor_type必须是VI_SENSOR_TYPE_BT656和分辨率、帧率是否在海思芯片的VI能力范围内。输出图像花屏、错位1. BT.656时序配置错误行场同步、消隐2. TW2868输出格式与海思VI配置不匹配如YUV顺序3. 内存访问越界或缓存一致性问题1.这是最棘手的问题。使用示波器测量BT.656的时钟PCLK、行同步HSYNC、场同步VSYNC信号与TW2868数据手册和海思VI要求的时序图对比。2. 仔细核对TW2868寄存器中关于输出数据格式YUV422顺序是CbYCrY还是YCrYCb、同步信号极性高有效还是低有效的配置与海思VI模块的配置VI_DEV_ATTR_S中的work_mode等必须完全一致。3. 确认海思VI模块分配的缓冲区大小足够容纳一帧图像宽度高度2 bytes for YUV422。只有某一通道无图像1. TW2868对应通道的输入未使能或制式不对PAL/NTSC2. 海思VI多通道配置错误1. 检查TW2868寄存器确认所有需要的通道都已使能Output Channel Enable相关寄存器。2. 确认输入信号制式。TW2868需要根据PAL或NTSC自动或手动调整解码参数。检查对应通道的“标准检测”寄存器状态。3. 在海思侧确认为TW2868的每个物理通道都正确创建并启动了独立的VI_CHN。独家避坑技巧利用海思的Debug Level。海思MPP库在编译时通常可以设置调试等级。在mpp/component目录下的各个模块如vi的Makefile中往往有CFLAGS -DHI_DEBUG之类的选项。打开调试编译后重新运行样例程序会输出非常详细的VI模块内部状态、错误码和数据流信息对于定位配置不匹配问题有奇效。例如你可以看到VI是否成功收到了场中断VSYNC以及每一行的数据长度是否匹配预期。6. 性能优化与高级功能探讨6.1 中断模式与轮询模式的选择海思VI模块接收数据有两种方式中断模式和轮询模式。在设备树中配置VI设备属性时可以指定。中断模式VI硬件在收到一场完整的视频数据VSYNC后产生一个中断通知CPU来搬运一帧数据。这种方式CPU占用率低更节能是推荐的方式。轮询模式CPU不断查询VI硬件状态检查是否有一帧数据就绪。这种方式会持续占用CPU效率低仅在调试或特殊情况下使用。确保在设备树中为VI设备配置了正确的中断号并在驱动中无误。在/proc/interrupts中可以看到VI中断是否被触发。6.2 多路视频流与带宽考量TW2868同时输出多路视频数据量巨大。以4路1080P25fps YUV422计算1920 * 1080 * 2 bytes/pixel * 25 fps * 4路 ≈ 398 MB/s。 这已经接近甚至超过了某些海思芯片内部总线如AXI的带宽上限。因此在实际项目中需要仔细评估降低分辨率或帧率如果不需全高清可降低为720P或D1。启用海思的压缩传输一些海思芯片的VI模块支持“在线压缩”Online Compression将YUV数据在存入DDR前先进行轻量级压缩如H.264/H.265 I帧可以大幅减少带宽压力。这需要在VI_DEV_ATTR_S中配置compress_mode。分时复用如果业务上不需要同时观看所有通道可以通过快速切换TW2868的输出通道修改寄存器来实现“伪”多路但这会增加软件复杂性。6.3 图像质量参数调节TW2868内部有亮度、对比度、饱和度、色调等调节寄存器。不建议在驱动初始化时写死这些值。更好的做法是在驱动中暴露这些寄存器控制接口例如实现VIDIOC_S_CTRL和VIDIOC_G_CTRL的v4l2_ioctl_ops。在上层应用程序中通过标准的V4L2控制接口或海思可能提供的扩展接口来动态调节。这样可以为每个摄像头提供独立的图像调节功能适应不同的现场环境。7. 总结与展望完成一个像TW2868这样的视频解码芯片在海思Linux平台上的驱动是一个典型的嵌入式Linux驱动开发项目它综合了对硬件芯片手册、时序、内核I2C框架、设备树、以及特定平台框架海思MPP的理解。整个过程就像搭积木从最底层的I2C读写到中间层的V4L2子系统和海思SENSOR模型适配再到最上层的应用数据流对接每一层都要严丝合缝。我个人最大的体会是数据手册和示波器是最好的老师。当图像出现任何异常时回归到最基础的信号时序和寄存器配置逐项对比、验证往往比在代码里盲目猜测更有效率。另外充分利用海思SDK中的样例代码和调试信息能帮你快速理解数据在MPP框架中的流动路径。这个驱动稳定运行后还可以考虑进一步的优化比如实现电源管理在无视频流时让TW2868进入低功耗模式或者加入自动检测输入信号制式PAL/NTSC并自适应配置的功能使得驱动更加智能和健壮。对于更复杂的多芯片级联场景可能还需要考虑I2C地址扩展和同步初始化等问题但核心的驱动框架和调试思路都是相通的。希望这篇详细的梳理能为你点亮海思平台下类似外设驱动开发的道路。本文还有配套的精品资源点击获取