From 623dfe5ecfa3777854c31e0ad2f66bad7787433a Mon Sep 17 00:00:00 2001 From: nien-zhu Date: Thu, 9 May 2024 17:17:49 +0800 Subject: [PATCH 1/2] lab3 and lab4 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e08226b3a..0d4abe531 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# OSC2024 +# OSC2024 Lab3 | Github Account | Student ID | Name | |----------------|------------|---------------| From d5aa1ae36676efaa45735a15679f3e6eb81c6b99 Mon Sep 17 00:00:00 2001 From: nien-zhu Date: Thu, 9 May 2024 19:07:51 +0800 Subject: [PATCH 2/2] lab3 --- Lab3/kernel/Makefile | 42 +++++ Lab3/kernel/README.md | 31 ++++ Lab3/kernel/bcm2710-rpi-3-b-plus.dtb | Bin 0 -> 34228 bytes Lab3/kernel/config.txt | 1 + Lab3/kernel/include/allocator.h | 1 + Lab3/kernel/include/cpio.h | 39 +++++ Lab3/kernel/include/dtb.h | 43 +++++ Lab3/kernel/include/except_c.h | 4 + Lab3/kernel/include/gpio.h | 38 +++++ Lab3/kernel/include/interrupt.h | 21 +++ Lab3/kernel/include/mailbox.h | 42 +++++ Lab3/kernel/include/printf.h | 106 ++++++++++++ Lab3/kernel/include/reboot.h | 7 + Lab3/kernel/include/shell.h | 1 + Lab3/kernel/include/tasklist.h | 19 +++ Lab3/kernel/include/time_c.h | 22 +++ Lab3/kernel/include/uart.h | 43 +++++ Lab3/kernel/include/utils.h | 15 ++ Lab3/kernel/include/utils_h.h | 7 + Lab3/kernel/initramfs.cpio | Bin 0 -> 1024 bytes Lab3/kernel/src/allocater.c | 20 +++ Lab3/kernel/src/cpio.c | 167 +++++++++++++++++++ Lab3/kernel/src/dtb.c | 172 +++++++++++++++++++ Lab3/kernel/src/except.c | 133 +++++++++++++++ Lab3/kernel/src/interrupt.c | 9 + Lab3/kernel/src/linker.ld | 19 +++ Lab3/kernel/src/mailbox.c | 50 ++++++ Lab3/kernel/src/main.c | 34 ++++ Lab3/kernel/src/printf.c | 233 ++++++++++++++++++++++++++ Lab3/kernel/src/reboot.c | 16 ++ Lab3/kernel/src/shell.c | 180 ++++++++++++++++++++ Lab3/kernel/src/start.S | 186 +++++++++++++++++++++ Lab3/kernel/src/tasklist.c | 86 ++++++++++ Lab3/kernel/src/time.c | 89 ++++++++++ Lab3/kernel/src/uart.c | 241 +++++++++++++++++++++++++++ Lab3/kernel/src/utils.S | 9 + Lab3/kernel/src/utils.c | 156 +++++++++++++++++ Lab3/kernel/uploader.py | 54 ++++++ 38 files changed, 2336 insertions(+) create mode 100644 Lab3/kernel/Makefile create mode 100644 Lab3/kernel/README.md create mode 100644 Lab3/kernel/bcm2710-rpi-3-b-plus.dtb create mode 100644 Lab3/kernel/config.txt create mode 100644 Lab3/kernel/include/allocator.h create mode 100644 Lab3/kernel/include/cpio.h create mode 100644 Lab3/kernel/include/dtb.h create mode 100644 Lab3/kernel/include/except_c.h create mode 100644 Lab3/kernel/include/gpio.h create mode 100644 Lab3/kernel/include/interrupt.h create mode 100644 Lab3/kernel/include/mailbox.h create mode 100644 Lab3/kernel/include/printf.h create mode 100644 Lab3/kernel/include/reboot.h create mode 100644 Lab3/kernel/include/shell.h create mode 100644 Lab3/kernel/include/tasklist.h create mode 100644 Lab3/kernel/include/time_c.h create mode 100644 Lab3/kernel/include/uart.h create mode 100644 Lab3/kernel/include/utils.h create mode 100644 Lab3/kernel/include/utils_h.h create mode 100644 Lab3/kernel/initramfs.cpio create mode 100644 Lab3/kernel/src/allocater.c create mode 100644 Lab3/kernel/src/cpio.c create mode 100644 Lab3/kernel/src/dtb.c create mode 100644 Lab3/kernel/src/except.c create mode 100644 Lab3/kernel/src/interrupt.c create mode 100644 Lab3/kernel/src/linker.ld create mode 100644 Lab3/kernel/src/mailbox.c create mode 100644 Lab3/kernel/src/main.c create mode 100644 Lab3/kernel/src/printf.c create mode 100644 Lab3/kernel/src/reboot.c create mode 100644 Lab3/kernel/src/shell.c create mode 100644 Lab3/kernel/src/start.S create mode 100644 Lab3/kernel/src/tasklist.c create mode 100644 Lab3/kernel/src/time.c create mode 100644 Lab3/kernel/src/uart.c create mode 100644 Lab3/kernel/src/utils.S create mode 100644 Lab3/kernel/src/utils.c create mode 100644 Lab3/kernel/uploader.py diff --git a/Lab3/kernel/Makefile b/Lab3/kernel/Makefile new file mode 100644 index 000000000..c37e006f5 --- /dev/null +++ b/Lab3/kernel/Makefile @@ -0,0 +1,42 @@ +ARMGNU ?= aarch64-linux-gnu + +COPS = -Iinclude -Wall -ffreestanding -fno-stack-protector -nostdlib -nostartfiles -mgeneral-regs-only +ASMOPS = -Iinclude -ggdb + +BUILD_DIR = build +SRC_DIR = src + +C_FILES = $(wildcard $(SRC_DIR)/*.c) +ASM_FILES = $(wildcard $(SRC_DIR)/*.S) +OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o) +OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o) + +DEP_FILES = $(OBJ_FILES:%.o=%.d) +-include $(DEP_FILES) + +all : kernel8.img + +clean : + rm -rf $(BUILD_DIR)/* *.img + +run : + qemu-system-aarch64 -M raspi3b -serial null -serial stdio -display none -kernel kernel8.img -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +test : + qemu-system-aarch64 -M raspi3b -serial null -serial stdio -display none -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb -kernel kernel8.img -S -s + +gdb : + aarch64-linux-gnu-gdb build/kernel8.elf + +$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c + $(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@ + +$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S + $(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@ + +kernel8.img: $(SRC_DIR)/linker.ld $(OBJ_FILES) + $(ARMGNU)-ld -T $(SRC_DIR)/linker.ld -Map $(BUILD_DIR)/kernel8.map -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES) + $(ARMGNU)-objcopy $(BUILD_DIR)/kernel8.elf -O binary kernel8.img + +#qemu-system-aarch64 -M raspi3b -kernel kernel8.img -nographic -serial null -chardev stdio,id=uart1 -serial chardev:uart1 -monitor none + \ No newline at end of file diff --git a/Lab3/kernel/README.md b/Lab3/kernel/README.md new file mode 100644 index 000000000..857ff77c9 --- /dev/null +++ b/Lab3/kernel/README.md @@ -0,0 +1,31 @@ +# OSC2024 + +| Github Account | Student ID | Name | +|----------------|------------|---------------| +| nien-zhu | 312515040 | Nien-Chu Yu | + +## Requirements + +* cross-compiler: aarch64-linux-gnu-gcc +* Emulator: qemu-system-aarch64 + +## Build + +``` +make +``` + +## Debug + +``` +make test +make gdb +``` + +## Test With QEMU + +``` +make run +(qemu-system-aarch64 -M raspi3b -serial null -serial stdio -display none -kernel kernel8.img) +``` + diff --git a/Lab3/kernel/bcm2710-rpi-3-b-plus.dtb b/Lab3/kernel/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000000000000000000000000000000000000..c83b0817e2eb5295a3dfe6aafe3aa55d93e9785d GIT binary patch literal 34228 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 +#include + + +#define FDT_BEGIN_NODE (0x00000001) +#define FDT_END_NODE (0x00000002) +#define FDT_PROP (0x00000003) +#define FDT_NOP (0x00000004) +#define FDT_END (0x00000009) + +typedef void (*fdt_callback)(int node,const char* name,const void* data,uint32_t size); + +uint32_t fdt_u32_le2be (const void *addr); +int fdt_traverse(fdt_callback cb, void* _dtb); +int struct_parse(fdt_callback cb, uintptr_t cur_ptr, uintptr_t strings_ptr,uint32_t totalsize); +void get_cpio_addr(int token,const char* name,const void* data,uint32_t size); +void print_dtb(int token, const char* name, const void* data, uint32_t size); +void data_parse(const char* name, const void* data, uint32_t len); + + + +struct fdt_header { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}; + +struct fdt_reserve_entry { + uint64_t address; + uint64_t size; +}; + +struct fdt_property{ + uint32_t len; + uint32_t nameoff; +}; diff --git a/Lab3/kernel/include/except_c.h b/Lab3/kernel/include/except_c.h new file mode 100644 index 000000000..07fe939db --- /dev/null +++ b/Lab3/kernel/include/except_c.h @@ -0,0 +1,4 @@ +void exception_entry(); +void core_timer_exception_entry(); +void irq_exception_entry(); +void test_entry(); \ No newline at end of file diff --git a/Lab3/kernel/include/gpio.h b/Lab3/kernel/include/gpio.h new file mode 100644 index 000000000..c50ecb9d5 --- /dev/null +++ b/Lab3/kernel/include/gpio.h @@ -0,0 +1,38 @@ +#ifndef GPIO_H +#define GPIO_H + +#include + +#define MMIO_BASE 0x3F000000 + +#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000)) +#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004)) +#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008)) +#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C)) +#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010)) +#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014)) +#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C)) +#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020)) +#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028)) +#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034)) +#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038)) +#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040)) +#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044)) +#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064)) +#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068)) +#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094)) +#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098)) +#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C)) + +// Helper function to write data to a memory-mapped I/O address +static inline void mmio_write(volatile uint32_t* reg, uint32_t data) { + *reg = data; +} + +// Helper function to read data from a memory-mapped I/O address +static inline uint32_t mmio_read(volatile uint32_t* reg) { + return *reg; +} + + +#endif \ No newline at end of file diff --git a/Lab3/kernel/include/interrupt.h b/Lab3/kernel/include/interrupt.h new file mode 100644 index 000000000..6ca395cde --- /dev/null +++ b/Lab3/kernel/include/interrupt.h @@ -0,0 +1,21 @@ +#include "gpio.h" + + +#define IRQ_BASIC_PENDING ((volatile unsigned int*)(MMIO_BASE+0x0000B200)) +#define IRQ_PENDING_1 ((volatile unsigned int*)(MMIO_BASE+0x0000B204)) +#define IRQ_PENDING_2 ((volatile unsigned int*)(MMIO_BASE+0x0000B208)) +#define FIQ_CONTROL ((volatile unsigned int*)(MMIO_BASE+0x0000B20C)) +#define ENABLE_IRQS_1 ((volatile unsigned int*)(MMIO_BASE+0x0000B210)) +#define ENABLE_IRQS_2 ((volatile unsigned int*)(MMIO_BASE+0x0000B214)) +#define ENABLE_BASIC_IRQS ((volatile unsigned int*)(MMIO_BASE+0x0000B218)) +#define DISABLE_IRQS_1 ((volatile unsigned int*)(MMIO_BASE+0x0000B21C)) +#define DISABLE_IRQS_2 ((volatile unsigned int*)(MMIO_BASE+0x0000B220)) +#define DISABLE_BASIC_IRQS ((volatile unsigned int*)(MMIO_BASE+0x0000B224)) + +#define SYSTEM_TIMER_IRQ_0 (1 << 0) +#define SYSTEM_TIMER_IRQ_1 (1 << 1) +#define SYSTEM_TIMER_IRQ_2 (1 << 2) +#define SYSTEM_TIMER_IRQ_3 (1 << 3) + +void enable_interrupt(); +void disable_interrupt(); \ No newline at end of file diff --git a/Lab3/kernel/include/mailbox.h b/Lab3/kernel/include/mailbox.h new file mode 100644 index 000000000..628076e5e --- /dev/null +++ b/Lab3/kernel/include/mailbox.h @@ -0,0 +1,42 @@ +#include "gpio.h" + +extern volatile unsigned int mailbox[36]; + + + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +/* tags */ +#define MBOX_TAG_GETBOARD 0x00010002 +#define MBOX_REQUEST 0x00000000 +#define MBOX_TAG_GETSERIAL 0x00010004 +#define TAG_REQUEST_CODE 0x00000000 +#define MBOX_TAG_GETARMMEM 0x00010005 +#define MBOX_TAG_LAST 0x00000000 +#define END_TAG 0x00000000 + +int mailbox_call(); +void get_board_revision(); +void get_arm_mem(); + +#define VIDEOCORE_MBOX (MMIO_BASE+0xB880) +#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MBOX_RESPONSE 0x80000000 +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 +#define REQUEST_SUCCEED 0x80000000 +#define REQUEST_FAILED 0x80000001 \ No newline at end of file diff --git a/Lab3/kernel/include/printf.h b/Lab3/kernel/include/printf.h new file mode 100644 index 000000000..f37c1bf2d --- /dev/null +++ b/Lab3/kernel/include/printf.h @@ -0,0 +1,106 @@ +/* +File: printf.h + +Copyright (C) 2004 Kustaa Nyholm + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +This library is realy just two files: 'printf.h' and 'printf.c'. + +They provide a simple and small (+200 loc) printf functionality to +be used in embedded systems. + +I've found them so usefull in debugging that I do not bother with a +debugger at all. + +They are distributed in source form, so to use them, just compile them +into your project. + +Two printf variants are provided: printf and sprintf. + +The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'. + +Zero padding and field width are also supported. + +If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the +long specifier is also +supported. Note that this will pull in some long math routines (pun intended!) +and thus make your executable noticably longer. + +The memory foot print of course depends on the target cpu, compiler and +compiler options, but a rough guestimate (based on a H8S target) is about +1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space. +Not too bad. Your milage may vary. By hacking the source code you can +get rid of some hunred bytes, I'm sure, but personally I feel the balance of +functionality and flexibility versus code size is close to optimal for +many embedded systems. + +To use the printf you need to supply your own character output function, +something like : + + void putc ( void* p, char c) + { + while (!SERIAL_PORT_EMPTY) ; + SERIAL_PORT_TX_REGISTER = c; + } + +Before you can call printf you need to initialize it to use your +character output function with something like: + + init_printf(NULL,putc); + +Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc', +the NULL (or any pointer) you pass into the 'init_printf' will eventually be +passed to your 'putc' routine. This allows you to pass some storage space (or +anything realy) to the character output function, if necessary. +This is not often needed but it was implemented like that because it made +implementing the sprintf function so neat (look at the source code). + +The code is re-entrant, except for the 'init_printf' function, so it +is safe to call it from interupts too, although this may result in mixed output. +If you rely on re-entrancy, take care that your 'putc' function is re-entrant! + +The printf and sprintf functions are actually macros that translate to +'tfp_printf' and 'tfp_sprintf'. This makes it possible +to use them along with 'stdio.h' printf's in a single source file. +You just need to undef the names before you include the 'stdio.h'. +Note that these are not function like macros, so if you have variables +or struct members with these names, things will explode in your face. +Without variadic macros this is the best we can do to wrap these +fucnction. If it is a problem just give up the macros and use the +functions directly or rename them. + +For further details see source code. + +regs Kusti, 23.10.2004 +*/ + + +#ifndef __TFP_PRINTF__ +#define __TFP_PRINTF__ + +#include + +void init_printf(void* putp,void (*putf) (void*,char)); + +void tfp_printf(char *fmt, ...); +void tfp_sprintf(char* s,char *fmt, ...); + +void tfp_format(void* putp,void (*putf) (void*,char),char *fmt, va_list va); + +#define printf tfp_printf +#define sprintf tfp_sprintf + +#endif diff --git a/Lab3/kernel/include/reboot.h b/Lab3/kernel/include/reboot.h new file mode 100644 index 000000000..185b8da40 --- /dev/null +++ b/Lab3/kernel/include/reboot.h @@ -0,0 +1,7 @@ +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 + +void set(long addr, unsigned int value); +void reset(int tick); +void cancel_reset(); \ No newline at end of file diff --git a/Lab3/kernel/include/shell.h b/Lab3/kernel/include/shell.h new file mode 100644 index 000000000..7ce4cee06 --- /dev/null +++ b/Lab3/kernel/include/shell.h @@ -0,0 +1 @@ +void shell(); \ No newline at end of file diff --git a/Lab3/kernel/include/tasklist.h b/Lab3/kernel/include/tasklist.h new file mode 100644 index 000000000..49af22411 --- /dev/null +++ b/Lab3/kernel/include/tasklist.h @@ -0,0 +1,19 @@ +#include +#include + +typedef void (*task_callback)(); + +typedef struct task { + struct task *prev; + struct task *next; + task_callback callback; + uint64_t task_num; + uint64_t priority; + uint64_t elr; + uint64_t spsr; +} task_t; + +void execute_tasks(uint64_t elr,uint64_t spsr); +void create_task(task_callback callback,uint64_t priority); +void enqueue_task(task_t *new_task); +extern task_t *task_head; \ No newline at end of file diff --git a/Lab3/kernel/include/time_c.h b/Lab3/kernel/include/time_c.h new file mode 100644 index 000000000..90298cd82 --- /dev/null +++ b/Lab3/kernel/include/time_c.h @@ -0,0 +1,22 @@ +#ifndef __TIME_C_H +#define __TIME_C_H + +#define CORE0_TIMER_IRQ_CTRL ((volatile unsigned int*)(0x40000040)) +#define CORE0_INTERRUPT_SOURCE ((volatile unsigned int*)(0x40000060)) + +typedef void (*task_callback)(); + +typedef struct timer_info { + struct timer_info *prev; + struct timer_info *next; + char* msg; + task_callback callback; + unsigned long long executeTime; +}timer_info; + +extern timer_info *timer_head; + +void setTimeout(char* message, unsigned long long wait); +void timer_init(); + +#endif \ No newline at end of file diff --git a/Lab3/kernel/include/uart.h b/Lab3/kernel/include/uart.h new file mode 100644 index 000000000..29fd71954 --- /dev/null +++ b/Lab3/kernel/include/uart.h @@ -0,0 +1,43 @@ +#ifndef UART_H +#define UART_H + +#include "gpio.h" + +typedef unsigned int Reg; +void uart_init(); +void uart_send_char(unsigned int c); +char uart_get_char(); +void uart_display_string(char* s); +void uart_binary_to_hex(unsigned int d); +void uart_binary_to_int(unsigned int d); + +char uart_async_get(); +void uart_async_send_string(char *str); +void test_uart_async(); + +void uart_enable_interrupt(); +void uart_disable_interrupt(); +void set_transmit_interrupt(); +void clear_transmit_interrupt(); +void uart_handler(); +void uart_buf_init(); + +void putc ( void* p, char c); +void delay(unsigned int clock); + +#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004)) +#define AUX_MU_IO_REG ((volatile unsigned int*)(MMIO_BASE+0x00215040)) +#define AUX_MU_IER_REG ((volatile unsigned int*)(MMIO_BASE+0x00215044)) +#define AUX_MU_IIR_REG ((volatile unsigned int*)(MMIO_BASE+0x00215048)) +#define AUX_MU_LCR_REG ((volatile unsigned int*)(MMIO_BASE+0x0021504C)) +#define AUX_MU_MCR_REG ((volatile unsigned int*)(MMIO_BASE+0x00215050)) +#define AUX_MU_LSR_REG ((volatile unsigned int*)(MMIO_BASE+0x00215054)) +#define AUX_MU_MSR_REG ((volatile unsigned int*)(MMIO_BASE+0x00215058)) +#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C)) +#define AUX_MU_CNTL_REG ((volatile unsigned int*)(MMIO_BASE+0x00215060)) +#define AUX_MU_STAT_REG ((volatile unsigned int*)(MMIO_BASE+0x00215064)) +#define AUX_MU_BAUD_REG ((volatile unsigned int*)(MMIO_BASE+0x00215068)) + + + +#endif \ No newline at end of file diff --git a/Lab3/kernel/include/utils.h b/Lab3/kernel/include/utils.h new file mode 100644 index 000000000..873ecffec --- /dev/null +++ b/Lab3/kernel/include/utils.h @@ -0,0 +1,15 @@ +#include +#include + +int utils_string_compare(const char* str1,const char* str2); +unsigned long utils_hex2dec(const char *s, int char_size); +void utils_align(void *size, unsigned int s); +uint32_t utils_align_up(uint32_t size, int alignment); +size_t utils_strlen(const char *s); +int utils_keyword_compare(const char* str1,const char* str2); +int utils_find_api(const char* str1); +int utils_api_compare(const char* str1,const char* str2); +char* utils_api_analysis(char* str1); +int utils_api_elem_count(const char* str1); +void utils_api_get_elem(const char* str1, char** buff1, char** buff2); +int utils_str2int(const char* s); \ No newline at end of file diff --git a/Lab3/kernel/include/utils_h.h b/Lab3/kernel/include/utils_h.h new file mode 100644 index 000000000..0dfd29785 --- /dev/null +++ b/Lab3/kernel/include/utils_h.h @@ -0,0 +1,7 @@ +#ifndef _BOOT_H +#define _BOOT_H + +extern int get_el ( void ); +extern int get_sp ( void ); + +#endif /*_BOOT_H */ \ No newline at end of file diff --git a/Lab3/kernel/initramfs.cpio b/Lab3/kernel/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..c836d2dd1a61fe9e938dfc2a34c79cce4faf41be GIT binary patch literal 1024 zcmXpoH!wFaG%zqSFm`ouH2?w=LpK)?4HU3Ip@E9bObpzdEi578U`a3m;~OJ{P*_GV zo*o0xHiUg{AaM&rCljzdrhSH}_8G#=A!HxKJfNZZd8rHx42B9u3dUR}3Z@EXT;>WE z3YJ_9DDD7zn*?_l0mBOnh;~Owc|On`8L2rr`CJMhP@Z3ulLBFa`HCO_bQY?+!1h?+ zjt^k?7@1m_m_wao2y+jN#uXoqPz?s9#i>PxdYQTDK${ybF|aU9WMp8tA}_-5arOWI oAwWS9SbV{B;H6>Vf>#k1Nhg?CNRXqak82PxEP!^80y=~M08X)ljsO4v literal 0 HcmV?d00001 diff --git a/Lab3/kernel/src/allocater.c b/Lab3/kernel/src/allocater.c new file mode 100644 index 000000000..93e87be56 --- /dev/null +++ b/Lab3/kernel/src/allocater.c @@ -0,0 +1,20 @@ +#include "allocator.h" +#include "utils.h" + +#define SIMPLE_MALLOC_BUFFER_SIZE 8192 +static unsigned char simple_malloc_buffer[SIMPLE_MALLOC_BUFFER_SIZE]; +static unsigned long simple_malloc_offset = 0; + +void* simple_malloc(unsigned long size){ + //align to 8 bytes + utils_align(&size,8); + + if(simple_malloc_offset + size > SIMPLE_MALLOC_BUFFER_SIZE) { + //Not enough space left + return (void*) 0; + } + void* allocated = (void *)&simple_malloc_buffer[simple_malloc_offset]; + simple_malloc_offset += size; + + return allocated; +} \ No newline at end of file diff --git a/Lab3/kernel/src/cpio.c b/Lab3/kernel/src/cpio.c new file mode 100644 index 000000000..1fd0bd6d7 --- /dev/null +++ b/Lab3/kernel/src/cpio.c @@ -0,0 +1,167 @@ + +#include +#include + +#include "uart.h" +#include "utils.h" +#include "cpio.h" +#include "allocator.h" +#include "printf.h" +#include "utils_h.h" + +#define USTACK_SIZE 0x2000 + +int file_num = 0; +struct file *f = NULL; + +char *cpio_addr = (char *)0x20000000; +// char *cpio_addr = (char *)0x8000000; + + +char *findFile(char *name) +{ + char *addr = (char *)cpio_addr; + while (cpio_TRAILER_compare((char *)(addr+sizeof(struct new_cpio_header))) == 0) + { + if ((utils_string_compare((char *)(addr + sizeof(struct new_cpio_header)), name) != 0)) + { + return addr; + } + struct new_cpio_header* header = (struct new_cpio_header *)addr; + unsigned long pathname_size = utils_hex2dec(header->c_namesize,(int)sizeof(header->c_namesize));; + unsigned long file_size = utils_hex2dec(header->c_filesize,(int)sizeof(header->c_filesize)); + unsigned long headerPathname_size = sizeof(struct new_cpio_header) + pathname_size; + + utils_align(&headerPathname_size,4); + utils_align(&file_size,4); + addr += (headerPathname_size + file_size); + } + return 0; +} + +void cpio_ls(){ + char* addr = (char*) cpio_addr; + // uart_display_string(addr); + // uart_display_string("\n"); + // int i = 0; + while(1){ + uart_send_char('\r'); + uart_display_string((char *)(addr+sizeof(struct new_cpio_header))); + uart_display_string("\n"); + + struct new_cpio_header* header = (struct new_cpio_header*) addr; + unsigned long filename_size = utils_hex2dec(header->c_namesize,(int)sizeof(header->c_namesize)); + unsigned long headerPathname_size = sizeof(struct new_cpio_header) + filename_size; + unsigned long file_size = utils_hex2dec(header->c_filesize,(int)sizeof(header->c_filesize)); + + utils_align(&headerPathname_size,4); + utils_align(&file_size,4); + + if(cpio_TRAILER_compare((char *)(addr+sizeof(struct new_cpio_header)))){ + break; + } + + addr += (headerPathname_size + file_size); + } +} + +void cpio_cat(char *filename) +{ + char *target = findFile(filename); + if (target) + { + struct new_cpio_header *header = (struct new_cpio_header *)target; + unsigned long pathname_size = utils_hex2dec(header->c_namesize,(int)sizeof(header->c_namesize)); + unsigned long file_size = utils_hex2dec(header->c_filesize,(int)sizeof(header->c_filesize)); + unsigned long headerPathname_size = sizeof(struct new_cpio_header) + pathname_size; + + utils_align(&headerPathname_size,4); + utils_align(&file_size,4); + + char *file_content = target + headerPathname_size; + uart_send_char('\r'); + for (unsigned int i = 0; i < file_size; i++) + { + uart_send_char(file_content[i]); + } + uart_display_string("\n"); + } + else + { + uart_display_string("\rNot found the file\n"); + } +} + +int cpio_TRAILER_compare(const char* str1){ + const char* str2 = "TRAILER!!!"; + for(;*str1 !='\0'||*str2 !='\0';str1++,str2++){ + + if(*str1 != *str2){ + return 0; + } + else if(*str1 == '!' && *str2 =='!'){ + return 1; + } + } + return 1; +} + +void cpio_load_program(char *filename) +{ + // 查找文件,返回該文件的地址,如果找到了,prog_addr 就不為空 + char *prog_addr = findFile(filename); + + // 定義變量 put_addr,將目標地址設置為 0x200000 + void *put_addr = (void *)0x200000; + + // 如果找到了文件 + if (prog_addr) + { + struct new_cpio_header* header = (struct new_cpio_header*) prog_addr; + + unsigned int pathname_size = utils_hex2dec(header->c_namesize,(int)sizeof(header->c_namesize)); + unsigned int file_size = utils_hex2dec(header->c_filesize,(int)sizeof(header->c_filesize)); + + unsigned int headerPathname_size = sizeof(struct new_cpio_header) + pathname_size; + + utils_align(&headerPathname_size, 4); + utils_align(&file_size, 4); + + uart_display_string("\r----------------"); + uart_display_string(prog_addr + sizeof(struct new_cpio_header)); + uart_display_string("----------------\n"); + + // 將文件內容從源地址放到目標地址上 + // 將二進制內容讀出來從0x200000開始放,所以linker script裡寫的0x200000不代表檔案就真的會load入0x20000 + char *file_content = prog_addr + headerPathname_size; + unsigned char *target = (unsigned char *)put_addr; + + uart_display_string("put the target to 0x200000\n"); + + while (file_size--) + { + *target = *file_content; + target++; + file_content++; + } + + + asm volatile("mov x0, 0x3c0 \n"); + asm volatile("msr SPSR_EL1, x0 \n"); + asm volatile("msr ELR_EL1, %0 \n" ::"r"(put_addr)); + asm volatile("mov x0, 0x200000"); + asm volatile("msr SP_EL0, x0 \n"); + asm volatile("mov x0, 0x0 \n"); + asm volatile("msr SPSR_EL1, x0 \n"); + asm volatile("eret \n"); + + // 在這段程式碼中,關鍵字 volatile 的作用是告訴編譯器不要對這些指令進行優化或重排, + // 以確保它們按照指定的順序執行。 + // 這是因為這些指令是直接操作 CPU 寄存器和系統狀態的,如果出現任何錯誤或異常行為, + // 可能會導致系統崩潰或不正常運行。 + } + else{ + // 如果沒有找到該文件,使用串口打印信息 + uart_display_string("Not found the program\n"); + } +} \ No newline at end of file diff --git a/Lab3/kernel/src/dtb.c b/Lab3/kernel/src/dtb.c new file mode 100644 index 000000000..06b0b4416 --- /dev/null +++ b/Lab3/kernel/src/dtb.c @@ -0,0 +1,172 @@ +#include "dtb.h" +#include "uart.h" +#include "utils.h" + +#define UNUSED(x) ( (void)(x) ) + +char* cpio_addr; +int space = 0; + +void send_space(int n) { + while(n--) uart_display_string("\t"); +} + +uint32_t fdt_u32_le2be (const void *addr) { + const uint8_t *bytes = (const uint8_t *) addr; + uint32_t ret = (uint32_t)bytes[0] << 24 |(uint32_t)bytes[1] << 16 |(uint32_t)bytes[2] << 8 |(uint32_t)bytes[3]; + return ret; +} + +int fdt_traverse(fdt_callback cb, void* _dtb){ + uintptr_t dtb_ptr = (uintptr_t) _dtb; + uart_send_char('\n'); + uart_send_char('\r'); + uart_display_string("dtb loading at "); + uart_binary_to_hex(dtb_ptr); + uart_send_char('\n'); + struct fdt_header* header = (struct fdt_header*) dtb_ptr; + uint32_t magic = fdt_u32_le2be(&(header->magic)); + + if (magic != 0xd00dfeed){ + uart_send_char('\r'); + uart_display_string("The header magic is wrong\n"); + return -1; + } + else{ + uart_send_char('\r'); + uart_display_string("magic == "); + uart_binary_to_hex(magic); + uart_send_char('\n'); + } + + uintptr_t struct_ptr = dtb_ptr + fdt_u32_le2be(&(header->off_dt_struct)); + uintptr_t strings_ptr = dtb_ptr + fdt_u32_le2be(&(header->off_dt_strings)); + uint32_t totalsize = fdt_u32_le2be(&header->totalsize); + uart_send_char('\r'); + uart_display_string("Structure offset is "); + uart_binary_to_hex(struct_ptr); + uart_send_char('\n'); + uart_send_char('\r'); + uart_display_string("Strings offset is at"); + uart_binary_to_hex(strings_ptr); + uart_send_char('\n'); + // uart_display_string("total size is "); + // uart_binary_to_hex(totalsize); + // uart_send_char('\n'); + uart_send_char('\n'); + + struct_parse(cb, struct_ptr, strings_ptr, totalsize); + + return 1; +} + +int struct_parse(fdt_callback cb, uintptr_t cur_ptr, uintptr_t strings_ptr,uint32_t totalsize){ + + uintptr_t end_ptr = cur_ptr + totalsize; + // int count = 0; + while(cur_ptr < end_ptr){ + + + uint32_t token = fdt_u32_le2be((char*) cur_ptr); + cur_ptr += 4; + + switch(token){ + case FDT_BEGIN_NODE: + // count += 1; + cb(token, (char*)cur_ptr, NULL, 0); + cur_ptr += utils_align_up(utils_strlen((char*)cur_ptr),4); + break; + case FDT_END_NODE: + cb(token, NULL, NULL,0); + break; + case FDT_PROP:{ + uint32_t len = fdt_u32_le2be((char*)cur_ptr); + cur_ptr += 4; + uint32_t nameoff = fdt_u32_le2be((char*)cur_ptr); + cur_ptr += 4; + cb(token,(char*)(strings_ptr + nameoff), (char*)cur_ptr, len); + cur_ptr += utils_align_up(len,4); + } + break; + case FDT_NOP: + cb(token,NULL,NULL,0); + break; + case FDT_END: + cb(token,NULL,NULL,0); + break; + } + // if (count > 10 && token == FDT_END_NODE){ + // break; + // } + } + return 0; + +} + +void print_dtb(int token, const char* name, const void* data, uint32_t len) { + // UNUSED(size); + + switch(token){ + case FDT_BEGIN_NODE: + uart_display_string("\n"); + send_space(space); + uart_display_string((char*)name); + uart_display_string("{\n "); + space++; + break; + case FDT_END_NODE: + uart_display_string("\n"); + space--; + if(space >0) send_space(space); + uart_display_string("}\n"); + break; + case FDT_NOP: + break; + case FDT_PROP: + send_space(space); + uart_display_string((char*)name); + uart_display_string(" : "); + data_parse((char*)name, data, len); + uart_display_string("\n"); + break; + case FDT_END: + break; + } +} + +void get_cpio_addr(int token,const char* name,const void* data,uint32_t size){ + UNUSED(size); + if(token==FDT_PROP && utils_string_compare((char *)name,"linux,initrd-start")){ + cpio_addr = (char*)(uintptr_t)fdt_u32_le2be(data); + uart_send_char('\r'); + uart_display_string("cpio address is at: "); + uart_binary_to_hex((uintptr_t)fdt_u32_le2be(data)); + uart_send_char('\n'); + } +} + +void data_parse(const char* name, const void* data, uint32_t len){ + + if(utils_keyword_compare(name, "microchip") || utils_string_compare(name, "reg") || utils_string_compare(name, "virtual-reg") || utils_string_compare(name, "ranges") || utils_string_compare(name, "size") || utils_string_compare(name, "reusable")){ + if(len == 0){ + uart_display_string(""); + } + while(len>0){ + uart_send_char('<'); + uart_binary_to_hex((uintptr_t)fdt_u32_le2be(data)); + uart_send_char('>'); + uart_send_char(' '); + len -= 4; + } + + } + else if(utils_string_compare(name, "compatible") || utils_string_compare(name, "clocks") || utils_keyword_compare(name, "assigned") || utils_keyword_compare(name, "linux") || name[0] == '#' || utils_string_compare(name, "phandle") || utils_keyword_compare(name, "interrupt")){ + uart_send_char('<'); + uart_binary_to_hex((uintptr_t)fdt_u32_le2be(data)); + uart_send_char('>'); + uart_send_char(' '); + } + else{ + uart_display_string((char*) data); + } +} diff --git a/Lab3/kernel/src/except.c b/Lab3/kernel/src/except.c new file mode 100644 index 000000000..5dafe1b7a --- /dev/null +++ b/Lab3/kernel/src/except.c @@ -0,0 +1,133 @@ +#include "uart.h" +#include "shell.h" +#include "time_c.h" +#include "except_c.h" +#include "interrupt.h" +#include "tasklist.h" +#include "printf.h" +#include "utils_h.h" +#include "utils.h" + +#include + +#define CNTPSIRQ_BIT_POSITION 0x02 +#define AUXINIT_BIT_POSTION 1<<29 + +void core_timer_exception_entry() { + + unsigned long long cntpct_el0 = 0;//The register count secs with frequency + asm volatile("mrs %0,cntpct_el0":"=r"(cntpct_el0)); + unsigned long long cntfrq_el0 = 0;//The base frequency + asm volatile("mrs %0,cntfrq_el0":"=r"(cntfrq_el0)); + + unsigned long long sec = cntpct_el0 / cntfrq_el0; + + uart_display_string("\r"); + uart_display_string(timer_head->msg); + printf(" <- show in %d sec (after booting up)",sec); + uart_display_string("\n"); + + + // timer_head->msg = ""; + + if (timer_head->next){ + timer_head = timer_head->next; + task_head->prev = NULL; + asm volatile ("msr cntp_cval_el0, %0"::"r"(timer_head->executeTime));//set new timer + asm volatile ("bl core_timer_irq_enable"); + } + else{ + timer_head = NULL; + asm volatile ("bl core_timer_irq_disable"); + } + +} +uint32_t count = 0; +uint64_t elr; +uint64_t spsr; +uint64_t nest_elr; +uint64_t nest_spsr; + +void irq_exception_entry(){ + disable_interrupt(); + // printf("IN IRQ\n"); + count++; + if(count == 1){ + asm volatile("mrs %0,elr_el1":"=r"(elr)); + asm volatile("mrs %0,spsr_el1":"=r"(spsr)); + } + else if(count == 2){ + asm volatile("mrs %0,elr_el1":"=r"(nest_elr)); + asm volatile("mrs %0,spsr_el1":"=r"(nest_spsr)); + } + + uint32_t irq_pending1 = *IRQ_PENDING_1; + uint32_t core0_interrupt_source = *CORE0_INTERRUPT_SOURCE; + uint32_t uart = irq_pending1 & AUXINIT_BIT_POSTION; + uint32_t core = core0_interrupt_source & 0x2; + + if(uart || core){ + if(uart) { + uart_disable_interrupt(); + create_task(uart_handler, 2); + // uart_handler(); + } + if(core){ + asm volatile("bl core_timer_irq_disable"); + create_task(core_timer_exception_entry,1); + // core_timer_exception_entry(); + } + } + else{ + asm volatile("bl core_timer_irq_disable"); + uart_disable_interrupt(); + } + + enable_interrupt(); + if(task_head && count == 1){ + execute_tasks(elr,spsr); + } + // printf("OUT IRQ\n"); + count--; +} + +void exception_entry() { + uart_display_string("\rIn Exception handler\n"); + + //read spsr_el1 + unsigned long long spsr_el1 = 0; + asm volatile("mrs %0, spsr_el1":"=r"(spsr_el1)); + uart_display_string("spsr_el1: "); + uart_binary_to_hex(spsr_el1); + uart_display_string("\n"); + + //read elr_el1 + unsigned long long elr_el1 = 0; + asm volatile("mrs %0, elr_el1":"=r"(elr_el1)); + uart_display_string("elr_el1: "); + uart_binary_to_hex(elr_el1); + uart_display_string("\n"); + + //esr_el1 + unsigned long long esr_el1 = 0; + asm volatile("mrs %0, esr_el1":"=r"(esr_el1)); + uart_display_string("esr_el1: "); + uart_binary_to_hex(esr_el1); + uart_display_string("\n"); + + //ec + unsigned ec = (esr_el1 >> 26) & 0x3F; // 0x3F == 0b111111(6) + uart_display_string("ec: "); + uart_binary_to_hex(ec); + uart_display_string("\n"); // SVC instruction execution in AArch64 state. +} + +void test_entry(){ + uart_display_string("I'm in the test entry\n"); +} + + + + + + diff --git a/Lab3/kernel/src/interrupt.c b/Lab3/kernel/src/interrupt.c new file mode 100644 index 000000000..11290118b --- /dev/null +++ b/Lab3/kernel/src/interrupt.c @@ -0,0 +1,9 @@ +#include "interrupt.h" +#include "printf.h" + +void enable_interrupt() { + asm volatile("msr DAIFClr, 0xf"); + } +void disable_interrupt() { + asm volatile("msr DAIFSet, 0xf"); + } \ No newline at end of file diff --git a/Lab3/kernel/src/linker.ld b/Lab3/kernel/src/linker.ld new file mode 100644 index 000000000..831b003bf --- /dev/null +++ b/Lab3/kernel/src/linker.ld @@ -0,0 +1,19 @@ +SECTIONS +{ + . = 0x80000; + .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) } + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) } + PROVIDE(_data = .); + .data : { *(.data .data.* .gnu.linkonce.d*) } + .bss (NOLOAD) : { + . = ALIGN(16); + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + __bss_end = .; + } + _end = .; + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} +__bss_size = (__bss_end - __bss_start) >> 3; diff --git a/Lab3/kernel/src/mailbox.c b/Lab3/kernel/src/mailbox.c new file mode 100644 index 000000000..c1ccd5032 --- /dev/null +++ b/Lab3/kernel/src/mailbox.c @@ -0,0 +1,50 @@ +#include "mailbox.h" +#include "uart.h" + +volatile unsigned int __attribute__((aligned(16))) mailbox[36]; + +int mailbox_call() +{ + unsigned int r = (((unsigned int)((unsigned long)&mailbox)&~0xF) | (MBOX_CH_PROP&0xF)); + /* wait until we can write to the mailbox */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL); + /* write the address of our message to the mailbox with channel identifier */ + *MBOX_WRITE = r; + /* now wait for the response */ + while(1) { + /* is there a response? */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY); + /* is it a response to our message? */ + if(r == *MBOX_READ){ + return mailbox[1]==MBOX_RESPONSE; + } + } + return 0; +} + +void get_board_revision(){ + mailbox[0] = 7 * 4; // buffer size in bytes + mailbox[1] = MBOX_REQUEST; + // tags begin + mailbox[2] = MBOX_TAG_GETBOARD; // tag identifier + mailbox[3] = 4; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + // tags end + mailbox[6] = MBOX_TAG_LAST; + // mailbox_call(); // message passing procedure call, we should implement it following the 6 steps provided above. +} + +void get_arm_mem(){ + mailbox[0] = 8 * 4; // buffer size in bytes + mailbox[1] = MBOX_REQUEST; + // tags begin + mailbox[2] = MBOX_TAG_GETARMMEM; // tag identifier + mailbox[3] = 8; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + mailbox[6] = 0; // value buffer + // tags end + mailbox[7] = MBOX_TAG_LAST; + // mailbox_call(); // message passing procedure call, we should implement it following the 6 steps provided above. +} \ No newline at end of file diff --git a/Lab3/kernel/src/main.c b/Lab3/kernel/src/main.c new file mode 100644 index 000000000..1e2298d15 --- /dev/null +++ b/Lab3/kernel/src/main.c @@ -0,0 +1,34 @@ +#include "printf.h" +#include "uart.h" +#include "shell.h" +#include "dtb.h" +#include "utils.h" +#include "utils_h.h" +#include "time_c.h" +#include "interrupt.h" + +extern void *_dtb_ptr; + +void main() +{ + uart_init(); // Set up the Uart + + init_printf(0, putc); + int el = get_el(); + int s = get_sp(); + printf("\r\nIn Exception level: %d \r\n", el); + printf("Stack Pinter Select is %d \r\n", s); + + // say hello + fdt_traverse(get_cpio_addr, _dtb_ptr); + uart_display_string("\r\n"); + + timer_init(); + + uart_display_string("\r\n"); + uart_display_string("Type in \"help\" to get instruction menu!\n"); + + + // echo everything back + shell(); +} \ No newline at end of file diff --git a/Lab3/kernel/src/printf.c b/Lab3/kernel/src/printf.c new file mode 100644 index 000000000..1383039a5 --- /dev/null +++ b/Lab3/kernel/src/printf.c @@ -0,0 +1,233 @@ +/* +File: printf.c + +Copyright (C) 2004 Kustaa Nyholm + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "printf.h" + +typedef void (*putcf) (void*,char); +static putcf stdout_putf; +static void* stdout_putp; + + +#ifdef PRINTF_LONG_SUPPORT + +static void uli2a(unsigned long int num, unsigned int base, int uc,char * bf) + { + int n=0; + unsigned int d=1; + while (num/d >= base) + d*=base; + while (d!=0) { + int dgt = num / d; + num%=d; + d/=base; + if (n || dgt>0|| d==0) { + *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10); + ++n; + } + } + *bf=0; + } + +static void li2a (long num, char * bf) + { + if (num<0) { + num=-num; + *bf++ = '-'; + } + uli2a(num,10,0,bf); + } + +#endif + +static void ui2a(unsigned int num, unsigned int base, int uc,char * bf) + { + int n=0; + unsigned int d=1; + while (num/d >= base) + d*=base; + while (d!=0) { + int dgt = num / d; + num%= d; + d/=base; + if (n || dgt>0 || d==0) { + *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10); + ++n; + } + } + *bf=0; + } + +static void i2a (int num, char * bf) + { + if (num<0) { + num=-num; + *bf++ = '-'; + } + ui2a(num,10,0,bf); + } + +static int a2d(char ch) + { + if (ch>='0' && ch<='9') + return ch-'0'; + else if (ch>='a' && ch<='f') + return ch-'a'+10; + else if (ch>='A' && ch<='F') + return ch-'A'+10; + else return -1; + } + +static char a2i(char ch, char** src,int base,int* nump) + { + char* p= *src; + int num=0; + int digit; + while ((digit=a2d(ch))>=0) { + if (digit>base) break; + num=num*base+digit; + ch=*p++; + } + *src=p; + *nump=num; + return ch; + } + +static void putchw(void* putp,putcf putf,int n, char z, char* bf) + { + char fc=z? '0' : ' '; + char ch; + char* p=bf; + while (*p++ && n > 0) + n--; + while (n-- > 0) + putf(putp,fc); + while ((ch= *bf++)) + putf(putp,ch); + } + +void tfp_format(void* putp,putcf putf,char *fmt, va_list va) + { + char bf[12]; + + char ch; + + + while ((ch=*(fmt++))) { + if (ch!='%') + putf(putp,ch); + else { + char lz=0; +#ifdef PRINTF_LONG_SUPPORT + char lng=0; +#endif + int w=0; + ch=*(fmt++); + if (ch=='0') { + ch=*(fmt++); + lz=1; + } + if (ch>='0' && ch<='9') { + ch=a2i(ch,&fmt,10,&w); + } +#ifdef PRINTF_LONG_SUPPORT + if (ch=='l') { + ch=*(fmt++); + lng=1; + } +#endif + switch (ch) { + case 0: + goto abort; + case 'u' : { +#ifdef PRINTF_LONG_SUPPORT + if (lng) + uli2a(va_arg(va, unsigned long int),10,0,bf); + else +#endif + ui2a(va_arg(va, unsigned int),10,0,bf); + putchw(putp,putf,w,lz,bf); + break; + } + case 'd' : { +#ifdef PRINTF_LONG_SUPPORT + if (lng) + li2a(va_arg(va, unsigned long int),bf); + else +#endif + i2a(va_arg(va, int),bf); + putchw(putp,putf,w,lz,bf); + break; + } + case 'x': case 'X' : +#ifdef PRINTF_LONG_SUPPORT + if (lng) + uli2a(va_arg(va, unsigned long int),16,(ch=='X'),bf); + else +#endif + ui2a(va_arg(va, unsigned int),16,(ch=='X'),bf); + putchw(putp,putf,w,lz,bf); + break; + case 'c' : + putf(putp,(char)(va_arg(va, int))); + break; + case 's' : + putchw(putp,putf,w,0,va_arg(va, char*)); + break; + case '%' : + putf(putp,ch); + default: + break; + } + } + } + abort:; + } + + +void init_printf(void* putp,void (*putf) (void*,char)) + { + stdout_putf=putf; + stdout_putp=putp; + } + +void tfp_printf(char *fmt, ...) + { + va_list va; + va_start(va,fmt); + tfp_format(stdout_putp,stdout_putf,fmt,va); + va_end(va); + } + +static void putcp(void* p,char c) + { + *(*((char**)p))++ = c; + } + + + +void tfp_sprintf(char* s,char *fmt, ...) + { + va_list va; + va_start(va,fmt); + tfp_format(&s,putcp,fmt,va); + putcp(&s,0); + va_end(va); + } diff --git a/Lab3/kernel/src/reboot.c b/Lab3/kernel/src/reboot.c new file mode 100644 index 000000000..133e7284f --- /dev/null +++ b/Lab3/kernel/src/reboot.c @@ -0,0 +1,16 @@ +#include "reboot.h" + +void set(long addr, unsigned int value) { + volatile unsigned int* point = (unsigned int*)addr; + *point = value; +} + +void reset(int tick) { // reboot after watchdog timer expire + set(PM_RSTC, PM_PASSWORD | 0x20); // reset + set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick +} + +void cancel_reset() { + set(PM_RSTC, PM_PASSWORD | 0); // cancel reset + set(PM_WDOG, PM_PASSWORD | 0); // number of watchdog tick +} \ No newline at end of file diff --git a/Lab3/kernel/src/shell.c b/Lab3/kernel/src/shell.c new file mode 100644 index 000000000..23beef50c --- /dev/null +++ b/Lab3/kernel/src/shell.c @@ -0,0 +1,180 @@ +#include "shell.h" +#include "uart.h" +#include "mailbox.h" +#include "utils.h" +#include "reboot.h" +#include "cpio.h" +#include "allocator.h" +#include "dtb.h" +#include "interrupt.h" +#include "time_c.h" +#include "printf.h" + +extern void *_dtb_ptr; + +#define BUFFER_MAX_SIZE 256u + +void read_command(char* buffer) { + int index = 0; + while(1) { + buffer[index] = uart_get_char(); + uart_send_char(buffer[index]); + if(buffer[index] == '\n') { + buffer[index] = '\0'; + buffer[index+1] = '\n'; + break; + } + index++; + } +} + +void shell(){ + + char buffer[BUFFER_MAX_SIZE]; + + + while(1) { + uart_buf_init(); + + + + uart_display_string("\r"); + uint32_t now; + asm volatile("adr %0,#0":"=r"(now)); + printf("0x%x",now); + uart_display_string(">>"); + read_command(buffer); + + char * input_string = buffer; + + if(!utils_find_api(input_string)){ + + if(utils_string_compare(input_string,"help")) { + uart_display_string("\r"); + uart_display_string("help : Print this help menu\n"); + uart_display_string("hello : Print Hello World!\n"); + uart_display_string("info : Get the hardware's information\n"); + uart_display_string("reboot : Reboot the device\n"); + uart_display_string("ls : List the file\n"); + uart_display_string("cat : show a file content\n"); + uart_display_string("malloc : give dynamic memory space\n"); + uart_display_string("dtb : read dtb\n"); + uart_display_string("exe : execute the user program & print Spec-info \n"); + uart_display_string("coretimer : coretimer testing\n"); + uart_display_string("async_print : print the message out of sync\n"); + uart_display_string("async_get : get the message out of sync and print the message\n"); + uart_display_string("addtimer(msg, time) : the message will print after five seconds\n"); + } + else if (utils_string_compare(input_string,"hello")) { + uart_display_string("\rHello World!\n"); + } + else if (utils_string_compare(input_string,"info")) { + get_board_revision(); + if (mailbox_call()) { + uart_display_string("\rMy board revision is: "); + uart_binary_to_hex(mailbox[5]); + uart_display_string("\n"); + } + else { + uart_display_string("Unable to query serial!\n"); + } + + get_arm_mem(); + if(mailbox_call()) { + uart_display_string("My ARM memory base address is: "); + uart_binary_to_hex(mailbox[5]); + uart_display_string("\n"); + uart_display_string("My ARM memory size is: "); + uart_binary_to_hex(mailbox[6]); + uart_display_string("\n"); + } + else { + uart_display_string("Unable to query serial!\n"); + } + } + else if (utils_string_compare(input_string,"reboot")) { + uart_display_string("Rebooting....\n"); + reset(1000); + } + else if (utils_string_compare(input_string,"ls")) { + cpio_ls(); + } + else if (utils_string_compare(input_string,"cat")){ + uart_send_char('\r'); + uart_display_string("Filename: "); + char filename[BUFFER_MAX_SIZE]; + read_command(filename); + cpio_cat(filename); + } + else if (utils_string_compare(input_string,"malloc")){ + char *a = simple_malloc(sizeof("allocater")); + char *b = simple_malloc(sizeof("345")); + a[0] = 'a'; a[1] = 'l'; a[2] = 'l'; a[3] = 'o'; + a[4] = 'c'; a[5] = 't'; a[6] = 'a'; a[7] = 'r'; + a[8] = '\0'; + b[0] = '3'; b[1] = '4'; b[2] = '5'; + b[3] = '\0'; + uart_send_char('\r'); + uart_display_string(a); + uart_send_char('\n'); + uart_send_char('\r'); + uart_display_string(b); + uart_send_char('\n'); + } + else if (utils_string_compare(input_string,"dtb")){ + fdt_traverse(print_dtb, _dtb_ptr); + } + else if (utils_string_compare(input_string, "exe")){ + uart_display_string("program name: "); + char buffer[BUFFER_MAX_SIZE]; + read_command(buffer); + cpio_load_program(buffer); + } + + else if (utils_string_compare(input_string, "async_print") || utils_string_compare(input_string, "ap")){ + uart_display_string("\r"); + uart_async_send_string("|---------->async test<----------|"); + uart_async_send_string("| | | o |"); + uart_async_send_string("| |----| | |"); + uart_async_send_string("| | | | ........... |"); + uart_async_send_string("|--------------------------------|"); + } + else if (utils_string_compare(input_string, "async_get")){ + test_uart_async(); + } + else if (utils_string_compare(input_string, "3timer")){ + setTimeout("This is 10", 10); + setTimeout("This is 5", 5); + setTimeout("This is 4", 4); + setTimeout("execute", 0); + } + else{ + uart_display_string("\rNo instruction\n"); + } + } + else{ + if(utils_api_compare(input_string,"addtimer()")){ + + + char* api_buff = (char*) simple_malloc(sizeof(input_string)); + char* message = (char*) simple_malloc(sizeof(input_string)); + char* delaytime = (char*) simple_malloc(sizeof(input_string)); + + api_buff = utils_api_analysis(input_string); + + utils_api_get_elem(api_buff, &message, &delaytime); + + char*msg = (char*) simple_malloc(sizeof(message)); + for(int i=0;i<=sizeof(message);i++){ + msg[i]=message[i]; + } + + setTimeout(msg,utils_str2int(delaytime)); + setTimeout("api executing",0); + } + else{ + uart_display_string("\rYou input a INVAILD function\n"); + } + } + } +} \ No newline at end of file diff --git a/Lab3/kernel/src/start.S b/Lab3/kernel/src/start.S new file mode 100644 index 000000000..8c4e0f58e --- /dev/null +++ b/Lab3/kernel/src/start.S @@ -0,0 +1,186 @@ +.section ".text.boot" + +.global _start + +_start: + ldr x1, =_dtb_ptr + str x0, [x1] + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #3 //Check processor id + cbz x1, exception //if CPU id = 0, jump to 2f + b hang + +hang: + wfe + b hang + +exception: + bl from_el2_to_el1 + bl set_exception_vector_table + +setup: + ldr x1, =_start + mov sp, x1 + ldr x1, =__bss_start + ldr w2, =__bss_size + +cleanBSS: + cbz w2, master + str xzr, [x1], #8 // x1* = xzr, x1 += 8 (write xzr represents discard, read xzr == 0) + sub w2, w2, #1 + cbnz w2, cleanBSS + +master: + bl core_timer_enable + bl main + b hang + +from_el2_to_el1: + mov x3, (1 << 31) // RW, bit [31] + msr hcr_el2, x3 // Execution state control for lower Exception levels (EL1) + mov x3, 0x3c5 // EL1h (SPSel = 1) with interrupt disabled + msr spsr_el2, x3 // 0x3c5 == 0b1111000101 + msr elr_el2, x30 // x30 is LR + eret // return to EL1 + +// save general registers to stack +.macro save_all + sub sp, sp, 32 * 8 + stp x0, x1, [sp ,16 * 0] + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] +.endm + +// load general registers from stack +.macro load_all + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + ldr x30, [sp, 16 * 15] + add sp, sp, 32 * 8 +.endm + +exception_handler: + save_all + bl exception_entry + load_all + eret + +irq_exception_handler: + save_all + bl irq_exception_entry + load_all + eret +.global exception_reload_all +exception_reload_all: + load_all + ret + +test_exception_handler: + save_all + bl test_entry + load_all + eret + +.align 11 // vector table should be aligned to 0x800 +.global exception_vector_table +exception_vector_table: + //同級exception level遷移,使用SP_EL0。 + b exception_handler // branch to a handler function. + .align 7 // entry size is 0x80, .align will pad 0 + b exception_handler + .align 7 + b exception_handler + .align 7 + b exception_handler + .align 7 + //同級exception level遷移,使用SP_ELx。 + b exception_handler + .align 7 + b irq_exception_handler + .align 7 + b exception_handler + .align 7 + b exception_handler + .align 7 + //ELx遷移到ELy,其中y>x且ELx處於AArch64狀態 + b exception_handler + .align 7 + b test_exception_handler + .align 7 + b exception_handler + .align 7 + b exception_handler + .align 7 + //ELx遷移到ELy,其中y>x且ELx處於AArch32狀態 + b exception_handler + .align 7 + b exception_handler + .align 7 + b exception_handler + .align 7 + b exception_handler + .align 7 + +set_exception_vector_table: + adr x1, exception_vector_table + msr vbar_el1, x1 + ret + +#define CORE0_TIMER_IRQ_CTRL 0x40000040 + +.global core_timer_enable +core_timer_enable: + mov x0, 1 + msr cntp_ctl_el0, x0 // unmask timer interrupt + ret + +.global core_timer_disable +core_timer_disable: + mov x0, 0 + msr cntp_ctl_el0,x0 + ret + +.global core_timer_irq_enable +core_timer_irq_enable: + mov x0, 2 // control timer in non-secure mode + ldr x1, =CORE0_TIMER_IRQ_CTRL + str w0, [x1] // unmask timer interrupt + ret + +.global core_timer_irq_disable +core_timer_irq_disable: + mov x0, 0 // control timer in non-secure mode + ldr x1, =CORE0_TIMER_IRQ_CTRL + str w0, [x1] // unmask timer interrupt + ret + +.global _dtb_ptr //define a global variable _dtb_ptr +.section .data //_dtb_ptr is in data section +_dtb_ptr: .dc.a 0x0 //it defines _dtb_ptr to be a 8-byte constant with a value of 0x0 \ No newline at end of file diff --git a/Lab3/kernel/src/tasklist.c b/Lab3/kernel/src/tasklist.c new file mode 100644 index 000000000..0d07d0629 --- /dev/null +++ b/Lab3/kernel/src/tasklist.c @@ -0,0 +1,86 @@ +#include "tasklist.h" +#include "allocator.h" +#include "uart.h" +#include "printf.h" +#include "interrupt.h" + +task_t *task_head = NULL; +uint64_t task_count = 0; + +void enqueue_task(task_t *new_task) { + if (!task_head) { + new_task->next = task_head; + new_task->prev = NULL; + task_head = new_task; + } + else{ + + if (new_task->priority <= task_head->priority){ //new_task的優先級比開頭的任務還大 + // new_task->callback(); + new_task->next = task_head; + new_task->prev = NULL; + task_head->prev = new_task; + task_head = new_task; + } + else { + // Find the correct position in the list + task_t *current = task_head; + while (current->next && current->next->priority <= new_task->priority) { + current = current->next; + } + // Insert the new task + new_task->next = current->next; + new_task->prev = current; + if (current->next) { + current->next->prev = new_task; + } + current->next = new_task; + } + + } +} + + +void create_task(task_callback callback, uint64_t priority) { + disable_interrupt(); + task_count++; + task_t* task = simple_malloc(sizeof(task_t)); + if(!task) { + return; + } + + task->callback = callback; + task->priority = priority; + task->task_num = task_count; + + enqueue_task(task); +} + + +void execute_tasks(uint64_t elr,uint64_t spsr) { + + while (task_head) { + int exetasknum = task_head->task_num; + // printf("execute \n"); + task_head->callback(); + // printf("execute completed\n"); + if(exetasknum != task_head->task_num){ + continue; + } + else if (task_head->next) { + // printf("task_head->next\n"); + task_head = task_head->next; + task_head->prev = NULL; + + } + else{ + // printf("ELSE\n"); + asm volatile("msr elr_el1,%0"::"r"(elr)); + asm volatile("msr spsr_el1,%0"::"r"(spsr)); + // asm volatile("msr elr_el1,%0"::"r"(task_head->elr)); + // asm volatile("msr spsr_el1,%0"::"r"(task_head->spsr)); + task_head = NULL; + task_count = 0; + } + } +} \ No newline at end of file diff --git a/Lab3/kernel/src/time.c b/Lab3/kernel/src/time.c new file mode 100644 index 000000000..9bb63b797 --- /dev/null +++ b/Lab3/kernel/src/time.c @@ -0,0 +1,89 @@ +#include "time_c.h" +#include "uart.h" +#include "interrupt.h" +#include "printf.h" +#include "utils.h" +#include "allocator.h" + +timer_info *timer_head = NULL; + + +void enqueue_timer(timer_info *newTimer){ + + if(!timer_head){ + newTimer->next = timer_head; + newTimer->prev = NULL; + timer_head = newTimer; + } + else{ + if(newTimer->executeTime < timer_head->executeTime){ + newTimer->next = timer_head; + newTimer->prev = NULL; + timer_head = newTimer; + } + else if(newTimer->executeTime >= timer_head->executeTime){ + timer_info* current = timer_head; + + while(current->next && newTimer->executeTime >= current->next->executeTime){ + current = current->next; + } + newTimer->next = current->next; + newTimer->prev = current; + if (current->next) { + current->next->prev = newTimer; + } + current->next = newTimer; + } + } + +} + +void add_timer(char* msg, unsigned long long wait){ + unsigned long long cntfrq_el0 = 0;//The base frequency + asm volatile("mrs %0,cntfrq_el0":"=r"(cntfrq_el0)); + wait = cntfrq_el0*wait;// wait 2 seconds + unsigned long long current = 0; + asm volatile("mrs %0,cntpct_el0":"=r"(current)); + + // asm volatile ("msr cntp_tval_el0, %0"::"r"(wait));//set new timer + // unsigned long long cntp_cval = 0;//The base frequency + // asm volatile("mrs %0,cntp_cval_el0":"=r"(cntp_cval)); + + timer_info* timer = simple_malloc(sizeof(timer_info)); + timer->msg = msg; + timer->executeTime = current+wait; + enqueue_timer(timer); +} + +void setTimeout(char* message, unsigned long long wait){ + // timer_head->msg = msg; + // unsigned long long cntfrq_el0 = 0;//The base frequency + // asm volatile("mrs %0,cntfrq_el0":"=r"(cntfrq_el0)); + // wait = cntfrq_el0*wait;// wait 2 seconds + // asm volatile ("msr cntp_tval_el0, %0"::"r"(wait));//set new timer + + // delay(1); + add_timer(message, wait); + asm volatile ("msr cntp_cval_el0, %0"::"r"(timer_head->executeTime));//set new timer + + asm volatile("bl core_timer_irq_enable"); + // enable_interrupt(); + + if(timer_head){ + asm volatile ("bl core_timer_irq_enable"); + } + + // while(!(utils_string_compare(timer_head->msg,""))); +} + +void timer_init(){ + // unsigned long long wait; + // timer_head->msg = "The computer has finished booting up"; + // asm volatile("bl core_timer_irq_enable"); + // unsigned long long cntfrq_el0 = 0;//The base frequency + // asm volatile("mrs %0,cntfrq_el0":"=r"(cntfrq_el0)); + // wait = cntfrq_el0*2;// wait 2 seconds + // asm volatile ("msr cntp_tval_el0, %0"::"r"(wait));//set new timer + setTimeout("The computer has finished booting up", 2); + enable_interrupt(); +} \ No newline at end of file diff --git a/Lab3/kernel/src/uart.c b/Lab3/kernel/src/uart.c new file mode 100644 index 000000000..605055541 --- /dev/null +++ b/Lab3/kernel/src/uart.c @@ -0,0 +1,241 @@ +#include "uart.h" +#include +#include +#include +#include "interrupt.h" +#include "utils.h" +#include "except_c.h" +#include "shell.h" +#include "printf.h" +#include "time_c.h" +#include "tasklist.h" + +#define RX_INTERRUPT_BIT 0x01 +#define TX_INTERRUPT_BIT 0x02 + +#define AUXINIT_BIT_POSTION 1<<29 + +#define BUFFER_MAX_SIZE 256u + +// Create a Uart read buffer +char read_buf[BUFFER_MAX_SIZE]; +// Create a Uart write buffer +char write_buf[BUFFER_MAX_SIZE]; + +char empty_buf[BUFFER_MAX_SIZE]; + +// Buffer state +int read_buf_start, read_buf_end; +int write_buf_start, write_buf_end; + +void uart_buf_init(){ + for(int i = 0; i < BUFFER_MAX_SIZE; i++){ + write_buf[i] = empty_buf[i]; + read_buf[i] = empty_buf[i]; + } + read_buf_start = read_buf_end = 0; + write_buf_start = write_buf_end = 0; +} + +void delay(unsigned int clock) +{ + while (clock--) + { + asm volatile("nop"); + } +} + +void uart_init(){ + register unsigned int r; + + r=*GPFSEL1; + r&=~((7<<12)|(7<<15)); // gpio14, gpio15 clear to 0 + r|=(2<<12)|(2<<15); // set gpio14 and 15 to 010/010 which is alt5 + *GPFSEL1 = r; // from here activate Trasmitter&Receiver + + *GPPUD = 0; + r=150; while(r--){ asm volatile("nop"); } //delay(150) + *GPPUDCLK0 = (1<<14)|(1<<15); + // GPIO control 54 pins + // GPPUDCLK0 controls 0-31 pins + // GPPUDCLK1 controls 32-53 pins + // set 14,15 bits = 1 which means we will modify these two bits + // trigger: set pins to 1 and wait for one clock + + r=150; while(r--){ asm volatile("nop"); } //delay(150) + *GPPUDCLK0 = 0; // flush GPIO setup + r=500; while(r--){ asm volatile("nop"); } //delay(500) + + /* initialize UART */ + *AUX_ENABLE |= 1; //Enable mini uart + *AUX_MU_CNTL_REG = 0; //Disable auto flow control, reciver, and transmitter + *AUX_MU_IER_REG = 0; //Disable receive and transmit interrupts + *AUX_MU_LCR_REG = 3; //Enalbe 8 bit mode + *AUX_MU_MCR_REG = 0; //Set RTS line to be always high + *AUX_MU_BAUD_REG = 270; //Set baud rate to 115200 + *AUX_MU_IIR_REG = 0x6; //0xc6 = 000110 + //bit 6 bit 7 No FIFO. Sacrifice reliability(buffer) to get low latency + //Writing with bit 1 set will clear the receive FIFO + //Writing with bit 2 set will clear the transmit FIFO + *AUX_MU_CNTL_REG = 3; //enable transmitter and receiver + + read_buf_start = read_buf_end = 0; + write_buf_start = write_buf_end = 0; +} + +void uart_send_char(unsigned int c){ + while(!(*AUX_MU_LSR_REG&0x20)); + *AUX_MU_IO_REG=c; +} + +char uart_get_char(){ + char r; + while(!(*AUX_MU_LSR_REG&0x01)); + r=(char)(*AUX_MU_IO_REG); + return r=='\r'?'\n':r; +} + +void uart_display_string(char* s){ + while(*s) { + if(*s=='\n'){ + uart_send_char('\r'); + } + uart_send_char(*s++); + } +} + +void uart_binary_to_hex(unsigned int d) { + unsigned int n; + int c; + uart_display_string("0x"); + for(c=28;c>=0;c-=4) { + // get highest tetrad(4 bits) + n=(d>>c)&0xF; + // 0-9 => '0'-'9', 10-15 => 'A'-'F' + n += n>9 ? 0x37 : 0x30; + uart_send_char(n); + } +} + +void uart_binary_to_int(unsigned int d) { + unsigned int n; + int c = 0; + while(1){ + n = d - 10*c; + if(n<10){ + uart_send_char(n); + break; + } + c = 0; + while(n>10){ + n = n/10; + c++; + } + uart_send_char(n); + } +} + +void uart_enable_interrupt() { + uintptr_t enable_irqs1 = (uintptr_t) ENABLE_IRQS_1; + enable_irqs1 |= AUXINIT_BIT_POSTION; // Set bit29 + mmio_write(ENABLE_IRQS_1, enable_irqs1); +} + +void uart_disable_interrupt() { + uintptr_t disable_irqs1 = (uintptr_t) DISABLE_IRQS_1; + disable_irqs1 |= AUXINIT_BIT_POSTION; // Set bit29 + mmio_write(DISABLE_IRQS_1, disable_irqs1); +} + +void set_transmit_interrupt() { *AUX_MU_IER_REG |= 0x2; } + +void clear_transmit_interrupt() { *AUX_MU_IER_REG &= ~(0x2); } + + +void uart_handler() +{ + int RX = (*AUX_MU_IIR_REG & 0x4); // 檢查 RX 中斷是否觸發 + int TX = (*AUX_MU_IIR_REG & 0x2); // 檢查 TX 中斷是否觸發 + int tasknum = task_head->task_num; + + + if (RX){ + uart_display_string("*"); + char c; + c = uart_get_char(); + read_buf[read_buf_end++] = c; + uart_disable_interrupt(); + *AUX_MU_IER_REG &= ~(0x1); + } + else if (TX) // 如果 TX 中斷觸發 + { + while(write_buf_start != write_buf_end){ + printf("%d", task_head->task_num); + if(task_head->task_num != tasknum){ + break; + } + char c = write_buf[write_buf_start++]; + uart_send_char(c); + delay(10000); + } + uart_disable_interrupt(); + clear_transmit_interrupt(); + } +} + +char uart_async_get() { + + *AUX_MU_IER_REG |= (0x1); + + while (read_buf_start == read_buf_end) + { + uart_enable_interrupt(); + // enable_interrupt(); + } + char c = read_buf[read_buf_start++]; + return c; +} + +void uart_async_send_string(char *str) { + write_buf[write_buf_end++] = '\r'; + + for (int i = 0; str[i]; i++){ + // printf("\rwrite_buf_end = %d\r\n", write_buf_end); + if (write_buf_end == BUFFER_MAX_SIZE) + write_buf_end = 0; + write_buf[write_buf_end++] = str[i]; + } + + if(write_buf[write_buf_end-1] != '\n'){ + write_buf[write_buf_end++] = '\n'; + } + // uart_display_string("\r*****************************\r\n"); + while(write_buf_start != write_buf_end){ + uart_enable_interrupt(); + set_transmit_interrupt(); + // enable_interrupt(); + } +} + +void test_uart_async() +{ + char buffer[BUFFER_MAX_SIZE]; + size_t index = 0; + uart_display_string("\r"); + while(1){ + buffer[index] = uart_async_get(); + if(buffer[index]=='\n'){ + break; + } + index++; + } + uart_display_string("\r\n"); + uart_async_send_string(read_buf); + +} + +// This function is required by printf function +void putc ( void* p, char c) +{ + uart_send_char(c); +} \ No newline at end of file diff --git a/Lab3/kernel/src/utils.S b/Lab3/kernel/src/utils.S new file mode 100644 index 000000000..24999d0b5 --- /dev/null +++ b/Lab3/kernel/src/utils.S @@ -0,0 +1,9 @@ +.global get_el +get_el: + mrs x0, CurrentEL + lsr x0, x0, #2 + ret +.global get_sp +get_sp: + mrs x0, SPSel + ret \ No newline at end of file diff --git a/Lab3/kernel/src/utils.c b/Lab3/kernel/src/utils.c new file mode 100644 index 000000000..1d68c9cc4 --- /dev/null +++ b/Lab3/kernel/src/utils.c @@ -0,0 +1,156 @@ +#include "utils.h" +#include "uart.h" +#include +#include + +int utils_string_compare(const char* str1,const char* str2) { + + for(;*str1 !='\n'||*str2 !='\0';str1++,str2++){ + + if(*str1 != *str2){ + return 0; + } + else if(*str1 == '\n' || *str2 =='\0'){ + return 1; + } + + } + return 1; + +} + +char* utils_api_analysis(char* str1){ + + while(*str1){ + + if(*str1 == '('){ + break; + } + str1++; + } + return str1; +} + +int utils_api_compare(const char* str1,const char* str2) { + + for(;*str1 !='('||*str2 !='(';str1++,str2++){ + + if(*str1 != *str2){ + return 0; + } + } + return 1; + +} + +int utils_api_elem_count(const char* str1){ + int count = 0; + if(*(str1+1) == ')'){ + return 0; + } + while(*str1){ + if(*str1 == ',' || *str1 == ')'){ + count++; + } + str1++; + } + return count; +} + +int utils_find_api(const char* str1) { + int bracket_before = 0; + int bracket_after = 0; + while(*str1 !='\n'){ + + if(*str1 == '('){ + bracket_before = 1; + } + else if(bracket_before && *str1 == ')'){ + bracket_after = 1; + } + + if(bracket_after && bracket_after){ + return 1; + } + + str1++; + } + return 0; +} + +void utils_api_get_elem(const char* str1, char** buff1, char** buff2){ + char* copy = (char*) str1; + char* commaPos = copy; + char* bracketPos = copy; + while (*commaPos != ',') { + ++commaPos; + } + while (*bracketPos != ')') { + ++bracketPos; + } + + if(*commaPos ==','){ + *commaPos = '\0'; + *bracketPos = '\0'; + *buff1 = copy+1; + *buff2 = commaPos+1; + } +} + +unsigned long utils_hex2dec(const char *s, int char_size) { + unsigned long num = 0; + for (int i = 0; i < char_size; i++) { + num = num * 16; + if (*s >= '0' && *s <= '9') { + num += (*s - '0'); + } else if (*s >= 'A' && *s <= 'F') { + num += (*s - 'A' + 10); + } else if (*s >= 'a' && *s <= 'f') { + num += (*s - 'a' + 10); + } + s++; + } + return num; +} + +void utils_align(void *size, unsigned int s) { + unsigned long* x = (unsigned long*) size; + unsigned long mask = s-1; + *x = ((*x) + mask) & (~mask); +} + +uint32_t utils_align_up(uint32_t size, int alignment) { + return (size + alignment - 1) & ~(alignment-1); +} + +size_t utils_strlen(const char *s) { + size_t i = 0; + while (s[i]) i++; + return i+1; +} + +int utils_keyword_compare(const char* str1,const char* str2) { + + while(*str1 !='\0' && *str2 !='\0'){ + + if(*str1 != *str2){ + return 0; + } + else{ + str1++; + str2++; + } + } + return 1; +} + +int utils_str2int(const char* s){ + int num = 0; + while(*s){ + if(*s == '\0' || *s == '\n') break; + num = num *10; + num = num + (*s - '0'); + s++; + } + return num; +} \ No newline at end of file diff --git a/Lab3/kernel/uploader.py b/Lab3/kernel/uploader.py new file mode 100644 index 000000000..0be5daa8a --- /dev/null +++ b/Lab3/kernel/uploader.py @@ -0,0 +1,54 @@ +import serial +import os +import os.path +import sys +import time + +BAUD_RATE = 115200 + +def read_line(s): + received_string = "" + while True: + try: + c = s.read(1).decode() + except UnicodeDecodeError: + c = s.read(1).decode() + + if c=="\r": + continue + if c=="\n": + break + received_string += c + return received_string + +def send_img(ser, kernel): + print(read_line(ser)) + + kernel_size = os.stat(kernel).st_size + print((str(kernel_size) + "\n").encode()) + ser.write(("."+ str(kernel_size) + "\n").encode()) + + print("kernel size is ", read_line(ser)) + # print(read_line(ser)) + print(read_line(ser)) + + # 將映像檔逐一傳輸到對方端 + with open(kernel, "rb") as image: + while kernel_size > 0: + ser.write(image.read(1)) + kernel_size -= 1 + # ser.read_until(b".") + # 讀取對方端傳來的結束訊息 + print(read_line(ser)) + print(read_line(ser)) + print(ser.read_until("> ").decode(), end="") + return + +# 程式進入點 +if __name__ == "__main__": + # 設定串列通訊的埠號和傳輸速率,以及逾時時間 + # ser = serial.Serial("/dev/ttyUSB0", BAUD_RATE, timeout=5) + ser = serial.Serial("COM10", BAUD_RATE, timeout=5) + + # 傳輸映像檔 + send_img(ser, "kernel8.img") \ No newline at end of file