Using U-boot to boot kernel8.img
ptrk8 opened this issue · 2 comments
I've been trying to use U-boot to boot some of the images in these tutorials. The process I've employed involves:
- Interrupting U-boot.
- Loading
kernel8.img
to0x80000
. In my case, I do this withtftp 0x80000 <path to kernel8.img>
since I have a TFTP server already set up for loading images. - Running the
kernel8.img
binary with thego 0x80000
U-boot command.
In your experience, is this all that is theoretically required to run your kernel images with U-boot or have a missed something? I ask because I tried these steps with your writesector
tutorial and got garbled mess as serial output after running the image as shown below.
...
U-Boot> tftp 0x80000 rpi3bp/kernel8.img
lan78xx_eth Waiting for PHY auto negotiation to complete....... done
Using lan78xx_eth device
TFTP from server 192.168.0.198; our IP address is 192.168.0.111
Filename 'rpi3bp/kernel8.img'.
Load address: 0x80000
Loading: ################################################## 6.6 KiB
603.5 KiB/s
done
Bytes transferred = 6808 (1a98 hex)
U-Boot> go 0x80000
## Starting application at 0x000080000 ...
�ogK��R��rK
I've already confirmed that the kernel image runs fine when using the existing Rpi bootloader without U-boot. I'm trying to use U-boot to boot your kernel images so that I can use my TFTP server to load images over the network. Any advice in this regard would be most appreciated!
In your experience, is this all that is theoretically required to run your kernel images with U-boot or have a missed something?
I'm sorry, I can't help, I've never used U-Boot, I don't know it (took a quick glance at its source and list of unresolved issues and decided to be way too bloated and way too buggy for my taste).
I've already confirmed that the kernel image runs fine when using the existing Rpi bootloader without U-boot.
Yep, one of the reasons why I don't like having a bloated middleware: you'll never know what it messes up.
Loading kernel8.img to 0x80000. In my case, I do this with tftp 0x80000 since I have a TFTP server already set up for loading images.
If your intend is purely to load the kernel from your host machine, then you can take a look at the 14_raspbootin64 tutorial. Granted, it does not use network, just the serial cable, but it gets the job done.
Cheers,
bzt
So I did some investigating and I believe I understand some of the issues and I think you might be interested in the reason?
The first problem I encountered was that once the binary was launched by U-boot, I was getting the following garbled output:
## Starting application at 0x000080000 ...
�ogK��R��rK
The reason is because by default, U-boot uses UART1
on the Raspberry Pi 3B+ for serial output and UART0
for Bluetooth as shown by U-Boot’s Device Tree nodes for UART0
and UART1
below:
/* uart0 communicates with the BT module */
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32 &gpclk2_gpio43>;
status = "okay";
bluetooth {
compatible = "brcm,bcm43438-bt";
max-speed = <2000000>;
shutdown-gpios = <&expgpio 0 GPIO_ACTIVE_HIGH>;
};
};
/* uart1 is mapped to the pin header */
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_gpio14>;
status = "okay";
};
By modifying the following registers in uart.c so that registers for UART0
are used instead, I was able to get the correct serial output when booting the binary from U-boot!
#define UART0_DR ((volatile unsigned int*)(MMIO_BASE+0x00201000))
#define UART0_FR ((volatile unsigned int*)(MMIO_BASE+0x00201018))
#define UART0_IBRD ((volatile unsigned int*)(MMIO_BASE+0x00201024))
#define UART0_FBRD ((volatile unsigned int*)(MMIO_BASE+0x00201028))
#define UART0_LCRH ((volatile unsigned int*)(MMIO_BASE+0x0020102C))
#define UART0_CR ((volatile unsigned int*)(MMIO_BASE+0x00201030))
#define UART0_IMSC ((volatile unsigned int*)(MMIO_BASE+0x00201038))
#define UART0_ICR ((volatile unsigned int*)(MMIO_BASE+0x00201044))
However, this begs the question, even if U-boot uses gpio14
for UART1
in their device tree (shown above), your UART initialisation code in uart_init() seemingly tries to enable pins 14 and 15 for UART0
as shown below:
...
/* map UART0 to GPIO pins */
r=*GPFSEL1;
r&=~((7<<12)|(7<<15)); // gpio14, gpio15
r|=(4<<12)|(4<<15); // alt0
*GPFSEL1 = r;
*GPPUD = 0; // enable pins 14 and 15
wait_cycles(150);
*GPPUDCLK0 = (1<<14)|(1<<15);
wait_cycles(150);
*GPPUDCLK0 = 0; // flush GPIO setup
*UART0_ICR = 0x7FF; // clear interrupts
*UART0_IBRD = 2; // 115200 baud
*UART0_FBRD = 0xB;
*UART0_LCRH = 0x7<<4; // 8n1, enable FIFOs
*UART0_CR = 0x301; // enable Tx, Rx, UART
...
Is the above initialisation snippet supposed to work regardless of how the hardware has been configured by the bootloader? If so, I’d love to get to the bottom of why this isn't the case.
After getting the serial output to work by using UART1
as opposed to UART0
(a temporary workaround), I faced another issue with the SD Card driver with a similar root cause.
When using U-Boot to boot the binary, this SD Card driver would consistently get stuck at the following point:
EMMC: GPIO set up
EMMC: reset OK
sd_clk divisor 00000068, shift 00000006
EMMC: Sending command 00000000 arg 00000000
EMMC: Sending command 08020000 arg 000001AA
ERROR: failed to send EMMC command
After trying a bunch of other fixes (such as doing a Soft Reset of the Arasan SDHCI controller), I looked into U-Boot’s Device Tree again and saw that by default, U-Boot uses the Arasan SDHCI controller for WiFi and the (custom) SDHOST controller for SD cards.
/* SDHCI is used to control the SDIO for wireless */
&sdhci {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&emmc_gpio34>;
status = "okay";
bus-width = <4>;
non-removable;
mmc-pwrseq = <&wifi_pwrseq>;
brcmf: wifi@1 {
reg = <1>;
compatible = "brcm,bcm4329-fmac";
};
};
/* SDHOST is used to drive the SD card */
&sdhost {
pinctrl-names = "default";
pinctrl-0 = <&sdhost_gpio48>;
status = "okay";
bus-width = <4>;
};
However, since the hardware has been configured by U-Boot in the above manner, this seems to conflict with this tutorial’s SD Card driver that uses the Arasan SDHCI driver to interact with the SD Card.
The workaround to get this tutorial’s SD card driver running properly when booted via U-Boot was to change the pinctrl
attribute of the &sdhci
Device Tree node from <&emmc_gpio34>
to <&sdhost_gpio48>
as shown below:
/* SDHCI is used to control the SDIO for wireless */
&sdhci {
...
pinctrl-0 = <&sdhost_gpio48>;
...
};
Then I had to recompile U-Boot with this Device Tree change and use the new U-Boot bootloader binary to launch this tutorial’s binary.
However, again I’m slightly perplexed as to why the side-effects from U-Boot’s hardware choices/configurations are affecting our ability to set up the hardware how we like.
For example again in sd_init()
here, I see there is initialisation code to configure the right pins for the SDHCI controller that should theoretically override U-Boot’s preferences as shown below:
// GPIO_CD
r=*GPFSEL4; r&=~(7<<(7*3)); *GPFSEL4=r;
*GPPUD=2; wait_cycles(150); *GPPUDCLK1=(1<<15); wait_cycles(150); *GPPUD=0; *GPPUDCLK1=0;
r=*GPHEN1; r|=1<<15; *GPHEN1=r;
// GPIO_CLK, GPIO_CMD
r=*GPFSEL4; r|=(7<<(8*3))|(7<<(9*3)); *GPFSEL4=r;
*GPPUD=2; wait_cycles(150); *GPPUDCLK1=(1<<16)|(1<<17); wait_cycles(150); *GPPUD=0; *GPPUDCLK1=0;
// GPIO_DAT0, GPIO_DAT1, GPIO_DAT2, GPIO_DAT3
r=*GPFSEL5; r|=(7<<(0*3)) | (7<<(1*3)) | (7<<(2*3)) | (7<<(3*3)); *GPFSEL5=r;
*GPPUD=2; wait_cycles(150);
*GPPUDCLK1=(1<<18) | (1<<19) | (1<<20) | (1<<21);
wait_cycles(150); *GPPUD=0; *GPPUDCLK1=0;
However, this doesn’t seem to be the case… Do you have an idea as to why?