i.MX6ULL 嵌入式 Linux 入门学习文档(第一周学习总结)
一 学习路线和当前进度
tip:这是我的学习路径规划,基本靠ai学习
这条路线不是让你把三本厚书从头背到尾,而是先完成四个看得见的任务。每个任务都会产出一个能运行的结果。
| 阶段 | 要完成的事 | 为什么先做它 | 当前状态 |
|---|---|---|---|
| 第一阶段 | Ubuntu 和开发板联网 搭好 NFS 交叉编译并运行 Hello World | 先把电脑和板子之间的开发通道修好 后面写的程序才能送过去 | 核心已完成 |
| --- | --- | --- | --- |
| 第二阶段 | 用 C 操作文件 再练 fork 和 pthread | 学会让 Linux 程序保存数据并同时做多件事 | 下一步 |
| 流程了解 | 系统移植和文件系统构建跟着教程走一遍 | 知道开发板系统从哪里来 但暂时不钻底层 | 未开始 |
| 第三阶段 | 用 C 控制 LED 和蜂鸣器 | 让程序开始接触真实硬件 | 未开始 |
| 第四阶段 | 做 Qt 窗口并部署到开发板 | 让板子运行一个看得见的完整应用 | 未开始 |
六周安排
| 周次 | 本周任务 | 本周交付结果 |
|---|---|---|
| 第一周 | 串口 网络 双网卡 NFS 交叉编译 Hello World | 开发板成功输出 Hello i.MX6ULL 和可复现日志 |
| --- | --- | --- |
| 第二周 | Linux C 文件的打开 读取 写入 关闭 | 一个能保存和读取文本的 C 程序 |
| 第三周 | fork 多进程和 pthread 多线程 | 两个小程序分别展示进程和线程 |
| 第四周 | 系统移植流程浏览 LED 和蜂鸣器入门 | 知道系统组成并至少控制一个外设 |
| 第五周 | Qt 基础和简单窗口 | Ubuntu 中能运行自己的 Qt 窗口 |
| 第六周 | Qt 交叉编译 部署 开机运行 整理总结 | 开发板运行自己的界面程序和总日志 |
为什么按这个顺序
-
先修路。网络和 NFS 不通,程序写好了也送不到开发板。
-
再学做事。文件 进程和线程是 Linux 应用最常见的基本能力。
-
然后碰硬件。应用通过驱动提供的接口去控制 LED 和蜂鸣器。
-
最后做界面。Qt 依赖前面的编译 部署和硬件环境,放最后最稳。
送外卖故事总览
把整个开发过程想成送外卖。Ubuntu 是后厨,你在里面写菜谱,也就是 C 代码。交叉编译器是专门给 ARM 顾客打包的机器。蓝色网线是马路,IP 地址是门牌号,NFS 是双方都能打开的取餐柜,开发板是最后真正执行任务的店员,串口是你和店员直接说话的对讲机。
记忆图
Ubuntu 后厨 -> ARM 交叉编译器 -> NFS 共享取餐柜 -> 蓝色网线 -> i.MX6ULL 开发板
二 Linux 基础知识
命令行和 Shell
命令行就是一个可以打字控制电脑的窗口。你输入 ls,电脑就列出文件。它像餐厅的点单窗口。
Shell 是听懂这些命令并让 Linux 去执行的程序。它像服务员:你说一句命令,Shell 把要求交给系统。Ubuntu 常见的 Shell 是 Bash。
终端是窗口,Shell 是窗口里听命令的人,命令是你说的话。
最常用的文件命令
| 命令 | 人话解释 | 例子 |
|---|---|---|
| pwd | 我现在在哪个文件夹 | pwd |
| --- | --- | --- |
| ls | 看看这里有什么 | ls |
| ls -a | 连隐藏文件也显示 | ls -a |
| cd 路径 | 走进指定文件夹 | cd ~/nfs_share |
| cd ... | 返回上一层 | cd ... |
| mkdir | 新建文件夹 | mkdir orders |
| touch | 新建空文件 | touch order.txt |
| cat | 把文件内容显示出来 | cat order.txt |
| echo | 显示文字 也能把文字写入文件 | echo hello > test.txt |
| cp | 复制文件 | cp order.txt copy.txt |
| mv | 移动文件或改名 | mv copy.txt done.txt |
| rm | 删除文件 | rm done.txt |
| rmdir | 删除空文件夹 | rmdir empty_dir |
| file | 看看文件是什么类型 | file hello |
rm 删除后通常没有回收站。刚开始不要随便加 -r 或 -f,更不要对不确定的路径执行删除。
查找和系统查看命令
| 命令 | 人话解释 | 例子 |
|---|---|---|
| find | 按名字找文件 | find . -name "order.txt" |
| --- | --- | --- |
| grep | 在文件内容里找文字 | grep "牛肉面" order.txt |
| man | 查看命令说明书 | man ls |
| clear | 清空终端画面 | clear |
| uname -a | 查看系统和内核信息 | uname -a |
| ps | 查看当前进程 | ps |
| top | 实时查看系统运行状态 | top |
| df -h | 查看磁盘还剩多少空间 | df -h |
| du -sh | 查看一个文件夹多大 | du -sh ~/nfs_share |
| ip addr | 查看现代 Linux 网卡和 IP | ip addr |
| ifconfig | 查看或设置旧系统网卡 | ifconfig eth1 |
| ping | 测试另一台电脑能否联系 | ping -c 4 192.168.10.20 |
find . -name "order.txt" 里,find 是查找,点号表示从当前文件夹开始,-name 表示按名字找,order.txt 是目标名字。四部分缺一不可。
正确命令是 gedit,不是 gredit。gedit 是图形文本编辑器;没有桌面环境时就用 vim。
需要知道但不常用的命令
| 命令 | 作用 | 注意 |
|---|---|---|
| sudo 命令 | 临时用管理员权限执行一条命令 | 只给确实需要权限的命令使用 |
| --- | --- | --- |
| su | 切换用户 | 初学阶段很少需要 |
| sync | 把还在内存里的数据写入磁盘 | 拔 U 盘或关机前可用 |
| reboot | 重启系统 | 会中断当前工作 |
| poweroff | 关闭系统 | 拼写不是 powerof |
Linux 目录和路径
Linux 的所有文件都从根目录 / 往下长,像一棵倒过来的树。路径就是从一个位置走到另一个位置的路线。
| 目录 | 把它想成 | 主要放什么 |
|---|---|---|
| / | 整栋大楼 | 所有目录的起点 |
| --- | --- | --- |
| /home | 普通用户的宿舍 | 个人文件和项目 |
| /root | 管理员宿舍 | root 用户文件 |
| /etc | 总设置室 | 系统和服务配置 |
| /bin 和 /sbin | 工具房 | 系统命令 |
| /usr | 软件仓库 | 大部分程序和资源 |
| /lib | 公共零件库 | 程序需要的库 |
| /dev | 设备窗口 | 串口 磁盘等设备文件 |
| /mnt 和 /media | 外接物品入口 | 挂载 NFS U 盘 SD 卡 |
| /proc 和 /sys | 系统仪表盘 | 运行状态 内核和设备信息 |
| /tmp | 临时桌面 | 临时文件 |
| /var | 不断变化的记录柜 | 日志 缓存等 |
绝对路径从 / 开始,例如 /home/zyy/nfs_share。相对路径从当前位置开始,例如当前在 /home/zyy 时,nfs_share 就是相对路径。
软链接和硬链接
inode 可以先理解为文件在 Linux 里的身份证号。系统先找到这个身份证,再找到真正的数据。
| 类型 | 生活类比 | 特点 | 命令 |
|---|---|---|---|
| 软链接 | Windows 快捷方式 | 能链接目录 能跨磁盘 源文件删掉后链接失效 | ln -s 源文件 链接名 |
| --- | --- | --- | --- |
| 硬链接 | 同一个房间的第二扇门 | 多个名字指向同一份数据 不能跨文件系统 通常不链接目录 | ln 源文件 新名字 |
嵌入式入门阶段先会用软链接即可。创建软链接时尽量写绝对路径,最不容易出错。
文件权限
Linux 会问三件事:谁可以看,谁可以改,谁可以运行。r 是读,w 是写,x 是执行。权限分给三类人:拥有者 所在组 其他人。
怎么读权限
-rw-rw-r--
│ │ │ └─ 其他人 只读
│ │ └──── 同组用户 可读可写
│ └─────── 拥有者 可读可写
└───────── 普通文件
| 权限 | 数字 | 人话 |
|---|---|---|
| r | 4 | 可以读 |
| --- | --- | --- |
| w | 2 | 可以写 |
| x | 1 | 可以运行 |
常见写法
chmod +x hello # 给 hello 增加执行权限
chmod 755 hello # 拥有者可读写执行 其他人可读执行
chown zyy file.txt # 把文件拥有者改成 zyy
我们在开发板运行 hello 前执行 chmod +x /mnt/nfs/hello,就是给程序一张可以上岗的工作证。
Vim 最小用法
Vim 有三种状态。刚打开时是普通模式;按 i 或 A 进入编辑模式;按 Esc 回到普通模式;再输入冒号命令保存退出。
| 操作 | 作用 |
|---|---|
| vim hello.c | 打开或创建文件 |
| --- | --- |
| i | 在光标前开始输入 |
| A | 移动到当前行末尾并开始输入 你记得的 A 完全正确 |
| Esc | 退出编辑 回到普通模式 |
| :w | 保存 |
| :q | 退出 |
| :wq | 保存并退出 |
| :q! | 不保存 强制退出 |
| yy 和 p | 复制当前行 再粘贴 |
| dd | 删除当前行 |
| u | 撤销上一步 |
| /文字 | 在文件里搜索文字 |
看到自己不能输入时,先按 i 或 A。退出前先按 Esc,再输入 :wq。
GCC Make 和 Makefile
C 源代码是人能读的菜谱,CPU 不能直接执行。gcc 是编译器,负责把菜谱做成可执行程序。文件少时直接用 gcc;文件多时让 make 按 Makefile 的规则自动编译。
make 是执行者,Makefile 是施工单。没有 Makefile,make 不知道先编什么、怎么编。
Makefile 基本格式
目标: 依赖文件
要执行的命令
最小 Makefile 例子
app: main.c add.c
gcc main.c add.c -o app
clean:
rm -f app
使用方法
make # 按规则生成 app
./app # 运行 app
make clean # 执行 clean 规则 删除 app
Makefile 中命令前必须是键盘 Tab,不能用普通空格。文件名通常写 Makefile,大小写要一致。
Shell 脚本
Shell 脚本就是把原来要一条一条输入的终端命令写进一个 .sh 文件,让系统从上到下自动执行。像把多张外卖单订成一张流程单。
一个能看懂的脚本
#!/bin/bash
echo "开始处理订单"
read food
count=2
price=15
total=$((count * price))
if "$food" = "牛肉面" ; then
echo "找到餐品 总价 $total 元"
else
echo "没有这个餐品"
fi
for number in 1 2 3; do
echo "第 $number 次检查订单"
done
保存后运行
chmod +x order.sh
./order.sh
| 写法 | 作用 | 对照 C 语言 |
|---|---|---|
| #!/bin/bash | 说明用 Bash 解释这个文件 | 告诉系统使用哪种语言 |
| --- | --- | --- |
| name=value | 保存一个值 等号两边不能有空格 | 变量赋值 |
| $name | 取出变量的值 | 读取变量 |
| read name | 等待用户输入 | scanf |
| $((a+b)) | 整数计算 | a + b |
| 条件 | 判断条件 中括号两边必须留空格 | if 条件 |
| && | 前一条成功才执行下一条 | 逻辑与 |
| || | 前一条失败才执行下一条 | 逻辑或 |
| if then else fi | 条件判断 | if else |
| case esac | 多个固定选项中选择 | switch case |
| while do done | 条件成立就循环 | while |
| until do done | 条件不成立时循环 | 和 while 方向相反 |
| for do done | 按次数或列表循环 | for |
| function name() | 把一段功能包装起来 | 函数 |
| 0 1 # @ | 脚本名 第一个参数 参数数量 所有参数 | main 的命令行参数 |
作为嵌入式初学者,先会写 shebang 变量 read 整数计算 if 和 for 就够用,其他语法见到时再查。
三 第一阶段实战过程
先认识四个角色
| 东西 | 它是什么 | 本次负责什么 |
|---|---|---|
| Windows 笔记本 | 真实电脑和总平台 | 运行 VMware 和串口助手 |
| --- | --- | --- |
| Ubuntu 虚拟机 | 电脑里的另一台 Linux 电脑 | 写代码 安装工具 交叉编译 提供 NFS |
| i.MX6ULL 开发板 | 一台小型 ARM Linux 电脑 | 运行最终程序 控制未来的硬件 |
| 串口调试助手 | 直接和开发板终端说话的工具 | 输入开发板命令 查看启动和报错 |
i.MX6ULL 开发板可以理解为单板计算机。它有处理器 内存 接口和 Linux 系统,只是它更适合连接和控制硬件。
串口连接
串口像一部对讲机。即使网络还没配置好,你仍然可以通过串口看到开发板启动信息并输入命令。
| 设置项 | 本次实际值 |
|---|---|
| 接口 | 开发板 USB_TTL |
| --- | --- |
| 串口 | COM9 USB SERIAL CH34C |
| 波特率 | 115200 |
| 数据位 | 8 |
| 停止位 | 1 |
| 校验位 | None |
按钮显示 打开串口,说明现在还没打开;点击后按钮变成 关闭串口,才是真的连上。看到 root@ATK-IMX6U:~#,说明已经进入开发板 Linux。
串口里偶尔出现方框或奇怪字符,多数是颜色控制码,不影响命令执行。
网络基础
| 概念 | 生活类比 | 这次实际含义 |
|---|---|---|
| IP 地址 | 门牌号 | Ubuntu 是 192.168.10.10 开发板是 192.168.10.20 |
| --- | --- | --- |
| 同一网段 | 住在同一个小区 | 两者前三段都是 192.168.10 |
| ping | 敲门并等对方回应 | 测试两台机器能不能互相找到 |
| 桥接 | 虚拟机直接接上真实网卡 | ens33 经 VMnet0 接 USB 网卡和开发板 |
| NAT | 借 Windows 的网络上网 | ens37 负责访问软件源和网页 |
| 网卡 | 一扇网络大门 | 不同网卡可以走不同道路 |
我们给 Ubuntu 配两块虚拟网卡,是因为一条路专门去开发板,另一条路专门上网。两条路互不抢工作。
本次网络结构
Ubuntu ens33 192.168.10.10
|
VMnet0 桥接到 NX USB2.0 Fast Ethernet Adapter
|
蓝色网线
|
i.MX6ULL eth1 192.168.10.20
Ubuntu ens37 NAT -> 互联网
判断网线和网卡
在开发板串口输入
ls /sys/class/net
cat /sys/class/net/eth0/carrier
cat /sys/class/net/eth1/carrier
结果中 eth0 的 carrier 是 0,eth1 的 carrier 是 1,所以蓝色网线实际接在 eth1。carrier 为 1 就是检测到物理连接。
启动早期出现 eth1 link is not ready 不一定是故障。后来又出现 Link is Up 100Mbps Full 和 link becomes ready,说明协商成功。
设置两边的临时 IP
在 Ubuntu 终端输入
sudo ip addr add 192.168.10.10/24 dev ens33
ip addr show ens33
在开发板串口输入
ifconfig eth1 192.168.10.20 netmask 255.255.255.0 up
ifconfig eth1
这两个地址是临时设置,Ubuntu 或开发板重启后可能消失。现在这样做是为了先把流程跑通,之后再学习永久配置。
测试双向通信
在 Ubuntu 终端输入
ping -c 4 192.168.10.20
在开发板串口输入
ping -c 4 192.168.10.10
两边都得到 4 packets transmitted 4 received 0 percent packet loss,说明网络双向畅通。-c 4 的意思是只发 4 次,避免一直 ping。
在 Ubuntu 检查互联网
wget --spider --timeout=10 https://www.baidu.com
看到 200 OK,说明 ens37 的 NAT 上网正常。以前 ping 外网失败不一定代表没网,有些网络会阻止 ping,所以用网页请求再次验证。
NFS 共享文件夹
NFS 就像 Ubuntu 和开发板共用一个取餐柜。Ubuntu 把程序放进柜子,开发板在 /mnt/nfs 打开柜门就能看到。它不是每次手动复制,而是两边看见同一份目录内容。
TFTP 更像一次送一个包裹;NFS 更像一直连着的共享柜。本次选择 NFS,所以 TFTP 只安装,没有继续配置。
第一步 在 Ubuntu 安装工具
sudo apt update
sudo apt install -y nfs-kernel-server tftpd-hpa
第二步 在 Ubuntu 建共享目录
mkdir -p ~/nfs_share
echo "hello from Ubuntu" > ~/nfs_share/test.txt
cat ~/nfs_share/test.txt
第三步 在 Ubuntu 写共享规则
sudo mkdir -p /etc/exports.d
echo "/home/zyy/nfs_share 192.168.10.0/24(rw,sync,no_subtree_check,no_root_squash)" | sudo tee /etc/exports.d/imx6ull.exports
| 配置内容 | 意思 |
|---|---|
| /home/zyy/nfs_share | 要共享的 Ubuntu 文件夹 |
| --- | --- |
| 192.168.10.0/24 | 允许同一网段里的设备访问 |
| rw | 允许读取和写入 |
| sync | 写入时立即同步到磁盘 |
| no_subtree_check | 不做子目录检查 减少兼容问题 |
| no_root_squash | 允许开发板 root 保留写权限 只适合当前隔离实验网 |
第四步 在 Ubuntu 让规则生效并检查
sudo exportfs -rav
sudo systemctl restart nfs-kernel-server
showmount -e 192.168.10.10
第五步 在开发板挂载 NFS
mkdir -p /mnt/nfs
mount -t nfs -o nolock,vers=3 192.168.10.10:/home/zyy/nfs_share /mnt/nfs
ls /mnt/nfs
cat /mnt/nfs/test.txt
mount 就是把远处的共享柜接到本机的一扇门上。vers=3 是为了兼容开发板较老的系统,nolock 用来避免文件锁服务不兼容。
第六步 在开发板写一个文件
echo "hello from board" > /mnt/nfs/board.txt
回到 Ubuntu 检查
cat ~/nfs_share/board.txt
Ubuntu 成功看到 hello from board,说明 NFS 不仅能读,还能双向写。
交叉编译
笔记本通常是 x86 处理器,i.MX6ULL 是 ARM 处理器。普通 gcc 做出的程序是给笔记本吃的,开发板看不懂。arm-linux-gnueabihf-gcc 是翻译器,专门在 Ubuntu 上生成 ARM 能运行的程序。
交叉编译就是在 A 机器上制作给 B 机器运行的程序。
在 Ubuntu 安装并检查交叉编译器
sudo apt install -y gcc-arm-linux-gnueabihf
arm-linux-gnueabihf-gcc --version
编写和运行 Hello World
Ubuntu 中的 hello.c
#include <stdio.h>
int main(void)
{
printf("Hello i.MX6ULL!\n");
return 0;
}
在 Ubuntu 编译并检查
cd ~/nfs_share
arm-linux-gnueabihf-gcc -static hello.c -o hello
file hello
-static 表示把程序需要的大部分库一起装进程序,像把餐具调料都装进外卖盒,能减少开发板系统库版本不一致的问题。
file hello 的实际结果包含 ELF 32-bit ARM 和 statically linked。这证明生成的是 ARM 32 位静态程序,不是 Ubuntu 自己的 x86 程序。
在开发板运行
chmod +x /mnt/nfs/hello
/mnt/nfs/hello
实际输出
Hello i.MX6ULL!
这一行输出证明整条链路已经跑通:写代码 交叉编译 NFS 共享 开发板执行。第一阶段的核心目标已经完成。
应用 驱动和硬件的关系
应用和驱动不是同一个东西。应用负责你想做什么,驱动负责怎么和硬件说话,硬件负责真正发光 发声或采集数据。
从上到下的关系
Qt 或 C 应用 -> Linux 提供的文件或设备接口 -> 驱动 -> LED 蜂鸣器等硬件
用送外卖类比:应用是顾客下单页面,驱动是调度员,硬件是骑手和车辆。下单页面不能自己骑车,必须通过调度系统。
四 我们遇到的错误和解决办法
| 看到的现象 | 真正原因 | 解决办法 |
|---|---|---|
| ens33 显示 NO CARRIER | VMware 虚拟网卡没有连接 或桥接的物理网卡不对 | 勾选已连接和启动时连接 VMnet0 桥接到 NX USB2.0 网卡 |
| --- | --- | --- |
| Destination Host Unreachable | Ubuntu 有 IP 但找不到开发板的物理链路 | 检查网线 板子 eth1 carrier VMware 桥接对象 |
| 网络不可达 | ens33 上没有 192.168.10.10 地址 | 重新执行 sudo ip addr add 命令 |
| 启动时 link is not ready | 网口还在协商 | 等待后续 Link is Up 和 link becomes ready |
| dhclient command not found | 系统没有安装 dhclient | 本实验直接使用静态临时 IP 不需要它 |
| curl command not found | 系统没有安装 curl | 使用已存在的 wget 检查网页 |
| 外网 ping 不通 | 网络可能屏蔽 ICMP | 用 wget spider 看是否得到 200 OK |
| /etc/exports.d 不存在 | 系统未自动建立目录 | sudo mkdir -p /etc/exports.d |
| 找不到交叉编译器 | gcc-arm-linux-gnueabihf 未安装 | sudo apt install -y gcc-arm-linux-gnueabihf |
| 串口不能输入 | 串口还是关闭状态 | 点击打开串口 按钮变成关闭串口后再输入 |
| 重启后 IP 消失 | 使用的是临时 IP | 按恢复清单重新设置 |
错误信息怎么读
-
先看命令是在哪台机器执行的。提示符 zyy@... 是 Ubuntu,root@ATK-IMX6U 是开发板。
-
先读最后一两行。大多数关键原因就在最后,例如 command not found 或 No such file or directory。
-
一次只改一个地方,再重新测试。否则最后不知道是哪一步起作用。
-
保存成功命令和实际输出,形成日志。下次照着恢复,不用重猜。
重启后的最短恢复清单
Ubuntu 终端
sudo ip addr add 192.168.10.10/24 dev ens33
sudo systemctl restart nfs-kernel-server
ping -c 4 192.168.10.20
开发板串口
ifconfig eth1 192.168.10.20 netmask 255.255.255.0 up
mkdir -p /mnt/nfs
mount -t nfs -o nolock,vers=3 192.168.10.10:/home/zyy/nfs_share /mnt/nfs
ping -c 4 192.168.10.10
ls /mnt/nfs
如果 add IP 提示 File exists,说明地址可能已经存在,先用 ip addr show ens33 检查,不要重复添加。
五 接下来四个学习任务
任务一 已完成的开发通道
目标是 Ubuntu 写程序,开发板运行程序。现在网络 NFS 交叉编译和 Hello World 已经全部跑通。下一步只需要把临时配置逐渐整理成稳定流程。
任务二 Linux C 应用
只练两类程序,不从书头看到尾。
- 文件操作:fopen 打开,fread 或 fgets 读取,fwrite 或 fprintf 写入,fclose 关闭。类比打开笔记本 写字 看字 合上。
- 多进程:fork 像把一个店复制成两家店,各自继续工作。
- 多线程:pthread 像一家店里的多个员工,共用同一间厨房,同时做不同工作。
学习成果应该是三个很小的程序:文件读写程序 fork 程序 pthread 程序。
系统移植和文件系统构建
这一部分像给一套新房安装地基 电路和家具。你只需要跟教程把启动加载器 Linux 内核 设备树 根文件系统的整体流程走一遍,知道它们各自负责什么,不要求现在会从零修改内核。
任务三 控制开发板硬件
目标是让 C 程序控制板载 LED 和蜂鸣器。Linux 下通常不直接改寄存器,而是打开系统提供的文件或设备接口,再读写它。应用通过接口找到驱动,驱动再控制硬件。
任务四 Qt 图形界面
Qt 是用 C++ 做窗口 按钮 文本和界面的工具。先在 Ubuntu 上做一个最小窗口,再交叉编译放到开发板,最后让开发板启动后运行自己的界面程序。完成这一步,就具备继续做一个完整嵌入式产品界面的基础。
暂时不学什么
- ARM 裸机篇暂时不学。现阶段先把 Linux 路线走通。
- 驱动开发指南不用从第一页啃到最后一页,只在做 LED 蜂鸣器和系统流程时查对应章节。
- Qt 不要一开始追求漂亮界面,先让一个窗口成功上板。
- 遇到暂时用不到的细节,先知道名字和作用,等项目需要时再深挖。
六 用送外卖故事复习整条流程
现在把所有技术词暂时放下,只看一个送外卖故事。读完这个故事,再看后面的技术对照,你就能知道每一步为什么存在。
-
你在 Ubuntu 后厨写了一张菜谱 hello.c。它现在只是文字,还不能直接让开发板干活。
-
普通打包机 gcc 只会打包给 x86 笔记本吃。你换成 ARM 专用打包机 arm-linux-gnueabihf-gcc,把菜谱做成开发板能吃的 hello。
-
为了避免开发板缺少餐具和调料,你加上 -static,把常用库一起装进外卖盒。
-
Ubuntu 和开发板先要有一条路。蓝色网线是马路,192.168.10.10 和 192.168.10.20 是两边的门牌号,ping 是敲门确认。
-
NFS 是共享取餐柜。Ubuntu 把 hello 放进 ~/nfs_share,开发板从 /mnt/nfs 看见同一个 hello,不需要再次手动搬运。
-
chmod +x 像给 hello 发一张上岗证。最后开发板执行 /mnt/nfs/hello,屏幕出现 Hello i.MX6ULL。
-
以后控制 LED 和蜂鸣器时,应用负责下单,驱动负责调度,硬件负责真正发光或发声。
技术词和生活类比对照
| 技术词 | 送外卖类比 | 真正作用 |
|---|---|---|
| Ubuntu | 后厨 | 写代码 安装工具 编译程序 |
| --- | --- | --- |
| 开发板 | 真正干活的店员 | 运行程序并控制硬件 |
| 串口 | 对讲机 | 直接输入开发板命令并看启动信息 |
| 网线 | 马路 | 传递网络数据 |
| IP | 门牌号 | 让两台机器找到对方 |
| ping | 敲门 | 检查对方是否能回应 |
| 交叉编译器 | ARM 专用打包机 | 把 C 代码变成 ARM 程序 |
| NFS | 共享取餐柜 | 两边访问同一个共享目录 |
| mount | 把取餐柜接到一扇门 | 把远程目录接到开发板 /mnt/nfs |
| chmod +x | 发上岗证 | 允许程序执行 |
| 应用 | 顾客下单页面 | 说明想让系统做什么 |
| 驱动 | 调度员 | 把应用要求变成硬件动作 |
自我检查
□ 我能说出 Windows Ubuntu 虚拟机和开发板分别负责什么
□ 我知道串口是对讲机 网络是传文件和通信的道路
□ 我知道 IP 是门牌号 ping 是敲门测试
□ 我能分清 Ubuntu 命令提示符和开发板命令提示符
□ 我能解释桥接和 NAT 的区别
□ 我能解释 NFS 为什么像共享文件夹
□ 我能解释普通编译和交叉编译的区别
□ 我知道 chmod +x 是给程序执行权限
□ 我能说明第一阶段已经成功输出 Hello i.MX6ULL
□ 我知道下一步是文件操作 多进程和多线程
最后只记住这条主线
第一阶段主线
写 C 代码 -> 在 Ubuntu 交叉编译 -> 放进 NFS 共享目录 -> 开发板运行
你现在不需要把每条命令背下来。能说清楚每一步为什么存在,能照日志重新做一遍,并且知道报错时先检查哪一层,就已经达到第一阶段的学习目标。