diff options
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/init.c | 2 | ||||
-rw-r--r-- | src/kernel/serial.c | 60 | ||||
-rw-r--r-- | src/kernel/serial.h | 48 | ||||
-rw-r--r-- | src/kernel/svc.c | 3 | ||||
-rw-r--r-- | src/kernel/task.c | 21 | ||||
-rw-r--r-- | src/kernel/task.h | 2 | ||||
-rw-r--r-- | src/kernel/vfs.c | 35 | ||||
-rw-r--r-- | src/kernel/vfs.h | 23 |
8 files changed, 183 insertions, 11 deletions
diff --git a/src/kernel/init.c b/src/kernel/init.c index 2ba607d..3bd6b39 100644 --- a/src/kernel/init.c +++ b/src/kernel/init.c @@ -21,6 +21,7 @@ #include "clock.h"
#include "gpio.h"
#include "heap.h"
+#include "serial.h"
#include "task.h"
#include "vfs.h"
#include <fs/initrd.h>
@@ -46,6 +47,7 @@ int main(void) heap_init(&__bss_end__);
gpio_init();
+ serial_init(9600);
vfs_init();
initrd_init();
diff --git a/src/kernel/serial.c b/src/kernel/serial.c new file mode 100644 index 0000000..6f112a8 --- /dev/null +++ b/src/kernel/serial.c @@ -0,0 +1,60 @@ +/** + * @file serial.c + * Provides basic serial IO (through STM debug stuff) + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <arch/stm/stm32l476xx.h> +#include "gpio.h" +#include "clock.h" + +void serial_init(uint32_t baud) +{ + gpio_mode(GPIOA, 2, ALTERNATE); + gpio_mode(GPIOA, 3, ALTERNATE); + GPIOA->AFR[0] &= ~(0x0000FF00); + GPIOA->AFR[0] |= 0x00007700; + RCC->APB1ENR1 |= RCC_APB1ENR1_USART2EN; + + // start usart device + USART2->BRR = 80000000L / baud; + USART2->CR1 |= USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; +} + +void serial_put(int c) +{ + while (!(USART2->ISR & USART_ISR_TXE)); + USART2->TDR = c & 0xFF; +} + +char serial_get(void) +{ + while (!(USART2->ISR & USART_ISR_RXNE)) + delay(10); + return USART2->RDR & 0xFF; +} + +void serial_gets(char *buf, int max) +{ + uint16_t index = 0; + + do { + buf[index] = serial_get(); + serial_put(buf[index]); + } while (buf[index] != '\r' && index++ < max); + buf[index] = '\0'; +} diff --git a/src/kernel/serial.h b/src/kernel/serial.h new file mode 100644 index 0000000..e721d6c --- /dev/null +++ b/src/kernel/serial.h @@ -0,0 +1,48 @@ +/** + * @file serial.h + * Provides basic serial IO (through STM debug stuff) + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef SERIAL_H_ +#define SERIAL_H_ + +/** + * Initializes the serial device. + */ +void serial_init(uint32_t baud); + +/** + * Puts the given character through serial. + * @param c the character to send + */ +void serial_put(int c); + +/** + * Gets a character from serial. + * @return the character + */ +char serial_get(void); + +/** + * Gets a string from serial, cut off by a newline. + * @param buf the initialized buffer to fill + * @param max the max amount of bytes to write to the buffer + */ +void serial_gets(char *buf, int max); + +#endif // SERIAL_H_ diff --git a/src/kernel/svc.c b/src/kernel/svc.c index 83bd568..7d171c3 100644 --- a/src/kernel/svc.c +++ b/src/kernel/svc.c @@ -47,6 +47,7 @@ void SVC_Handler(void) { * 1 - fork * 2 - getpid * 3 - waitpid + * 4 - sbrk (TODO bad) */ task_svc(args); break; @@ -71,6 +72,8 @@ void SVC_Handler(void) { case 3: /* Filesystem-related calls * 0 - mount * 1 - open + * 2 - close + * 3 - read */ vfs_svc(args); break; diff --git a/src/kernel/task.c b/src/kernel/task.c index 2550e4b..dfe50a7 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -46,11 +46,30 @@ void task_svc(uint32_t *args) *((int *)args[4]) = task_waitpid(args[1], (int *)args[2], args[3]); break; + case 4: + *((void **)args[2]) = task_sbrk(args[1]); + break; default: break; } } +void *task_sbrk(uint32_t bytes) +{ + if (task_current->heap == 0) { + task_current->heap = malloc(1024 * 16); + return (uint8_t *)task_current->heap + (1024 * 16); + } + + if (bytes == 0) { + alloc_t *alloc = (alloc_t *)((uint8_t *)task_current->heap - + sizeof(alloc_t)); + return (uint8_t *)task_current->heap + alloc->size; + } + + return (void *)-1; +} + void task_hold(uint8_t hold) { if (hold != 0) @@ -124,6 +143,7 @@ void task_purge(void) // Since we're single core, no one else can claim this memory until // a task switch, after which we're done with this memory anyway. free(task_current->stack); + free(task_current->heap); free(task_current); YIELD; @@ -163,6 +183,7 @@ task_t *task_create(void (*code)(void), uint16_t stackSize) t->status.state = TASK_RUNNING; t->status.value = 0; + t->heap = 0; t->stack = (uint32_t *)malloc(stackSize); void *sp = (uint8_t *)t->stack + stackSize - 68; // excep. stack + regs t->sp = sp; diff --git a/src/kernel/task.h b/src/kernel/task.h index 30e3e66..5875e3c 100644 --- a/src/kernel/task.h +++ b/src/kernel/task.h @@ -35,6 +35,7 @@ typedef struct task_t { struct task_t *next; /**< pointer to the next task_t instance */ uint32_t *sp; /**< pointer to the task's last sp register value */ uint32_t *stack; /**< pointer to the task's stack */ + uint32_t *heap; pid_t pid; /**< Task (Process) ID */ pid_t pgid; /**< Process Group ID */ struct { @@ -82,5 +83,6 @@ pid_t task_getpid(void); pid_t task_waitpid(pid_t pid, int *wstatus, int options); +void *task_sbrk(uint32_t bytes); #endif // TASK_H_ diff --git a/src/kernel/vfs.c b/src/kernel/vfs.c index 1720a6b..d6f9e14 100644 --- a/src/kernel/vfs.c +++ b/src/kernel/vfs.c @@ -1,9 +1,11 @@ #include "vfs.h" #include <kernel/task.h> +#include <fs/stdio.h> -#define VFS_MAX_VOLS 8 -#define VFS_MAX_FILES 10 +// +1 vol for stdio, +3 fd's for stdout, in, err +#define VFS_MAX_VOLS (1 + 8) +#define VFS_MAX_FILES (3 + 10) static vfs_volume vfs_volumes[VFS_MAX_VOLS]; static vfs_file vfs_files[VFS_MAX_FILES]; @@ -19,6 +21,9 @@ void vfs_svc(uint32_t *args) *((int *)args[3]) = vfs_open((const char *)args[1], args[2]); break; case 2: + *((int *)args[2]) = vfs_close(args[1]); + break; + case 3: *((int *)args[4]) = vfs_read(args[1], args[2], (uint8_t *)args[3]); break; default: @@ -32,6 +37,12 @@ void vfs_init(void) vfs_volumes[i].flags = 0; for (int i = 0; i < VFS_MAX_FILES; i++) vfs_files[i].flags = 0; + + vfs_mount(&stdio_funcs, 0); + // order is crucial + vfs_open("in", VFS_FILE_READ); + vfs_open("out", VFS_FILE_WRITE); + vfs_open("err", VFS_FILE_WRITE); } int vfs_mount(vfs_volume_funcs *funcs, uint32_t flags) @@ -98,6 +109,26 @@ int vfs_open(const char *path, uint32_t flags) return file; } +int vfs_close(int fd) +{ + if (fd < 0 || fd > VFS_MAX_FILES) + return -1; + if (vfs_volumes[vfs_files[fd].vol].funcs->close == 0) + return -1; + if (vfs_files[fd].pid != task_getpid()) + return -1; + if (!(vfs_files[fd].flags & VFS_FILE_OPEN)) + return 0; + + // TODO care + /*int ret =*/ vfs_volumes[vfs_files[fd].vol].funcs->close( + vfs_files[fd].fsinfo); + + vfs_files[fd].flags = 0; + vfs_files[fd].pid = 0; + return 0; +} + uint32_t vfs_read(int fd, uint32_t count, uint8_t *buffer) { if (fd < 0 || fd > VFS_MAX_FILES || count == 0 || buffer == 0) diff --git a/src/kernel/vfs.h b/src/kernel/vfs.h index a6de690..c9c9179 100644 --- a/src/kernel/vfs.h +++ b/src/kernel/vfs.h @@ -7,15 +7,17 @@ typedef struct { char name[32]; } vfs_dirent; -typedef struct { +typedef struct vfs_volume_funcs_t { void *(*open)(const char *file); - void (*close)(void *info); + int (*close)(void *info); uint32_t (*read)(void *info, uint32_t count, uint8_t *buffer); uint32_t (*write)(void *info, uint32_t count, const uint8_t *buffer); vfs_dirent *(*readdir)(const char *path); } vfs_volume_funcs; +// Indicates mounted volume #define VFS_MOUNTED (1 << 0) +// Set if filesystem is read-only #define VFS_READONLY (1 << 1) typedef struct { @@ -23,24 +25,27 @@ typedef struct { vfs_volume_funcs *funcs; } vfs_volume; +// Indicates an opened file #define VFS_FILE_OPEN (1 << 0) +// Indicates read permission on file #define VFS_FILE_READ (1 << 1) +// Indicates write permission on file #define VFS_FILE_WRITE (1 << 2) -#define VFS_FILE_MODF (1 << 3) -#define VFS_TEMPORARY (1 << 4) -#define VFS_EOF (1 << 5) +// Set if EOF has been reached +#define VFS_EOF (1 << 3) typedef struct { - uint32_t flags; - uint32_t vol; - uint32_t pid; - void *fsinfo; + uint32_t flags; /**< File attribute flags */ + uint32_t vol; /**< Index of volume file is stored on */ + uint32_t pid; /**< PID of process handling this file */ + void *fsinfo; /**< Filesystem-specific data, handled by fs driver */ } vfs_file; void vfs_init(void); int vfs_mount(vfs_volume_funcs *funcs, uint32_t flags); int vfs_open(const char *path, uint32_t flags); +int vfs_close(int fd); uint32_t vfs_read(int fd, uint32_t count, uint8_t *buffer); #endif // VFS_H_ |