aboutsummaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/init.c2
-rw-r--r--src/kernel/serial.c60
-rw-r--r--src/kernel/serial.h48
-rw-r--r--src/kernel/svc.c3
-rw-r--r--src/kernel/task.c21
-rw-r--r--src/kernel/task.h2
-rw-r--r--src/kernel/vfs.c35
-rw-r--r--src/kernel/vfs.h23
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_