January 20, 2022

Orange Pi 4 (Rockchip 3399) "Really" bare metal coding

Up to this point I have been using U-Boot to load and launch my demos and have been calling that "bare metal" coding. However, we can take this to a much more primitive level by getting in the game ahead of U-Boot and figuring out how to get the bootrom to load our code.

This is different in many ways. Most hardware (such as the serial port) has not been initialized. DRAM has not been initialized. We don't have the handy ability of letting U-Boot use TFTP to load a binary file for us over the network. What we have to do is to package up our binary in a form that the bootrom will recognize then put it onto an SD card. This means that any experimentation involves taking cards in and out of the SD card socket and writing new images onto them using an SD card reader, connected to a USB port on my linux development system.

This diagram is someones view of the boot process. What we are doing is replacing what the diagram shows as "idbloader.img" with something of our own.

The diagram indicates that this needs to be at sector offset 0x40 (which is 64 decimal) and we put our image there via:
dd if=bare.img of=/dev/sdx seek=64 conv=notrunc
I will note in passing that the diagram above also indicates that the USB-OTG port can be used to send a boot image to the bootrom. I have not investiated the details of this, but it does require a host side program to communicate with the board.

The bootrom loads code into SRAM within the RK3399. There is 200K of this (some references say 192K). I have never had any temptations to push the limit, so the exact size is so far unimportant. Looking at existing code (namely the U-Boot TPL), the code loads to 0xff8c2000 and execution starts at 0xff8c2004. This is 0x2000 into the SRAM, skipping the first 8K bytes, which perhaps holds a stack.

I wrote a program called "mkrock" to generate the bootable image. This has a special header, which is rc4 encrypted using a well known rockchip key. I wrote this program after inspecting the mkimage program which ships with U-Boot. I could have simply used mkimage with the proper image, but I was interesting in learning all the details.

The first thing I tried to do was to blink the onboard LED. This worked the first time, but the blink rate was extremely slow (it stayed on for 45 seconds, then was off for 45 second). Adjusting a delay loop gave a 1 Hz blink rate. The next thing I tried was to do the usual "hello" experiment using the serial port, this worked once I realized that Uart 2 can appear in 3 different places and once I set up the IO mux properly for the proper set of pins, it all worked.

After this it was easy to copy my already tested and working printf function and write code to dump the bootrom locations, which was my goal in all of this anyway.


Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org