i got this funny thing in the mail about a month ago and i had one plan for it. port my extremely
basic "operating system" AlpacOS to it (which i will hopefully write another post about). i initially
wrote it in x86 but i quickly realised i wanted to port it to risc-v after seeing this thing online.
porting virtual memory and interrupts would be a hurdle but i thought i would start with the display.
my thought is that if i have any kind of output, debugging would be easier and i could have something
cool to show off. considering it came with a microsd card that booted it into linux already, i thought
i could wrestle the display driver into my own code through some esoteric means.
boy was i wrong
one pixel was all i needed to work up the rest of a rudimentary display system. hell, even the backlight didn't need to work for me to be sated. no matter how slow, placing one pixel at a time could construct something meaningful on the screen. i had used the grub framebuffer when working on alpacos in a virtual setting (qemu), so i thought that this could be similar.
this is the brain of the uconsole. there are others but this one is the only risc-v core
available. (source)
the big square in the middle is the allwinner d1, my partner in crime for the last month.
to be honest, i didn't have a real path to that one pixel at this point so i kinda just messed around
with what i had. the uconsole came with a microsd card that booted into linux though, so i had something
to start with. this website has been a crucial resource this whole time. they host a mirror of the allwinner sdk (which i tried to get access to, but the whole website was in chinese) and
link to the user manual
at some point i might try to write a bootloader, but not for a board with as little
documentation as this one. i tried editing the bootloader initial commands (uEnv.txt), but that
didn't work for me. i also tried replacing the linux kernel with my own kernel, but that didn't
work either (even through uart). at this point, i knew their bundled version of linux would boot
but i wanted to pin down what i could change in the actual bootloader so i could boot my own
code. the boot loader build process was fraught, but it allowed me to do a couple of things i
otherwise wouldn't have (more on that later). as of the time this post was written (2024-10-12)
this official tutorial from Clockwork for the DevTerm (a similar device) does *not* work but i found... a multipart workaround.
this image from the fedora wiki gives a great rundown of what the build process is like. I focused
on just the bootloader part (pre-GRUB)
(source)
when building the OpenSBI repo, i hit this error: which i fixed by adding "_zifencei" to a line in the Makefile (found out where to do this because
of this insightful series from sifive):
MMC Controller Host Support" is under "Device Drivers" in the menu config (also make sure your actual
terminal is large enough to run menuconfig)
when building u-boot i ran into a few issues, the first one was this version error: which i had to remove a line in u-boot/scripts/dtc/pylibfdt/Makefile to make sure the version numbers
were compatible
the second one was this error:
which i fixed by adding "_zifencei_zicsr" to a line in u-boot/arch/riscv/Makefile:
at this point, i had a machine that would... start up and not do anything. the main trick
though, was that if i gave this bootloader the same boot commands and linux kernel as the
included sd card, it would boot! successfully! which was crazy to me. it meant my bootloader was
actually running the code i had intended it to and that maybe a pixel was not too far away.
so after many hours of trial and error, trying to get anything out of the screen with my own
code, i tried another route. there are some exposed UART pins inside the uconsole that are...
not the easiest to get to
they are pins GPIO 32 (TX) and GPIO 33 (RX)
(source)
i used a uart -> usb adapter and initially read the boot log just by touching a wire to the TX pin
on the mini pcie port. i got lots of helpful data out of this (raw data) and finally understood what was going on inside the device even though the screen was totally
dark.
now i wanted to finally run my own code on this thing. i took advantage of the fact that the
uart port was already set up from the bootloader. the source code is here - it just prints "hello world" to the serial port, which is enough for me to know that i can run
my own code. i compiled it and placed it in the boot partition of the sd card, then changed my
u-boot default boot command. i used the load and go commands. it's under Boot options > bootcmd value edit that setting to load mmc 0:1 43000000 hello_world.bin; go 43000000;
that gave me this
(although i don't know why the executable is so large)
after the test run i decided to get a little more serious about the serial port. when booting
up, u-boot has an option to interrupt the boot process and interact with a shell. i thought this
would be pretty useful because i could figure out in real time what my computer had access to
and i could read what was actually going on in memory. however now i needed to write to the
port, not just read from it, and touching two wires in there while typing on my keyboard was
kinda unworkable. so i picked up my soldering iron and hit up amazon to get an mpcie extender...
BEHOLD
THIS BEAUTIFUL CREATION is my serial communicator.
weep your tears of ecstacy
the .dts files in the patch provided by clockwork have settings & all of the memory locations for hardware access. those are passed in to u-boot & the linux kernel to find hardware locations for drivers. many of my hours have been spent crawling through these files & i kinda find them fascinating. this website was helpful for understanding what they are.
now that i had a shell with u-boot, i could start interacting with the computer a little bit
more. i saw this entry in the device tree from that patch and got interested...
this is from the clockwork r01 patch, in the device tree file. there is a gpio pin referenced there,
PD20, which i could fortunately control with u-boot. i typed in gpio set PD20
and like
magic, the backlight turned on. this was the closest i got lol. i tried the gpio pin referenced in
the lcd section (PD19) but idk what i really expected to happen.
i couldn't get anywhere with the linux drivers, nor the drivers in u-boot, so i was kind of stuck. my last hope was to make my own driver but... the lcd screen uses a protocol called MIPI DSI to communicate with the cpu. MIPI stands for "Mobile Industry Processor Interface", a closed-source standard ;-;. I couldn't really figure out what to do at this point. I found a MIPI driver in U-Boot, as well as the patch for the linux kernel from here, but I couldn't extract enough meaningful information to make my own driver and any edits to the device tree were not hooking into the u-boot MIPI driver.
tried to actually write that driver for u-boot, got something that at least showed up in the
device tree (dm tree
in uboot) but no actual communication. i don't really know what
i need a gpio pin for and what i don't. there is also something in the d1 called the "Display Engine"
that i see tossed around a lot, but i don't think the driver in u boot interfaces with most of that.
trying to figure out if the DSI ports are a subset of that (the user guide says so? but doesn't give
any info), but there isn't a clean way for me to test stuff outside of just compiling the driver
code by itself and running that because my microsd card reader isn't working.
been discussing with someone on the clockwork forums about this, link here
huge props to ylyamin on the clockwork forums!