1.准备工作
根文件系统下载解压
官网地址:Index of /
Ubuntu 的移植非常简单,不需要编译任何东西,因为 Ubuntu 官方已经将根文件系统制作好了,只需简单配置
Ubuntu 官方提供的 base 根文件系统,使其在我们的开发板上跑起来即可。
->首先
->其次
->最后
这里选择低于18.04的根文件系统都可以,理论上适配最优解是18.04 我选择的是16.04.6
Ubuntu 针对不同的 CPU 架构提供相应的 ubuntu base 根文件系统,有 amd64(64位X86)、 armhf、 i386(32 位 X86) , powerpc、 ppc64el 等系统的。 MP157 是 CortexA 内核的 CPU,并且有 硬件Q 浮 点运算单元,因此选择 armhf 版本。
下载后放一份到Ubuntu
去ubuntu解压然后复制到opt新建的xyrootfs目录中
mkdir xyrootfs sudo tar -vzxf ubuntu-base-16.04.6-base-armhf.tar.gz -C xyrootfs/ sudo vi /etc/exports //配置NFS文件配置 |
正式移植之前需要一个辅助工具,对根文件系统进行一个基本的搭建使其文件结构清晰,我的一个老师梁老师说过,毕竟linux一切皆文件
sudo apt-get install qemu-user-static //apt下载不了的检查一下软件源,后续在开发板上跑起来的Ubuntu要下载同理 |
stm32mp157平台是32位控制器,因此选择以下指令:
sudo cp /usr/bin/qemu-arm-static ./xyrootfs/usr/bin/ sudo cp /etc/resolv.conf ./xyrootfs/etc/resolv.conf sudo vim ./xyrootfs/etc/resolv.conf //谷歌的公开DNS nameserver 8.8.8.8 |
64bit的也附上:
sudo cp /usr/bin/qemu-aarch64-static ./rootfs/usr/bin/ sudo cp /etc/resolv.conf ./rootfs/etc/resolv.conf sudo vim ./rootfs/etc/resolv.conf nameserver 8.8.8.8 |
2.移植过程
根文件系统要运行起来,还需要虚拟文件系统,也就是说现在需要模拟根文件系统的运行环境。
接下来将上面制作的根文件系统挂载到主机上,需要挂载 proc、 sys、 dev、 dev/pts 等文件系统,最 后使用 chroot 将主机的根文件系统切换到我们前面制作的根文件系统中。这里我们通过脚本文件来完成 挂载和卸载操作
新建一个mk.sh
chmod 777 mk.sh |
脚本内容:
#!/bin/bash
# 指定脚本的解释器为 Bash
mnt ()
# 定义一个名为 mnt 的函数,用来挂载所需的文件系统
{
echo "MOUNTING"
# 输出 "MOUNTING",表明正在执行挂载操作
sudo mount -t proc /proc ${2}proc
# 挂载 proc 文件系统,将目标文件系统路径的 `/proc` 目录挂载到当前文件系统的 `${2}proc`
目录
sudo mount -t sysfs /sys ${2}sys
# 挂载 sysfs 文件系统,将目标文件系统路径的 `/sys` 目录挂载到当前文件系统的 `${2}sys`
目录
sudo mount -o bind /dev ${2}dev
# 挂载当前系统的 `/dev` 目录到目标文件系统的 `${2}dev` 目录, `bind` 表示硬链接方式挂载
sudo mount -o bind /dev/pts ${2}dev/pts
# 同理,挂载当前系统的 `/dev/pts` 目录到目标文件系统的 `${2}dev/pts` 目录
sudo chroot ${2}
# 切换到目标文件系统 `${2}` 目录下,执行 chroot 操作,改变根目录到指定路径
}
umnt ()
# 定义一个名为 umnt 的函数,用来卸载之前挂载的文件系统
{
echo "UNMOUNTING"
# 输出 "UNMOUNTING",表明正在执行卸载操作
sudo umount ${2}proc
# 卸载目标文件系统的 `${2}proc` 目录 sudo umount ${2}sys
# 卸载目标文件系统的 `${2}sys` 目录 sudo umount ${2}dev/pts
# 卸载目标文件系统的 `${2}dev/pts` 目录 sudo umount ${2}dev
# 卸载目标文件系统的 `${2}dev` 目录
}
if [ "$1" = "-m" ] && [ -n "$2" ];
then
# 判断第一个参数是否为 "-m"(挂载操作)且第二个参数不为空
mnt $1 $2
# 调用 mnt 函数,传递 `$1`(-m)和 `$2`( 目标文件系统路径)作为参数
echo "mnt -m pwd"
# 输出 "mnt -m pwd",提示挂载操作完成
elif [ "$1" = "-u" ] && [ -n "$2" ];
then
# 判断第一个参数是否为 "-u"(卸载操作)且第二个参数不为空
umnt $1 $2
# 调用 umnt 函数,传递 `$1`(-u)和 `$2`( 目标文件系统路径)作为参数
echo "mnt -u pwd"
# 输出 "mnt -u pwd",提示卸载操作完成
else
# 如果参数不符合要求,执行 else 分支
echo ""
echo "Either 1'st, 2'nd or both parameters were missing"
# 输出参数缺失的提示信息
echo ""
echo "1'st parameter can be one of these: -m(mount) OR -u(umount)"
# 提示第一个参数应为 "-m"(挂载)或 "-u"(卸载) echo "2'nd parameter is the rootfs path"
# 提示第二个参数是根文件系统路径 echo ""
echo "For example: ./mk.sh -m ./rootfs/"
# 提供一个示例命令
echo ""
echo "1st parameter : ${1}"
# 输出第一个参数的值
echo "2nd parameter : ${2}"
# 输出第二个参数的值
fi
执行语句挂载:
sudo ./mk.sh -m ./xyrootfs/ |
注意脚本存放路径在xyrootfs外面
sudo ./mk.sh -m ./xyrootfs/ sudo ./mk.sh -u ./xyrootfs/ |
挂载成功后,已切换到上面制作的rootfs根文件系统中。
安装常用的命令和软件
由于 ubuntu base 是一个最小根文件系统,很多命令和软件都没有,因此我们需要先安装一下常用的命令和软件,输入如下命令
apt update
apt install sudo
apt install vim
apt install kmod net-tools ethtool ifupdown language-pack-en-base rsyslog htop iputils-ping
用户配置:
1.设置一下 root 用户的密码,设置简单一点, root 用户密码也设置为“root”,相当于用户名和密码一 样,命令如下:
passwd root |
2.输入“passwd root”以后会让你输入 root 用户密码,输入两次。 添加一个普通用户xieya:
useradd -s '/bin/bash' -m -G adm,sudo xieya |
3.给用户 xieya 设置密码:
passwd xieya |
输入“passwdsdr”以后会让你输入用户密码,输入两次。
主机配置
因为现在我们挂载的根文件系统也是一个主机,当然也需要设置些基础信息
echo “sdr” > /etc/hostname echo “127.0.0.1 localhost” >> /etc/hosts echo “127.0.0.1 sdr” >> /etc/hosts |
终端设置
因为我们的开发板是使用串口作为终端的,所以需要设置一下
ubuntu 根文件系统在开发板上启动以后我们通常也希望串口终端正常工作,首先确定自己所使用的串 口设备文件,比如正点原子的 STM32MP157 开发板使用的UART4对应的串口设备文件为tySTM0,我们 需要添加一个名
为getty@ttySTM0.service 的链接,链接到getty@.service 服务上,输入如下命令:
ln -s /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@ttySTM0.service 注意:ttySTM32为串口节点,具体根据自己的板子设置 |
如果是18.04的Ubuntu.base有可能会提示
/bin/ls: cannot access '/lib/systemd/system/getty@.service': No such file or directory |
解决办法:
apt install systemd |
正确现象:
ls /lib/systemd/system/getty@.service 提示/lib/systemd/system/getty@.service |
安装图形化界面
图形程序安装,安装的桌面是xubuntu-desktop:
apt install xubuntu-desktop |
取决于网速可能会有点久
中间可能会弹出来紫色界面让选择键盘界面布局,可参考该帖子解决:
Linux系统UI界面_please select the layout matching the keyboard for-CSDN博客 fromshare=blogdetail&sharetype=blogdetail&sharerId=126789586&sharerefer=PC&share source=m0_68220839&sharefrom=from_link |
取决于网速该过程可能会有点久 执行命令之后会报错:
Errors were encountered while processing: blueman E: Sub-process /usr/bin/dpkg returned an error code (1) |
这是正常现象,不用管。
这样基本配置我们就设置好了,我们退出这个根文件系统,然后取消挂载。设置好以后就可以退出根文 件系统了,输入如下命令退出:
exit ./mk.sh -u ./rootfs/ |
至此, ubuntu base 根文件系统就已经制作好了,接下来就是挂载到开发板上去测试
3.开发板验证
uboot
1.首先准备
一份uImage和stm32mp157a-fsmp1a.dtb
2.进入开发板uboot
开机狂按enter 然后配置开发板
env set -f ethaddr 00:80:E1:42:60:10//物理地址不固定
env set serverip 192.168.80.136//你的Ubuntu服务器ip
env set gatewayip 192.168.80.1//你的局域网网关
env set ipaddr 192.168.80.3//你的开发板ip自定义,确保和Ubuntu服务器同一网段即可
env set -f bootcmd tftp 0xc2000000 uImage;tftp 0xc4000000 stm32mp157a-fsmp1a.dtb;bootm 0xc2000000 - 0xc4000000
//使用bootm指令通过tftp服务,将内核写入起始为0xc2000000的开发板地址,设备树同理
//nfs 挂载测试根文件系统已经制作完成了,接下来就是测试,先用 nfs 挂载根文件系统,在 uboot 里面设置 bootargs 环境变量的值如下:
env set -f bootargs root=/dev/nfs nfsroot=192.168.80.136:/opt/xyrootfs intr rsize=1024 wsize=1024 rootwait rw earlyprintk ip=192.168.80.3 console=ttySTM0,115200
在保证内核正确的前提下,能进入根文件系统,即为成功。
串口登录开发板出现例如这样的界面:
wqc login: root Password: Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.14.0-xilinx armv7l) * Documentation: Official Ubuntu Documentation * Management: Landscape * Support: Ubuntu Pro | Ubuntu The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. root@xieya:~# |
因为此时LCD屏幕未移植,还无法查看图形化界面
4.移植LCD(屏幕型号st7701)
内核配置
在内核根目录下,执行:
make ARCH=arm menuconfig //层级关系 Device Drivers —> Graphics support —> — 图形配置 |
选中配置如图:
开机logo
[*] Bootup logo —> [*] Standard black and white Linux logo [*] Standard 16-color Linux logo [*] Standard 224-color Linux logo |
设备树
1. 添加pwm2内容
修改stm32mp15xx-fsmp1x.dtsi,在stm32mp15xx-fsmp1x.dtsi文件末尾添加如下内容: (如已添加请忽略)
&timers2 { /* spare dmas for other usage */ /delete-property/dmas; /delete-property/dma-names; status = “okay”; pwm2: pwm { pinctrl-0 = <&pwm2_pins_b>; pinctrl-1 = <&pwm2_sleep_pins_b>; pinctrl-names = “default”, “sleep”; #pwm-cells = <2>; status = “okay”; }; timer@2 { status = “okay”; }; }; 把status设置为okay。 设置此节点不用dma。 pwm2 是我们为pwm设置的一个别名。 设置 PWM 所使用的IO配置。 此参数是用来规定pwms属性的参数。比如:#pwm-cells =<2>,表示pwms属性 有2个参数,如下所示: pwms= <&pwm2 1 5000000> 其中pwm2表示使用PWM2,后面两个是参数,其中1表示使用PWM2的通道2(通道从1开始),5000000表示为 200Hz |
2. 添加背光内容
修改stm32mp15xx-fsmp1x.dtsi,在根节点中添加如下内容:
panel_backlight: panel-backlight { compatible = “pwm-backlight”; pwms = <&pwm2 0 5000000>; brightness-levels = <0 4 8 16 32 64 128 255>; default-brightness-level = <6>; status = “okay”; }; 设置背光使用pwm2的第二个通道,PWM频率为200Hz。 设置背8级背光(0~7),分别为0、4、8、16、32、64、128、255对应占空比为0%、1.57%、3.13%、 6.27%、12.55%、25.1%、50.19%、100% 设置默认背光等级为7,也就是100%的亮度 //参考内核PWM文档 |
(添加请忽略)
3. 修改stm32mp157a-fsmp1a.dts
<dc { status = “okay”; port { #address-cells = <1>; #size-cells = <0>; ltdc_ep1_out: endpoint@1 { remote-endpoint = <&dsi_in>; }; }; }; 在port下添加了一个子节点为ltdc_ep1_out remote-endpoint属性是用来告诉ltdc节点输出到那里 |
添加dsi内容: &dsi { #address-cells = <1>; #size-cells = <0>; status = “okay”; ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; dsi_in: endpoint { remote-endpoint = <<dc_ep1_out>; }; }; port@1 { reg = <1>; dsi_out: endpoint { remote-endpoint = <&dsi_panel_in>; }; }; }; panel_dsi: panel-dsi@0 { compatible = “sitronix,st7701”; reg = <0>; reset-gpios = <&gpiog 9 GPIO_ACTIVE_HIGH>; backlight = <&panel_backlight>; power-supply = <&v3v3>; status = “okay”; port { dsi_panel_in: endpoint { remote-endpoint = <&dsi_out>; }; }; }; }; |
代码移植
和厂商沟通发现这个屏幕和demo板的有所不同,所以要修改原代码文件:
驱动代码路径如下:
/home/crl/crl/linux-5.4.31/drivers/gpu/drm/panel vim panel-sitronix-st7701.c |
之前的给他注释掉
初始化序列:
/**
* ST7701_SPEC_V1.2 is unable to provide enough information above this
* specific command sequence, so grab the same from vendor BSP driver.
*/
ST7701_DSI(st7701,0xe0, 0x00, 0x00, 0x02);
ST7701_DSI(st7701,0xe1, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20);
ST7701_DSI(st7701,0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
ST7701_DSI(st7701,0xe3, 0x00, 0x00, 0x33, 0x00);
ST7701_DSI(st7701,0xe4, 0x22, 0x00);ST7701_DSI(st7701,0xe5, 0x07, 0x34, 0xa0, 0xa0, 0x05, 0x34, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
ST7701_DSI(st7701,0xe6, 0x00, 0x00, 0x33, 0x00);
ST7701_DSI(st7701,0xe7, 0x22, 0x00);
ST7701_DSI(st7701,0xe8, 0x06, 0x34, 0xa0, 0xa0, 0x04, 0x34, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
ST7701_DSI(st7701,0xeb, 0x02, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00);
ST7701_DSI(st7701,0xec, 0x02, 0x00);
ST7701_DSI(st7701,0xed, 0xaa, 0x54, 0x0b, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xb0, 0x45, 0xaa);
/* disable Command2 */
模式:
Video模式分三种子模式:
1.Non-burst Mode Sync pulses: 在这种模式下,DSI基于各种不同的同步数据包来做数据同步。这种数据包括:重构,时间校准等。更具体的请参考DSI协议标准。
2.Non-burst Mode Sync event: 这种模式和第一种模式很像,但是这种模式不会发重构和时间校准的数据包,它们只发送一种叫做”Sync event”的包。
3.Burst mode: 在horizontal 的时序是一样的情况下DSI会把连接的速度提升到Panel支持的最大速
度。在这种模式下发送RGB数据包的时间被压缩,以留出更多的时间用来传送其他的数据。
//.flags = MIPI_DSI_MODE_VIDEO, .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM, |
.vsync_end = 854 + 18 + 18, .vtotal = 854 + 18 + 18 + 11, |
回头检查
选中完毕即可上电启动开发板,进行屏幕测试
至此, LCD屏幕移植完成。接下来需要移植USB驱动,使得可以直接在开发板上插上鼠标键盘就能像电脑一样进行操作。
排查问题的思路很关键
panel-sitronix-st7701
然后去内核的buildroot找这个屏幕
默认没有选中给他选中,之后make -j8就会把它一起编译到内核了
检查阶段:
新思路:锁定范围后ai介入解释设备树节点代码
如果是拷贝的别人现成的内核,那么设备树中已经包含有这个定时器节点了,不用再加
背光节点也有了不用再加,以后工作了回头翻阅笔记记得注意这点 所以我们真正要添加的设备树节点是ltdc
编译常用语句
make -j4 ARCH=arm uImage vmlinux LOADADDR=0xC2000040 make arch=arm dtbs 16> 拷贝文件到对应的目录 cp -raf arch/arm/boot/dts/stm32mp157a-fsmp1a.dtb /tftpboot/ cp -raf arch/arm/boot/uImage /tftpboot/ |
compatible匹配不成功导致内核死机 所以要改如下:
发现核心层和设备控制层都没问题,只能是驱动问题了,接下来去找panel.c
5.USB驱动部分
设备树
USB子系统是一个标准和复杂的接口,所以驱动基本我们不用写,都是内核里有现成的,我们只需要在设备树 提供对应的设备节点即可。 USBH是只能主机模式,要编写USB HOST就用USBH控制器即可。 ST官方的STM3MP157开发板已经配置好了USBH的节点信息,所以我们直接参考此节点即可,这样开发板就能 够使用USB Host模式 |
1. USBH 控制器节点信息
打开“stm32mp151.dtsi”文件,找到 USBH 两个控制器的节点信息,名字分别为“usbh_ohci”和 “usbh_ehci”。如下示例代码所示:
2. 配置 PHY 控制器
我们先去了解一下 PHY 控制器, 一些通用配置,打开 stm32mp151.dtsi 文件,找的如下内 容所示:
usbphyc: usbphyc@5a006000 {
#address-cells = <1>;
#size-cells = <0>;
#clock-cells = <0>;
compatible = "st,stm32mp1-usbphyc";
reg = <0x5a006000 0x1000>;
clocks = <&rcc USBPHY_K>;
resets = <&rcc USBPHY_R>;
vdda1v1-supply = <®11>;
vdda1v8-supply = <®18>;
status = "disabled";
usbphyc_port0: usb-phy@0 {
#phy-cells = <0>;
reg = <0>;
};
usbphyc_port1: usb-phy@1 {
#phy-cells = <1>;
reg = <1>;
};
};
usbphyc 节点就是 STM32MP1 的 USB PHY。我已经知道 PHY 控制器有两个端口,刚好 usbphyc 节点里有两个子节点名字分别为:usbphyc_port0 和 usbphyc_port1,这个两个子节点就是 PHY 控制器的两个端口,其中 usbphyc_port0 只能分配给 USB Host。注意:“#phy-cells”属性和“#gpio-cells”属性作用是一样的,如果#phy-cells 为 1,表示一个 cell,此cell 表示端口做 USBH 的 PHY 端口还是 OTG 的 PHY 端口,0 表示做 OTG 的 PHY 端口,1 表示做 USBH 的 PHY 端口。
打开“stm32mp15xx-dkx.dtsi”文件找到“usb_phy_tuning”节点,把此节点的内容拷贝到 stm32mp157a- fsmp157.dts 的根目录下,拷贝内容如下所示:
usb_phy_tuning: usb-phy-tuning { st,hs-dc-level = <2>; st,fs-rftime-tuning; st,hs-rftime-reduction; st,hs-current-trim = <15>; st,hs-impedance-trim = <1>; st,squelch-level = <3>; st,hs-rx-offset = <2>; st,no-lsfs-sc; }; usb_phy_tuning 此节点负责调整PHY的配置,对于此节点的属性内容感兴趣的可以去看 Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml文件 |
接 着 我 还 是 在 stm32mp157a-fsmp157.dts 文件中使能 usbphyc 以及向 usbphyc_port0 节点追加的 内容,要修改的如下所示:
&usbphyc { status = “okay”; }; &usbphyc_port0 { phy-supply = <&v3v3>; st,phy-tuning =<&usb_phy_tuning>; }; 第2行,这里我们把usbphyc的status属性修改为“okay”,使能usbphyc。 第6行,给usbphyc_port0节点追加phy-supply属性,添加一个电源管理属性。 第7行,把我们要修改的PHY配置,添加到usbphyc_port0节点里。 |
最后我们在 stm32mp157d-atk.dts 文件,使能 usbh_ehci 和指定 PHY 端口:
&usbh_ehci { phys = <&usbphyc_port0>; status = “okay”; }; 这里的内容很简单,就是修改status属性为“okay”和指定使用usbphyc_port0端口 |
内核配置
1.USB鼠标键盘驱动使能
USB 鼠标键盘属于 HID 设备,内核已经集成了相应的驱动,ST 官方提供的 linux 内核默认 已经使能了 USB 鼠标键盘驱动,但是我们还要学习一下如何手动使能这些驱动。输入“make menuconfig”,打开 linux 内核配置界面,首先打开 HID 驱动,按照如下路径到相应的配置项目: -> Device Drivers -> HID support -> HID bus support -> <*> Generic HID driver //使能通用 HID 驱动 -> Device Drivers -> HID support -> USB HID support //去掉该项,用自己的驱动程序来测试 -> < > USB HID transport layer //USB 键盘鼠标等 HID 设备驱动 |
到这里已经可以重启验证,先输入密码登录,由于芯片性能羸弱需要等待一会,进入ubuntu桌面系统成功!
2.U盘实验
ST 提供的Linux内核默认也已经使能了U盘驱动,因此我们可以直接插上去使用。但是我们还是需要学习一下 如何手动配置Linux内核,使能U盘驱动 -> Device Drivers -> SCSI device support -> <*> SCSI disk support //选中此选项 -> Device Drivers -> USB support -> USB Gadget Support -> USB Gadget functions configurable through configfs -> [*] Mass storage //选中 |
暂无评论内容