当前位置: 首页 > news >正文

【Linux系统移植】Cortex-A8 Linux系统移植(超详细)

目录

      • 前言
    • 一、ARM开发板
      • ARM简介
      • RISC和CISC
      • ARM产品分布
      • 核心板
      • S5pv210 SOC
      • 嵌入式系统开发方式
    • 二、嵌入式系统组成
      • 为什么要系统移植
      • 内核移植框图
    • 三、嵌入式开发环境搭建
      • 搭建开发环境总流程
      • 设置ubuntu与windows共享目录
      • 修改用户为root用户
      • 安装NFS服务器
      • 安装tftp服务器
      • 安装交叉编译器
      • 交叉编译工具链使用
      • 安装ncurses开发库
      • 安装USB转串口驱动
      • 串口调试助手
        • 在Ubuntu系统中使用minicom
      • 安装dnw
        • 安装dnw驱动
      • 安装dnw命令
    • 四、Bootloader简介
      • Bootloader功能
      • 编译bootloader
      • 烧写bootloader到Smart210开发板
        • 1.使用dnw下载bootloader到DRAM中烧写
        • 2. 使用tftp下载u-boot.bin到DRAM中烧写
        • 3.网络如果不通:

前言

为什么不能像Ubuntu那样直接下载linux系统到板子上?
原因:制作板子硬件厂家太多,板子资源受限

一、ARM开发板

ARM简介

  1. ARM代表一个公司,通过 IP 授权(如架构、内核设计)盈利,不直接生产芯片。
  2. ARM代表一种架构设计,采用精简指令集RISC的内核(arm-linux-gcc,arm-linux-g++等交叉编译器),intel AMD公司对应CISC复杂指令集:minGW,gcc,g++。
  3. ARM代表使用ARM核的芯片,统称ARM处理器(Cortex M3,CortexA8,CortexA53,CortexA55).

RISC和CISC

  1. CISC:复杂指令集(x86,x86-64)
    一个功能用一条指令可以完成,注重指令的功能性,指令的宽度不固定,指令的周期不固定

  2. RISC:精简指令集(ARM)
    一个功能需要多条指令完成,指令的宽度、周期固定,多为单周期指令,单条指令存储在内存中,占用多的空间

  3. RISC-V:
    基于精简指令集RISC原则的开源指令集架构

ARM产品分布

在这里插入图片描述

  1. Cortex-A(高性能):嵌入式,高端芯片,跑操作系统,linux内核,做高端产品
  2. Cortex-R(高实时):针对实时性
  3. Cortex-M(低功耗):stm32等芯片,一般无跑操

核心板

核心板 soc(系统级芯片)= CPU + RAM内存芯片 + Flash(emmc)存储芯片 + 电源芯片
在这里插入图片描述
本人使用的是友善之臂公司的 Smart210

ARm Cortex-A8 -> 三星在cortexA8上+RAM内存芯片+Flash存储芯片+电源管理芯片 = s5pv210 ->友善之臂公司 + 外围设备(地板):Smart210

S5pv210 SOC

三星 s5pv210 = 1个s5pv210cpu核1GHZ + 4个DDR2 RAM 内存512M + 1个nandflash K9f4G08u0B 512 M + 1个立体声工放解码器 WM8960G + 1个以太网控制器DM9000AEP
在这里插入图片描述

嵌入式系统开发方式

在这里插入图片描述

  1. Host:宿主机(开发主机)因为嵌入式系统的性能有限,所以开发工作代码编写,内核编译,驱动编译,应用程序编写和编译通常放在pc机上
  2. Target:目标机,开发的对象,最终为该目标构建一套软件环境。
  3. 连接介质:宿主机同目标机进行交互介质(控制,传输,结果显示)。

二、嵌入式系统组成

为什么要系统移植

嵌入式硬件不具备通用性,软件也不能做到标准化,不同硬件嵌入式平台所运行系统是有差异的,没有一个可以直接使用的通用的操作系统,需要我们根据硬件和软件的需求对系统进行修改后才能在目标平台上运行。

内核移植框图

在这里插入图片描述

  1. BootLoader:内核启动引导程序
    包括固化在固件IROM中的boot代码和BootLoader两部分
    bootLoader是在操作系统内核运行之前运行,主要获得硬件设备信息、初始化硬件设备,建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便最终启动linux内核准备好正确的环境
  2. Kernel:Linux内核
    特定于嵌入式平台的定制内核,根据嵌入式产品所需的硬件设备剪裁
    操作系统内核:提供CPU调度、存储管理、文件系统、IO设备驱动、网络等服务组成
  3. Rootfs: 根文件系统
    根文件系统,是存放运行、维护系统所必须的各种工具软件、库文件、脚本、配置文件和其它特殊文件的地方,也可以安装各种软件包。没有根文件系统,Linux内核只是一个内核,不能和用户交互,没有实际的应用价值。Linux系统中一切皆文件。

三、嵌入式开发环境搭建

搭建开发环境总流程

在宿主机做好以下环境的准备

  1. Linux 操作系统,可以是物理机也可以是虚拟机,如:ubuntu
  2. 安装驱动程序:宿主机通过各种接口同目标机进行交互,这些接口的硬件需要相应的驱动程序支持。如 CH340 串口驱动、dnw驱动
  3. 安装通信软件:方便同目标机之间完成交互和文件传输,如:串口终端软件(minicon)、文件共享服务器(nfs和tftp)、dnw软件
  4. 安装开发软件:安装能够编译出运行在目标机上的交叉编译工具链(arm-linux-gcc)及其它辅助工具
  5. 因为需要使用网络环境,所以必须使能ubuntu网卡,并能正常ping通window系统。

设置ubuntu与windows共享目录

用途:方便windows下的资料复制到ubuntu系统中
注意:驱动编程不能在共享目录进行

  1. 在D盘下建立workspace作为共享文件夹,文件名任意
    在这里插入图片描述

  2. 打开vmware菜单->虚拟机->设置->选项->共享文件夹->进入共享文件夹的设备窗口->选择总是启用->添加->设置主机路径为:->D:\workspace->完成
    在这里插入图片描述

  3. 在linux下访问:/mnt/hgfs/workspace则是共享目录 ,内容和windows下的一模一样,后面从windows上传即可
    在这里插入图片描述

修改用户为root用户

因为搭建环境和编写驱动很多需要管理员权限,所以为了方便,将用户修改为root用户

  1. 修改sudo vim /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf添加
greeter-show-manual-login=true //需要手动输入用户名
allow-guest=false   //禁用访客账户
  1. sudo vim /root/.profile,找到mesg n,将其替换成 tty -s && mesg n 主要是为了 避免非交互式 Shell 环境(如 cron 任务、SSH 命令等)执行 mesg n 时产生警告信息(如 mesg: ttyname failed: Inappropriate ioctl for device)。

在这里插入图片描述

  1. 输入init 6或者 reboot
  2. 在登陆界面选择输入用户登陆,输入密码即可

在这里插入图片描述

安装NFS服务器

用途:NFS服务器主要用于将PC上编写的驱动通过网络下载到ARM板子上
NFS服务器介绍:NFS服务器可以把服务器上的一个目录导出,从而客户端主机可以通过网络将NFS服务器上导出的目录挂载到客户端主机的一个目录下,从而实现文件共享。
在这里插入图片描述

  1. 安装NFS服务器:apt-get install rpcbind nfs-kernel-server
  2. 创建服务器根目录:mkdir /opt/rootfs -p
    每个网络服务器都有服务器要目录,用于存放用户要上传和下载的文件
  3. 配置NFS服务器:vim /etc/exports 加入这句/opt/rootfs *(rw,sync,no_subtree_check,no_root_squash)
    在这里插入图片描述

NFS服务器配置项的意义:
(1)/opt/rootfs:服务器根目录
(2)*:局域网中所有主机都能访问服务器
(3)rw:可下载可上传 ro:只下载
(4)sync:客户端与服务器端同步修改
(5)no_subtree_check:不检查子目录,使挂载速度更快
(6)no_root_squash:当客户端使用root用户登陆则用户享有服务器root的权限

  1. 重启NFS服务器:
    服务器每次重新配置后必须重新启动服务器,才能使新配置生效
service rpcbind restart
service nfs-kernel-server restart
  1. 使用客户端测试NFS服务器:

(1)查看服务器NFS服务是否在网络可见
showmount -e 192.168.1.38在这里插入图片描述
(2)创建要挂载到的目标子目录mkdir /mnt/nfs:挂载服务器nfs文件系统到/mnt/nfs:
例:mount -t nfs -o nolock 192.168.1.38:/opt/rootfs /mnt/nfs
参数意义:-o nolock:表示挂载时不加锁,提高加载速度
(3)下载或上传文件:
下载:cp /mnt/nfs/hello.c ~/ 上传:cp ~/test.c /mnt/nfs
(4)umount /mnt/nfs 卸载nfs文件系统
在这里插入图片描述

安装tftp服务器

用途:tftp服务器用于通过网络方式下载bootload、kernel、rootfs,也可将PC上编写的驱动通过网络下载到ARM板

  1. 安装tftp服务器:apt-get install tftpd tftp xinetd
  2. 配置tftp服务器:vim /etc/xinetd.d/tftp

service tftp
{
socket_type = dgram ##套接字的类型
protocol = udp ##所使用的协议
wait = yes ##是否等待
user = root ##登陆用户所用的角色
server = /usr/sbin/in.tftpd ##服务器的应用程序所在位置
server_args = -s /tftpboot ##服务器根目录
disable = no ##网络可见
per_source = 11
cps = 100 2
flags = IPv4 ##使用IPV4协议
}
在这里插入图片描述

  1. 创建tftp服务器根目录:mkdir /tftpboot
  2. 重启tftp服务器:/etc/init.d/xinetd restart
  3. 复制测试文件到tftp服务器根目录:cp hello.c /tftpboot
  4. 使用客户端测试测试:
    (1)登陆tftp服务器:tftp 192.168.1.38
    (2)下载文件到当前目录:get hello.c
    在这里插入图片描述

安装交叉编译器

网上下载包arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz

(1) 解压 tar -zxf arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz -C /
(2)修改权限chmod 777 /opt/FriendlyARM/toolschain/4.5.1/bin -R
(3)设置arm-none-linux-gnueabi-gcc交叉编译器路径环境变量,修改/etc/profile脚本文件,添加如下设置 PATH环境变量的命令
export PATH=$PATH:/opt/FriendlyARM/toolschain/4.5.1/bin
在这里插入图片描述
(4)修改之后使配置生效:source /etc/profile
(5)交叉编译器是32位的,ubuntu是64位的,所以还需要安装如下支持包
安装 sudo apt-get install lib32z1 lib32ncurses5
(6)测试arm-linux-gcc编译器:arm-linux-gcc -v或arm-none-linux-gnueabi-gcc -v
(7)编写hello.c 并使用arm-linux-gcc编译:arm-linux-gcc hello.c
在这里插入图片描述
ARM指令集在板子上运行
gcc 编译的X86 复杂指令集可以在ubuntu上运行
在这里插入图片描述
(8)file查看文件的属性:file a.out

交叉编译工具链使用

1.arm-linux-gcc 编译器
例:arm-none-linux-gnueabi-gcc -c beep.S -o beep.o #生成目标文件
arm-linux-gcc beep.c -o beep #生成可执行文件
2.arm-linux-ld 链接器
例:arm-none-linux-gnueabi-ld -Ttext 0 beep.o -o beep.elf #生成机器码
3.arm-linux-objcopy 文件类型转换工具ELF --> binary
例:arm-none-linux-gnueabi-obcopy -O binary beep.elf beep.bin #得到二进制的可执行文件
例:arm-none-linux-gnueabi-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
例:arm-none-linux-gnueabi-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
4.arm-linux-objdump 反汇编工具
例:arm-none-linux-gnueabi-objdump -d nm.o
5.arm-linux-strip 删除目标文件中符号链接和调试信息
例:arm-none-linux-gnueabi-strip hello
6.addr2line:把程序地址转换为文件名和行号。给定地址的源代码行数和可执行映像,前提是编译时使用了-g选项,即调试信息
$ arm-none-linux-gnueabi-gcc -o hello -Wl,-Map=hello.map -g hello.c
$ grep main hello.map
$ arm-none-linux-gnueabi-addr2line 0x00008370 -e hello -f
7.arm-linux-ar:建立、修改、提取归档文件。归档文件是包含多个文件内容的一个大文件,其结构保证了可以恢复原始文件内容。
8.arm-linux-as:主要用来编译GNU C编译器gcc输出的汇编文件,产生的目标文件由链接器ld连接
$ arm-none-linux-gnueabi-gcc -S hello.c
$ arm-none-linux-gnueabi-as -o hello hello.s
9.arm-linux-nm:列出目标文件中的符号
在这里插入图片描述
$ arm-none-linux-gnueabi-gcc -g -O -c nm.c
$ arm-none-linux-gnueabi-nm -A nm.o
10.arm-linux-ranlib:产生归档文件索引,并将其保存到这个归档文件中。在索引中列出了归档文件各成员所定义的可重分配目标文件。
11.arm-linux-readelf:显示elf格式可执行文件的信息。
$ arm-none-linux-gnueabi-gcc -o hello hello.c
$ arm-none-linux-gnueabi-readelf -S hello
12.arm-linux-size:列出目标文件每一段的大小以及总体的大小。默认情况下,对于每个目标文件或者一个归档文件中的每个模块只产生一行输出。
$ arm-none-linux-gnueabi-size hello
13.arm-linux-strings:打印某个文件的可打印字符串。默认情况下,只打印目标文件初始化和可加载段中的可打印字符;对于其它类型的文件它打印整个文件的可打印字符,这个程序对于了解非文本文件的内容很有帮助。
$ arm-none-linux-gnueabi-strings nm.o

安装ncurses开发库

用途:ncurses是Linux/Unix下广泛应用的图形函数库,在字符终端界面下绘制图形界面。在linux内核配置(make menuconfig)时需要。
sudo apt-get install libncurses5-dev

安装USB转串口驱动

  1. 在window下安装CH340驱动
  2. 查看系统所用COM端口号:右键我的电脑->管理->设备管理器->端口-> Prolific USB-to-Serial Comm Port ->COMx,如果查询到端口号表示USB转串口驱动安装成功

串口调试助手

在Ubuntu系统中使用minicom
  1. minicom工具安装: apt-get install minicom
  2. 将usb转串口线连接进虚拟机使用:点击vmware的虚拟机菜单->可移动设备->usb-to -serial Comm port->连接
  3. 查看串口设备是否存在:ll /dev/ttyUSB0
  4. 配置:minicom -s
    选择serial port setup ->按A键:设置serial device: /dev/ttyUSB0->按F键:设置Hardware Flow Control:No->回车确认设置->Save setup as dfl
  5. minicom常用命令
    (1) 打开minicom工具:minicom
    (2) 进入minicom命令菜单:ctrl+a z
    (3) O:配置minicom,等效minicom -s
    (4) X: eXit and reset,退出并保存
    (5) Q: Quit with no reset退出不保存
    (6) W: lineWrap on/off能否换行显示

安装dnw

用途:可使用dnw下载线将bootloader、kernel、rootfs下载到ARM板

安装dnw驱动
  1. 将dnw_linux.tar复制到Ubuntu:cp /mnt/hgfs/workspace/dnw_linux.tar ~/
  2. 进入用户主目录解压安装包:tar -xf dnw_linux.tar
  3. 进入驱动源码目录:cd secbulk
  4. 编译dnw驱动:make
  5. 安装dnw驱动:insmod secbulk.ko
  6. 配置Ubuntu启动时自动安装dnw驱动
    将secbulk.ko复制到/lib/modules/4.4.0-109-generic/extra/
    再修改/etc/rc.local,添加如下一行:
    /sbin/insmod /lib/modules/4.4.0-109-generic/extra/secbulk.ko
  7. 连接ARM板miniUSB线到PC机,并将其连接进虚拟机
    注意:如果Samsung Sec S5PC110 Test B/D未接入虚拟机,需要如下图连接入虚拟机,启动开发板时使用SD卡启动(卡槽不放卡),此时SD卡启动失败会自动转到NAND启动,在自检音通过后,再查看虚拟机的可移动设备
    在这里插入图片描述
  8. 查看dnw设备 :ll /dev/secbulk0

安装dnw命令

(1) 进入dnw源程序目录:cd dnw
(2) 编译dnw源程序:gcc dnw.c -o dnw(此步不执行,生成的64位程序不能用)
(3) 拷贝32位程序到/bin目录:cp dnw /usr/bin
(4) 测试dnw程序:dnw
注意:64位机只能使用32位dnw程序,可用file命名查看,直接使用dnw_linux.tar包中的dnw程序,将其直接复制到/bin目录。

四、Bootloader简介

BootLoader就是在操作系统运行之前的一段程序,用于初始化硬件设备(cpu、时钟、中断向量表、看门狗、内存设备),为启动操作系统做准备。
Bootloader的制作可以使用下列程序,但是最通用的是U-boot。
在这里插入图片描述

Bootloader功能

  • 核心功能

    • Bootloader最重要的核心功能就是启动操作系统,具体如下:
    • 初始化最底层的硬件,cpu、时钟、中断向量表、看门狗、内存设备等
    • 搬运内核映像文件到内存中
    • 将CPU控制权移交给内核执行
  • 其它功能
    Bootloader除了具备核心的操作系统加载功能外,为了方便使用,在Bootloader中通常还实现了一些其它的附加功能,通过这些附加功能,可以方便开发、安装、调试嵌入式系统软件。Bootloader通常会实现如下功能:

    • 下载和烧写bootloader、内核、文件系统功能:dnw,fastboot,tftp下载,nand(nand flash),mmc(emmc)烧写
    • 内核、文件系统启动参数设置功能(setenv,printenv,saveenv)(bootamd,bootargs)
    • 硬件测试功能
    • 设置系统启动界面和公司LOGO

编译bootloader

  1. 解压到/opt目录:tar -jxf dy210_uboot.tar.bz2 -C /opt/
  2. 进入uboot目录:cd /opt/sq210_uboot/
  3. 修改编译器配置:修改uboot根目录下Makefile,指定编译器为arm-linux-gcc,
    /opt/sq210_uboot#vim Makefile +144,内容如下:
    ifeq (arm,$(ARCH))
    144 CROSS_COMPILE = arm-linux-
    Endif
  4. 清除所有旧配置和目标文件:/opt/sq210_uboot#make distclean
  5. 删除目标文件:/opt/sq210_uboot#make clean
  6. 配置uboot为s5pv210的uboot:#make smdkv210single_config
  7. 编译uboot:#make -j4
    看到如下所示:表示u-boot.bin编译完成

arm-linux-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
arm-linux-objdump -d u-boot > u-boot.dis

  1. 使用ls命令查看编译成功后生成 u-boot.bin 二进制文件

烧写bootloader到Smart210开发板

烧写bootloader到开发板需要先将bootloader下载到开发板,再烧写,下载的方式主要有两种:

1.使用dnw下载bootloader到DRAM中烧写

(1)在ubuntu系统中打开minicom:minicom
(2)在ubuntu系统打开新终端,将E7 CortexA8移植\软件资料\superboot\目录下的dy210_usb.bin和u-boot.bin文件复制到windows共享目录,
(3)在ubuntu系统中进入dy210_usb.bin和u-boot.bin所在目录
(4)安装usb驱动:以SDBOOT启动模式打开Smart210电源开关,在长音后切换成低音时立即下载dy210_usb.bin到S5pv210的iRAM中(可以不断输入,直到成功),IRAM的地址参考三星<S5PV210_UM_REV1.1.pdf> 第1章第2小节 MEMORY MAP
在ubuntu系统中输入:dnw dy210_usb.bin 0xd0020010,安装完成显示如下:
file name : dy210_usb.bin
file size : 11168 bytes
Writing data…
100% 11178 bytes OK
(5)下载uboot.bin到S5pv210的DRAM:在ubuntu系统中输入 :dnw u-boot.bin 0x23e00000,下载完成后显示:
file name : u-boot.bin
file size : 278528 bytes
Writing data…
100% 278538 bytes OK
(6)当下载uboot成功后,Smart210会自动启动,快速切换到uboot中可以看到如下所示
Serial = CLKUART
Board: SQ210
DRAM: 512MB
Flash: 8 MB
SD/MMC: Card init fail!
0 MB
NAND: 512 MB
In: serial
Out: serial
Err: serial
checking mode for fastboot …
Hit any key to stop autoboot: 3 显示此处时必须在3秒内按回车键
注意:以上只是下载到内存中,断电后数据全部消失,临时有效,为方便使用要烧写u-boot.bin到nandfalsh中
(7) 重新下载u-boot.bin到ARM板的flash,在u-boot中输入:dnw 0x20008000
运行成功如下所示:
OTG cable Connected!
Now, Waiting for DNW to transmit data
此时,u-boot中的dnw处于等待状态,等待ubuntu端发送u-boot.bin文件数据
(8) 在Ubuntu中使用dnw命令发送u-boot.bin文件数据,在ubuntu系统中输入:dnw u-boot.bin
(9) 清空nandflash的u-boot区域,在uboot中输入:nand erase 0 0x100000
清空成功如下所示:
NAND erase: device 0 offset 0x0, size 0x100000
Erasing at 0xe0000 – 100% complete.
OK
(10) 烧写DRAM中的u-boot.bin程序到nand flash,在u-boot中输入:
nand write 0x20008000 0 0x100000
(11) 关闭板子电源,将启动模式修改为NAND启动模式,再开启电源,此时的bootloader是加载源于nandflash中bootloader,表示烧写成功

2. 使用tftp下载u-boot.bin到DRAM中烧写

(1)将bootloader下载到DRAM,重复完成上面流程的前6步。
(2)测试与tftp服务器是否连接(ubuntu系统)
SQ210 # setenv ipaddr 192.168.31.20
SQ210 # setenv serverip 192.168.31.223
SQ210 # setenv gatewayip 192.168.31.1
SQ210 # saveenv
需要在uboot中有网卡驱动和ping命令,在u-boot中输入:ping 192.168.0.253
测试结果如下:
host 192.168.0.253 is alive表示与tftp服务器联通
host 192.168.0.253 is not alive表示与tftp服务器未联通
(3)在ubuntu系统中将u-boot.bin复制到tftp服务器根目录下
cp u-boot.bin /tftpboot/
(4)使用u-boot的tftp工具将u-boot.bin下载到S5pv210的DDR中,在u-boot中输入:
tftp 0x20008000 u-boot.bin
如下所示表示下载成功
SQ210 # tftp 0x20008000 u-boot.bin
dm9000 i/o: 0x88000000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:40:5c:26:0a:5b
operating at 100M full duplex mode
TFTP from server 192.168.1.141; our IP address is 192.168.1.20
Filename ‘u-boot.bin’.
Load address: 0x48000000
Loading: #################################################################
################################
done
Bytes transferred = 491520 (0x78000)
(5)使用nand命令将在内存DDR中的u-boot.bin写入到nand flash,在u-boot中输入:
nand erase 0 0x100000
nand write 0x20008000 0x0 0x100000
显示如下表示已经写入成功
SQ210 # nand write 0x48000000 0x0 0x100000
NAND write: device 0 offset 0x0, size 0x100000
Checksum is calculated.
Main area write (8 blocks):
1048576 bytes written: OK
(6)测试:将启动模式开关拔到NAND启动模式,打开电源开关

3.网络如果不通:

(1)禁用无线网卡和其它不使用的有线网卡,只保留有线网卡和VMnet1和VMnet8
(2)检查ubuntu的网卡是否使能,ubuntu的网卡必须处于工作状态
(3)检查ubuntu与smart210板是否处于同一网段:在stmart210中使用printenv查看ipaddr,serverip,gatewayip与ubuntu是否同一网段,如果不在同一网段,需要使用setenv ipaddr 192.168.31.20等格式修改ipaddr,serverip,gatewayip的地址,再使用saveenv保存到flash
(4)如果还不通,则修改vmware的网络连接方式:桥接或net模式,必须处于同一网段

相关文章:

  • Next.js 布局(Layout)与模板(Template)深度解析:从原理到实战
  • Vue模板语法
  • 大模型应用开发之评估
  • LeetCode 75. 颜色分类 - 双指针法高效解决(Java实现)
  • 【评测】推理和微调 “GTE文本向量-中文-通用领域-base”模型
  • [嵌入式实验]实验二:LED控制
  • 公司数据不泄露,DeepSeek R1本地化部署+web端访问+个人知识库搭建与使用
  • 19、Python字符串高阶实战:转义字符深度解析、高效拼接与输入处理技巧
  • 网络安全的守护者:iVX 如何构建全方位防护体系
  • 【Linux】线程概念
  • 代购系统数据中台搭建指南:3 步实现订单、物流、用户行为的全链路数字化
  • 大模型在老年性白内障预测及诊疗方案中的应用技术方案
  • python模块和包
  • 搭建frp内网穿透
  • 可视化图解算法47:包含min函数的栈
  • 重温经典算法——冒泡排序
  • 【HarmonyOS 5】鸿蒙中的UIAbility详解(二)
  • Python中的sorted()函数:智能排序器详解
  • 中国国运新引擎:下一代液晶技术突破如何重塑全球显示格局
  • iOS 获取Wifi信息
  • 开源网站后台/怎么搭建网站
  • 靖安县城乡规划建设局网站/网站如何快速被百度收录
  • 阿德莱德做网站/厦门百度代理
  • 国内外贸b2c网站/种子搜索神器
  • 垂直门户网站/sem是什么电镜
  • 郑州做网站公司哪家好/互联网推广平台有哪些公司