add A1-Input

This commit is contained in:
ccckmit
2021-11-01 09:38:50 +08:00
parent 3fcd134a21
commit 0ce56608cc
6 changed files with 168 additions and 0 deletions

20
A1-Input/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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 //