mirror of
https://github.com/cccriscv/mini-riscv-os.git
synced 2025-11-16 04:24:33 +00:00
add A1-Input
This commit is contained in:
20
A1-Input/Makefile
Normal file
20
A1-Input/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
CC = riscv64-unknown-elf-gcc
|
||||
CFLAGS = -nostdlib -fno-builtin -mcmodel=medany -march=rv32ima -mabi=ilp32
|
||||
|
||||
QEMU = qemu-system-riscv32
|
||||
QFLAGS = -nographic -smp 4 -machine virt -bios none
|
||||
|
||||
OBJDUMP = riscv64-unknown-elf-objdump
|
||||
|
||||
all: os.elf
|
||||
|
||||
os.elf: start.s os.c
|
||||
$(CC) $(CFLAGS) -T os.ld -o os.elf $^
|
||||
|
||||
qemu: $(TARGET)
|
||||
@qemu-system-riscv32 -M ? | grep virt >/dev/null || exit
|
||||
@echo "Press Ctrl-A and then X to exit QEMU"
|
||||
$(QEMU) $(QFLAGS) -kernel os.elf
|
||||
|
||||
clean:
|
||||
rm -f *.elf
|
||||
13
A1-Input/linux.md
Normal file
13
A1-Input/linux.md
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
|
||||
```
|
||||
guest@localhost:~/sp/10-riscv/03-mini-riscv-os/01-HelloOs$ ls
|
||||
01-HelloOs--嵌入式RISC-V輸出入程式.md Makefile os.c os.ld run.md start.s
|
||||
guest@localhost:~/sp/10-riscv/03-mini-riscv-os/01-HelloOs$ make
|
||||
riscv64-unknown-elf-gcc -nostdlib -fno-builtin -mcmodel=medany -march=rv32ima -mabi=ilp32 -T os.ld -o os.elf start.s os.c
|
||||
guest@localhost:~/sp/10-riscv/03-mini-riscv-os/01-HelloOs$ make qemu
|
||||
Press Ctrl-A and then X to exit QEMU
|
||||
qemu-system-riscv32 -nographic -smp 4 -machine virt -bios none -kernel os.elf
|
||||
Hello OS!
|
||||
QEMU: Terminated
|
||||
```
|
||||
46
A1-Input/os.c
Normal file
46
A1-Input/os.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define UART 0x10000000 // RISC-V 的 virt 虛擬機,其 UART 映射區起始位址為 0x10000000
|
||||
#define UART_THR (uint8_t*)(UART+0x00) // THR:transmitter holding register 傳送暫存器
|
||||
#define UART_RHR (uint8_t*)(UART+0x00) // THR:transmitter holding register 傳送暫存器
|
||||
#define UART_LSR (uint8_t*)(UART+0x05) // LSR:line status register 輸出狀態暫存器
|
||||
#define UART_LSR_RX_READY 0x01 // input is waiting to be read from RHR
|
||||
#define UART_LSR_EMPTY_MASK 0x40 // LSR Bit 6: 當 LSR 的第六位元為 1 時,代表傳送區為空的,可以傳了 (Transmitter empty; both the THR and LSR are empty)
|
||||
|
||||
void lib_putc(char ch) { // 透過 UART 傳送字元 ch 給宿主機印出
|
||||
while ((*UART_LSR & UART_LSR_EMPTY_MASK) == 0); // 一直等到 UART LSR 傳送區為空,可以傳送了
|
||||
*UART_THR = ch; // 將字元 ch 發送出去
|
||||
}
|
||||
|
||||
void lib_puts(char *s) { // 印出字串到宿主機。
|
||||
while (*s) lib_putc(*s++);
|
||||
}
|
||||
|
||||
char lib_getc() {
|
||||
while ((*UART_LSR & UART_LSR_RX_READY) == 0); // 一直等到 UART RX_READY 有收到資料
|
||||
return *UART_RHR; // 傳回收到的字元
|
||||
}
|
||||
|
||||
int lib_gets(char *s) {
|
||||
char *p = s;
|
||||
while (1) {
|
||||
char ch = lib_getc();
|
||||
lib_putc(ch);
|
||||
if (ch == '\n' || ch == '\r') break;
|
||||
*p++ = ch;
|
||||
}
|
||||
*p = '\0';
|
||||
return p-s;
|
||||
}
|
||||
|
||||
int os_main(void)
|
||||
{
|
||||
lib_puts("type something:");
|
||||
char str[100];
|
||||
lib_gets(str);
|
||||
lib_puts("\r\nyou type:");
|
||||
lib_puts(str);
|
||||
lib_puts("\r\n");
|
||||
while (1) {} // 讓主程式卡在這裡,用無窮迴圈停止!
|
||||
return 0;
|
||||
}
|
||||
46
A1-Input/os.ld
Normal file
46
A1-Input/os.ld
Normal file
@@ -0,0 +1,46 @@
|
||||
OUTPUT_ARCH( "riscv" ) /* 處理器架構為 RISCV */
|
||||
|
||||
ENTRY( _start ) /* 進入點從 _start 開始執行 */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 128M /* RAM 從 0x80000000 開始,共 128M BYTES */
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD; /* text 段要載入*/ /* PT_LOAD (1) Indicates that this program header describes a segment to be loaded from the file. 參考 -- https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_23.html */
|
||||
data PT_LOAD; /* data 段要載入*/
|
||||
bss PT_LOAD; /* bss 段要載入*/
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
PROVIDE(_text_start = .); /* 設定 _text_start 為 .text 段開頭位址。 */
|
||||
*(.text.init) *(.text .text.*) /* 將所有程式碼放在這段。 */
|
||||
PROVIDE(_text_end = .); /* 設定 _text_end 為 .text 段開頭位址。 */
|
||||
} >ram AT>ram :text
|
||||
|
||||
.rodata : { /* 唯讀資料段 */
|
||||
PROVIDE(_rodata_start = .);
|
||||
*(.rodata .rodata.*)
|
||||
PROVIDE(_rodata_end = .);
|
||||
} >ram AT>ram :text
|
||||
|
||||
.data : { /* 資料段 */
|
||||
. = ALIGN(4096);
|
||||
PROVIDE(_data_start = .);
|
||||
*(.sdata .sdata.*) *(.data .data.*)
|
||||
PROVIDE(_data_end = .);
|
||||
} >ram AT>ram :data
|
||||
|
||||
.bss :{ /* 未初始化資料段 */
|
||||
PROVIDE(_bss_start = .);
|
||||
*(.sbss .sbss.*) *(.bss .bss.*)
|
||||
PROVIDE(_bss_end = .);
|
||||
} >ram AT>ram :bss
|
||||
|
||||
PROVIDE(_memory_start = ORIGIN(ram));
|
||||
PROVIDE(_memory_end = ORIGIN(ram) + LENGTH(ram));
|
||||
}
|
||||
16
A1-Input/run.md
Normal file
16
A1-Input/run.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# A1-Input
|
||||
|
||||
## Build & Run
|
||||
|
||||
```sh
|
||||
$ make clean
|
||||
rm -f *.elf
|
||||
$ make
|
||||
riscv64-unknown-elf-gcc -nostdlib -fno-builtin -mcmodel=medany -march=rv32ima -mabi=ilp32 -T os.ld -o os.elf start.s os.c
|
||||
$ make qemu
|
||||
Press Ctrl-A and then X to exit QEMU
|
||||
qemu-system-riscv32 -nographic -smp 4 -machine virt -bios none -kernel os.elf
|
||||
type something:hello
|
||||
you type:hello
|
||||
QEMU: Terminated
|
||||
```
|
||||
27
A1-Input/start.s
Normal file
27
A1-Input/start.s
Normal file
@@ -0,0 +1,27 @@
|
||||
# 來源 -- https://matrix89.github.io/writes/writes/experiments-in-riscv/
|
||||
.equ STACK_SIZE, 8192
|
||||
|
||||
.global _start
|
||||
|
||||
_start:
|
||||
# setup stacks per hart // hart: hardware thread, 差不多就是 core, 設定此 core 的堆疊
|
||||
csrr t0, mhartid # read current hart id // 讀取 core 的 id
|
||||
slli t0, t0, 10 # shift left the hart id by 1024 // t0 = t0*1024
|
||||
la sp, stacks + STACK_SIZE # set the initial stack pointer // 將堆疊指標 sp 放到堆疊底端
|
||||
# to the end of the stack space
|
||||
add sp, sp, t0 # move the current hart stack pointer // 設定 hart 的堆疊位置
|
||||
# to its place in the stack space
|
||||
|
||||
# park harts with id != 0
|
||||
csrr a0, mhartid # read current hart id
|
||||
bnez a0, park # if we're not on the hart 0 // 如果不是 hart 0 ,就進入無窮迴圈。
|
||||
# we park the hart
|
||||
|
||||
j os_main # hart 0 jump to c // 堆疊設好了,讓 hart 0 進入 C 語言主程式。
|
||||
|
||||
park: # 無窮迴圈,停住!
|
||||
wfi
|
||||
j park
|
||||
|
||||
stacks:
|
||||
.skip STACK_SIZE * 4 # allocate space for the harts stacks // 分配堆疊空間
|
||||
Reference in New Issue
Block a user