news 2026/10/8 11:25:50

U-Boot移植实战:从零添加新板卡的Kbuild构建流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
U-Boot移植实战:从零添加新板卡的Kbuild构建流程
刚拿到一块没有 U-Boot 支持的新板子,你大概会先百度一整天,然后被各种 start.S、configs/*_defconfig、设备树、链接脚本搅得头大。U-Boot 移植这个活儿,说难确实难,难在它把汇编、C 语言初始化、Kconfig 配置、Kbuild 构建规则和硬件手册全混在一起;但说简单也简单,因为整个移植流程已经被 Kbuild 这套构建系统标准化了,你只需要知道在哪个文件里加什么东西、改哪个宏、跑哪条 make 指令。 这篇内容就是围绕 U-Boot 移植和 Kbuild 展开的入门总结,适合刚拿到一块新开发板、准备自己把 U-Boot 跑起来的朋友。我会先讲清楚移植到底在移什么,再拆开 Kbuild 的配置与编译机制,然后按真实操作顺序走一遍从复制参考板到生成可执行镜像的流程,最后把那些藏在 make 输出背后的坑逐个挑出来。看完之后你会发现,移植 U-Boot 不是拼命写代码,而是“照着参考板改配置、调参数、看输出、再改”的循环,Kbuild 就是你在这个循环里最需要熟悉的工具。 ## 1. U-Boot 移植入门,先搞懂这三件事 ### 1.1 启动链路与“移植”的真实含义 在动代码之前,我建议你先把 SoC 的启动流程画出来。现在的芯片上电后,片内 ROM 里有一段出厂固件叫 BootROM,它负责从 SPI NOR、SD 卡、eMMC、NAND 或 USB 等介质里加载一段小程序到 SRAM,这段小程序通常是 U-Boot SPL。SPL 的任务是初始化外部 DDR、时钟和串口,然后把完整的 U-Boot 主体加载进内存。主体 U-Boot 继续初始化更多外设,最终通过网络、USB 或存储介质加载内核和设备树,完成启动接力。 这里最关键的一点是:移植 U-Boot 不等于重写 U-Boot。你真正要做的就是“让 SPL 能在你的板子上把 DDR 跑起来,让 U-Boot 主体能稳定地初始化板载外设,并且把内核引导起来”。听起来范围很大,但落到具体文件上,无非是板级目录下的一堆 C 文件、设备树源文件、头文件里的配置宏,以及 Kconfig 和 defconfig 里的选择项。Kbuild 负责把这些分散的东西组织成最终可以烧录的 u-boot.bin,所以它的作用一点不比写初始化代码小。 ### 1.2 Kbuild 为什么是移植流程里的关键一环 Kbuild 最早是 Linux 内核用的构建系统,U-Boot 直接继承了这套思路。它不只是一个 Makefile,而是由顶层 Makefile、子目录里的 Kconfig、Makefile 以及 scripts/ 下的一系列辅助脚本组成的完整框架。对移植工作来说,Kbuild 的价值有三个:配置可裁剪、层次清晰、依赖自动搞定。 配置可裁剪体现在 Kconfig 上,U-Boot 把 CPU 架构、板卡型号、驱动、命令、文件系统等都以菜单的形式组织起来,你通过 menuconfig 或者直接写 defconfig 来决定哪些代码编进去。层次清晰体现在目录结构上,arch/ 下面是 CPU 相关代码,board/ 下面是板级代码,drivers/ 下面是外设驱动,每个目录都有自己的 Kconfig 和 Makefile,Kbuild 会在编译时自动进入这些子目录。依赖自动搞定则是它会为你生成 include/autoconf.mk、include/generated/autoconf.h 等文件,把 .config 里的配置项转换成编译器和代码能直接用的宏定义。 我经常拿“流水线”来类比 Kbuild:源代码是原料,Kconfig 是菜单,defconfig 是订单,Makefile 是流水线上的工序,最后的二进制文件就是装箱成品。你说我要换一个 DDR 芯片,那就在设备的 dts 和头文件里改参数,而不是去手动调整几千行汇编和链接脚本。 ### 1.3 和 FreeRTOS、LVGL 等应用级移植不是一回事 网上搜“移植”两个字,出来的结果大半是 FreeRTOS 移植、LVGL 移植、某个游戏引擎移植这种。这些移植虽然也叫移植,但它们的核心工作通常是“让一套现成的应用代码跑在另一个平台上”,重点在 API 适配、中断处理、内存分配和图形驱动对接。 U-Boot 移植所处的层次完全不同。它更接近 firmware 移植,你需要面对的是芯片启动阶段那一堆汇编代码、内存控制器寄存器、时钟树配置,以及 Kbuild 是如何决定哪些源文件参与链接的。换句话说,应用级移植解决的是“让软件跑起来”,U-Boot 移植解决的是“让硬件先活过来,再给系统软件一个可运行的环境”。这两个难度完全不在一个量级,所以不能拿 LVGL 移植的经验往 U-Boot 上套。这也是为什么很多初学者拿着现成的板卡资料,改了半天配置文件,却连串口都没有输出——因为他根本还没到“跑应用”那一步,连最底层的启动链路都没建立起来。 ## 2. 拆开 Kbuild 这个盒子:配置、递归 Make 和自动生成文件 ### 2.1 配置从哪里来:Kconfig 树和 menuconfig U-Boot 源码里几乎每个有源文件的目录都会放一个 Kconfig 文件,这些 Kconfig 定义了这个目录下有哪些可配置选项、依赖关系、默认值。顶层 Kconfig 通过 source 语句把各个子目录的 Kconfig 串成一整棵配置树。你执行 make menuconfig 时,看到的那个层层嵌套的菜单界面,其实就是在解析这棵配置树。 对移植来说,你通常不需要在 menuconfig 里手忙脚乱地翻菜单,而是先在 configs/ 目录下创建一个 defconfig,然后在里面写下板卡所需的配置项。defconfig 的好处是它只保存与默认值不同的配置,执行 make xxx_defconfig 时,Kbuild 会根据 Kconfig 树自动展开生成完整的 .config 文件。我在首次接触 U-Boot 移植时吃过亏,直接在 .config 里改了一堆东西,结果下次 make clean 后全没了。正确做法是永远把自定义配置放在 defconfig 里,让 Kbuild 通过 defconfig 重新生成 .config。 这里还想提醒一点:改 Kconfig 文件之后,如果你发现 menuconfig 里没有新增的选项,通常是因为 Kconfig 文件里没有把它 source 进来,或者是 Kconfig 语法错误导致解析失败。可以先用 make defconfig 测试一下,如果报错,Kconfig 解析器会明确指出是哪个文件哪一行出了问题。 ### 2.2 defconfig 和 .config 的真实作用 defconfig 的语法并不复杂,本质就是一行一个 CONFIG_xxx=y 或者 CONFIG_xxx="string"。但它是 U-Boot 移植的起点,里面的每一个条目都决定了最终镜像里包含什么功能。比如: ```text CONFIG_SYS_CONFIG_NAME="myboard" CONFIG_DEFAULT_DEVICE_TREE="myboard" CONFIG_TARGET_MYBOARD=y CONFIG_SPL=y CONFIG_SYS_MMC_OS_DEVICE=0

当你执行 make myboard_defconfig 之后,Kbuild 会先根据 Kconfig 树里的依赖关系,把 defconfig 展开成一个完整的 .config,并生成一系列派生文件。这是很多初学者忽略的部分:你以为 .config 才是配置,实际上 Kbuild 还会生成 include/autoconf.mk,Makefile 通过它来判断哪些条件编译要开;生成 include/generated/autoconf.h,C 源文件通过它来访问配置宏;同时还会生成 include/config.h,它指向 include/configs/myboard.h。

我在实际调试中经常用一条命令来验证配置是否生效:

grep CONFIG_SPL include/config.h

如果这里没有你要的宏,要么是 defconfig 里没写,要么是 Kconfig 依赖没满足,后面的编译结果就一定会出问题。

2.3 Makefile 的递归魔法:scripts/Makefile.build

顶层 Makefile 是整个构建过程的总调度员,但它并不直接编译每个源文件,而是通过 scripts/Makefile.build 递归地进入各级子目录,这是 Kbuild 的核心机制之一。每个子目录里的 Makefile 通常只需要指定 obj-y、obj-$(CONFIG_xxx) 两种变量,Kbuild 就能自动编译并收集目标文件。

比如 board/vendor/myboard/Makefile 里可能只有一行:

obj-y += myboard.o

Kbuild 在编译时发现这类 obj-y 变量,就会把所有子目录收集到的 .o 文件按顺序排列,最后通过顶层 Makefile 里的链接脚本把它们链接成 u-boot 可执行文件。这个“按顺序排列”在移植中非常重要,因为很多底层的初始化代码对链接顺序敏感,比如 vectors 必须放在固定位置,start.o 必须最靠前。如果顺序不对,链接阶段会报错,或者即使链接成功,上电后也会跑飞。

我强烈建议在刚开始接触 U-Boot 时就养成一个习惯:遇到 make 输出看不懂,先加一个 V=1 再看一遍。

make V=1 CROSS_COMPILE=arm-linux-gnueabihf-

V=1 会让 Kbuild 显示每一条完整的编译命令、链接命令和变量展开结果。这能帮你确认源文件是否真的被编译了,编译器是否真的收到了某个宏。很多“改了半天没效果”的问题,用 V=1 一眼就能看出来——你的文件根本没进到编译列表里。

3. 从零添加一块新板卡的实操流程

3.1 复制参考板:千万不要从头开始写

我现在自己动手移植一块新板子,第一步永远是找参照物。所谓参照物,就是一颗主控芯片尽量接近、DDR 或存储介质尽量相似的已有板卡。因为芯片厂商一般会提供对应的评估板支持,比如 ST 的 eval 板、NXP 的 evk 板,这些板卡的 U-Boot 支持代码通常已经很完整了。

准备工作很简单,在源码根目录下:

mkdir -p board/vendor/myboard cp -r board/vendor/refboard/* board/vendor/myboard/ mkdir -p arch/arm/dts cp arch/arm/dts/refboard.dts arch/arm/dts/myboard.dts cp configs/refboard_defconfig configs/myboard_defconfig cp include/configs/refboard.h include/configs/myboard.h

复制完之后,你必须把参考板目录下的文件名、Kconfig 内容、defconfig 里的 CONFIG_SYS_CONFIG_NAME、CONFIG_DEFAULT_DEVICE_TREE 都替换成新板卡的名字和文件路径。否则 Kbuild 找的还是参考板的头文件和设备树。

这里有一个很多人踩过的细节:board/vendor/myboard 下的 Makefile 里 obj-y 的文件名要和实际 .c 文件名一致,路径也要正确。如果改了目录名但忘了改 Makefile 里的文件名,编译时会直接报找不到源文件,用 V=1 排查时会看到 Makefile.build 试图访问旧路径。

3.2 关键文件改动:Kconfig、MAINTAINERS、defconfig 一个都不能少

复制只是开始,你可以把这四类文件看作新板卡的“身份证”。

第一是 board/vendor/myboard/Kconfig,里面至少要有一段:

config TARGET_MYBOARD bool "MyBoard support" select ARM64 select SYS_CONFIG_NAME help This is my first custom board.

然后在 arch/arm/Kconfig 或者特定 SoC 的 Kconfig 里,加入 source "board/vendor/myboard/Kconfig"。如果没有这行,顶层 menuconfig 根本不会出现你的板卡选项,make myboard_defconfig 也不会认为 TARGET_MYBOARD 是一个有效配置。

第二是 configs/myboard_defconfig,这里要写清楚:

CONFIG_TARGET_MYBOARD=y CONFIG_DEFAULT_DEVICE_TREE="myboard" CONFIG_SYS_CONFIG_NAME="myboard" # 根据参考板保留其他必要配置 CONFIG_SPL=y CONFIG_SYS_MMC_OS_DEVICE=0

第三是 include/configs/myboard.h,这个头文件主要放一些 Kconfig 里不好表达的“板级硬件参数”,比如内存基地址、串口基地址、环境变量分区布局等。举个例子:

#define CONFIG_SYS_SDRAM_BASE 0x80000000 #define CONFIG_SYS_INIT_RAM_ADDR 0x40000000 #define CONFIG_SYS_UART_BASE 0x50000000

Kbuild 在处理 include/configs/myboard.h 时,会自动把它转换成 include/config.h,所以你在源码中直接写:

#include <config.h>

就能拿到这些板级宏。

第四是 MAINTAINERS 文件,虽然它不影响编译,但对于提交到上游和维护非常重要。我会在 board/vendor/myboard/MAINTAINERS 里写清楚板卡名称、维护者、Git 地址,这样以后 U-Boot 版本升级时,可以通过 get_maintainer.pl 找到这块板的负责人。

改完这些,先做一次配置尝试:

make CROSS_COMPILE=arm-linux-gnueabihf- myboard_defconfig

如果 Kconfig 没有报错,并且 .config 里的 TARGET_MYBOARD 是 y,说明板卡定义已经被 Kbuild 接受,接下来才能进入编译环节。

3.3 编译并验证最小镜像

配置完成后,直接编译:

make CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc)

首次编译时,Kbuild 会先编译工具链相关的 host 程序,比如 mkimage、dtc 以及各类生成脚本,然后才会进入架构相关代码。如果你的机器缺少必要依赖,比如 bison、flex、libssl-dev、device-tree-compiler,这里就会报错。我一般会在编译前先安装:

sudo apt-get install -y bison flex make gcc-arm-linux-gnueabihf libssl-dev device-tree-compiler

编译结束后,在源码根目录下应该能看到这些产物:

  • u-boot:ELF 格式的 U-Boot 主体
  • u-boot.bin:去掉调试信息的二进制镜像
  • u-boot.dtb:由设备树源文件编译出来的二进制设备树
  • u-boot-nodtb.bin:不带设备树的二进制
  • SPL:如果开启 SPL,则会在 spl/ 目录下生成 u-boot-spl.bin
  • u-boot.img:适合 mkimage 封装后烧写的镜像格式

拿到这些文件之后,先别急着烧录。我建议先用 QEMU 或者厂商提供的仿真环境,把 u-boot.bin 跑一次,确认编译产物至少在软件层面能加载。如果手头有开发板,则把 u-boot.bin 通过调试器或烧录工具写到启动介质中,连接串口,上电观察输出。

3.4 串口与 DDR 参数:看到输出才算迈出第一步

U-Boot 启动的第一条串口输出通常来自 SPL 完成 DDR 初始化之后。如果你上电之后串口只有空白,大概率是 DDR 初始化失败或者串口时钟配置不对。这时候要做的事情是翻 SoC 参考手册,把内存控制器相关的时序参数、地址映射和时钟树配置对照参考板重新核对。

常见的调试方法是在板级源码里临时加一个串口早期输出函数,利用 SoC 的 BootROM 阶段已经初始化好的 UART 寄存器,让代码在 DDR 初始化之前打印一个字符。比如很多 ARM 平台可以在 start.S 里添加一个 .weak 的 early_uart 函数,或者在 board_init_f 之前调用 debug_uart 相关接口。这个输出只要能出来,至少说明 CPU 已经开始执行你的 SPL 代码了,比对着黑屏猜问题强太多。

DDR 参数是另一个大头。不同厂商的 DDR 颗粒对刷新周期、时序参数、驱动强度要求不同,U-Boot 里的 dts 文件一般只是描述内存控制器和 DDR 控制器的寄存器配置,具体校准数据往往放在板级目录的 ddr.c 里。新人最容易犯的错误是直接照抄参考板 ddr 参数,结果因为电压和频率不同导致初始化失败。我的做法是先降频,首先把 DDR 频率设置为最低档,确保内存控制器能稳定识别颗粒,等串口输出稳定后再逐步提高频率。

4. 移植过程中最常见的坑和排查方法

4.1 完全没有串口输出:链路问题还是 UART 参数问题?

这是所有移植者最先遇到、也最头疼的问题。我遇到过的原因有五六种:SPL 没加到启动介质;BootROM 找不到 SPL;DDR 初始化失败卡死;UART 引脚复用没配置;波特率不对。

排查顺序是固定的:

  • 先用调试器确认 CPU 是否停留在 SPL 入口点
  • 确认 BootROM 是否正确加载了 SPL(看 SDK 工具日志)
  • 去掉 DDR 初始化,直接编译一个最简串口测试
  • 检查 UART 时钟是否来自外部晶振,是否已经使能
  • 用示波器或者逻辑分析仪看 TX 引脚上有没有电平翻转

我在一次实际移植中,卡了整整两天没用,最后发现是 U-Boot 的 Kconfig 里有一个 CONFIG_SYS_NS16550 没有配置好,导致串口驱动根本没被编进去。用 V=1 编译时,发现 drivers/serial/ns16550.c 完全没有出现在编译列表里,问题一下定位了。

4.2 链接错误和 undefined reference

SPL 编译时最常出现一批“undefined reference to”错误,比如:

undefined reference to `board_init_f` undefined reference to `dram_init` undefined reference to `lowlevel_init`

这些函数大部分在 board/ 或者 arch/ 目录下定义,如果 Kbuild 没有把对应的 .o 文件链接进来,或者 Kconfig 条件判断把它裁剪掉了,就会报这种错。定位方法依然是 V=1,看链接命令里到底包含了哪些 .o 文件。还有一种情况是源文件写了,但函数名拼错,或者函数定义了却被 __weak 符号覆盖成空实现,这种做法在 U-Boot 里很常见,需要仔细阅读参考板的代码。

针对 lowlevel_init 这个函数,特别提醒一下:如果你的 SPL 阶段并不需要很复杂的低层初始化,可以直接在 board 代码里定义空函数,但绝对不能把它的 .c 文件排除在编译列表之外,否则链接器找不到符号。

4.3 设备树和 CONFIG_OF_CONTROL 不匹配

进入 U-Boot 主体阶段后,最常见的现象是 U-Boot 能启动到命令行,但执行 bootz 或 booti 加载内核时报设备树地址无效,或者“Starting kernel ... ”之后就没有下文。

这个问题的根源通常是 U-Boot 启动时没有把自己编译好的 dtb 传递给内核,或者传给内核的 dtb 存放地址与内核解压地址冲突。检查点有三个:

  • defconfig 里 CONFIG_DEFAULT_DEVICE_TREE 是否和实际文件名一致
  • dts 文件里 model、compatible 是否和内核驱动匹配
  • bootcmd 中 fdt addr 命令指定的内存地址是否落在了 U-Boot 保留区域之外

我在调试中经常用一条命令来确认 U-Boot 是否携带了正确的 dtb:

fdt addr 0x88000000 fdt print /model

如果 fdt print 报错,说明这个地址处没有合法设备树,要么是 U-Boot 没把 dtb 加载到这里,要么就是设备树编译过程有问题。此时回到主机上单独执行:

make arch/arm/dts/myboard.dtb

确认 DTC 能成功编译这个设备树源文件,再检查 make 输出里是否有 dtc 报错。

4.4 配置文件改半天没生效:Kbuild 缓存与清理问题

这是个特别容易漏的坑。U-Boot 的 Kbuild 在编译过程中生成了大量带 .cmd 后缀的命令文件,如果你修改了某个 Kconfig 或者头文件,但 Kbuild 认为对应目标没有变化,它就不会重新编译。这时候最有效的操作是:

make mrproper

或者至少:

make clean make defconfig

我曾遇到过一种情况:修改了 include/configs/myboard.h 里的一个宏,重新执行 make,但编译产物完全没变,最后发现是 Kbuild 对头文件依赖追踪没覆盖到某个生成文件。这种情况用make clean && make myboard_defconfig && make一套组合拳,基本都能解决。

不建议直接把 .config 删掉然后重新 make,因为 .config 是 Kbuild 基于 defconfig 生成的,如果你手动改过 .config,删掉之后它会根据 Kconfig 默认值重新生成,可能丢掉你需要的配置。正确的做法是修改 defconfig,再用 make xxx_defconfig 重新生成。

5. 提高成功率的几个个人习惯

移植 U-Boot 走到后面,你会发现困难不再是某个函数怎么写,而是在几十个文件里找线索。我有几个习惯,每次都能帮我省下大量排查时间。

第一,每次准备编译前,先跑一次 make myboard_defconfig,确保配置同步。因为 .config 可能因为各种原因被手动修改过,重新生成一次可以避免“编译用的配置和 defconfig 不一致”的问题。

第二,把每次编译输出保存到日志文件,比如:

make CROSS_COMPILE=arm-linux-gnueabihf- -j8 > build.log 2>&1

编译结束之后用 grep Error、grep undefined、grep warning 这些关键词过滤。几百行输出看起来吓人,实际上错误信息往往只有几行,被淹没在大量命令回显里了。

第三,在改 dts 和板级头文件之前,先确认你即将改动的文件确实参与构建。用 V=1 编译一次,搜索源文件名,看看它是否真的被编译过。这花不了两分钟,却能避免“改了个寂寞”。

第四,也是最重要的一个习惯:只在改动一处之后编译一次,不要一次改 N 处再统一编译。U-Boot 移植中,如果同时改了几个变量,上电后出了问题,你根本不知道是哪一步导致系统挂死。我自己的节奏是改一个串口时钟,编译;改一个 DDR 参数,编译;串口输出变化了,再继续下一步。虽然编译时间长了点,但排查效率会高得多。

如果你能走到这一步,说明新板卡的 U-Boot 已经能在它自己的生命周期里完成“初始化硬件、跳到命令行、执行 bootcmd”这一整套动作。剩下的事情就是继续丰富驱动、裁剪配置、优化启动时间,以及把补丁整理成可以提交到社区的格式。这套方法论,我第一次成功点亮板卡用了整整一周,第二次移植同类板卡只用了半天,第三次几乎只是照着参考板检查差异。Kbuild 这个盒子虽然复杂,但它最大的价值就是把“机械化”的构建逻辑标准化了,让你可以集中精力去做真正有挑战性的那部分——理解硬件、调参、定位问题。如果你现在也被移植 U-Boot 卡在某个阶段,那我的建议只有一句:别急着乱改代码,先用 V=1 把构建过程看透,再针对性地动手。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 11:25:19

Agent技能系统实践:把大模型从聊天大脑变成能干活员工

在调过几个Agent原型项目之后&#xff0c;我越来越确信一件事&#xff1a;决定Agent上限的&#xff0c;往往不是模型本身&#xff0c;而是你给它配了哪些“技能”。agent-skills这个方向&#xff0c;本质上就是在解决一个问题——如何把大模型从“只会聊天的大脑”变成一个“能…

作者头像 李华
网站建设 2026/10/8 11:25:13

AI Agent技能管理:agent-skills的设计思路与落地实践

最近后台收到好几条私信&#xff0c;都在问同一个事&#xff1a;AI Agent 项目里经常看到 agent-skills 这个目录或者命名&#xff0c;它到底是干嘛的&#xff1f;怎么用&#xff1f;实话说&#xff0c;这个关键词今年在 Agent 工程化领域确实很火&#xff0c;我自己在几个项…

作者头像 李华
网站建设 2026/10/8 11:23:21

鸿蒙PC上可运行的AI Agent实战指南

1. 项目概述&#xff1a;鸿蒙 PC 上跑 AI Agent&#xff0c;不是概念&#xff0c;是正在发生的实操现场“鸿蒙 PC 上可用的 AI Agent 工具汇总”——这个标题里藏着三个关键事实&#xff1a;第一&#xff0c;“鸿蒙 PC”已不再是实验室里的PPT&#xff0c;而是真实可触达的操作…

作者头像 李华
网站建设 2026/10/8 11:22:52

Agent技能体系从零搭建:设计、调度与生产落地的避坑指南

1. 前置结论&#xff1a;我从零搭建了一套技能体系&#xff0c;先沉淀踩坑认知两年前我第一次尝试给聊天机器人叠能力的时候&#xff0c;以为"会做某件事"就是往提示词里塞一段描述&#xff0c;让大模型自由发挥。结果上线第一周就被现实教育了&#xff1a;同样一句&…

作者头像 李华
网站建设 2026/10/8 11:22:00

OpenMontage:命令行下的智能图片拼贴与批量自动化工具

做了这么多年命令行工具&#xff0c;我越来越觉得&#xff1a;很多项目苦于找不到一个真正“顺手”的切入点。OpenMontage这个名字&#xff0c;一开始是朋友扔给我的一个想法——他手头有上千张设计素材图&#xff0c;想要快速拼出带有视觉冲击力的“海报式”拼贴&#xff0c;又…

作者头像 李华
网站建设 2026/10/8 11:20:47

Ziya-LLaMA-13B-V1中医古籍问答:加载、微调与避坑指南

简介&#xff1a;基于Ziya-LLaMA-13B-V1的中医古籍知识问答大模型仓库&#xff0c;面向AI大模型应用开发者、自然语言处理研究人员及中医信息化从业者&#xff0c;旨在解决中医古籍智能问答、模型微调与部署落地等问题。压缩包共54个文件&#xff0c;约150KB&#xff0c;以Pyth…

作者头像 李华