TL;DR; press the reset button!
Quite a diversion from my day job with SQL and C# and web apps is this fascinating world of soft CPU's and embedded devices. Here's what I learned this weekend:
In my prior blogs, I considered getting Circuit Python running on the ULX3S. There are a lot of moving parts, so I got started with implementing the RISC-V soft CPU on the FPGA. Recall we cannot run Circuit Python on the ESP32 because of hardware limitations (missing USB OTG), however the ESP32-S2 will (in theory) work with Circuit Python. Next, I rambled on a bit regarding various features of LiteX that I was exploring in my prior blog, in the end creating a soft_cpu.sh script with everything I learned.
Refresher: Onboard the ULX3S is an ECP5 FPGA. We first need to create a soft CPU bitstream that is loaded onto the ECP5. LiteX also creates a BIOS that gets loaded over the serial port. Ok, all fine and dandy, but I seem to only be able to load that BIOS once and then the terminal becomes unresponsive. This makes sense, as the processor stays in the while loop after liftoff . The bios does not appears to be an RTOS.
ULX3S shown with FPGA/BIOS/firmware programming USB cable |
Supposedly that BIOS should be able to reload firmware apps. Well, there's this mystery boot_helper. What does this extern do? I suspect that's what loads the BIOS. Then what? There's this 4 line boot-helper-picorv32.S file. Not much help there. The "What is LiteX" introduction does seem to indicate that the development cycle includes reloading the soft CPU, as the "design flow in a nutshell " indicates going back to step 1. I'd like to go back to step 6, skipping the re-synthesis of the soft CPU every time I change the firmware.
The LiteX for the ULX3S has a serial port configured as Tx on Pin L4 (FTDI RxD) and Rx on Pin M1 (FTDI TxD). See the schematic . These pins are not available on either of the external ULX3S headers.
FTDI RxD/TxD USB Serial on ULX3S FPGA pins L4 and M1 |
So what else is there? Well, the BIOS is clearly not an RTOS. So we're definitely waiting forever and doing nothing in that
while (1)
statement. How else does a CPU begin again? Reset of course! Check out the rst implementation
in LiteX. It is hooked to R1 of the FPGA. What's that?R1 (aka BTN_F1) on the ULX3S |
It turns out the architecture is not [CPU] - [BIOS] - [firmware]. Instead, the simpler: [CPU (with tiny, baked in BIOS] - [BIOS (with external firmware)]. Now, one could certainly write something in the BIOS to, say load an OS. But that's not what LiteX is doing out of the box in this example.
The architecture naming is a bit misleading, as there is part of the CPU implemented as a BIOS as seen at processor boot time on the LiteX. Unfortunately the external "C" program is also called BIOS (firmware).
So just leave litex_term running and press the F1 (CPU reset) button to reload the BIOS firmware. See my soft_cpu.sh bash script. Each time you update and compile the BIOS code, press the F1 button to reload it onto the soft CPU.
I've created LiteX Pull Request #445 that adds some comments to hopefully help others that may encounter these issues.
How many times can an FPGA be reprogrammed? Well, the folks at Numato claim "SRAM based FPGAs can be programmed as many times as necessary. There is no limit... "
There's also the possibility of using a logic analyzer internally to the FPGA. Also mentioned in the What is LiteX is something called litescope. See the Debugging with ChipScope for more information, as there's not much in the Wiki as of the data of this blog. The architecture image provides some insight. See also the test_analyzer.py .
So now.. I wonder if I can single-step code soft CPU code with OpenOCD. And that litescope! That sounds super interesting...
Copyright (c) gojimmypi all rights reserved. Blogger Image Move Cleaned: 5/3/2021 1:35:54 PM