IMX6ULL驱动开发uboot篇01

目录

所以,啥是UBoot

使用uboot的命令行完成点事情

[bdinfo, printenv和version](#bdinfo, printenv和version)

环境变量

内存操作


所以,啥是UBoot

我们搞过STM32或者啥其他单片机的朋友都知道,我们的程序想要跑上去,需要一个BOOTLoader来提供一个最基本的,被初始化后的软硬件环境(比如说中断向量要布置好,C语言的栈环境要布置好等等!),对于跑操作系统,想要让一个大系统跑在一个板子上的重要步骤就是提供一个提供一个BootLoader,把操作系统的环境建立好后,才能跑操作系统。就像UEFI/BIOS对于我们的电脑一样,想要跑Windows/Linux,就是需要过一下前者。

UBoot的作用就是如此,全称是 Universal Boot Loader,uboot 是一个遵循 GPL 协议的开源软件。

按照面像的开发者,我们有三"种"UBoot:

种类 描述
官方的 uboot 代码 由 uboot 官方维护开发的 uboot 版本,版本更新快,基本包含所有常用的芯片。
半导体厂商的 uboot 代码 半导体厂商维护的一个 uboot,专门针对自家的芯片,在对自家芯片支持上要比 uboot 官方的好。
开发板厂商的 uboot 代码 开发板厂商在半导体厂商提供的 uboot 基础上加入了对自家开发板的支持。

我们学习的初步阶段,就是直接用开发板厂商的 uboot 代码,学透了,再尝试自己修改半导体厂商的 uboot 代码,我们很少碰官方的 uboot 代码,毕竟,除非自己对芯片非常理解,谁会自己踩一大堆有的没的坑?

我自己使用的是正点原子的板子,

复制代码
#!/bin/sh
# 上面这个是固定格式,可写可不写,写一定不出事
​
# ARCH=arm
# CROSS_COMPILE=arm-linux-gnueabihf-
# uboot的makefile似乎禁掉了这种方式传递ARCH和CROSS_COMPILE,所以只好:👇
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_ddr512_emmc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc)

我们直接执行这个脚本,注意,看清楚我们传递的变量直接需要中间存在一个空格,不理解Makefile的朋友我强烈推介先去看看《跟我一起学Makefile》这本书。

不管是用何种方式,总而言之,我们一上板子就会得到这个结果。

复制代码
U-Boot 2016.03 (Mar 06 2025 - 00:18:41 -0800)
​
CPU:   Freescale i.MX6ULL rev1.1 792 MHz (running at 396 MHz)
CPU:   Industrial temperature grade (-40C to 105C) at 48C
Reset cause: POR
Board: I.MX6U ALPHA|MINI
I2C:   ready
DRAM:  512 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
*** Warning - bad CRC, using default environment
​
In:    serial
Out:   serial
Err:   serial
switch to partitions #0, OK
mmc1(part 0) is current device
Net:   FEC1
Error: FEC1 address not set.
​
Normal Boot
Hit any key to stop autoboot:  0 
=>      

上述信息说了点东西,我们一行行看

  1. U-Boot版本:2016.03,编译时间为2025年3月6日。对的,就是今天笔者发布的时候编译的。

  2. CPU信息:Freescale i.MX6ULL rev1.1,运行频率为396 MHz(最大频率为792 MHz),属于工业级温度范围(-40°C 到 105°C),当前温度为48°C。其实i.MX6ULL之前是飞思卡尔的板子,后来飞思卡尔被NXP收购了

  3. 复位原因:POR(上电复位)。

  4. 板子信息:I.MX6U ALPHA|MINI。

  5. I2C:已准备好。

  6. DRAM:512 MiB。

  7. MMC:检测到两个SDHC控制器(FSL_SDHC: 0 和 FSL_SDHC: 1),当前使用的是mmc1的第0分区。

  8. 环境变量:CRC校验失败,使用默认环境变量。

  9. 串口:输入、输出和错误都使用串口。

  10. 网络:FEC1(以太网控制器)未设置MAC地址,导致错误。

  11. 自动启动:系统正在等待用户按键中断自动启动过程,如果没有按键,系统将在0秒后继续启动。

使用uboot的命令行完成点事情

复制代码
=> help
?       - alias for 'help'
base    - print or set address offset
bdinfo  - print Board Info structure
bmode   - sd1|sd2|qspi1|normal|usb|sata|ecspi1:0|ecspi1:1|ecspi1:2|ecspi1:3|esdhc1|esdhc2|esdhc3|esdhc4 [noreset]
boot    - boot default, i.e., run 'bootcmd'
bootd   - boot default, i.e., run 'bootcmd'
bootelf - Boot from an ELF image in memory
bootm   - boot application image from memory
bootp   - boot image via network using BOOTP/TFTP protocol
...

等等,具体查询一个指令,我们直接在help后面跟上指令就好了。

复制代码
=> help bootz
bootz - boot Linux zImage image from memory
​
Usage:
bootz [addr [initrd[:size]] [fdt]]
    - boot Linux zImage stored in memory
    The argument 'initrd' is optional and specifies the address
    of the initrd in memory. The optional argument ':size' allows
    specifying the size of RAW initrd.
    When booting a Linux kernel which requires a flat device-tree
    a third argument is required which is the address of the
    device-tree blob. To boot that kernel without an initrd image,
    use a '-' for the second argument. If you do not pass a third
    a bd_info struct will be passed instead

bdinfo, printenv和version

查询板子的信息等内容全靠这三个。

这些就是板子的具体硬件信息

复制代码
=> bdinfo
arch_number = 0x00000000
boot_params = 0x80000100
DRAM bank   = 0x00000000
-> start    = 0x80000000
-> size     = 0x20000000
eth0name    = FEC1
ethaddr     = (not set)
current eth = FEC1
ip_addr     = <NULL>
baudrate    = 115200 bps
TLB addr    = 0x9FFF0000
relocaddr   = 0x9FF55000
reloc off   = 0x18755000
irq_sp      = 0x9EF52EA0
sp start    = 0x9EF52E90
​

version用来查看uboot编译的具体信息

复制代码
U-Boot 2016.03 (Mar 06 2025 - 00:18:41 -0800)
arm-linux-gnueabihf-gcc (Linaro GCC 4.9-2017.01) 4.9.4
GNU ld (GNU Binutils for Ubuntu) 2.26.1

printenv也可以简单的写成print,我们后面查看环境信息使用的就是这个玩意。

环境变量

是的,uboot自身也有一个最小环境变量系统。我们使用setenv来设置环境变量,想要持久化就需要使用saveenv指令完成固化

复制代码
=> print bootdelay
bootdelay=1
=> setenv bootdelay 5
=> saveenv
Saving Environment to MMC...
Writing to MMC(1)... done

删除一个环境变量也是非常的简单,直接设置这个环境变量为空即可。

内存操作

md 命令用于显示内存值

复制代码
md[.b, .w, .l] address [# of objects] 

举个例子,我们想要看启动0x87800000启动地址处的后20个字节放置了怎样的二进制数据的时候,显然,一个:

复制代码
=> md.b 87800000 14
87800000: be 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5    ................
87800010: 14 f0 9f e5                                        ....

是0x14而不是14,因为uboot的操作数默认都是16位的。至于w和l,就是我们的长度单位,b是字节,w是字,l就是双字

nm 命令 用于修改指定地址的内存值,命令格式如下:

复制代码
nm [.b, .w, .l] address 

mm 命令 也是修改指定地址内存值的,使用 mm 修改内存值的时候地址会自增,而使用命 令 nm 的话地址不会自增。比如以.l 格式修改从地址 0x80000000 开始的连续3 个内存块(3*4=12 个字节)的数据为 0x12345678

复制代码
=> mm.l 80000000
80000000: ffffffff ? 12345678
80000004: ffffffff ? 12345678 
80000008: ffffffff ? 12345678
8000000c: ffffffff ? q

看看丁不丁真:

复制代码
=> md.b 80000000 c
80000000: 78 56 34 12 78 56 34 12 78 56 34 12                xV4.xV4.xV4.

命令mw 用于使用一个指定的数据填充一段内存,相比起来直接简化了mm指令。cp 是数据拷贝命令,用于将 DRAM 中的数据从一段内存拷贝到另一段内存中,或者把Nor Flash 中的数据拷贝到DRAM 中,cmp 是比较命令,用于比较两段内存的数据是否相等

相关推荐
智商偏低1 小时前
单片机之helloworld
单片机·嵌入式硬件
青牛科技-Allen2 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
白鱼不小白4 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D5 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术8 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt8 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘8 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
几个几个n11 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件
Despacito0o14 小时前
ESP32-s3摄像头驱动开发实战:从零搭建实时图像显示系统
人工智能·驱动开发·嵌入式硬件·音视频·嵌入式实时数据库
门思科技14 小时前
设计可靠 LoRaWAN 设备时需要考虑的关键能力
运维·服务器·网络·嵌入式硬件·物联网