【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
之前开发过程中,整个linux的启动都是基于sd卡进行的。此外,我们有这么几点发现,首先,v3s本身是识别sd卡的,不然无法加载uboot的bin文件;第二,uboot可以驱动sd卡的,不然没有办法加载zImage和dtb文件;第三,linux kernel本身也可以驱动sd卡,不然就不能在根文件目录下面正常添加、删除文件了。
1、了解之前uboot的加载命令
v3s可以识别sd卡,通过标准的硬件协议来加载uboot bin文件。这一点和spi norflash、spi nandflash很相似。下面,我们可以看看uboot是怎么加载sd卡里面的内容的,
setenv bootm_boot_mode sec
load mmc 0:1 0x41000000 zImage
load mmc 0:1 0x41800000 sun8i-v3s-licheepi-zero-with-480x272-lcd.dtb
setenv bootargs console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 earlyprintk rw vt.global_cursor_default=0
bootz 0x41000000 - 0x41800000
第一句表示模式设定。
第二句表示把zImage加载到0x41000000这个地址。
第三句表示把dtb文件加载到0x41800000这个地址。
第四句设置参数,比较重要的是console和root,前者表示串口选择,后者表示根文件位置。
第五句开始启动,两个地址就是zImage和dtb加载的地方。
2、sd卡电路
sd卡电路表简单,主要就是6个信号,其中D0-D3表示数据,CLK表示时钟,CMD表示命令。
3、设备树配置
v3s中关于设备树的配置也是比较简单的。首先是sun8i-v3s-licheepi-zero.dts 文件,
&mmc0 {
pinctrl-0 = <&mmc0_pins_a>;
pinctrl-names = "default";
broken-cd;
bus-width = <4>;
vmmc-supply = <®_vcc3v3>;
status = "okay";
};
电路中其实是有两组sd信号的,一组给了sd卡,命名为mmc0;另外一组是给了无线wifi esp 8089。具体的pin脚参考文件sun8i-v3s.dtsi,
mmc0_pins_a: mmc0@0 {
pins = "PF0", "PF1", "PF2", "PF3",
"PF4", "PF5";
function = "mmc0";
drive-strength = <30>;
bias-pull-up;
};
关于寄存器的部分,可以在文件的前半部分找到,
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun7i-a20-mmc";
reg = <0x01c0f000 0x1000>;
clocks = <&ccu CLK_BUS_MMC0>,
<&ccu CLK_MMC0>,
<&ccu CLK_MMC0_OUTPUT>,
<&ccu CLK_MMC0_SAMPLE>;
clock-names = "ahb",
"mmc",
"output",
"sample";
resets = <&ccu RST_BUS_MMC0>;
reset-names = "ahb";
interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
这三处配置都是默认选上的,所以大家不需要自己手动添加,当然也就不需要自己编译和重新烧入了。
4、驱动文件
驱动文件可以通过关键字sun7i-a20-mmc来查找,可以比较容易的找到具体的驱动文件位置,
即linux-zero-4.14.y/drivers/mmc/host/sunxi-mmc.c,有兴趣的同学可以去看看代码,
static const struct of_device_id sunxi_mmc_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-mmc", .data = &sun4i_a10_cfg },
{ .compatible = "allwinner,sun5i-a13-mmc", .data = &sun5i_a13_cfg },
{ .compatible = "allwinner,sun7i-a20-mmc", .data = &sun7i_a20_cfg },
{ .compatible = "allwinner,sun8i-a83t-emmc", .data = &sun8i_a83t_emmc_cfg },
{ .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg },
{ .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg },
{ .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
5、确认驱动加载正常
虽然我们心里知道,驱动加载肯定是没有问题的,这个时候也可以通过查看/dev/mmc*节点的方法,再次确认sd卡已经被正确加载了,
当然,也许有同学会问,知道了sd卡驱动有什么用。举个例子,大家就明白了。通过看上面的设备节点,其实就清楚了里面包含了zImage和dtb文件,所以如果我们需要升级内核和修改dtb数据的话,完全就可以把/dev/mmcblk0p1加载到/mnt上面,直接替换就可以了,非常方便。
# mount /dev/mmcblk0p1 /mnt