From af5212a59020ebaaabca7d77588aecf7f32f7f46 Mon Sep 17 00:00:00 2001 From: Aaron7noraA Date: Thu, 25 Apr 2024 21:52:06 +0800 Subject: [PATCH] akokoq --- LAB3/.vscode/settings.json | 5 + LAB3/Makefile | 84 ++++++++ LAB3/archive/rootfs/file1 | 1 + LAB3/archive/rootfs/file2.txt | 1 + LAB3/archive/rootfs/testfile | 1 + LAB3/archive/rootfs/user1.img | Bin 0 -> 24 bytes LAB3/bcm2710-rpi-3-b-plus.dtb | Bin 0 -> 34228 bytes LAB3/bootloader/linker.ld | 28 +++ LAB3/bootloader/main.c | 48 +++++ LAB3/bootloader/start.s | 46 +++++ LAB3/config.txt | 3 + LAB3/include/_cpio.h | 34 ++++ LAB3/include/allocator.h | 6 + LAB3/include/dtb.h | 35 ++++ LAB3/include/exception_c.h | 27 +++ LAB3/include/mini_uart.h | 23 +++ LAB3/include/peripheral/base.h | 7 + LAB3/include/peripheral/gpio.h | 12 ++ LAB3/include/peripheral/mailbox.h | 27 +++ LAB3/include/peripheral/mini_uart.h | 30 +++ LAB3/include/shell.h | 7 + LAB3/include/sprintf.h | 31 +++ LAB3/include/timer.h | 29 +++ LAB3/include/utils_c.h | 29 +++ LAB3/include/utils_s.h | 27 +++ LAB3/initramfs.cpio | Bin 0 -> 512 bytes LAB3/kernel/exception_c.c | 161 +++++++++++++++ LAB3/kernel/exception_s.s | 106 ++++++++++ LAB3/kernel/linker.ld | 27 +++ LAB3/kernel/main.c | 28 +++ LAB3/kernel/start.s | 42 ++++ LAB3/loadImg/loadImg.py | 30 +++ LAB3/src/_cpio.c | 142 +++++++++++++ LAB3/src/allocator.c | 16 ++ LAB3/src/dtb.c | 137 +++++++++++++ LAB3/src/mailbox.c | 63 ++++++ LAB3/src/memzero.s | 7 + LAB3/src/mini_uart.c | 301 ++++++++++++++++++++++++++++ LAB3/src/shell.c | 162 +++++++++++++++ LAB3/src/sprintf.c | 152 ++++++++++++++ LAB3/src/timer.c | 134 +++++++++++++ LAB3/src/utils_c.c | 167 +++++++++++++++ LAB3/src/utils_s.s | 6 + LAB3/users/user1/linker.ld | 15 ++ LAB3/users/user1/main.s | 11 + 45 files changed, 2248 insertions(+) create mode 100644 LAB3/.vscode/settings.json create mode 100644 LAB3/Makefile create mode 100644 LAB3/archive/rootfs/file1 create mode 100644 LAB3/archive/rootfs/file2.txt create mode 100644 LAB3/archive/rootfs/testfile create mode 100755 LAB3/archive/rootfs/user1.img create mode 100644 LAB3/bcm2710-rpi-3-b-plus.dtb create mode 100644 LAB3/bootloader/linker.ld create mode 100644 LAB3/bootloader/main.c create mode 100644 LAB3/bootloader/start.s create mode 100644 LAB3/config.txt create mode 100644 LAB3/include/_cpio.h create mode 100644 LAB3/include/allocator.h create mode 100644 LAB3/include/dtb.h create mode 100644 LAB3/include/exception_c.h create mode 100644 LAB3/include/mini_uart.h create mode 100644 LAB3/include/peripheral/base.h create mode 100644 LAB3/include/peripheral/gpio.h create mode 100644 LAB3/include/peripheral/mailbox.h create mode 100644 LAB3/include/peripheral/mini_uart.h create mode 100644 LAB3/include/shell.h create mode 100644 LAB3/include/sprintf.h create mode 100644 LAB3/include/timer.h create mode 100644 LAB3/include/utils_c.h create mode 100644 LAB3/include/utils_s.h create mode 100644 LAB3/initramfs.cpio create mode 100644 LAB3/kernel/exception_c.c create mode 100644 LAB3/kernel/exception_s.s create mode 100644 LAB3/kernel/linker.ld create mode 100644 LAB3/kernel/main.c create mode 100644 LAB3/kernel/start.s create mode 100644 LAB3/loadImg/loadImg.py create mode 100644 LAB3/src/_cpio.c create mode 100644 LAB3/src/allocator.c create mode 100644 LAB3/src/dtb.c create mode 100644 LAB3/src/mailbox.c create mode 100644 LAB3/src/memzero.s create mode 100644 LAB3/src/mini_uart.c create mode 100644 LAB3/src/shell.c create mode 100644 LAB3/src/sprintf.c create mode 100644 LAB3/src/timer.c create mode 100644 LAB3/src/utils_c.c create mode 100644 LAB3/src/utils_s.s create mode 100644 LAB3/users/user1/linker.ld create mode 100644 LAB3/users/user1/main.s diff --git a/LAB3/.vscode/settings.json b/LAB3/.vscode/settings.json new file mode 100644 index 000000000..5e6760a31 --- /dev/null +++ b/LAB3/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "base.h": "c" + } +} diff --git a/LAB3/Makefile b/LAB3/Makefile new file mode 100644 index 000000000..40f58b4ba --- /dev/null +++ b/LAB3/Makefile @@ -0,0 +1,84 @@ +CFLAG = -Iinclude -Wall -ffreestanding -fno-stack-protector -nostdlib -nostartfiles -mgeneral-regs-only +K8=kernel8 +BL=bootloader +LINKER=linker.ld +START=start +CPIO:=archive/initramfs.cpio +DTB:=archive/bcm2710-rpi-3-b-plus.dtb +USER_DIR:=users/user +USER1:=user1 +BUILD:=build/ + +BUILD_ELF:=$(shell find build/ -name '*.elf') +BUILD_IMG:=$(shell find build/ -name '*.img') +ARC_IMG:=$(shell find archive/ -name '*.img') + +SRC_C:=$(shell find src/ -name '*.c') +SRC_S:=$(shell find src/ -name '*.s') + +KER_C:=$(shell find kernel/ -name '*.c') +KER_S:=$(shell find kernel/ -name '*.s') + +BL_C:=$(shell find bootloader/ -name '*.c') +BL_S:=$(shell find bootloader/ -name '*.s') + +USER1_S:=$(shell find users/user1/ -name '*.s') +USER1_OBJS:= $(USER1_S:%.s=%.o) + +OBJS:= $(SRC_C:%.c=%.o) \ + $(SRC_S:%.s=%.o) \ + rd.o + + +KERNEL_OBJS:=$(KER_C:%.c=%.o) \ + $(KER_S:%.s=%.o) + + + +BL_OBJS:=$(BL_C:%.c=%.o) \ + $(BL_S:%.s=%.o) \ + src/mini_uart.o src/utils_c.o src/utils_s.o src/memzero.o src/sprintf.o + + + + +all: $(BUILD)$(USER1).img $(BUILD)$(K8).img $(BUILD)$(BL).img + + + +rd.o:$(CPIO) + aarch64-linux-gnu-ld -r -b binary -o rd.o $(CPIO) + + +%.o: %.s + aarch64-linux-gnu-gcc -g -o $@ -c $< + +%.o: %.c + aarch64-linux-gnu-gcc -g -o $@ $(CFLAG) -c $< + + +$(BUILD)$(K8).img: $(OBJS) $(KERNEL_OBJS) + aarch64-linux-gnu-ld -T kernel/$(LINKER) -o $(BUILD)$(K8).elf $^ + aarch64-linux-gnu-objcopy -O binary $(BUILD)$(K8).elf $@ + +$(BUILD)$(BL).img: $(BL_OBJS) + aarch64-linux-gnu-ld -T bootloader/$(LINKER) -o $(BUILD)$(BL).elf $^ + aarch64-linux-gnu-objcopy -O binary $(BUILD)$(BL).elf $@ + +$(BUILD)$(USER1).img:$(USER1_OBJS) + aarch64-linux-gnu-ld -T $(USER_DIR)1/$(LINKER) -o $(BUILD)$(USER1).elf $< + aarch64-linux-gnu-objcopy -O binary $(BUILD)$(USER1).elf $@ + cp $@ archive/rootfs/ + +$(CPIO): + cd archive/rootfs&&find . | cpio -o -H newc > ../initramfs.cpio + +on: + screen /dev/cu.usbserial-0001 115200 + +clean: + $(RM) $(BUILD_ELF) $(CPIO) \ + $(OBJS) $(KERNEL_OBJS) $(BL_OBJS) $(USER1_OBJS) \ + $(BUILD_IMG) \ + # $(BUILD_IMG) $(ARC_IMG) + \ No newline at end of file diff --git a/LAB3/archive/rootfs/file1 b/LAB3/archive/rootfs/file1 new file mode 100644 index 000000000..ea25c3f29 --- /dev/null +++ b/LAB3/archive/rootfs/file1 @@ -0,0 +1 @@ +Testing for File1 \ No newline at end of file diff --git a/LAB3/archive/rootfs/file2.txt b/LAB3/archive/rootfs/file2.txt new file mode 100644 index 000000000..07b33ba34 --- /dev/null +++ b/LAB3/archive/rootfs/file2.txt @@ -0,0 +1 @@ +Testing for file2 \ No newline at end of file diff --git a/LAB3/archive/rootfs/testfile b/LAB3/archive/rootfs/testfile new file mode 100644 index 000000000..16e0f2d50 --- /dev/null +++ b/LAB3/archive/rootfs/testfile @@ -0,0 +1 @@ +aaaaaasq \ No newline at end of file diff --git a/LAB3/archive/rootfs/user1.img b/LAB3/archive/rootfs/user1.img new file mode 100755 index 0000000000000000000000000000000000000000..1adf648a4c1b9d2d1b5e9fa08b84e52ef2fafc78 GIT binary patch literal 24 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 +#define BUFFER_MAX_SIZE 256u + +extern char *_dtb; +void load_img() +{ + char * kernel_addr = (char *)0x80000; + uart_send_string("Please sent the kernel image size:"); + char buffer[BUFFER_MAX_SIZE]; + // read_command(buffer); + size_t index = 0; + while (1) + { + buffer[index] = uart_recv(); + uart_send(buffer[index]); + if (buffer[index] == '\n') + { + break; + } + index++; + } + buffer[index + 1] = '\0'; + utils_newline2end(buffer); + uart_send('\r'); + unsigned int img_size = utils_str2uint_dec(buffer); + uart_send_string("Start to load the kernel image... \n"); + + unsigned char *current = (unsigned char *)kernel_addr; + while (img_size--) + { + *current = uart_recv_raw(); + current++; + uart_send('.'); + } + uart_send_string("loading...\n"); + // branchAddr(kernel_addr); + ((void (*)(char *))kernel_addr)(_dtb); +} + +void bootloader_main(void) +{ + uart_init(); + uart_send_string("In bootloader_main!\n"); + load_img(); +} \ No newline at end of file diff --git a/LAB3/bootloader/start.s b/LAB3/bootloader/start.s new file mode 100644 index 000000000..549ee4109 --- /dev/null +++ b/LAB3/bootloader/start.s @@ -0,0 +1,46 @@ +.section ".text.relo" +.globl _start + +# need to relocate the bootloader from 0x80000 to 0x60000 +_start: + adr x10, . //x10=0x80000 + ldr x11, =_blsize + add x11, x11, x10 + ldr x12, =_stext // x12=0x60000 + +moving_relo: + cmp x10, x11 //without bootloader + b.eq end_relo + ldr x13, [x10] + str x13, [x12] //move 0x80000 data to 0x60000 + add x12, x12, #8 + add x10, x10, #8 + b moving_relo +end_relo: + ldr x14, =_bl_entry //jump to boot part + br x14 + + +.section ".text.boot" +.globl _start_bl + ldr x20, =_dtb + str x0, [x20] + mrs x20, mpidr_el1 + and x20, x20,#0xFF // Check processor id + cbz x20, master // Hang for all non-primary CPU + +hang: + b hang + +master: + adr x20, _sbss + adr x21, _ebss + sub x21, x21, x20 + bl memzero + + mov sp, #0x400000 // 4MB + bl bootloader_main + +.global _dtb +.section .data +_dtb: .dc.a 0x0 diff --git a/LAB3/config.txt b/LAB3/config.txt new file mode 100644 index 000000000..13201285b --- /dev/null +++ b/LAB3/config.txt @@ -0,0 +1,3 @@ +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x2000000 \ No newline at end of file diff --git a/LAB3/include/_cpio.h b/LAB3/include/_cpio.h new file mode 100644 index 000000000..da4093d5a --- /dev/null +++ b/LAB3/include/_cpio.h @@ -0,0 +1,34 @@ +#ifndef __CPIO_H +#define __CPIO_H +// #define CPIO_ADDR (char *)0x8000000; // qemu +// #define CPIO_ADDR (char *)0x20000000; // raspi3 + +/* + cpio archive comprises a header record with basic numeric metadata followed by + the full pathname of the entry and the file data. +*/ +typedef struct cpio_header +{ + // uses 8-byte hexadecimal fields for all numbers + char c_magic[6]; //determine whether this archive is written with little-endian or big-endian integers. + char c_ino[8]; //determine when two entries refer to the same file. + char c_mode[8]; //specifies both the regular permissions and the file type. + char c_uid[8]; // numeric user id + char c_gid[8]; // numeric group id + char c_nlink[8]; // number of links to this file. + char c_mtime[8]; // Modification time of the file + char c_filesize[8]; // size of the file + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; // number of bytes in the pathname + char c_check[8]; // always set to zero by writers and ignored by readers. +}cpio_header; + +extern char * cpio_addr; +void cpio_ls(); +void cpio_cat(char *filename); +char * findFile(char *name); +void cpio_load_program(char *filename); +#endif \ No newline at end of file diff --git a/LAB3/include/allocator.h b/LAB3/include/allocator.h new file mode 100644 index 000000000..ba8ca9a9e --- /dev/null +++ b/LAB3/include/allocator.h @@ -0,0 +1,6 @@ +#ifndef _ALLOCATOR_H +#define _ALLOCATOR_H +#include + +void* malloc(size_t size); +#endif \ No newline at end of file diff --git a/LAB3/include/dtb.h b/LAB3/include/dtb.h new file mode 100644 index 000000000..7b2c0b23b --- /dev/null +++ b/LAB3/include/dtb.h @@ -0,0 +1,35 @@ +#ifndef _DTB_H +#define _DTB_H +#include +#include +/* + structure block: located at a 4-byte aligned offset from the beginning of the devicetree blob + token is a big-endian 32-bit integer, alligned on 32bit(padding 0) + +*/ + +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +typedef struct fdt_header +{ + uint32_t magic; // contain the value 0xd00dfeed (big-endian). + uint32_t totalsize; // in byte + uint32_t off_dt_struct; // the offset in bytes of the structure block from the beginning of the header + 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; // the length in bytes of the strings block section + uint32_t size_dt_struct; +} fdt_header; + +typedef void (*fdt_callback)(int type, const char *name, const void *data, uint32_t size); +void print_dtb(int type, const char *name, const void *data, uint32_t size) ; +void get_initramfs_addr(int type, const char *name, const void *data, uint32_t size) ; +int fdt_traverse(fdt_callback cb, void* dtb_ptr); +#endif \ No newline at end of file diff --git a/LAB3/include/exception_c.h b/LAB3/include/exception_c.h new file mode 100644 index 000000000..0fbf7125b --- /dev/null +++ b/LAB3/include/exception_c.h @@ -0,0 +1,27 @@ +#ifndef _EXCEPTION_C_H +#define _EXCEPTION_C_H + +typedef void (*task_callback)(void *); + +void enable_interrupt(); +void disable_interrupt(); +void default_handler(); +void lower_sync_handler(); +void curr_irq_handler(); +void curr_sync_handler(); + +void task_init(); +void add_task(task_callback cb,void *arg ,unsigned int priority); +void exec_task(); + +typedef struct task +{ + unsigned long priority; + unsigned long duration; + void *arg; + task_callback callback; + char msg[20]; + struct task *prev, *next; +} task; + +#endif diff --git a/LAB3/include/mini_uart.h b/LAB3/include/mini_uart.h new file mode 100644 index 000000000..88fa5dd91 --- /dev/null +++ b/LAB3/include/mini_uart.h @@ -0,0 +1,23 @@ +#ifndef _MINI_UART_H +#define _MINI_UART_H + + +void delay(unsigned int clock); +void enable_uart_interrupt(); +void disable_uart_interrupt(); +void uart_init(); +void uart_send_string(const char* str); +void uart_send_int(int num, int newline); +void uart_send_uint(unsigned int num,int newline); +void uart_send(const char c); +char uart_recv(); +char uart_recv_raw(); +void uart_hex(unsigned int d); +void uart_dec(unsigned int num); +void uart_handler(void *arg); +void test_uart_async(); +char uart_async_recv(); +void uart_async_send_string(char *str); +unsigned int uart_printf(char* fmt, ...); +typedef unsigned int Reg; +#endif \ No newline at end of file diff --git a/LAB3/include/peripheral/base.h b/LAB3/include/peripheral/base.h new file mode 100644 index 000000000..1eb154198 --- /dev/null +++ b/LAB3/include/peripheral/base.h @@ -0,0 +1,7 @@ +#ifndef _PERIPHERAL_BASE_H +#define _PERIPHERAL_BASE_H + +#define MMIO_BASE 0x3F000000 +#define MAILBOX_BASE MMIO_BASE + 0xb880 + +#endif \ No newline at end of file diff --git a/LAB3/include/peripheral/gpio.h b/LAB3/include/peripheral/gpio.h new file mode 100644 index 000000000..8246c40ae --- /dev/null +++ b/LAB3/include/peripheral/gpio.h @@ -0,0 +1,12 @@ +#ifndef _PERIPHERAL_GPIO_H +#define _PERIPHERAL_GPIO_H + +#include "peripheral/base.h" + +#define GPFSEL1 ((volatile unsigned int *)(MMIO_BASE+0x00200004)) +#define GPSET0 ((volatile unsigned int *)(MMIO_BASE+0x0020001C)) +#define GPCLR0 ((volatile unsigned int *)(MMIO_BASE+0x00200028)) +#define GPPUD ((volatile unsigned int *)(MMIO_BASE+0x00200094)) +#define GPPUDCLK0 ((volatile unsigned int *)(MMIO_BASE+0x00200098)) + +#endif \ No newline at end of file diff --git a/LAB3/include/peripheral/mailbox.h b/LAB3/include/peripheral/mailbox.h new file mode 100644 index 000000000..70c462304 --- /dev/null +++ b/LAB3/include/peripheral/mailbox.h @@ -0,0 +1,27 @@ +#ifndef _MAILBOX_H +#define _MAILBOX_H + +#include "peripheral/base.h" + +#define MAILBOX_READ ((volatile unsigned int *)(MAILBOX_BASE)) +#define MAILBOX_STATUS ((volatile unsigned int *)(MAILBOX_BASE + 0x18)) +#define MAILBOX_WRITE ((volatile unsigned int *)(MAILBOX_BASE + 0x20)) + +#define MAILBOX_EMPTY 0x40000000 +#define MAILBOX_FULL 0x80000000 +#define MAILBOX_RESPONSE 0x80000000 +#define ARM_MEMORY 0x00010005 + +#define GET_BOARD_REVISION 0x00010002 +#define REQUEST_CODE 0x00000000 +#define REQUEST_SUCCEED 0x80000000 +#define REQUEST_FAILED 0x80000001 +#define TAG_REQUEST_CODE 0x00000000 +#define END_TAG 0x00000000 + + +int mailbox_call(); +void get_board_revision(); +void get_arm_memory(); + +#endif \ No newline at end of file diff --git a/LAB3/include/peripheral/mini_uart.h b/LAB3/include/peripheral/mini_uart.h new file mode 100644 index 000000000..0ac714e1c --- /dev/null +++ b/LAB3/include/peripheral/mini_uart.h @@ -0,0 +1,30 @@ +#ifndef _PERIPHERAL_MINI_UART_H +#define _PERIPHERAL_MINI_UART_H + +#include "peripheral/base.h" + +#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)) + + + +#define ARM_IRQ_REG_BASE ((volatile unsigned int*)(MMIO_BASE + 0x0000b000)) +#define IRQ_PENDING_1 ((volatile unsigned int*)(MMIO_BASE + 0x0000b204)) +#define ENB_IRQS1 ((volatile unsigned int*)(MMIO_BASE + 0x0000b210)) +#define DISABLE_IRQS1 ((volatile unsigned int*)(MMIO_BASE + 0x0000b21c)) +#define AUX_IRQ (1 << 29) + + + + +#endif \ No newline at end of file diff --git a/LAB3/include/shell.h b/LAB3/include/shell.h new file mode 100644 index 000000000..08f251990 --- /dev/null +++ b/LAB3/include/shell.h @@ -0,0 +1,7 @@ +#ifndef _SHELL_H +#define _SHELL_H + +void shell(); +void read_command(char *str); +void parse_command(char *str); +#endif \ No newline at end of file diff --git a/LAB3/include/sprintf.h b/LAB3/include/sprintf.h new file mode 100644 index 000000000..a7c47f848 --- /dev/null +++ b/LAB3/include/sprintf.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __SPRINT_H +#define __SPRINT_H + +unsigned int sprintf(char *dst, char* fmt, ...); +unsigned int vsprintf(char *dst,char* fmt, __builtin_va_list args); + +#endif \ No newline at end of file diff --git a/LAB3/include/timer.h b/LAB3/include/timer.h new file mode 100644 index 000000000..97a8e178c --- /dev/null +++ b/LAB3/include/timer.h @@ -0,0 +1,29 @@ +#ifndef __TIMER_H +#define __TIMER_H +#define CORE0_TIMER_IRQ_CTRL ((volatile unsigned int *)(0x40000040)) +#define CORE0_INTERRUPT_SOURCE ((volatile unsigned int *)(0x40000060)) + +typedef void (*timer_callback)(char *); + +void core_timer_enable(); +void core_timer_disable(); +void set_expired_time(unsigned long duration); +unsigned long get_current_time(); +void core_timer_handler(); +void set_timeout(char *message, char *_time); +void print_message(char *msg); +void add_timer(timer_callback cb,char *msg, unsigned long duraction); +void timeout_event_init(); +void timer_handler(void *arg); + +typedef struct timeout_event { + unsigned long register_time; + unsigned long duration; + timer_callback callback; + char msg[20]; + struct timeout_event *prev, *next; +} timeout_event; + +extern timeout_event *timeout_queue_head, *timeout_queue_tail; + +#endif diff --git a/LAB3/include/utils_c.h b/LAB3/include/utils_c.h new file mode 100644 index 000000000..1719cf83f --- /dev/null +++ b/LAB3/include/utils_c.h @@ -0,0 +1,29 @@ +#ifndef _UTILS_C_H +#define _UTILS_C_H + +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 +#include +#include + + +/* string */ +int utils_str_compare(const char *a,const char *b); +void utils_newline2end(char *str); +char utils_int2char(int a); +void utils_int2str_dec(int a, char *str); +void utils_uint2str_dec(unsigned int num, char *str); +void mini_printf(const char *format, const char *str); +void cat_two_strings(char *str1, char *str2, char *new_str); +unsigned int utils_str2uint_dec(const char *str); +void align(void *size, size_t s); // aligned to 4 byte +size_t utils_strlen(const char *s); +uint32_t align_up(uint32_t size, int alignment); + +/* reboot */ +void set(long addr, unsigned int value); +void reset(int tick); +void cancel_reset(); + +#endif diff --git a/LAB3/include/utils_s.h b/LAB3/include/utils_s.h new file mode 100644 index 000000000..5088d9d12 --- /dev/null +++ b/LAB3/include/utils_s.h @@ -0,0 +1,27 @@ +#ifndef __UTILS_S_H +#define __UTILS_S_H + +#define read_sysreg(r) ({ \ + unsigned long __val; \ + asm volatile("mrs %0, " #r : "=r" (__val)); \ + __val; \ +}) + +#define write_sysreg(r, __val) ({ \ + asm volatile("msr " #r ", %0" :: "r" (__val)); \ +}) + +#define read_gpreg(r) ({ \ + unsigned long __val; \ + asm volatile("mov %0, " #r : "=r" (__val)); \ + __val; \ +}) + +#define write_gpreg(r, __val) ({ \ + asm volatile("mov " #r ", %0" :: "r" (__val)); \ +}) + +int get_el_TYPE(); + + +#endif diff --git a/LAB3/initramfs.cpio b/LAB3/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..077bf7caf26e8e2f94226a94cbfd86fc06b83624 GIT binary patch literal 512 zcma)&O%B2!5QRC4y#T&J3f;PJVdARs0<|r%i95UK@#Sww)Yv*9c`#w#`v4Xe1l8+q zI5_yyG!8*Qu8s=QNuiBFT^q;e-1hUaC@Z&%D&9%q(^8)IF-_<<)Fr>~Jc@Z1nFC|? z*~;rn-rh}*QOS9kg%I<7dhYy6J@LlU*uPkeV+PhOmiWftEh7tkaF8q<485+u{&;-~ SxbcN+dpuuGZBpriority = priority; + new_task->callback = cb; + new_task->arg = arg; + new_task->next = 0; + new_task->prev = 0; + if (task_queue_head == 0) + { + task_queue_head = new_task; + task_queue_tail = new_task; + } + else + { + task *cur = task_queue_head; + while (cur) + { + if (cur->priority < new_task->priority) + break; + cur = cur->next; + } + if (cur == 0) + { // cur at end + new_task->prev = task_queue_tail; + task_queue_tail->next = new_task; + task_queue_tail = new_task; + } + else if (cur->prev == 0) + { // cur at head + new_task->next = cur; + (task_queue_head)->prev = new_task; + task_queue_head = new_task; + } + else + { // cur at middle + new_task->next = cur; + new_task->prev = cur->prev; + (cur->prev)->next = new_task; + cur->prev = new_task; + } + } +} + +void exec_task(){ + while(1){ + + task_queue_head->callback(task_queue_head->arg); + disable_interrupt(); + task_queue_head = task_queue_head->next; + + if(task_queue_head){ + // if still got task + task_queue_head->prev = 0; + } + else{ + task_queue_head = task_queue_tail = 0; + return; + } + enable_interrupt(); + + } +} + +void curr_irq_handler_decouple() +{ + // Manual p 112 + unsigned int uart = (*IRQ_PENDING_1 & AUX_IRQ); + unsigned int core_timer = (*CORE0_INTERRUPT_SOURCE & 0x2); + if (uart) + { + Reg *reg = (Reg *)malloc(sizeof(Reg)); + *reg = *AUX_MU_IER_REG; + add_task(uart_handler, reg, 3); + *AUX_MU_IER_REG &= ~(0x3); + } + else if (core_timer) + { + add_task(timer_handler, NULL, 0); + core_timer_disable(); + } + if (!doing_task) + { + + doing_task = 1; + enable_interrupt(); + exec_task(); + enable_interrupt(); + doing_task = 0; + } +} +void curr_sync_handler(unsigned long esr_el1, unsigned long elr_el1) +{ + disable_interrupt(); + return; + enable_interrupt(); +} \ No newline at end of file diff --git a/LAB3/kernel/exception_s.s b/LAB3/kernel/exception_s.s new file mode 100644 index 000000000..66e390d67 --- /dev/null +++ b/LAB3/kernel/exception_s.s @@ -0,0 +1,106 @@ +// 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 + +.macro exception_entry label + .align 7 + b \label // branch to a handler function. + +.endm + + +.global el1_vector_base + +.align 11 +el1_vector_base: + exception_entry exception_handler + exception_entry exception_handler + exception_entry exception_handler + exception_entry exception_handler + + + exception_entry _el1_curr_el_spx_sync + exception_entry _el1_curr_el_spx_irq + exception_entry exception_handler + exception_entry exception_handler + + + exception_entry _el1_lower_el_aarch64_sync + exception_entry _el1_lower_el_aarch64_irq + exception_entry exception_handler + exception_entry exception_handler + + + exception_entry exception_handler + exception_entry exception_handler + exception_entry exception_handler + exception_entry exception_handler + + +_el1_lower_el_aarch64_sync: + save_all + bl lower_sync_handler + load_all + eret + +_el1_lower_el_aarch64_irq: + save_all + bl lower_irq_handler + load_all + eret + +_el1_curr_el_spx_sync: + save_all + bl curr_sync_handler + load_all + eret + +_el1_curr_el_spx_irq: + save_all + bl curr_irq_handler_decouple + load_all + eret + +exception_handler: + save_all + bl default_handler + load_all + eret diff --git a/LAB3/kernel/linker.ld b/LAB3/kernel/linker.ld new file mode 100644 index 000000000..79f7185a9 --- /dev/null +++ b/LAB3/kernel/linker.ld @@ -0,0 +1,27 @@ +ENTRY(_start) + + +SECTIONS +{ + . = 0x80000; + _stext = .; + .text : { + *(.text.kernel) + *(.text) + *(.rodata) + } + . = ALIGN(0x1000); + _etext = .; + + _sdata = .; + .data : { *(.data) } + . = ALIGN(0x1000); + _edata = .; + + + _sbss = .; + .bss : { *(.bss*) } + . = ALIGN(0x1000); + _ebss = .; + +} \ No newline at end of file diff --git a/LAB3/kernel/main.c b/LAB3/kernel/main.c new file mode 100644 index 000000000..c4abacf38 --- /dev/null +++ b/LAB3/kernel/main.c @@ -0,0 +1,28 @@ +#include "mini_uart.h" +#include "dtb.h" +#include "exception_c.h" +#include "utils_s.h" +#include "utils_c.h" +#include "shell.h" +#include "timer.h" + +extern void *_dtb_ptr; + +void kernel_main(void) +{ + // uart_init(); + timeout_event_init(); + uart_send_string("Hello, world!\n"); + fdt_traverse(get_initramfs_addr, _dtb_ptr); + + // To print out el number + int el = get_el_TYPE(); + char el_int[2]; + utils_int2str_dec(el, el_int); + char tmp[100]; + cat_two_strings("kernel Exception level: ", el_int, tmp); + mini_printf("%s\n", tmp); + + enable_interrupt(); + shell(); +} \ No newline at end of file diff --git a/LAB3/kernel/start.s b/LAB3/kernel/start.s new file mode 100644 index 000000000..801caae78 --- /dev/null +++ b/LAB3/kernel/start.s @@ -0,0 +1,42 @@ +.section ".text.kernel" +.globl _start + +_start: + ldr x1, =_dtb_ptr + str x0, [x1] + + /* cpu id pass */ + mrs x20, mpidr_el1 + and x20, x20,#0xFF // Check processor id + cbz x20, master // Hang for all non-primary CPU + +hang: + b hang + +master: + bl from_el2_to_el1 + + // Set Up interrupt vector table + ldr x0, =el1_vector_base + msr vbar_el1, x0 + + adr x20, _sbss + adr x21, _ebss + sub x21, x21, x20 + bl memzero + + mov sp, #0x200000 // 2MB + bl kernel_main + +from_el2_to_el1: + mov x0, (1 << 31) // EL1 uses aarch64 + msr hcr_el2, x0 + mov x0, 0x3c5 // EL1h (SPSel = 1) with interrupt disabled + msr spsr_el2, x0 + msr elr_el2, lr + eret // return to EL1 + + +.global _dtb_ptr +.section .data +_dtb_ptr: .dc.a 0x0 diff --git a/LAB3/loadImg/loadImg.py b/LAB3/loadImg/loadImg.py new file mode 100644 index 000000000..4179bfad7 --- /dev/null +++ b/LAB3/loadImg/loadImg.py @@ -0,0 +1,30 @@ +#! /usr/bin/python3 + +import os +from socket import timeout +import time +import sys +import serial +from time import sleep + +BAUD_RATE = 115200 + +def send_img(ser,kernel): + print("Please sent the kernel image size:") + kernel_size=os.stat(kernel).st_size + ser.write((str(kernel_size)+"\n").encode()) + print(ser.read_until(b"Start to load the kernel image... \r\n").decode(), end="") + + with open(kernel, "rb") as image: + while kernel_size > 0: + kernel_size -= ser.write(image.read(1)) + ser.read_until(b".") + print(ser.read_until(b"$ ").decode(), end="") + return + +if __name__ == "__main__": + ser = serial.Serial("/dev/cu.usbserial-0001", BAUD_RATE, timeout=5) + send_img(ser,"../build/kernel8.img") + + + diff --git a/LAB3/src/_cpio.c b/LAB3/src/_cpio.c new file mode 100644 index 000000000..9ff48a8e8 --- /dev/null +++ b/LAB3/src/_cpio.c @@ -0,0 +1,142 @@ +#include "_cpio.h" +#include "utils_c.h" +#include "allocator.h" +#include "mini_uart.h" +#include "timer.h" + +#define KSTACK_SIZE 0x2000 +#define USER_STACK_SIZE 0x2000 + +unsigned int hex2dec(char *s) +{ + unsigned int r = 0; + for (int i = 0; i < 8; ++i) + { + if (s[i] >= '0' && s[i] <= '9') + { + r = r * 16 + s[i] - '0'; + } + else + { + r = r * 16 + s[i] - 'a' + 10; + } + } + return r; +} + +char *findFile(char *name) +{ + char *addr = cpio_addr; + while (utils_str_compare((char *)(addr + sizeof(cpio_header)), "TRAILER!!!") != 0) + { + if ((utils_str_compare((char *)(addr + sizeof(cpio_header)), name) == 0)) + { + return addr; + } + cpio_header *header = (cpio_header *)addr; + unsigned int pathname_size = hex2dec(header->c_namesize); + unsigned int file_size = hex2dec(header->c_filesize); + unsigned int headerPathname_size = sizeof(cpio_header) + pathname_size; + + align(&headerPathname_size, 4); + align(&file_size, 4); + addr += (headerPathname_size + file_size); + } + return 0; +} +void cpio_ls() +{ + char *addr = cpio_addr; + while (utils_str_compare((char *)(addr + sizeof(cpio_header)), "TRAILER!!!") != 0) + { + cpio_header *header = (cpio_header *)addr; + unsigned int pathname_size = hex2dec(header->c_namesize); + unsigned int file_size = hex2dec(header->c_filesize); + unsigned int headerPathname_size = sizeof(cpio_header) + pathname_size; + + align(&headerPathname_size, 4); + align(&file_size, 4); + + uart_send_string(addr + sizeof(cpio_header)); // print the file name + uart_send_string("\n"); + + addr += (headerPathname_size + file_size); + } +} + +void cpio_cat(char *filename) +{ + char *target = findFile(filename); + if (target) + { + cpio_header *header = (cpio_header *)target; + unsigned int pathname_size = hex2dec(header->c_namesize); + unsigned int file_size = hex2dec(header->c_filesize); + unsigned int headerPathname_size = sizeof(cpio_header) + pathname_size; + + align(&headerPathname_size, 4); + align(&file_size, 4); + + char *file_content = target + headerPathname_size; + for (unsigned int i = 0; i < file_size; i++) + { + uart_send(file_content[i]); // print the file content + } + uart_send_string("\n"); + } + else + { + uart_send_string("Not found the file\n"); + } +} + +void cpio_load_program(char *filename) +{ + char *prog_addr = findFile(filename); + void * user_addr = (void * )0x200000; + if (prog_addr) + { + cpio_header *header = (cpio_header *)prog_addr; + unsigned int pathname_size = hex2dec(header->c_namesize); + unsigned int file_size = hex2dec(header->c_filesize); + unsigned int headerPathname_size = sizeof(cpio_header) + pathname_size; + + align(&headerPathname_size, 4); + align(&file_size, 4); + + uart_send_string(prog_addr + sizeof(cpio_header)); + uart_send_string("\n"); + + char *file_content = prog_addr + headerPathname_size; + unsigned char *target = (unsigned char *)user_addr; + while (file_size--) + { + *target = *file_content; + target++; + file_content++; + } + + core_timer_enable(); + + // bit 7 is the irq mask bit + // if mask => no irq handling + asm volatile("mov x0, 0x340 \n"); + asm volatile("msr spsr_el1, x0 \n"); + asm volatile("msr elr_el1, %0 \n" ::"r"(user_addr)); + asm volatile("msr sp_el0, %0 \n" ::"r"(user_addr + USER_STACK_SIZE)); + asm volatile("eret \n"); + // asm volatile + // ( + // "mov x1,0x0;" //open interrupt for 2sec time_interrupt , 0000: EL0t(jump to EL0) + // "msr SPSR_EL1,x1;" //saved process state when an exception is taken to EL1 + // "msr ELR_EL1,x0;" //put program_start -> ELR_EL1 + // "mov x1,#0x20000;" //set sp on 0x20000 + // "msr SP_EL0,x1;" //set EL0 stack pointer + // "ERET" //exception return , will load from ELR_EL2 -> PC + // ); + } + else + { + uart_send_string("No Such Program\n"); + } +} diff --git a/LAB3/src/allocator.c b/LAB3/src/allocator.c new file mode 100644 index 000000000..18c8b9d5d --- /dev/null +++ b/LAB3/src/allocator.c @@ -0,0 +1,16 @@ +#include "allocator.h" +#include "utils_c.h" +#include "mini_uart.h" + +#define MEM_SIZE 0x10000000 // 0.25G +#define MEM_START 0x10000000 + +unsigned long *malloc_cur = (unsigned long *)MEM_START; + +void *malloc(size_t size) +{ + align(&size,4);//allocated the memory size is mutiple of 4 byte; + unsigned long *malloc_ret = malloc_cur; + malloc_cur+=(unsigned int)size; + return malloc_ret; +} \ No newline at end of file diff --git a/LAB3/src/dtb.c b/LAB3/src/dtb.c new file mode 100644 index 000000000..e30ccaf0a --- /dev/null +++ b/LAB3/src/dtb.c @@ -0,0 +1,137 @@ +#include "dtb.h" +#include "_cpio.h" +#include "mini_uart.h" +#include "utils_c.h" +/* + It consists of + a small header + + the memory reservation block + space(aligned) + + the structure block + space(aligned) + + the strings block + space(aligned) +*/ +int space = 0; +char * cpio_addr; + +uint32_t get_le2be_uint(const void *p) +{ + // transfer little endian to big endian + const unsigned char *bytes = p; + uint32_t res = bytes[3]; + res |= bytes[2] << 8; + res |= bytes[1] << 16; + res |= bytes[0] << 24; + return res; +} + +void send_sapce(int n) { + while (n--) uart_send_string(" "); +} + +int parse_struct(fdt_callback cb, uintptr_t cur_ptr, uintptr_t strings_ptr, uint32_t totalsize) +{ + uintptr_t end_ptr = cur_ptr + totalsize; + + while (cur_ptr < end_ptr) + { + uint32_t token = get_le2be_uint((char *)cur_ptr); + cur_ptr += 4; + switch (token) + { + case FDT_BEGIN_NODE: + // uart_send_string("In FDT_BEGIN_NODE\n"); + cb(token, (char *)cur_ptr, NULL, 0); + cur_ptr += align_up(utils_strlen((char *)cur_ptr), 4); + break; + case FDT_END_NODE: + // uart_send_string("In FDT_END_NODE\n"); + cb(token, NULL, NULL, 0); + break; + case FDT_PROP:{ + // uart_send_string("In FDT_PROP\n"); + uint32_t len = get_le2be_uint((char *)cur_ptr); + cur_ptr += 4; + uint32_t nameoff = get_le2be_uint((char *)cur_ptr); + cur_ptr += 4; + cb(token, (char *)(strings_ptr + nameoff), (void *)cur_ptr, len); + cur_ptr += align_up(len, 4);; + break; + } + case FDT_NOP: + // uart_send_string("In FDT_NOP\n"); + cb(token, NULL, NULL, 0); + break; + case FDT_END: + // uart_send_string("In FDT_END\n"); + cb(token, NULL, NULL, 0); + return 0; + default:; + return -1; + } + } + return 0; +} + + + +void print_dtb(int type, const char *name, const void *data, uint32_t size) +{ + switch (type) + { + case FDT_BEGIN_NODE: + uart_send_string("\n"); + send_sapce(space); + uart_send_string(name); + uart_send_string("{\n "); + space++; + break; + + case FDT_END_NODE: + uart_send_string("\n"); + space--; + if (space>0) send_sapce(space); + + uart_send_string("}\n"); + break; + + case FDT_NOP: + break; + + case FDT_PROP: + send_sapce(space); + uart_send_string(name); + break; + + case FDT_END: + break; + } +} + +void get_initramfs_addr(int type, const char *name, const void *data, uint32_t size) +{ + if(type==FDT_PROP&&!utils_str_compare(name,"linux,initrd-start")){ + cpio_addr=(char *)(uintptr_t)get_le2be_uint(data); + uart_send_string("initramfs_addr at "); + uart_hex((uintptr_t)get_le2be_uint(data)); + uart_send('\n'); + } +} + +int fdt_traverse(fdt_callback cb, void* _dtb) +{ + uintptr_t dtb_ptr = (uintptr_t)_dtb; + uart_send_string("\ndtb loading at:"); + uart_hex(dtb_ptr); + uart_send('\n'); + fdt_header *header = (fdt_header *)dtb_ptr; + + if (get_le2be_uint(&(header->magic)) != 0xd00dfeed) + { + uart_send_string("header magic != 0xd00dfeed\n"); + return -1; + } + uint32_t totalsize = get_le2be_uint(&(header->totalsize)); + uintptr_t struct_ptr = dtb_ptr + get_le2be_uint(&(header->off_dt_struct)); + uintptr_t strings_ptr = dtb_ptr + get_le2be_uint(&(header->off_dt_strings)); + parse_struct(cb, struct_ptr, strings_ptr, totalsize); + return 0; +} diff --git a/LAB3/src/mailbox.c b/LAB3/src/mailbox.c new file mode 100644 index 000000000..ce7afc067 --- /dev/null +++ b/LAB3/src/mailbox.c @@ -0,0 +1,63 @@ +#include "peripheral/mailbox.h" +#include "utils_c.h" +#include "mini_uart.h" + +volatile unsigned int __attribute__((aligned(16))) mailbox[8]; + +int mailbox_call() +{ + unsigned int readChannel = (((unsigned int)((unsigned long)&mailbox) & ~0xF) | (0x8 & 0xF)); + while (*MAILBOX_STATUS & MAILBOX_FULL) + { + } + *MAILBOX_WRITE = readChannel; + while (1) + { + while (*MAILBOX_STATUS & MAILBOX_EMPTY) + { + } + if (readChannel == *MAILBOX_READ) + { + return mailbox[1] == MAILBOX_RESPONSE; + } + } + return 0; +} + +void get_board_revision() +{ + uart_send_string("In get_board_revision\n"); + mailbox[0] = 7 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_BOARD_REVISION; // 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] = END_TAG; + mailbox_call(); // message passing procedure call, you should implement it following the 6 steps provided above. + // printf("0x%x\n", mailbox[5]); // it should be 0xa020d3 for rpi3 b+ + uart_hex(mailbox[5]); + uart_send_string("\n"); +} +void get_arm_memory() +{ + mailbox[0] = 8 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = ARM_MEMORY; // 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] = END_TAG; + mailbox_call(); // message passing procedure call, you should implement it following the 6 steps provided above. + uart_send_string("Arm base address: "); + uart_hex(mailbox[5]); + uart_send_string("\n"); + uart_send_string("Arm memory size: "); + uart_hex(mailbox[6]); + uart_send_string("\n"); +} diff --git a/LAB3/src/memzero.s b/LAB3/src/memzero.s new file mode 100644 index 000000000..c3720caf7 --- /dev/null +++ b/LAB3/src/memzero.s @@ -0,0 +1,7 @@ +.globl memzero +memzero: + str xzr, [x20], #8 + subs x21, x21, #8 + b.gt memzero + ret + \ No newline at end of file diff --git a/LAB3/src/mini_uart.c b/LAB3/src/mini_uart.c new file mode 100644 index 000000000..a407ee881 --- /dev/null +++ b/LAB3/src/mini_uart.c @@ -0,0 +1,301 @@ +#include "peripheral/mini_uart.h" +#include "peripheral/gpio.h" +#include "sprintf.h" +#include "utils_c.h" +#include +#include +#include "mini_uart.h" + +#define ENABLE_RECEIVE_INTERRUPTS_BIT (1 << 0) +#define ENABLE_TRANSMIT_INTERRUPTS_BIT (1 << 1) +#define AUX_INT_BIT (1 << 29) + +#define BUFFER_MAX_SIZE 256u + +char read_buf[BUFFER_MAX_SIZE]; +char write_buf[BUFFER_MAX_SIZE]; +int read_buf_start, read_buf_end; +int write_buf_start, write_buf_end; + + +// AUX_MU_IER_REG the controler for enable/disable {receive/transmit} + +// if setted +// bit 1 enable transmit +// bit 0 enable receive + + +void delay(unsigned int clock) +{ + while (clock--) + { + asm volatile("nop"); + } +} +void enable_uart_interrupt() { *ENB_IRQS1 = AUX_IRQ; } + +void disable_uart_interrupt() { *DISABLE_IRQS1 = AUX_IRQ; } + +void set_transmit_interrupt() { *AUX_MU_IER_REG |= 0x2; } + +void clear_transmit_interrupt() { *AUX_MU_IER_REG &= ~(0x2); } + +void uart_init() +{ + unsigned int selector; + + selector = *GPFSEL1; + selector &= ~(7u << 12); // clean gpio14 + selector |= 2u << 12; // set alt5 for gpio14 + selector &= ~(7u << 15); // clean gpio15 + selector |= 2u << 15; // set alt5 for gpio 15 + *GPFSEL1 = selector; + + *GPPUD = 0; // set the required control signal (i.e. Pull-up or Pull-Down ) + delay(150u); // provides the required set-up time for the control signal + *GPPUDCLK0 = (1u << 14) | (1u << 15); + delay(150u); + *GPPUDCLK0 = 0u; + *AUX_ENABLE = 1u; // Enable mini uart (this also enables access to its registers) + *AUX_MU_CNTL_REG = 0u; // Disable auto flow control and disable receiver and transmitter (for now) + *AUX_MU_IER_REG = 1u; // Enable receive + *AUX_MU_LCR_REG = 3u; // Enable 8 bit mode + *AUX_MU_MCR_REG = 0u; // Set RTS line to be always high + *AUX_MU_BAUD_REG = 270u; // Set baud rate to 115200 + *AUX_MU_IIR_REG = 6; + + *AUX_MU_CNTL_REG = 3; // Finally, enable transmitter and receiver + + read_buf_start = read_buf_end = 0; + write_buf_start = write_buf_end = 0; + // enable_uart_interrupt(); +} + +void uart_send(const char c) +{ + /* + bit_5 == 1 -> writable + 0x20 = 0000 0000 0010 0000 + ref BCM2837-ARM-Peripherals p5 + */ + if (c == '\n') + { + uart_send('\r'); + } + while (!(*(AUX_MU_LSR_REG)&0x20)) + { + } + *AUX_MU_IO_REG = c; +} +char uart_recv() +{ + /* + bit_0 == 1 -> readable + 0x01 = 0000 0000 0000 0001 + ref BCM2837-ARM-Peripherals p5 + */ + while (!(*(AUX_MU_LSR_REG)&0x01)) + { + } + char temp = *(AUX_MU_IO_REG)&0xFF; + return temp == '\r' ? '\n' : temp; +} + +char uart_recv_raw() +{ + /* + bit_0 == 1 -> readable + 0x01 = 0000 0000 0000 0001 + ref BCM2837-ARM-Peripherals p5 + */ + while (!(*(AUX_MU_LSR_REG)&0x01)) + { + } + char temp = *(AUX_MU_IO_REG)&0xFF; + return temp; +} + +void uart_send_string(const char *str) +{ + while (*str) + { + uart_send(*str++); + } +} + +void uart_send_int(int num, int newline) +{ + char str[256]; + utils_int2str_dec(num, str); + uart_send_string(str); + if (newline) + { + uart_send_string("\n"); + } +} +void uart_send_uint(unsigned int num, int newline) +{ + char str[256]; + utils_uint2str_dec(num, str); + uart_send_string(str); + if (newline) + { + uart_send_string("\n"); + } +} + +void uart_hex(unsigned int d) +{ + unsigned int n; + int c; + uart_send_string("0x"); + for (c = 28; c >= 0; c -= 4) + { + n = (d >> c) & 0xF; + // 0-9 => '0'-'9', 10-15 => 'A'-'F' + n += n > 9 ? 0x57 : 0x30; + uart_send(n); + } +} +void uart_dec(unsigned int num) +{ + if (num == 0) + uart_send('0'); + else + { + if (num >= 10) + uart_dec(num / 10); + uart_send(num % 10 + '0'); + } +} + +unsigned int uart_printf(char *fmt, ...) +{ + char dst[100]; + // __builtin_va_start(args, fmt): "..." is pointed by args + // __builtin_va_arg(args,int): ret=(int)*args;args++;return ret; + __builtin_va_list args; + __builtin_va_start(args, fmt); + unsigned int ret = vsprintf(dst, fmt, args); + uart_send_string(dst); + return ret; +} + +/* + async part +*/ + +//AUX_MU_IIR_REG -> 2:1 + // 00 : No interrupt + // 01 : Transmit hold + // 10 : Receive hold + // 11 : Not Possible + +// AUX_MU_IO_REG -> Read data to ot Write data from register + // In this register, it only care about least 8 bit + // Hence only one byte + + + + +void uart_handler(void *arg) +{ + Reg *ier=(Reg *)arg; + disable_uart_interrupt(); + int RX = (*AUX_MU_IIR_REG & 0x4); + int TX = (*AUX_MU_IIR_REG & 0x2); + if (RX) + { + char c = (char)(*AUX_MU_IO_REG); + read_buf[read_buf_end++] = c; + if (read_buf_end == BUFFER_MAX_SIZE) + read_buf_end = 0; + } + else if (TX) + { + // AUX_MU_LSR_REG -> Bit5 : This bit is set if the transmit FIFO can accept at least one byte + while (*AUX_MU_LSR_REG & 0x20) + { + if (write_buf_start == write_buf_end) + { + *ier&=~(0x2); + break; + } + char c = write_buf[write_buf_start++]; + *AUX_MU_IO_REG = c; + if (write_buf_start == BUFFER_MAX_SIZE) + write_buf_start = 0; + } + } + // enable transmit interrupt + *AUX_MU_IER_REG |= *ier; + enable_uart_interrupt(); +} + +char uart_async_recv() +{ + // wait until there are new data + *AUX_MU_IER_REG |= (0x1); + while (read_buf_start == read_buf_end) + { + asm volatile("nop"); + } + char c = read_buf[read_buf_start++]; + if (read_buf_start == BUFFER_MAX_SIZE) + read_buf_start = 0; + return c == '\r' ? '\n' : c; +} + +void uart_async_send_string(char *str) +{ + + for (int i = 0; str[i]; i++) + { + if (str[i] == '\n') + { + write_buf[write_buf_end++] = '\r'; + write_buf[write_buf_end++] = '\n'; + continue; + } + write_buf[write_buf_end++] = str[i]; + if (write_buf_end == BUFFER_MAX_SIZE) + write_buf_end = 0; + } + set_transmit_interrupt(); +} + +void uart_async_send(char c) +{ + if (c == '\n') + { + write_buf[write_buf_end++] = '\r'; + write_buf[write_buf_end++] = '\n'; + set_transmit_interrupt(); + return; + } + write_buf[write_buf_end++] = c; + if (write_buf_end == BUFFER_MAX_SIZE) + write_buf_end = 0; + set_transmit_interrupt(); +} + +void test_uart_async() +{ + enable_uart_interrupt(); + delay(15000); + char buffer[BUFFER_MAX_SIZE]; + size_t index = 0; + while (1) + { + buffer[index] = uart_async_recv(); + // uart_async_send(buffer[index]); + if (buffer[index] == '\n') + { + break; + } + index++; + } + buffer[index + 1] = '\0'; + uart_async_send_string(buffer); + disable_uart_interrupt(); +} diff --git a/LAB3/src/shell.c b/LAB3/src/shell.c new file mode 100644 index 000000000..1e1f40ac6 --- /dev/null +++ b/LAB3/src/shell.c @@ -0,0 +1,162 @@ +#include "shell.h" +#include "mini_uart.h" +#include "utils_c.h" +#include "utils_s.h" +#include "peripheral/mailbox.h" +#include "_cpio.h" +#include "allocator.h" +#include "exception_c.h" +#include "timer.h" +#include "dtb.h" +#include +#define BUFFER_MAX_SIZE 256u +#define COMMNAD_LENGTH_MAX 20u + +extern void *_dtb_ptr; + +void read_command(char *buffer) +{ + size_t index = 0; + while (1) + { + buffer[index] = uart_recv(); + uart_send(buffer[index]); + if (buffer[index] == '\n') + { + break; + } + index++; + } + buffer[index + 1] = '\0'; + utils_newline2end(buffer); + uart_send('\r'); +} + +void parse_arg(char *buffer, int argc, int *argi) +{ + int i = 0; + int argi_index=0; + argi[argi_index]=i; + while (buffer[i]!='\0') + { + if(buffer[i]==' '){ + buffer[i]='\0'; + argi[++argi_index]=++i; + continue; + } + i++; + } +} + +void help() +{ + uart_send_string("help :"); + uart_send_string("print this help menu\n"); + uart_send_string("hello :"); + uart_send_string("print Hello World!\n"); + uart_send_string("reboot : "); + uart_send_string("reboot the device\n"); + uart_send_string("info : "); + uart_send_string("the mailbox hardware info\n"); + uart_send_string("ls : "); + uart_send_string("list the all file\n"); + uart_send_string("cat : "); + uart_send_string("print the file content\n"); + uart_send_string("dtb : "); + uart_send_string("print the device name tree \n"); + uart_send_string("async : "); + uart_send_string("test uart async send and recv\n"); + uart_send_string("exe : "); + uart_send_string("executing your program\n"); + uart_send_string("set : "); + uart_send_string("set the timeout (set message second)\n"); +} + +void hello() +{ + uart_send_string("Hello World!\n"); +} + +void info() +{ + get_board_revision(); + get_arm_memory(); +} + +void parse_command(char *buffer) +{ + int argc = 0; + int argi[BUFFER_MAX_SIZE]; + parse_arg(buffer, argc, argi); + if (utils_str_compare(buffer, "") == 0) + { // enter empty + return; + } + else if (utils_str_compare(buffer, "help") == 0) + { + help(); + } + else if (utils_str_compare(buffer, "hello") == 0) + { + hello(); + } + else if (utils_str_compare(buffer, "reboot") == 0) + { + uart_send_string("rebooting...\n"); + reset(1000); + } + else if (utils_str_compare(buffer, "info") == 0) + { + info(); + } + else if (utils_str_compare(buffer, "ls") == 0) + { + cpio_ls(); + } + else if (utils_str_compare(buffer, "cat") == 0) + { + uart_send_string("Filename: "); + char buffer[BUFFER_MAX_SIZE]; + read_command(buffer); + cpio_cat(buffer); + } + else if (utils_str_compare(buffer, "dtb") == 0) + { + fdt_traverse(print_dtb, _dtb_ptr); + } + else if (utils_str_compare(buffer, "exe") == 0) + { + uart_send_string("---- All of your files ----\n"); + cpio_ls(); + uart_send_string("---------------------------\n"); + uart_send_string("program name: "); + char buffer[BUFFER_MAX_SIZE]; + read_command(buffer); + cpio_load_program(buffer); + } + else if (utils_str_compare(buffer, "async") == 0) + { + test_uart_async(); + } + else if (utils_str_compare(buffer, "set") == 0) + { + set_timeout(&buffer[argi[1]], &buffer[argi[2]]); + } + else + { + uart_send_string("commnad '"); + uart_send_string(buffer); + uart_send_string("' not found\n"); + } +} + +void shell() +{ + while (1) + { + char buffer[BUFFER_MAX_SIZE]; + uart_send_string("$ "); + read_command(buffer); + parse_command(buffer); + } +} \ No newline at end of file diff --git a/LAB3/src/sprintf.c b/LAB3/src/sprintf.c new file mode 100644 index 000000000..246748b62 --- /dev/null +++ b/LAB3/src/sprintf.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/** + * minimal sprintf implementation + */ +#include "../include/sprintf.h" + +unsigned int vsprintf(char *dst, char* fmt, __builtin_va_list args) +{ + long int arg; + int len, sign, i; + char *p, *orig=dst, tmpstr[19]; + + // failsafes + if(dst==(void*)0 || fmt==(void*)0) { + return 0; + } + + // main loop + arg = 0; + while(*fmt) { + // argument access + if(*fmt=='%') { + fmt++; + // literal % + if(*fmt=='%') { + goto put; + } + len=0; + // size modifier + while(*fmt>='0' && *fmt<='9') { + len *= 10; + len += *fmt-'0'; + fmt++; + } + // skip long modifier + if(*fmt=='l') { + fmt++; + } + // character + if(*fmt=='c') { + arg = __builtin_va_arg(args, int); + *dst++ = (char)arg; + fmt++; + continue; + } else + // decimal number + if(*fmt=='d') { + arg = __builtin_va_arg(args, int); + // check input + sign=0; + if((int)arg<0) { + arg*=-1; + sign++; + } + if(arg>99999999999999999L) { + arg=99999999999999999L; + } + // convert to string + i=18; + tmpstr[i]=0; + do { + tmpstr[--i]='0'+(arg%10); + arg/=10; + } while(arg!=0 && i>0); + if(sign) { + tmpstr[--i]='-'; + } + // padding, only space + if(len>0 && len<18) { + while(i>18-len) { + tmpstr[--i]=' '; + } + } + p=&tmpstr[i]; + goto copystring; + } else + // hex number + if(*fmt=='x') { + arg = __builtin_va_arg(args, long int); + // convert to string + i=16; + tmpstr[i]=0; + do { + char n=arg & 0xf; + // 0-9 => '0'-'9', 10-15 => 'A'-'F' + tmpstr[--i]=n+(n>9?0x37:0x30); + arg>>=4; + } while(arg!=0 && i>0); + // padding, only leading zeros + if(len>0 && len<=16) { + while(i>16-len) { + tmpstr[--i]='0'; + } + } + p=&tmpstr[i]; + goto copystring; + } else + // string + if(*fmt=='s') { + p = __builtin_va_arg(args, char*); +copystring: if(p==(void*)0) { + p="(null)"; + } + while(*p) { + *dst++ = *p++; + } + } + } else { +put: *dst++ = *fmt; + } + fmt++; + } + *dst=0; + // number of bytes written + return dst-orig; +} + +/** + * Variable length arguments + */ +unsigned int sprintf(char *dst, char* fmt, ...) +{ + //__builtin_va_start(args, fmt): "..." is pointed by args + //__builtin_va_arg(args,int): ret=(int)*args;args++;return ret; + __builtin_va_list args; + __builtin_va_start(args, fmt); + return vsprintf(dst,fmt,args); +} \ No newline at end of file diff --git a/LAB3/src/timer.c b/LAB3/src/timer.c new file mode 100644 index 000000000..14677cb3c --- /dev/null +++ b/LAB3/src/timer.c @@ -0,0 +1,134 @@ +#include "timer.h" +#include "utils_s.h" +#include "allocator.h" +#include "mini_uart.h" +#include "utils_c.h" +timeout_event *timeout_queue_head, *timeout_queue_tail; + +void core_timer_enable() +{ + /* + cntpct_el0 >= cntp_cval_el0 -> interrupt + cntp_tval_el0 = cntpct_el0 - cntp_cval_el0 + */ + write_sysreg(cntp_ctl_el0, 1); // enable + unsigned long frq = read_sysreg(cntfrq_el0); + write_sysreg(cntp_tval_el0, frq * 2); // set expired time + *CORE0_TIMER_IRQ_CTRL = 2; // unmask timer interrupt +} + +void core_timer_disable() +{ + write_sysreg(cntp_ctl_el0, 0); // disable + *CORE0_TIMER_IRQ_CTRL = 0; // unmask timer interrupt +} + +void set_expired_time(unsigned long duration) +{ + unsigned long frq = read_sysreg(cntfrq_el0); + write_sysreg(cntp_tval_el0, frq * duration); // set expired time +} + +unsigned long get_current_time() +{ + // cntpct_el0: The timer’s current count. + unsigned long frq = read_sysreg(cntfrq_el0); + unsigned long current_count = read_sysreg(cntpct_el0); + return (unsigned long)(current_count / frq); +} + +void set_timeout(char *message, char *_time) +{ + unsigned int time = utils_str2uint_dec(_time); + add_timer(print_message, message, time); +} + +void print_message(char *msg) +{ + uart_send_string(msg); +} + +void timeout_event_init() +{ + timeout_queue_head = 0; + timeout_queue_tail = 0; +} + +void add_timer(timer_callback cb, char *msg, unsigned long duration) +{ + timeout_event *new_event = (timeout_event *)malloc(sizeof(timeout_event)); + new_event->register_time = get_current_time(); + new_event->duration = duration; + new_event->callback = cb; + for (int i = 0; i < 20; i++) + { + new_event->msg[i] = msg[i]; + if (msg[i] == '\0') + break; + } + new_event->next = 0; + new_event->prev = 0; + + if (timeout_queue_head == 0) + { + timeout_queue_head = new_event; + timeout_queue_tail = new_event; + core_timer_enable(); + set_expired_time(duration); + } + else + { + unsigned long timeout= new_event->register_time + new_event->duration; + timeout_event *cur = timeout_queue_head; + while (cur) + { + if ( (cur->register_time + cur->duration) > timeout) + break; + cur = cur->next; + } + if (cur == 0) + { // cur at end + new_event->prev = timeout_queue_tail; + timeout_queue_tail->next = new_event; + timeout_queue_tail = new_event; + } + else if (cur->prev == 0) + { // cur at head + new_event->next = cur; + (timeout_queue_head)->prev = new_event; + timeout_queue_head = new_event; + set_expired_time(duration); + } + else + { // cur at middle + new_event->next = cur; + new_event->prev = cur->prev; + (cur->prev)->next = new_event; + cur->prev = new_event; + } + } +} + +void timer_handler(void *arg) +{ + unsigned long current_time = get_current_time(); + uart_send_string("\nmessage :"); + timeout_queue_head->callback(timeout_queue_head->msg); + uart_printf("\ncurrent time : %ds\n", current_time); + uart_printf("command executed time : %ds\n", timeout_queue_head->register_time); + uart_printf("command duration time : %ds\n\n", timeout_queue_head->duration); + + timeout_event *next = timeout_queue_head->next; + if (next) + { + next->prev = 0; + timeout_queue_head = next; + core_timer_enable(); + set_expired_time(next->register_time + next->duration - get_current_time()); + } + else // no other event + { + timeout_queue_head = timeout_queue_tail = 0; + core_timer_disable(); + } +} \ No newline at end of file diff --git a/LAB3/src/utils_c.c b/LAB3/src/utils_c.c new file mode 100644 index 000000000..d2bb520f5 --- /dev/null +++ b/LAB3/src/utils_c.c @@ -0,0 +1,167 @@ +#include "utils_c.h" +#include "mini_uart.h" +#include + +/* + string part +*/ + +int utils_str_compare(const char *a,const char *b) +{ + char aa, bb; + do + { + aa = (char)*a++; + bb = (char)*b++; + if (aa == '\0' || bb == '\0') + { + return aa - bb; + } + } while (aa == bb); + return aa - bb; +} +void utils_newline2end(char *str) +{ + while (*str != '\0') + { + if (*str == '\n') + { + *str = '\0'; + return; + } + ++str; + } +} + +void utils_int2str_dec(int num, char *str) +{ + // num=7114 digit=4 + int digit = -1, temp = num; + while (temp > 0) + { + temp /= 10; + digit++; + } + for (int i = digit; i >= 0; i--) + { + int t = 1; + for (int j = 0; j < i; j++) + { + t *= 10; + } + *str = '0' + num / t; + num = num % t; + str++; + } + *str = '\0'; +} + +void utils_uint2str_dec(unsigned int num, char *str) +{ + char *start = str; + if(num == 0){ + *str++ = '0'; + *str = '\0'; + return; + } + + while(num > 0){ + *str++ = (num%10) + '0'; + num /= 10; + } + + *str = '\0'; + + char *end = str - 1; + char tmp; + while(start < end){ + tmp = *start; + *start = *end; + *end = tmp; + start++; + end--; + } +} + +void cat_two_strings(char *str1, char *str2, char *new_str){ + + char *ptr = new_str; + + while (*str1 != '\0') { + *ptr++ = *str1++; + } + while (*str2 != '\0') { + *ptr++ = *str2++; + } + + *ptr = '\0'; +} + +void mini_printf(const char *format, const char *str) { + while (*format) { + if (*format == '%' && *(format + 1) == 's') { + uart_send_string(str); // Assuming uart_send_string sends strings + format += 2; // Skip the format specifier + } else { + uart_send(*format); // Assuming uart_send_char sends individual characters + format++; + } + } +} + +unsigned int utils_str2uint_dec(const char *str) +{ + unsigned int value = 0u; + + while (*str) + { + value = value * 10u + (*str - '0'); + ++str; + } + return value; +} + +size_t utils_strlen(const char *s) { + size_t i = 0; + while (s[i]) i++; + return i+1; +} + +/* + reboot part +*/ + +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); // full reset + set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick +} + +void cancel_reset() +{ + set(PM_RSTC, PM_PASSWORD | 0); // full reset + set(PM_WDOG, PM_PASSWORD | 0); // number of watchdog tick +} + +/* + others +*/ + +void align(void *size, size_t s) +{ + unsigned int *x = (unsigned int *)size; + if ((*x) & (s-1)) + { + (*x) += s - ((*x) & (s-1)); + } +} + +uint32_t align_up(uint32_t size, int alignment) { + return (size + alignment - 1) & -alignment; +} \ No newline at end of file diff --git a/LAB3/src/utils_s.s b/LAB3/src/utils_s.s new file mode 100644 index 000000000..590800b84 --- /dev/null +++ b/LAB3/src/utils_s.s @@ -0,0 +1,6 @@ +.globl get_el_TYPE +get_el_TYPE: + mrs x0, CurrentEl + lsr x0, x0, #2 + ret + diff --git a/LAB3/users/user1/linker.ld b/LAB3/users/user1/linker.ld new file mode 100644 index 000000000..8142116f5 --- /dev/null +++ b/LAB3/users/user1/linker.ld @@ -0,0 +1,15 @@ +SECTIONS +{ + . = 0x200000; + __prog_start = .; + .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) } + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) } + .data : { *(.data .data.* .gnu.linkonce.d*) } + .bss (NOLOAD) : { + . = ALIGN(16); + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + __bss_end = .; + } +} \ No newline at end of file diff --git a/LAB3/users/user1/main.s b/LAB3/users/user1/main.s new file mode 100644 index 000000000..ce7e53908 --- /dev/null +++ b/LAB3/users/user1/main.s @@ -0,0 +1,11 @@ +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b