# lichee-pi_u-boot **Repository Path**: qrtman/u-boot ## Basic Information - **Project Name**: lichee-pi_u-boot - **Description**: "Das U-Boot" Source Tree - **Primary Language**: C - **License**: Not specified - **Default Branch**: test_dev - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2024-10-07 - **Last Updated**: 2024-10-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ``` 1. 默认用户 root 默认密码 licheepi 2. 安装vim :sudo apt-get install vim 3. 若vim不支持系统的复制粘贴运行: sudo apt-get install vim-gnome 4. 在 ~/.zshrc或~/.bashrc 最后加入路径环境变量 :export PATH="$HOME/design/linux/licheepi/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi/bin:$PATH" 5. 安装 sunxi-tools:make && sudo make install,如果出现:fel_lib.c:26:20: fatal error: libusb.h: No such file or directory,那需要安装libusb:sudo apt-get install libusb-1.0-0-dev 6. 进入uboot目录基于nano-v2018.01 tag,git checkout -b test_dev 添加一个新的分支用于测试 7. uboot 目录结构: . ├── api //封装一些平台无关的操作,如字符串打印,显示,网络,内存 ├── arch //以平台架构区分 │ ├──arm │ │ └──cpu │ │ │ └──arm926ejs │ │ │ │ └──sunxi //cpu相关的一些操作,如定时器读取 │ │ │ │ │ └──u-boot-spl.lds //spl的放置方法 │ │ └──dts │ │ │ └──suniv-f1c100s-licheepi-nano.dts // f1c100s芯片的一些配置 │ │ │ └──suniv-f1c100s-licheepi-nano.dtb │ │ │ └──suniv-f1c100s.dtsi │ │ │ └──suniv.dtsi │ │ └──lib //一些库文件 │ │ └──mach-sunxi │ │ │ └──board.c //board_init_f │ │ │ └──dram_sun4i.c //ddr的操作,复位,时钟,延时,odt,etc. │ │ │ └──dram_helpers.c //ddr的设置及读写测试 ├── board │ ├──sunxi │ │ └──board.c //sunxi_board_init 入口 │ │ └──dram_suniv.c //DRAM的一些默认参数 ├── cmd //Uboot命令行的一些命令 ├── common //含spl ├── configs //menuconfig里的默认配置,比如各类驱动适配 │ ├── licheepi_nano_defconfig │ ├── licheepi_nano_spiflash_defconfig ├── disk //硬盘分区的驱动 ├── doc ├── drivers //外设驱动 ├── dts ├── examples ├── fs //多种文件系统 ├── include │ ├──configs │ │ └──sunxi_common.h //预配置的参数,如串口号等 │ │ └──suniv.h ├── lib //加密压缩等算法 ├── net //nfs,tftp等网络协议 ├── post ├── scripts 8. 编译uboot : 变量及参数配置: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- licheepi_nano_spiflash_defconfig # 若不带spi-flash的板子,请换成 licheepi_nano_defconfig # 进行可视化配置 make ARCH=arm menuconfig 编译: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8 9. 出现 unable to execute 'swig': No such file or directory 错误 安装 sudo apt-get install swig 10. 若flash中已有 uboot 可使用如下三命令从uboot擦除:sf probe 0;sf erase 0 0x100000;reset,之后采用 sudo sunxi-fel ver 命令查询是否进入fel模式。 11. 重新烧写到RAM:sudo sunxi-fel uboot ./u-boot-sunxi-with-spl.bin 12. 重新烧写到Flash: sudo sunxi-fel -p spiflash-write 0 ./u-boot-sunxi-with-spl.bin 13. GPIO驱动:以驱动PE12为例 1. 确认 CONFIG_DM=y,CONFIG_DM_GPIO=y 2. arch/arm/dts/suniv.dtsi 在pio中加入以下内容(实际上不要也可以): lcd_black_light_pwm: lcd_black_light_pwm_pe { pins = "PE12"; function = "pwm0"; }; 3. drivers/gpio/sunxi_gpio.c 在 sunxi_gpio_ids 数组中添加: ID("allwinner,suniv-pinctrl", a_all), 4. 编译,下载 在uboot shell中输入 gpio s pe12 将其输出为 1 , gpio c pe12 将其输出为 0 14. SPI驱动:以SPI1为例: 1. arch/arm/dts/suniv.dtsi 在pio中加入以下内容: spi1_pins_a: spi1-pins-pa { pins = "PA0", "PA1", "PA2", "PA3";//CS,MOSI,CLK,MISO //编写并无固定顺 function = "spi1"; }; 2. 在soc中添加: spi1: spi@1c06000 { compatible = "allwinner,suniv-spi", "allwinner,sun8i-h3-spi"; reg = <0x01c06000 0x1000>; interrupts = <11>; clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_BUS_SPI1>; clock-names = "ahb", "mod"; resets = <&ccu RST_BUS_SPI1>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; }; 3. 在 arch/arm/dts/suniv-f1c100s-licheepi-nano.dts 中添加: &spi1 { pinctrl-names = "default"; pinctrl-0 = <&spi1_pins_a>; status = "okay"; }; 在 aliases 中添加 : spi1 = &spi1; 15. 支持 SPI LCD : 1. 添加文件 drivers/video/sunxi/sunxi_spi_lcd.c 2. drivers/video/sunxi/makefile 中添加 obj-$(CONFIG_LCD_SPI) += sunxi_spi_lcd.o 3. configs/licheepi_nano_spiflash_defconfig 中添加 CONFIG_SUN6I_SPI=y 或 make menuconfig 中选中: Device Drivers ---> SPI Support ---> [*] Enable Driver Model for SPI drivers [*] Allwinner (sun6i+) SPI driver 在 arch/arm/mach-sunxi/kconfig 620 行 config VIDEO_SUNXI 之前 添加: config LCD_SPI bool "Enable Use SPI LCD on SPI bus" select LCD ---help--- enable SPI LCD on SPI. config LCD_HWSPI bool "LCD spi bus use hardware" depends on LCD_SPI default y config LCD_HWSPIX string "LCD hw spi bus" depends on LCD_HWSPI default "spi1" config LCD_CS string "LCD soft spi bus cs pin" depends on (LCD_SPI && !LCD_HWSPI) default "pa0" config LCD_MOSI string "LCD soft spi bus mosi pin" depends on (LCD_SPI && !LCD_HWSPI) default "pa1" config LCD_CLK string "LCD soft spi bus clk pin" depends on (LCD_SPI && !LCD_HWSPI) default "pa2" config LCD_MISO string "LCD soft spi bus miso pin" depends on (LCD_SPI && !LCD_HWSPI) default "pa3" config LCD_DC string "LCD panel backlight dc pin" depends on LCD_SPI default "pe2" config LCD_BL_PWM string "LCD panel backlight pwm pin" depends on LCD_SPI default "pe12" 4. 在 arch/arm/mach-sunxi/clock.c 的 clock_init() 函数中添加: //#if defined(CONFIG_SUN6I_SPI) || defined(CONFIG_LCD_HWSPI) // clock_init_spi(); //#endif 废弃 5. 在 arch/arm/mach-sunxi/clock_sun6i.c 中添加时钟配置: //void clock_init_spi(void) //{ // #if CONFIG_CONS_INDEX < 5 // struct sunxi_ccm_reg *const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; /* Deassert SPI1 reset on SUN6I */ // if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I)) // { // setbits_le32(&ccm->ahb_reset0_cfg, (1 << 21)); /* Open the SPI1 gate */ // setbits_le32(&ccm->ahb_gate0, (1 << 21)); /* Divide by 4 */ // writel(0x1001, (SUNXI_SPI1_BASE + 0x24)); /* 24MHz from OSC24M */ // writel((1 << 31), &ccm->spi1_clk_cfg); /* Enable SPI in the master mode and do a soft reset */ // setbits_le32((SUNXI_SPI1_BASE + 0x04), 0x80000003); /* Wait for completion */ // while (readl(SUNXI_SPI1_BASE + 0x04) & 0x80000000); // } // #endif //} 废弃 6. 在 arch/arm/include/asm/arch-sunxi/clock.h 中添加: //void clock_init_spi(void); 废弃 7. 在 drivers/spi/sun6i_spi.c 的 static int sunxi_spi_probe(struct udevice *dev) 中添加 GPIO 复用: if (IS_ENABLED(CONFIG_MACH_SUNIV)) { if(dev->seq == 1) pin_func = SUNIV_GPA_SPI1; else pin_func = SUNIV_GPC_SPI0; } 的 static int sunxi_spi_set_mode(struct udevice *bus, unsigned int mode) 中添加 模式设置: struct sunxi_spi_platdata *plat = dev_get_platdata(bus); struct sunxi_spi_reg *spi = (struct sunxi_spi_reg *)plat->base; #ifdef CONFIG_MACH_SUNIV clrsetbits_le32(&spi->TCR,0x03,mode&0x03); #endif 的 static int sunxi_spi_set_speed(struct udevice *bus, unsigned int hz) 中改写: setbits_le32(&ccm->ahb_reset0_cfg, 1 << (AHB_RESET_OFFSET_SPI0 + bus->seq)); --------------------------------------------------------------------- setbits_le32(&ccm->ahb_gate0, 1 << (AHB_GATE_OFFSET_SPI0 + bus->seq)); --------------------------------------------------------------------- if (target_freq < 24000000) { writel(BIT(31) | max(24000000 / target_freq - 1, 0xf), &ccm->spi0_clk_cfg + bus->seq * 4); hz_ahb = 24000000 / ((readl(&ccm->spi0_clk_cfg + bus->seq * 4) & 0xf) + 1); } else { writel(BIT(31) | (0x01 << 24) | max(600000000 / target_freq - 1, 0xf), &ccm->spi0_clk_cfg + bus->seq * 4); hz_ahb = 600000000 / ((readl(&ccm->spi0_clk_cfg + bus->seq * 4) & 0xf) + 1); } --------------------------------------------------------------------- setbits_le32(&ccm->ahb_gate0, 1 << (AHB_GATE_OFFSET_SPI0 + bus->seq)); 8. 在 arch/arm/include/asm/arch_sunxi/gpio.h 中添加 GPIO 复用: #define SUNIV_GPA_SPI1 6 9. 在 driver/video/sunxi 中添加 sunxi_spi_lcd.c 文件代码 16. 添加 LCD 驱动: 1. 在 arch/arm/dts/suniv-f1c100s-licheepi-nano.dts 的 &spi1 中添加: spilcd@0 { compatible = "my,spilcd"; reg = <0>; status = "okay"; spi-max-frequency = <50000000>; buswidth = <8>; dc-gpios = <&pio 4 12 GPIO_ACTIVE_HIGH>; bl-gpios = <&pio 4 2 GPIO_ACTIVE_HIGH>; fps = <30>; rotate = <0>; }; 2. make ARCH=arm menuconfig 按如下步骤设置: ARM architecture ---> [*] Enable Use SPI LCD on SPI bus [*] LCD spi bus use hardware (spi1) LCD hw spi bus (pe2) LCD panel backlight dc pin (pe12) LCD panel backlight pwm pin 3. include/configs/sunxi.h 添加: #define LCD_BPP LCD_COLOR16 4. driver/video/sunxi/sunxi_spi_lcd.c 中添加: vidinfo_t panel_info = { .vl_col = 320, .vl_row = 240, .vl_bpix = LCD_BPP, }; void lcd_ctrl_init(void *lcdbase) { spi_lcd_init(); lcd_set_flush_dcache(1); } void lcd_enable(void) { spi_lcd_display_on(); } void lcd_flush(unsigned long start,unsigned long stop) { spi_lcd_flush(0,0,320,240,(uint16_t*)start); } 5. include/lcd.h 中加入: #ifdef CONFIG_LCD_SPI void lcd_flush(unsigned long start,unsigned long stop); #endif 6. common/lcd.c 中加入: void lcd_sync(void) { /* * flush_dcache_range() is declared in common.h but it seems that some * architectures do not actually implement it. Is there a way to find * out whether it exists? For now, ARM is safe. */ #if defined(CONFIG_ARM) && !defined(CONFIG_SYS_DCACHE_OFF) int line_length; if (lcd_flush_dcache) #ifndef CONFIG_LCD_SPI flush_dcache_range((ulong)lcd_base, (ulong)(lcd_base + lcd_get_size(&line_length))); #else lcd_flush((ulong)lcd_base,(ulong)(lcd_base + lcd_get_size(&line_length))); #endif #endif } 7. include/configs/sunxi-common.h 中添加: #elif defined(CONFIG_LCD) #define CONSOLE_STDOUT_SETTINGS \ "stdout=serial,lcd\0" \ "stderr=serial,lcd\0" 8. 17. PWM驱动: 1. arch/arm/dts/suniv.dtsi 中添加: pwm: pwm@1c21000 { compatible = "allwinner,suniv-pwm","allwinner,sun7i-a20-pwm"; reg = <0x01c21000 0x0c>; clocks = <&osc24M>; #pwm-cells = <3>; status = "disabled"; }; 2. 在pio中加入以下内容: pwm0_pins: pwm0_pins-pe { pins = "PE12"; function = "pwm0"; }; pwm1_pins: pwm1_pins-pe { pins = "PE6"; function = "pwm1"; }; 3. 在 arch/arm/dts/suniv-f1c100s-licheepi-nano.dts 中添加: &pwm { pinctrl-names = "default"; pinctrl-0 = <&pwm0_pins>,<&pwm1_pins>; status = "okay"; }; 18. 杂项修改 1. 启动始模块信息: U-Boot 信息在 include/version.h 中是一系列宏定义 CPU 信息在 arch/arm/mach-sunxi/cpu_info.c 中 Model 信息在 common/board_info.c 和 arch/arm/dts/suniv-f1c100s-licheepi-nano.dts ->"model" 中 DRAM 信息在 board/sunxi/board.c:566 中 MMC 信息在 common/board_r.c:427 和 drivers/mmc/sunxi_mmc.c:487 中 SF 信息在 drivers/mtd/spi/spi_flash.c:1138 中 In 信息在 common/console.c:751 中 Out 信息在 common/console.c:751 中 Err 信息在 common/console.c:751 中 => 每一行的开头 在 .config 中的 CONFIG_SYS_PROMPT 定义 2. 在include/common.h中可以打开调试开关,若无可添加如下: #define DEBUG #ifdef DEBUG #define _DEBUG 1 #else #define _DEBUG 0 #endif 19. U_BOOT_CMD 宏中各参数意义依次是 :命令名字、最多参数数、返回值、执行函数、功能解释、帮助。 20. 启动流程 1. arch/arm/cpu/arm926ejs/start.S 2. arch/arm/cpu/arm926ejs/sunxi/lowlevel_init.S 3. arch/arm/lib/crt0.S //_main() 4. arch/arm/mach-sunxi/board.c //s_init() -> board_init_f() 5. common/board_f.c //board_init_f() 6. common/board_r.c //board_init_r() 7. common/main.c //main_loop() 21. licheepi_nano_spiflash_defconfig 内容添加: CONFIG_SYS_PROMPT="U-Boot$ " CONFIG_LCD_SPI=y CONFIG_LCD_HWSPI=y CONFIG_LCD_HWSPIX="spi1" CONFIG_LCD_DC="pe2" CONFIG_LCD_BL_PWM="pe12" CONFIG_USE_BOOTCOMMAND=y CONFIG_BOOTCOMMAND="sf probe 0:0 50000000; sf read 0x80C00000 0x100000 0x4000; sf read 0x80008000 0x110000 0x400000; bootz 0x80008000 - 0x80C00000" CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 panic=5 rootwait root=/dev/mtdblock3 rw rootfstype=jffs2" 也可以将以上内容添加至 include/configs/suniv.h中,如: #define CONFIG_BOOTCOMMAND "sf probe 0:50000000; " \ "sf read 0x80C00000 0x100000 0x4000; " \ "sf read 0x80008000 0x110000 0x400000; " \ "bootz 0x80008000 - 0x80C00000" 22. 如果要成功引导linux内核,还需要一下操作: a. make ARCH=arm menuconfig 勾选 [*] Enable boot arguments; 在下方一项中填入 bootargs 参数: console=tty0 console=ttyS0,115200 panic=5 rootwait root=/dev/mtdblock3 rw rootfstype=jffs2 内核启动出现 “Waiting for root device /dev/mtdblock3...” 需要改为如下: console=tty0 console=ttyS0,115200 panic=5 rootwait root=31:3 rw rootfstype=jffs2 #(root=/dev/mtdblock3 指的是mtd设备第三分区,分区指定在dts中声明) b. dts 修改: 修改内核源码目录下的 ./arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts &spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi0_pins_a>; status = "okay"; spi-max-frequency = <50000000>; flash: w25q128@0 { #address-cells = <1>; #size-cells = <1>; compatible = "winbond,w25q128", "jedec,spi-nor"; reg = <0>; spi-max-frequency = <50000000>; partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; partition@0 { label = "u-boot"; reg = <0x000000 0x100000>; read-only; }; partition@100000 { label = "dtb"; reg = <0x100000 0x10000>; read-only; }; partition@110000 { label = "kernel"; reg = <0x110000 0x400000>; read-only; }; partition@510000 { label = "rootfs"; reg = <0x510000 0xAF0000>; }; }; }; }; 此处在dts中为mtd设备预先划分好了分区内容,内核将会自动解析 另一种通过bootargs传递给内核进行解析分区信息的方法,include/configs/suniv.h中添加: #define CONFIG_BOOTARGS "console=ttyS0,115200 earlyprintk panic=5 rootwait " \ "mtdparts=flash: w25q128@0:1M(uboot)ro,64k(dtb)ro,4M(kernel)ro,-(rootfs) root=31:03 rw rootfstype=jffs2" 23. 将生成的 u-boot-sunxi-with-spl.bin 复制到 Nano_pub_spilcd/uboot/spi_lcd 并更名为 u-boot-spi-flash.bin ```