Skip to content

Commit

Permalink
Merge pull request #13 from akriese/feature/syscall
Browse files Browse the repository at this point in the history
Feature/syscall
  • Loading branch information
akriese authored Jan 19, 2024
2 parents 72c36b1 + 6e7646a commit e74f350
Show file tree
Hide file tree
Showing 33 changed files with 1,227 additions and 351 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ LSCRIPT = kernel.lds

OBJ = driver/dbgu.o
OBJ += lib/print.o lib/util.o lib/mem.o lib/thread.o lib/scheduler.o
OBJ += lib/programs/dbgu.o lib/programs/exceptions.o lib/programs/interrupts.o lib/programs/threads.o
OBJ += lib/sys_call.o
OBJ += lib/programs/dbgu.o lib/programs/exceptions.o lib/programs/interrupts.o
OBJ += lib/programs/threads.o lib/programs/sys_calls.o
OBJ += lib/sys_call/handling.o lib/sys_call/swi.o

OBJ += system/main.o system/start.o system/memory_controller.o system/exceptions.o
OBJ += system/timer.o system/interrupt.o
Expand Down
25 changes: 11 additions & 14 deletions driver/dbgu.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#define IER_RXRDY_BIT 0

struct dbgu {
typedef struct dbgu_mem {
unsigned int cr;
unsigned int __mr;
unsigned int ier;
Expand All @@ -26,11 +26,11 @@ struct dbgu {
unsigned int __reserved[(0x40 - 0x24) >> 2];
unsigned int __cidr;
unsigned int __exid;
};
} dbgu_mem;

volatile struct dbgu *const dbgu = (struct dbgu *)DBGU;
volatile dbgu_mem *const dbgu = (dbgu_mem *)DBGU;

volatile struct ring_buffer *receive_buffer;
volatile ring_buffer *receive_buffer;

/*
* Returns 1 if a bit at the given position at the given address is set.
Expand Down Expand Up @@ -76,17 +76,12 @@ void write_char(char c) { dbgu->thr = c; }
* as that is done by the controller upon the register read instruction.
*/
char dbgu_getc() {
// enable receive controller

// wait for new character in ring buffer
unsigned int *c;
do {
c = ring_buffer_get(receive_buffer);
} while (c == 0);

return *(char *)c;
// disable read
// set_status(RXDIS_BIT);
while (!ring_buffer_available(receive_buffer)) {
}

unsigned int c = ring_buffer_get(receive_buffer);
return (char)c;
}

/*
Expand Down Expand Up @@ -143,6 +138,8 @@ void dbgu_receive_interrupt_handler() {
ring_buffer_put(receive_buffer, (unsigned int)c);
}

int dbgu_has_next() { return ring_buffer_available(receive_buffer); }

char dbgu_grab_char() {
while (!check_status(RXRDY_BIT)) {
}
Expand Down
34 changes: 20 additions & 14 deletions include/data_structures.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* @brief Ring buffer for [unsigned int] with a length and two indices marking
* current input and output pointers
*/
struct ring_buffer {
typedef struct ring_buffer {
unsigned int length;
unsigned int next_in;
unsigned int next_out;
unsigned int *buffer;
};
} ring_buffer;

/**
* @brief Creates a ring buffer where the buffer lies directly after the *buffer
Expand All @@ -23,9 +23,9 @@ struct ring_buffer {
* @param start Pointer to the start of the object in memory.
* @return Pointer to the created object.
*/
volatile struct ring_buffer *ring_buffer_create(unsigned int size,
unsigned int *start) {
volatile struct ring_buffer *b = (struct ring_buffer *)start;
volatile ring_buffer *ring_buffer_create(unsigned int size,
unsigned int *start) {
volatile ring_buffer *b = (ring_buffer *)start;
b->length = (size / 4) - 4;
b->buffer = start + 4;
b->next_in = 0;
Expand All @@ -34,21 +34,27 @@ volatile struct ring_buffer *ring_buffer_create(unsigned int size,
return b;
}

void ring_buffer_put(volatile struct ring_buffer *b, unsigned int element) {
/**
* @brief Checks if the given ring_buffer has a next element.
*/
int ring_buffer_available(volatile ring_buffer *b) {
return b->next_out != b->next_in;
}

void ring_buffer_put(volatile ring_buffer *b, unsigned int element) {
b->buffer[b->next_in] = element;
b->next_in = (b->next_in + 1) % b->length;
}

/**
* Returns 0 if there is no new element in the buffer.
* Otherwise returns the pointer to the object to get.
* Returns the next object of the buffer.
*
* Assumes that a next item is available.
* If not, the returned value will be unexpected and the internal pointers
* are broken.
*/
unsigned int *ring_buffer_get(volatile struct ring_buffer *b) {
if (b->next_out == b->next_in) {
return 0;
}

unsigned int *element = b->buffer + b->next_out;
unsigned int ring_buffer_get(volatile ring_buffer *b) {
unsigned int element = *(b->buffer + b->next_out);
b->next_out = (b->next_out + 1) % b->length;

return element;
Expand Down
2 changes: 2 additions & 0 deletions include/dbgu.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ char dbgu_grab_char();

void dbgu_enable();

int dbgu_has_next();

#endif // !_DBGU_H_
2 changes: 2 additions & 0 deletions include/example_programs.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ int exception_program();
int interrupt_program();

int thread_program();

int sys_call_application();
4 changes: 2 additions & 2 deletions include/mem_layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
// Thread management object
#define _INTERNAL_THREADS_MANAGEMENT_START \
_INTERNAL_DBGU_THREAD_INPUT_BUFFER_END
#define _INTERNAL_THREADS_MANAGEMENT_SIZE sizeof(struct thread_management)
#define _INTERNAL_THREADS_MANAGEMENT_SIZE sizeof(thread_management)
#define _INTERNAL_THREADS_MANAGEMENT_END \
(_INTERNAL_THREADS_MANAGEMENT_START + _INTERNAL_THREADS_MANAGEMENT_SIZE)

// Thread control blocks
#define _INTERNAL_THREADS_TCB_ARRAY_START _INTERNAL_THREADS_MANAGEMENT_END
#define _INTERNAL_THREADS_TCB_ARRAY_SIZE \
(sizeof(struct thread_control_block) * MAX_NUM_THREADS)
(sizeof(thread_control_block) * MAX_NUM_THREADS)
#define _INTERNAL_THREADS_TCB_ARRAY_END \
(_INTERNAL_THREADS_TCB_ARRAY_START + _INTERNAL_THREADS_TCB_ARRAY_SIZE)

Expand Down
11 changes: 11 additions & 0 deletions include/resource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef _RESOURCES_H_
#define _RESOURCES_H_

typedef enum resource_type {
RESOURCE_NONE,
RESOURCE_DBGU_RECEIVE,
RESOURCE_DBGU_TRANSMIT,
RESOURCE_WAITING_TIME,
} resource_type;

#endif /* ifndef _RESOURCES_H_ */
16 changes: 11 additions & 5 deletions include/scheduler.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
void scheduler_start();

void scheduler_register_thread(unsigned int thread_id);
#include <thread.h>

void scheduler_end_thread();

void scheduler_next(void *context);
void scheduler_next(thread_context *context);

void scheduler_init();

void scheduler_count_time();

void scheduler_switch(unsigned int thread_id, thread_context *context);

unsigned int scheduler_count_ready();

void scheduler_init(int (*idle_fun)());
void scheduler_set_idle_fun(int (*idle_fun)());
14 changes: 14 additions & 0 deletions include/shrine_os_lib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef _SHRINE_OS_LIB_H_
#define _SHRINE_OS_LIB_H_

void sys_call_exit_thread();
int sys_call_create_thread(int (*fun)(void *), void *input);
void sys_call_sleep(unsigned int duration);
char sys_call_read_char();
void sys_call_put_char(char c);
void sys_call_register_irq_callback(unsigned int callback_id,
int (*fun)(void *));
void sys_call_st_set_pits_intervall(unsigned int ms);
void sys_call_set_idle_function(int (*idle_fun)());

#endif /* ifndef _SHRINE_OS_LIB_H_ */
24 changes: 23 additions & 1 deletion include/sys_call.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
#ifndef _SYS_CALL_H_
#define _SYS_CALL_H_

void sys_call_handler(unsigned int number, void *context);
#include <resource.h>
#include <thread.h>

#define SYSCALL_NUM_THREAD_EXIT 1
#define SYSCALL_NUM_THREAD_CREATE 2
#define SYSCALL_NUM_THREAD_SLEEP 3
#define SYSCALL_NUM_IO_READ_CHAR 4
#define SYSCALL_NUM_IO_PUT_CHAR 5
#define SYSCALL_NUM_REGISTER_IRQ_CALLBACK 6
#define SYSCALL_NUM_ST_SET_PITS_INTERVALL 7
#define SYSCALL_NUM_SET_IDLE_FUNCTION 8

void sys_call_handler(unsigned int number, thread_context *context);
void sys_call_post_unblock(resource_type blocking_resource,
unsigned int unblocked_thread_id);

void sys_call_exit_thread();
int sys_call_create_thread(int (*fun)(void *), void *input);
void sys_call_sleep(unsigned int duration);
char sys_call_read_char();
void sys_call_put_char(char c);
void sys_call_register_irq_callback(unsigned int callback_id,
int (*fun)(void *));
void sys_call_st_set_pits_intervall(unsigned int ms);
void sys_call_set_idle_function(int (*idle_fun)());

#endif // !_SYS_CALL_H_
20 changes: 13 additions & 7 deletions include/system.h
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
#ifndef _SYSTEM_H_
#define _SYSTEM_H_

enum cpu_mode {
#include <thread.h>

typedef enum cpu_mode {
CPU_MODE_USER = 0x10,
CPU_MODE_FIQ = 0x11,
CPU_MODE_IRQ = 0x12,
CPU_MODE_SVC = 0x13,
CPU_MODE_ABT = 0x17,
CPU_MODE_UND = 0x1b,
CPU_MODE_SYS = 0x1f,
};
} cpu_mode;

enum interrupt_handler_routines {
typedef enum interrupt_handler_routines {
SYSTEM_TIMER_HANDLER,
DBGU_RECEIVE_HANDLER,
_INTERRUPT_HANDLER_ROUTINES_END // used to find out the number of routines
};
} interrupt_handler_routines;

void mc_remap();

void st_activate_pits(unsigned short ms);
void st_activate_pits();

int st_interrupt_active();

int st_get_intervall();

void st_set_intervall(unsigned int ms);

void init_sys_interrupts();

void register_interrupt_routines(enum interrupt_handler_routines routine,
void (*handler)(void *));
void register_interrupt_routines(interrupt_handler_routines routine,
void (*handler)(thread_context *));

void cpsr_enable_interrupts();

Expand Down
53 changes: 40 additions & 13 deletions include/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,63 @@

#define MAX_NUM_THREADS 32

enum thread_status {
#include <resource.h>

typedef enum thread_status {
THREAD_READY = -1,
TCB_UNUSED = 0,
THREAD_ASLEEP = -1,
THREAD_ACTIVE = 1,
IDLE = 2,
};
THREAD_ASLEEP = 2,
THREAD_BLOCKED = 3,
} thread_status;

typedef enum thread_role {
THREAD_ROLE_SYSTEM,
THREAD_ROLE_USER,
THREAD_ROLE_IDLE,
} thread_role;

struct thread_management {
enum thread_status status[MAX_NUM_THREADS]; // 0 if thread block is free
typedef struct thread_management {
int active_thread_id; // id of the currently running thread
unsigned int last_created_id;
};
unsigned int time_counter;
unsigned int last_scheduled_thread;
} thread_management;

// IMPORTANT: cpsr has to come after registers due to an assumption
struct thread_control_block {
typedef struct thread_context {
unsigned int registers[13];
unsigned int sp;
unsigned int lr;
unsigned int pc;
unsigned int cpsr;
unsigned int registers[13];
};
} thread_context;

typedef struct thread_control_block {
thread_context ctx;
thread_status status;
thread_role role;
unsigned int wake_up_time;
resource_type block_reason;
} thread_control_block;

int thread_create(int (*fun)(void *), void *input);

void thread_finish();

void thread_save_context(unsigned int thread_id, void *context);
void thread_save_context(unsigned int thread_id, thread_context *context);

void *thread_get_context(unsigned int thread_id);
thread_context *thread_get_context(unsigned int thread_id);

void create_idle_thread(int (*idle_fun)());

void thread_sleep(unsigned int duration);

void thread_wait(resource_type blocking_resource);

int thread_unblock(resource_type blocking_resource);

void thread_wakeup(unsigned int thread_id);

unsigned int *thread_registers_from_context(thread_context *context);

#endif /* ifndef _THREAD_H_ */
10 changes: 10 additions & 0 deletions include/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@ int _print_exception(int type);
int get_line(char *buffer, unsigned int max_length);

int str_to_int(char *s);

int get_number(char *prompt, int default_number);

int is_upper(char c);

int is_lower(char c);

int is_digit(char c);

int idling();
Loading

0 comments on commit e74f350

Please sign in to comment.