diff --git a/apps/user/clock.c b/apps/user/clock.c index ca4b6792..103f600d 100644 --- a/apps/user/clock.c +++ b/apps/user/clock.c @@ -11,12 +11,10 @@ #include int main(int argc, char** argv) { - volatile int i, j, cnt = (argc == 1)? 100 : atoi(argv[1]); - - for (i = 0; i < cnt; i++) { - for (j = 0; j < 5000000; j++); + int cnt = (argc == 1)? 1000 : atoi(argv[1]); + + for (int i = 0; i < cnt; i++) printf("clock: tick#%d / #%d\r\n", i + 1, cnt); - } return 0; } diff --git a/apps/user/ult.c b/apps/user/ult.c index 1c7c2ff5..5b6eb9bc 100644 --- a/apps/user/ult.c +++ b/apps/user/ult.c @@ -5,67 +5,71 @@ /* Author: Robbert van Renesse * Description: course project, user-level threading + * Students implement a threading package and semaphore; + * And then spawn multiple threads as either producer or consumer. */ #include "app.h" -/* These two functions are defined in grass/context.S */ +/** These two functions are defined in grass/context.S **/ void ctx_start(void** old_sp, void* new_sp); void ctx_switch(void** old_sp, void* new_sp); -/* Thread and Semaphore */ +/** Multi-threading functions **/ struct thread { - /* Student's code goes here (user-level threading). */ + /* Student's code goes here. */ }; void thread_init(){ - /* Student's code goes here (user-level threading). */ + /* Student's code goes here */ +} + +void ctx_entry(void){ + /* Student's code goes here. */ } void thread_create(void (*f)(void *), void *arg, unsigned int stack_size){ - /* Student's code goes here (user-level threading). */ + /* Student's code goes here. */ } void thread_yield(){ - /* Student's code goes here (user-level threading). */ + /* Student's code goes here. */ } void thread_exit(){ - /* Student's code goes here (user-level threading). */ + /* Student's code goes here. */ } -void ctx_entry(void){ - /* Student's code goes here (user-level threading). */ -} +/** Semaphore functions **/ struct sema { - /* Student's code goes here (user-level threading). */ + /* Student's code goes here. */ }; void sema_init(struct sema *sema, unsigned int count){ - /* Student's code goes here (user-level threading). */ + /* Student's code goes here. */ } void sema_inc(struct sema *sema){ - /* Student's code goes here (user-level threading). */ + /* Student's code goes here. */ } void sema_dec(struct sema *sema){ - /* Student's code goes here (user-level threading). */ + /* Student's code goes here. */ } int sema_release(struct sema *sema){ - /* Student's code goes here (user-level threading). */ + /* Student's code goes here. */ } -/* Producer and Consumer */ +/** Producer and consumer functions **/ #define NSLOTS 3 -static struct sema s_empty, s_full; -static unsigned int in, out; static char *slots[NSLOTS]; +static unsigned int in, out; +static struct sema s_empty, s_full; static void producer(void *arg){ for (;;) { diff --git a/earth/cpu_intr.c b/earth/cpu_intr.c index 4a21dc1a..2caf1962 100644 --- a/earth/cpu_intr.c +++ b/earth/cpu_intr.c @@ -9,9 +9,13 @@ #include "egos.h" +/* These are two static variables storing + * the addresses of the handler functions; + * Initially, both variables are NULL */ static void (*intr_handler)(int); static void (*excp_handler)(int); +/* Register handler functions by modifying the static variables */ int intr_register(void (*_handler)(int)) { intr_handler = _handler; } int excp_register(void (*_handler)(int)) { excp_handler = _handler; } @@ -22,20 +26,18 @@ void trap_entry() { int id = mcause & 0x3FF; if (mcause & (1 << 31)) - (intr_handler)? intr_handler(id) : - FATAL("trap_entry: intr_handler not registered"); + (intr_handler)? intr_handler(id) : FATAL("trap_entry: interrupt handler not registered"); else - (excp_handler)? excp_handler(id) : - FATAL("trap_entry: exception handler not registered"); + (excp_handler)? excp_handler(id) : FATAL("trap_entry: exception handler not registered"); } int intr_enable() { - int mstatus, mie; - asm("csrr %0, mstatus" : "=r"(mstatus)); - asm("csrw mstatus, %0" ::"r"(mstatus | 0x8)); - asm("csrr %0, mie" : "=r"(mie)); + int mstatus_val, mie_val; + asm("csrr %0, mstatus" : "=r"(mstatus_val)); + asm("csrw mstatus, %0" ::"r"(mstatus_val | 0x8)); + asm("csrr %0, mie" : "=r"(mie_val)); /* For now, egos-2000 only uses timer and software interrupts */ - asm("csrw mie, %0" ::"r"(mie | 0x88)); + asm("csrw mie, %0" ::"r"(mie_val | 0x88)); } void intr_init() { diff --git a/earth/cpu_mmu.c b/earth/cpu_mmu.c index 4d891f5b..9b1bf825 100644 --- a/earth/cpu_mmu.c +++ b/earth/cpu_mmu.c @@ -116,7 +116,7 @@ void pagetable_identity_mapping(int pid) { setup_identity_region(pid, 0x20400000, 1024); /* boot ROM */ setup_identity_region(pid, 0x20800000, 1024); /* disk image */ setup_identity_region(pid, 0x80000000, 1024); /* DTIM memory */ - for (int i = 0; i < 8; i++) /* ITIM memory */ + for (int i = 0; i < 8; i++) /* ITIM memory is 32MB on QEMU */ setup_identity_region(pid, 0x08000000 + i * 0x400000, 1024); } diff --git a/earth/dev_disk.c b/earth/dev_disk.c index 01937fe3..6a34ddad 100644 --- a/earth/dev_disk.c +++ b/earth/dev_disk.c @@ -40,8 +40,9 @@ void disk_init() { earth->disk_write = disk_write; if (earth->platform == QEMU) { + /* QEMU only uses the on-board ROM as disk; + * SD card is only supported on the Arty board */ type = FLASH_ROM; - INFO("QEMU is detected and therefore use on-board ROM as disk"); return; } diff --git a/earth/earth.c b/earth/earth.c index cf7064f1..e3420f78 100644 --- a/earth/earth.c +++ b/earth/earth.c @@ -39,7 +39,7 @@ static void earth_init() { intr_init(); SUCCESS("Finished initializing the CPU interrupts"); - /* Detect the hardware platform */ + /* Detect the hardware platform (Arty or QEMU) */ earth->platform = QEMU; earth->excp_register(platform_detect); /* This memory access triggers an exception on Arty, but not QEMU */ diff --git a/earth/sd/sd_init.c b/earth/sd/sd_init.c index c7d8e283..cd33e5ea 100644 --- a/earth/sd/sd_init.c +++ b/earth/sd/sd_init.c @@ -10,13 +10,6 @@ #include "sd.h" -static void spi_config(); -static void spi_set_clock(long baud_rate); - -static void sd_reset(); -static int sd_check_type(); -static void sd_check_capacity(); - enum { SD_TYPE_SD1, SD_TYPE_SD2, @@ -25,28 +18,18 @@ enum { }; static int SD_CARD_TYPE = SD_TYPE_UNKNOWN; -void sdinit() { - spi_set_clock(100000); - spi_config(); - - sd_reset(); - INFO("Set SPI clock frequency to %ldHz", CPU_CLOCK_RATE / 4); - spi_set_clock(CPU_CLOCK_RATE / 4); +static void sd_check_capacity() { + INFO("Check SD card capacity with cmd58"); + while (recv_data_byte() != 0xFF); - INFO("Check SD card type and voltage with cmd8"); - if (0 != sd_check_type()) FATAL("Fail to check SD card type"); + char reply, payload[4], cmd58[] = {0x7A, 0x00, 0x00, 0x00, 0x00, 0xFF}; + if (sd_exec_cmd(cmd58)) FATAL("SD card cmd58 fails"); + for (int i = 0; i < 4; i++) payload[3 - i] = recv_data_byte(); - char acmd41[] = {0x69, (SD_CARD_TYPE == SD_TYPE_SD2)? 0x40 : 0x00, 0x00, 0x00, 0x00, 0xFF}; - while (sd_exec_acmd(acmd41)); - while (recv_data_byte() != 0xFF); + if ((payload[3] & 0xC0) == 0xC0) SD_CARD_TYPE = SD_TYPE_SDHC; + INFO("SD card replies cmd58 with payload 0x%.8x", *(int*)payload); - INFO("Set block size to 512 bytes with cmd16"); - char cmd16[] = {0x50, 0x00, 0x00, 0x02, 0x00, 0xFF}; - char reply = sd_exec_cmd(cmd16); while (recv_data_byte() != 0xFF); - - if (SD_CARD_TYPE == SD_TYPE_SD2) sd_check_capacity(); - if (SD_CARD_TYPE != SD_TYPE_SDHC) FATAL("Only SDHC/SDXC supported"); } static int sd_check_type() { @@ -72,20 +55,6 @@ static int sd_check_type() { return 0; } -static void sd_check_capacity() { - INFO("Check SD card capacity with cmd58"); - while (recv_data_byte() != 0xFF); - - char reply, payload[4], cmd58[] = {0x7A, 0x00, 0x00, 0x00, 0x00, 0xFF}; - if (sd_exec_cmd(cmd58)) FATAL("SD card cmd58 fails"); - for (int i = 0; i < 4; i++) payload[3 - i] = recv_data_byte(); - - if ((payload[3] & 0xC0) == 0xC0) SD_CARD_TYPE = SD_TYPE_SDHC; - INFO("SD card replies cmd58 with payload 0x%.8x", *(int*)payload); - - while (recv_data_byte() != 0xFF); -} - static void sd_reset() { /* Keep chip select line high */ INFO("Set CS and MOSI to 1 and toggle clock."); @@ -107,11 +76,6 @@ static void sd_reset() { while (recv_data_byte() != 0xFF); } -static void spi_set_clock(long baud_rate) { - long div = (CPU_CLOCK_RATE / (2 * baud_rate)) - 1; - REGW(SPI1_BASE, SPI1_SCKDIV) = (div & 0xFFF); -} - static void spi_config() { /* Set phase as 0*/ /* Set polarity as 0 */ @@ -133,3 +97,32 @@ static void spi_config() { /* Set frame length */ REGW(SPI1_BASE, SPI1_FMT) = 0x80000; } + +static void spi_set_clock(long baud_rate) { + long div = (CPU_CLOCK_RATE / (2 * baud_rate)) - 1; + REGW(SPI1_BASE, SPI1_SCKDIV) = (div & 0xFFF); +} + +void sdinit() { + spi_set_clock(100000); + spi_config(); + + sd_reset(); + INFO("Set SPI clock frequency to %ldHz", CPU_CLOCK_RATE / 4); + spi_set_clock(CPU_CLOCK_RATE / 4); + + INFO("Check SD card type and voltage with cmd8"); + if (0 != sd_check_type()) FATAL("Fail to check SD card type"); + + char acmd41[] = {0x69, (SD_CARD_TYPE == SD_TYPE_SD2)? 0x40 : 0x00, 0x00, 0x00, 0x00, 0xFF}; + while (sd_exec_acmd(acmd41)); + while (recv_data_byte() != 0xFF); + + INFO("Set block size to 512 bytes with cmd16"); + char cmd16[] = {0x50, 0x00, 0x00, 0x02, 0x00, 0xFF}; + char reply = sd_exec_cmd(cmd16); + while (recv_data_byte() != 0xFF); + + if (SD_CARD_TYPE == SD_TYPE_SD2) sd_check_capacity(); + if (SD_CARD_TYPE != SD_TYPE_SDHC) FATAL("Only SDHC/SDXC supported"); +} diff --git a/grass/process.h b/grass/process.h index 36d6d3f7..1a6652fc 100644 --- a/grass/process.h +++ b/grass/process.h @@ -3,13 +3,22 @@ #include "elf.h" #include "disk.h" +enum { + PROC_UNUSED, + PROC_LOADING, /* allocated and wait for loading elf binary */ + PROC_READY, /* finished loading elf and wait for first running */ + PROC_RUNNING, + PROC_RUNNABLE, + PROC_WAIT_TO_SEND, + PROC_WAIT_TO_RECV +}; + struct process{ int pid; int status; int receiver_pid; /* used when waiting to send a message */ void *sp, *mepc; /* process context = stack pointer (sp) * + machine exception program counter (mepc) */ - }; #define MAX_NPROCESS 16 @@ -18,16 +27,6 @@ extern struct process proc_set[MAX_NPROCESS]; #define curr_pid proc_set[proc_curr_idx].pid #define curr_status proc_set[proc_curr_idx].status -enum { - PROC_UNUSED, - PROC_LOADING, /* allocated and wait for loading elf binary */ - PROC_READY, /* finished loading elf and wait for first running */ - PROC_RUNNING, - PROC_RUNNABLE, - PROC_WAIT_TO_SEND, - PROC_WAIT_TO_RECV -}; - void timer_init(); void timer_reset(); diff --git a/grass/syscall.h b/grass/syscall.h index 546e615d..f6206bf6 100644 --- a/grass/syscall.h +++ b/grass/syscall.h @@ -16,9 +16,9 @@ struct sys_msg { }; struct syscall { - enum syscall_type type; - struct sys_msg msg; - int retval; + enum syscall_type type; /* Type of the system call */ + struct sys_msg msg; /* Data of the system call */ + int retval; /* Return value of the system call */ }; void sys_exit(int status); diff --git a/library/elf/elf.c b/library/elf/elf.c index 2bea90f9..9164891f 100644 --- a/library/elf/elf.c +++ b/library/elf/elf.c @@ -85,13 +85,12 @@ void elf_load(int pid, elf_reader reader, int argc, void** argv) { struct elf32_header *header = (void*) buf; struct elf32_program_header *pheader = (void*)(buf + header->e_phoff); - if (pheader->p_vaddr == GRASS_ENTRY) { + if (pheader->p_vaddr == GRASS_ENTRY) load_grass(reader, pheader); - } else if (pheader->p_vaddr == APPS_ENTRY) { + else if (pheader->p_vaddr == APPS_ENTRY) load_app(pid, reader, argc, argv, pheader); - } else { + else FATAL("elf_load: ELF gives invalid p_vaddr: 0x%.8x", pheader->p_vaddr); - } }