-
Notifications
You must be signed in to change notification settings - Fork 0
robertlipe/riscv7
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This is the (not-yet working) port of UNIXv7 system to RISC-V. It's currently targeting the GD32V as found on the Longnan Nano, a super-inexpensive ($5-ish) SBC that includes a full USB-C controller, including OTG. This makes it possible to appear as a mass storage device, a serial port, or other USB peripherals. This is more powerful than devices like the K210 or BL602 which require an external USB->Serial adapter that can support none of these. RISCv7 does not (yet) use any of this awesomeness. There are some remnanats in the code of me starting with the K210. That is a 64-bit part that has 8MB of RAM and 2 cores. While I may go back to that part some day (more RAM and protected mode would be nice) I learned early on that there were a lot of structures with implicit sizes that burst into flames with int > 32 bits. In the name of focus, I went down to a single part. An early design choice was to NOT design my own ABI and calling convention. Nor did I choose to torture myself with ancient Make. Relying on a sane GNU make on the host is fair game. It's easy to find riscv64-gcc in prepackaged binaries (Mac: Homebrew. Debian has a package) where 32-bit tools are harder to find. The tools support 32-bit modes so the convenience of calling riscv32-gcc over riscv64-gcc with -march=rv32imac -mabi=ilp32 to get 32-bit code isn't worth it[1]. The ABI is "whatever these tools do". Like the early UNIXes, binary compatibilty isn't a concern; I may change system call numbers or visible symbols pretty much at whim. Similarly, I've not fought a fierce battle to keep the code K&R. As this code is meant to be educational (it certainly has been for this author) more than historical purity, familiarity with ANSI function declarations, judicious use of declarations, va_arg, not relying on implicit int, the presence of 'void', the absence of 'register' and so on are all considered good taste. Indeed, especially with 64-bit being in sight, implicit int and such can lead to really screwy stack frames so we're just trying to head that off. I started development thinking I would write ALL the code myself and not rely on any namby-pamby vendor code. That quickly got old. In sys/n200 (another unfortunate naming choice) is code for the Nucleisys 200 core as used in the GD32V, the Gigadevice libraries for interfacing with SPI, DMA, and more, as well as some other third party libraries. There is evidence in this directory of several failed experiments with different abstractions. I've been happily using the SEGGER Mini EDU JTAG device. Using something like Openocd with an FTDI board is probably possible, but that's what I started with. The best way to build the kernel is to be in usr/sys/conf and run make. There is a convenience script named 'upload' which does the obvious thing, calling Jlink with the appropriate fiddly parameters. 'run_nano' does a build, uploads the kernel to the board, and starts a GDB server. For debugging, there are x/ and z/ subdirectories (bad, I know...) that have .gdbinits that offer convenience macros to reboot the kernel, reload it (via GDB), start the remote debugging, and automatically have breakpoints on panic and other places you hope to not be. These will probably need customized to a developer's system and style. Little attention has been given to user-space so far. I expect most of it will fall into place. crt0.S for these parts is straight-forward. I just need to work through things like the global for errno and the assembly code that sets it, the header tension between usr/include and usr/sys/h, and signal handlers that need to decode interrupted instructions so that the $PC can be set right. There is also the need for standardized kernel exception frames. Status & Known problems: Boot is working. Timer interrupts are working. The display is mostly working. It's too small to be really useful, but displaying interrupt ticks or enter/exit style prints can still be handy. The display is NOT hooked as a console device with ANSI escape sequences nor is it even hooked as a serial console. It's shoved into putchar() inside sc.c,. Memory management is a mess. The code I started from, Robert Nordier's 386 port of UNIXv7 has some hard coded page numbers in memory layout in the kernel. This has proven hard to undo. The code currently gets to the point where it trampolines the assembler code to start an exec() to load and run. Sometime the LCD doesn't wake properly. I think there's something missing in the reset sequence. As embarrassing/ridiculous as this sounds, building and running gd32vf103inator/examples/LonganNano will "fix" the display. Once it's run and whacked the LCD (DMA? SPI?) once, the LCD will literally run for days and across hundreds of load/run cycles. The chip has a hardware scroll, but I cannot make it scroll in the axis it needs to scroll. Horizontal scroll is not very useful in a UNIX console. One possible way to implement scrolling is to define a text frame buffer (maybe with 8-bit color like CGA or VGA) and fully redraw the screen on a scroll. I'm not sure if that's a good use of our memory budget. SD card support is working at a proof-of-concept level. I can open a DOS-formattted memory card and read files and directories from it. I've not implemented partition table support. With SD cards being so cheap, I'm not sure it makes sense. More importantly, I've not implemented any "real" UNIX-level disk support. Even being a serial device attached to SPI, SD is so crazy fast relative to the VAX disk that I'm not sure that just spin-waiting a DMA-driven interface isn't the way to go. Shimming the code in tf_card.c for disk_read() and disk_write() for synchronous reads and writes may be OK. There is no root filesystem created by the build process. The kernel is just injected into flash memory and executed. It works at a reasonable speed because flash is copied to SRAM on boot. SRAM is apparently cheaper than caches at this size. (!!) Segger's equivalent of ARM's Semihosting would probably be good to implement for debugging. [1] For more info on RISC-V embedded chains, see https://riscv.org/wp-content/uploads/2015/02/riscv-software-stack-tutorial-hpca2015.pdf https://github.com/riscv/riscv-gnu-toolchain
About
UNIXv7 ported to RISC-V, specifically the Longnan Nano SBC
Topics
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published