diff --git a/lab3/kernel/build/kernel8.elf b/lab3/kernel/build/kernel8.elf index 03d4b2547..5e498fa1c 100755 Binary files a/lab3/kernel/build/kernel8.elf and b/lab3/kernel/build/kernel8.elf differ diff --git a/lab3/kernel/src/exception.c b/lab3/kernel/src/exception.c index c91cf021d..33f3b7c0e 100644 --- a/lab3/kernel/src/exception.c +++ b/lab3/kernel/src/exception.c @@ -24,13 +24,13 @@ void el1h_irq_router(){ if (*AUX_MU_IIR_REG & (1 << 1)) // FIFO clear bits { *AUX_MU_IER_REG &= ~(2); // disable write interrupt - irqtask_add(uart_w_irq_handler, UART_IRQ_PRIORITY); + irqtask_add(uart_w_irq_handler, UART_IRQ_PRIORITY); //rpi write mean we read irqtask_run_preemptive(); // run the queued task before returning to the program. } else if (*AUX_MU_IIR_REG & (2 << 1)) // Interrupt ID bits { *AUX_MU_IER_REG &= ~(1); // disable read interrupt - irqtask_add(uart_r_irq_handler, timer_priority); + irqtask_add(uart_r_irq_handler, UART_IRQ_PRIORITY); //rpi read mean we write irqtask_run_preemptive(); } } @@ -154,8 +154,7 @@ void irqtask_run_preemptive() // Run new task (early return) if its priority is lower than the scheduled task. if (curr_task_priority <= the_task->priority) { - exit = 1; - + //exit = 1; el1_interrupt_enable(); break; } diff --git a/lab3/kernel/src/shell.c b/lab3/kernel/src/shell.c index cc8a69974..e6d7c6193 100644 --- a/lab3/kernel/src/shell.c +++ b/lab3/kernel/src/shell.c @@ -33,12 +33,12 @@ void cli_cmd_read(char* buffer) while (1) { if (idx >= CMD_MAX_LEN) break; - c = uart_async_getc(); //test preemtive + c = uart_async_getc(); if (c == '\n') break; if (c == 127 && idx > 0) { - uart_puts("\b \b"); //test preemptive + uart_puts("\b \b"); idx--; continue; } @@ -301,7 +301,7 @@ void do_cmd_reboot() void do_test_preemptive() { add_timer(test_loop, 1, "test loop"); - add_timer(set_exit, 10, "exit"); + add_timer(set_exit, 5, "exit"); } volatile int exit = 0; @@ -314,6 +314,6 @@ void test_loop() void set_exit() { - //exit = 1; - uart_sendline("We set exit as 1 to exit infinite loop at t = 10s.\n"); + exit = 1; + uart_sendline("We set exit as 1 to exit infinite loop at t = 5s.\n"); } \ No newline at end of file diff --git a/lab3/kernel/src/timer.c b/lab3/kernel/src/timer.c index 3f24138af..58bdfc594 100644 --- a/lab3/kernel/src/timer.c +++ b/lab3/kernel/src/timer.c @@ -7,6 +7,7 @@ #define STR(x) #x #define XSTR(s) STR(s) + struct list_head* timer_event_list; // first head has nothing, store timer_event_t after it void timer_list_init(){ @@ -60,12 +61,13 @@ void timer_event_callback(timer_event_t * timer_event){ } core_timer_enable(); ((void (*)(char*))timer_event->callback)(timer_event->args); // call the event + } void timer_set2sAlert(char* str) { static int count = 0; - if(count > 10){ + if(count > 3){ return; } count++; diff --git a/lab3/kernel/src/uart1.c b/lab3/kernel/src/uart1.c index 557043054..d56dddabd 100644 --- a/lab3/kernel/src/uart1.c +++ b/lab3/kernel/src/uart1.c @@ -90,32 +90,53 @@ int uart_sendline(char* fmt, ...) { } -// uart_async_getc read from buffer -// uart_r_irq_handler write to buffer then output +// Read a character asynchronously from UART receive buffer. char uart_async_getc() { - *AUX_MU_IER_REG |=1; // enable read interrupt - // do while if buffer empty - while (uart_rx_buffer_ridx == uart_rx_buffer_widx) *AUX_MU_IER_REG |=1; // enable read interrupt + // Enable read interrupt + *AUX_MU_IER_REG |= 1; + + // Loop until the buffer has data + while (uart_rx_buffer_ridx == uart_rx_buffer_widx) { + *AUX_MU_IER_REG |= 1; // Keep enabling read interrupt + } + + // Disable interrupts to ensure atomic operations el1_interrupt_disable(); + + // Read character from the buffer and increment read index char r = uart_rx_buffer[uart_rx_buffer_ridx++]; + // Wrap around the index if it exceeds the buffer size if (uart_rx_buffer_ridx >= VSPRINT_MAX_BUF_SIZE) uart_rx_buffer_ridx = 0; + + // Re-enable interrupts el1_interrupt_enable(); - return r; + + return r; // Return the read character } - -// uart_async_putc writes to buffer -// uart_w_irq_handler read from buffer then output +// Write a character asynchronously to UART transmit buffer. void uart_async_putc(char c) { - // if buffer full, wait for uart_w_irq_handler - while( (uart_tx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_tx_buffer_ridx ) *AUX_MU_IER_REG |=2; // enable write interrupt + // Wait if the buffer is full + while((uart_tx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_tx_buffer_ridx) { + *AUX_MU_IER_REG |= 2; // Enable write interrupt + } + + // Disable interrupts to ensure atomic operations el1_interrupt_disable(); + + // Write character to the buffer and increment write index uart_tx_buffer[uart_tx_buffer_widx++] = c; - if(uart_tx_buffer_widx >= VSPRINT_MAX_BUF_SIZE) uart_tx_buffer_widx=0; // cycle pointer + // Wrap around the index if it exceeds the buffer size + if(uart_tx_buffer_widx >= VSPRINT_MAX_BUF_SIZE) uart_tx_buffer_widx = 0; + + // Re-enable interrupts el1_interrupt_enable(); - *AUX_MU_IER_REG |=2; // enable write interrupt + + // Enable write interrupt + *AUX_MU_IER_REG |= 2; } + int uart_puts(char* fmt, ...) { __builtin_va_list args; __builtin_va_start(args, fmt); @@ -147,25 +168,36 @@ void uart_interrupt_disable(){ } -void uart_r_irq_handler(){ - if((uart_rx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_rx_buffer_ridx) - { - *AUX_MU_IER_REG &= ~(1); // disable read interrupt +// UART receive interrupt handler +void uart_r_irq_handler() { + // Check if the buffer is full + if((uart_rx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_rx_buffer_ridx) { + // Disable read interrupt to prevent overflow + *AUX_MU_IER_REG &= ~(1); return; } + // Read data from UART and store it in the buffer uart_rx_buffer[uart_rx_buffer_widx++] = uart_recv(); - if(uart_rx_buffer_widx>=VSPRINT_MAX_BUF_SIZE) uart_rx_buffer_widx=0; - *AUX_MU_IER_REG |=1; + // Wrap the write index if it reaches the buffer size + if(uart_rx_buffer_widx >= VSPRINT_MAX_BUF_SIZE) uart_rx_buffer_widx = 0; + // Re-enable read interrupt + *AUX_MU_IER_REG |= 1; } -void uart_w_irq_handler(){ - if(uart_tx_buffer_ridx == uart_tx_buffer_widx) - { - *AUX_MU_IER_REG &= ~(2); // disable write interrupt - return; // buffer empty +// UART write interrupt handler +void uart_w_irq_handler() { + // Check if the buffer is empty + if(uart_tx_buffer_ridx == uart_tx_buffer_widx) { + // Disable write interrupt to avoid unnecessary interrupts + *AUX_MU_IER_REG &= ~(2); + return; // Exit if nothing to send } + // Send data from the buffer via UART uart_send(uart_tx_buffer[uart_tx_buffer_ridx++]); - if(uart_tx_buffer_ridx>=VSPRINT_MAX_BUF_SIZE) uart_tx_buffer_ridx=0; - *AUX_MU_IER_REG |=2; // enable write interrupt + // Wrap the read index if it reaches the buffer size + if(uart_tx_buffer_ridx >= VSPRINT_MAX_BUF_SIZE) uart_tx_buffer_ridx = 0; + // Re-enable write interrupt + *AUX_MU_IER_REG |= 2; } + diff --git a/lab4/bootloader/bcm2710-rpi-3-b-plus.dtb b/lab4/bootloader/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..38395a23f Binary files /dev/null and b/lab4/bootloader/bcm2710-rpi-3-b-plus.dtb differ diff --git a/lab4/bootloader/config.txt b/lab4/bootloader/config.txt new file mode 100644 index 000000000..15654a481 --- /dev/null +++ b/lab4/bootloader/config.txt @@ -0,0 +1,3 @@ +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x8000000 diff --git a/lab4/bootloader/include/bcm2837/rpi_base.h b/lab4/bootloader/include/bcm2837/rpi_base.h new file mode 100644 index 000000000..e3259e8de --- /dev/null +++ b/lab4/bootloader/include/bcm2837/rpi_base.h @@ -0,0 +1,6 @@ +#ifndef _RPI_BASE_H_ +#define _RPI_BASE_H_ + +#define PERIPHERAL_BASE 0x3F000000 + +#endif /*_RPI_BASE_H_ */ diff --git a/lab4/bootloader/include/bcm2837/rpi_gpio.h b/lab4/bootloader/include/bcm2837/rpi_gpio.h new file mode 100644 index 000000000..e5133708a --- /dev/null +++ b/lab4/bootloader/include/bcm2837/rpi_gpio.h @@ -0,0 +1,25 @@ +#ifndef _RPI_GPIO_H_ +#define _RPI_GPIO_H_ + +#include "bcm2837/rpi_base.h" + +#define GPFSEL0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200000)) +#define GPFSEL1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200004)) +#define GPFSEL2 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200008)) +#define GPFSEL3 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0020000C)) +#define GPFSEL4 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200010)) +#define GPFSEL5 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200014)) +#define GPSET0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0020001C)) +#define GPSET1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200020)) +#define GPCLR0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200028)) +#define GPLEV0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200034)) +#define GPLEV1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200038)) +#define GPEDS0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200040)) +#define GPEDS1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200044)) +#define GPHEN0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200064)) +#define GPHEN1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200068)) +#define GPPUD ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200094)) +#define GPPUDCLK0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200098)) +#define GPPUDCLK1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0020009C)) + +#endif /*_RPI_GPIO_H_*/ diff --git a/lab4/bootloader/include/bcm2837/rpi_uart1.h b/lab4/bootloader/include/bcm2837/rpi_uart1.h new file mode 100644 index 000000000..959130656 --- /dev/null +++ b/lab4/bootloader/include/bcm2837/rpi_uart1.h @@ -0,0 +1,19 @@ +#ifndef _RPI_UART1_H_ +#define _RPI_UART1_H_ + +#include "bcm2837/rpi_base.h" + +#define AUX_ENABLES ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215004)) +#define AUX_MU_IO_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215040)) +#define AUX_MU_IER_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215044)) +#define AUX_MU_IIR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215048)) +#define AUX_MU_LCR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x0021504C)) +#define AUX_MU_MCR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215050)) +#define AUX_MU_LSR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215054)) +#define AUX_MU_MSR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215058)) +#define AUX_MU_SCRATCH ((volatile unsigned int*)(PERIPHERAL_BASE+0x0021505C)) +#define AUX_MU_CNTL_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215060)) +#define AUX_MU_STAT_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215064)) +#define AUX_MU_BAUD_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215068)) + +#endif /*_RPI_UART1_H_ */ diff --git a/lab4/bootloader/include/power.h b/lab4/bootloader/include/power.h new file mode 100644 index 000000000..baf990974 --- /dev/null +++ b/lab4/bootloader/include/power.h @@ -0,0 +1,8 @@ +#ifndef _POWER_H_ +#define _POWER_H_ + +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 + +#endif /*_POWER_H_*/ diff --git a/lab4/bootloader/include/shell.h b/lab4/bootloader/include/shell.h new file mode 100644 index 000000000..702f5eb14 --- /dev/null +++ b/lab4/bootloader/include/shell.h @@ -0,0 +1,23 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ + +#define CLI_MAX_CMD 3 +#define CMD_MAX_LEN 32 +#define MSG_MAX_LEN 128 + +typedef struct CLI_CMDS +{ + char command[CMD_MAX_LEN]; + char help[MSG_MAX_LEN]; +} CLI_CMDS; + +void cli_cmd_clear(char*, int); +void cli_cmd_read(char*); +void cli_cmd_exec(char*); +void cli_print_banner(); + +void do_cmd_help(); +void do_cmd_loadimg(); +void do_cmd_reboot(); + +#endif /* _SHELL_H_ */ diff --git a/lab4/bootloader/include/uart1.h b/lab4/bootloader/include/uart1.h new file mode 100644 index 000000000..329d25c81 --- /dev/null +++ b/lab4/bootloader/include/uart1.h @@ -0,0 +1,11 @@ +#ifndef _UART1_H_ +#define _UART1_H_ + +void uart_init(); +char uart_getc(); +char uart_recv(); +void uart_send(unsigned int c); +int uart_puts(char* fmt, ...); +void uart_2hex(unsigned int d); + +#endif /*_UART1_H_*/ diff --git a/lab4/bootloader/include/utils.h b/lab4/bootloader/include/utils.h new file mode 100644 index 000000000..e65ece675 --- /dev/null +++ b/lab4/bootloader/include/utils.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#define VSPRINT_MAX_BUF_SIZE 128 + +unsigned int sprintf(char *dst, char* fmt, ...); +unsigned int vsprintf(char *dst,char* fmt, __builtin_va_list args); + +int strcmp(const char*, const char*); + +#endif /* _UTILS_H_ */ diff --git a/lab4/bootloader/makefile b/lab4/bootloader/makefile new file mode 100644 index 000000000..b81bad692 --- /dev/null +++ b/lab4/bootloader/makefile @@ -0,0 +1,42 @@ +ARMGNU ?= aarch64-linux-gnu + +CFLAGS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only +ASMFLAGS = -Iinclude + +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) + +$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c + @mkdir -p $(@D) + $(ARMGNU)-gcc $(CFLAGS) -MMD -c $< -o $@ + +$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S + $(ARMGNU)-gcc $(ASMFLAGS) -MMD -c $< -o $@ + +bootloader.img: $(SRC_DIR)/link.ld $(OBJ_FILES) + $(ARMGNU)-ld -T $(SRC_DIR)/link.ld -o $(BUILD_DIR)/bootloader.elf $(OBJ_FILES) + $(ARMGNU)-objcopy $(BUILD_DIR)/bootloader.elf -O binary bootloader.img + +all: bootloader.img + +clean: + rm -rf $(BUILD_DIR) *.img + +run_std: + qemu-system-aarch64 -M raspi3b -kernel bootloader.img -serial null -serial stdio -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +run_pty: + qemu-system-aarch64 -M raspi3b -kernel bootloader.img -serial null -serial pty -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +debug: + qemu-system-aarch64 -M raspi3b -kernel bootloader.img -display none -S -s + diff --git a/lab4/bootloader/src/boot.S b/lab4/bootloader/src/boot.S new file mode 100644 index 000000000..c872f56a7 --- /dev/null +++ b/lab4/bootloader/src/boot.S @@ -0,0 +1,52 @@ +/* ARMv8 Assembly Instruction */ +/** + +mov x0, x1 + sets: x0 = x1 +ldr x0, + load 32bits from to x0 +ldr w0, + load 64bits from to w0 +cbz x0,