Risc-V Bare Metal C Hello World!
ฝัง
- เผยแพร่เมื่อ 5 ก.ย. 2024
- I walk through creating a bare-metal hello world C program for the Risc-V architecture and test it using QEMU.
My prior assembly language video that I referred to in this video is here: • Risc-V Bare Metal Asse...
My github repo with source code: github.com/chu...
Inspiration for this was derived from the excellent blog by Tyler Wilcock at: twilco.github....
If you want to know everything about linker script development, try: mcyoung.xyz/20...
The TI datasheet I referenced is at: www.ti.com/lit...
One note that I did not mention in the video...some might say why I did not use the ENTRY(_start) clause in the linker. Because it would make no difference in this case. ENTRY just writes to the elf header. Because there is not boot loader, the entry point in the header does not matter. The only thing that matters is the order of the code sections. And because I placed the hello.o before start.o in the linker, unless the KEEP directive is used, listing order will govern.
As a person learning c and microcontrollers, this was very informative. The way you organized the lecture also made it easy to follow. I now understand a little better how a computer boots and runs the main function.
Thanks for the kind words.
Awesome. Nice work spreading knowledge ❤
Thanks for the kind words.
this is simply awesome
Thanks!
2 questions:
Is that linker file stuff working the same way if using clang instead of gcc?
Also, will you show how it is done with Rust and Zig in future videos?
Bonus question :)
in riscv assembler with gcc is it mov , or mov , ?
Since GCC for x86 keeps insisting to use that AT&T notation or however it is called...
Bonus remark:
It has been a few decades since I did UART16550 programming. But the way your uart_putchar() function is written, you do not really use the FIFO. There is a way to check if the FIFO can still hold one more character. You, in turn check if the FIFO is empty.
Since the GNU linker is used by both, the syntax should port no problem. What the compilers emit may differ, however, plus the platform matters too, and so I suspect that's why a generalized linker script is so freakin' complicated. Running `riscv64-unknown-elf-ld --verbose` is educational.
Re other languages, I am working on Python right now. Thinking about Go. I actually ported a version of Java to run bare metal on rPi years ago. I thought about revisiting that project for Risc-V. I've never used Rust or Zig. But sure, why not?
Funny enough, there is no mov instruction for Risc-V. There is a mv psuedo instruction, `mv rd, rs`, which translates to `addi rd, rs, 0`, with the destination register being first. I find the green sheets helpful, for example: www.cs.sfu.ca/~ashriram/Courses/CS295/assets/notebooks/RISCV/RISCV_GREEN_CARD.pdf
The FIFO is actually used, it's just never filled. THRE clears before the shift register finishes munching on its data. I wanted to show a technique that would prevent data from being dropped, not optimize throughput. But your point is valid. I was not clear in the video.
Great questions. Thanks!
LLVM’s lld is a drop in replacement for GNU ld, so it should be identical. Rust and Zig are using LLVM so again, same scripts. (Zig wants to get rid of LLVM)
There is also mold which is also a drop-in replacement. So you can use the same script with any of those three linkers.
@@chuckbenedict7235 btw do you guys know, is msvc support gnu linker script? Bcz their kinda s..t
@@Kerojey I'm not sure I understand your question fully. If the question is...do GNU MinGW tools, and specifically the linker, link to libs built by msvc? There can be C++ name mangling problems. If the msvc libs export functions as extern "C", then this problem is avoided. Also, runtime libs between the two are separate and may pose naming conflicts. May have to use -nodefaultlib to remove one. In short, the answer is yes, but there are gotchas that aren't worth the trouble IMHO. It's much easier to stick with one toolchain or else build mscv code into dlls and call into those from MinGW built code.