From 350437ef4b8ba0811d285f7454d2b54ffce6b029 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Tue, 8 Apr 2014 13:18:27 +0200 Subject: change build structure --- Makefile | 61 ++++-- apps/shell/app.c | 15 ++ apps/shell/app.mk | 1 + kernel/bug/include/bug/debug.h | 6 - kernel/bug/include/bug/panic.h | 6 - kernel/collection/include/collection/list.h | 244 --------------------- kernel/collection/include/collection/rbuffer.h | 48 ---- kernel/include/init.h | 10 + kernel/include/mux/clock.h | 21 ++ kernel/include/mux/debug.h | 7 + kernel/include/mux/idle.h | 6 + kernel/include/mux/io.h | 30 +++ kernel/include/mux/list.h | 244 +++++++++++++++++++++ kernel/include/mux/lock.h | 24 ++ kernel/include/mux/rbuffer.h | 48 ++++ kernel/include/mux/sched.h | 101 +++++++++ kernel/init.c | 29 +++ kernel/io/include/io/io.h | 30 --- kernel/io/io.c | 12 +- kernel/io/mcu/atmega2560/include/mcu/io/usart.h | 12 - kernel/io/mcu/atmega2560/usart.c | 148 ------------- kernel/mcu/atmega2560/clock.c | 37 ++++ kernel/mcu/atmega2560/context.c | 98 +++++++++ kernel/mcu/atmega2560/include/mcu/context.h | 123 +++++++++++ kernel/mcu/atmega2560/include/mcu/usart.h | 12 + kernel/mcu/atmega2560/usart.c | 148 +++++++++++++ kernel/sched/idle.c | 19 ++ kernel/sched/sched.c | 57 +++++ kernel/task/idle.c | 19 -- kernel/task/include/task/idle.h | 6 - kernel/task/include/task/lock.h | 24 -- kernel/task/include/task/sched.h | 58 ----- kernel/task/include/task/task.h | 46 ---- kernel/task/mcu/atmega2560/context.c | 98 --------- .../task/mcu/atmega2560/include/mcu/task/context.h | 117 ---------- kernel/task/mcu/atmega2560/include/mcu/task/task.h | 11 - kernel/task/sched.c | 55 ----- kernel/time/include/time/clock.h | 21 -- kernel/time/mcu/atmega2560/clock.c | 37 ---- kernel/tshield/include/tshield/tshield.h | 51 ----- kernel/tshield/mcu/atmega2560/tshield.c | 140 ------------ main.c | 58 ----- modules/tshield/include/tshield/tshield.h | 51 +++++ modules/tshield/mcu/atmega2560/tshield.c | 140 ++++++++++++ 44 files changed, 1267 insertions(+), 1262 deletions(-) create mode 100644 apps/shell/app.c create mode 100644 apps/shell/app.mk delete mode 100644 kernel/bug/include/bug/debug.h delete mode 100644 kernel/bug/include/bug/panic.h delete mode 100644 kernel/collection/include/collection/list.h delete mode 100644 kernel/collection/include/collection/rbuffer.h create mode 100644 kernel/include/init.h create mode 100644 kernel/include/mux/clock.h create mode 100644 kernel/include/mux/debug.h create mode 100644 kernel/include/mux/idle.h create mode 100644 kernel/include/mux/io.h create mode 100644 kernel/include/mux/list.h create mode 100644 kernel/include/mux/lock.h create mode 100644 kernel/include/mux/rbuffer.h create mode 100644 kernel/include/mux/sched.h create mode 100644 kernel/init.c delete mode 100644 kernel/io/include/io/io.h delete mode 100644 kernel/io/mcu/atmega2560/include/mcu/io/usart.h delete mode 100644 kernel/io/mcu/atmega2560/usart.c create mode 100644 kernel/mcu/atmega2560/clock.c create mode 100644 kernel/mcu/atmega2560/context.c create mode 100644 kernel/mcu/atmega2560/include/mcu/context.h create mode 100644 kernel/mcu/atmega2560/include/mcu/usart.h create mode 100644 kernel/mcu/atmega2560/usart.c create mode 100644 kernel/sched/idle.c create mode 100644 kernel/sched/sched.c delete mode 100644 kernel/task/idle.c delete mode 100644 kernel/task/include/task/idle.h delete mode 100644 kernel/task/include/task/lock.h delete mode 100644 kernel/task/include/task/sched.h delete mode 100644 kernel/task/include/task/task.h delete mode 100644 kernel/task/mcu/atmega2560/context.c delete mode 100644 kernel/task/mcu/atmega2560/include/mcu/task/context.h delete mode 100644 kernel/task/mcu/atmega2560/include/mcu/task/task.h delete mode 100644 kernel/task/sched.c delete mode 100644 kernel/time/include/time/clock.h delete mode 100644 kernel/time/mcu/atmega2560/clock.c delete mode 100644 kernel/tshield/include/tshield/tshield.h delete mode 100644 kernel/tshield/mcu/atmega2560/tshield.c delete mode 100644 main.c create mode 100644 modules/tshield/include/tshield/tshield.h create mode 100644 modules/tshield/mcu/atmega2560/tshield.c diff --git a/Makefile b/Makefile index 17cb279..49c728e 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,36 @@ # CPU model +# MCU=atmega2560 + # CPU Frequency +# F_CPU=16000000L -# Name of image to produce (can be arbitrary) -TARGET=firmware +# App +# +APP?=shell +include apps/$(APP)/app.mk + + +# Hardware modules +# +MODULES?= + # Serial port used for uploading +# SERIAL=/dev/ttyACM0 BAUD=115200 -# Modules to include in kernel -MODULES=bug collection task tshield time io + +# Name of image to produce (can be arbitrary) +# +TARGET=firmware + # Toolchain flags +# CC=avr-gcc CFLAGS= -std=gnu99 -O2 -Wall -finline-functions -ffunction-sections -fdata-sections -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -mmcu=$(MCU) -DF_CPU=$(F_CPU) LD=avr-gcc @@ -32,23 +48,28 @@ CPPFLAGS= -O2 -Wall -fno-exceptions -ffunction-sections -fdata-sections -funsign GDBINITFILE=gdb.conf # Derived variables +SOURCEDIRS=\ + kernel \ + kernel/io \ + kernel/sched \ + kernel/mcu/$(MCU) \ + $(foreach module,$(MODULES),modules/$(module)) \ + $(foreach module,$(MODULES),modules/$(module)/mcu/$(MCU)) \ + apps/$(APP) + +INCLUDES=\ + kernel/include \ + kernel/mcu/$(MCU)/include \ + $(foreach module,$(MODULES),modules/$(module)/include) + SOURCES=\ - $(foreach module,$(MODULES),$(wildcard kernel/$(module)/*.c)) \ - $(foreach module,$(MODULES),$(wildcard kernel/$(module)/mcu/$(MCU)/*.S)) \ - $(foreach module,$(MODULES),$(wildcard kernel/$(module)/mcu/$(MCU)/*.c)) \ - $(wildcard arduino/*.s) $(wildcard arduino/*.c) $(wildcard arduino/*.cpp) \ - $(wildcard *.s) $(wildcard *.c) $(wildcard *.cpp) + $(foreach dir,$(SOURCEDIRS),$(wildcard $(dir)/*.c)) \ + $(foreach dir,$(SOURCEDIRS),$(wildcard $(dir)/*.S)) OBJECTS=$(addsuffix .o, $(basename $(SOURCES))) -INCLUDES=\ - $(foreach module, $(MODULES), kernel/$(module)/include) \ - $(foreach module, $(MODULES), kernel/$(module)/mcu/$(MCU)/include) - # Rules -all: target - -target: $(TARGET).hex +all: $(TARGET).hex $(TARGET).hex: $(TARGET).elf $(OC) $(OCFLAGS) $< $@ @@ -92,11 +113,9 @@ cycle: clean: @rm -f *.o - @for module in $(MODULES); do \ - rm -f kernel/$$module/*.o; \ - rm -f kernel/$$module/mcu/$(MCU)/*.o; \ + @for dir in $(SOURCEDIRS); do \ + rm -f $$dir/*.o; \ done - @rm -f arduino/*.o @rm -f $(TARGET).hex @rm -f $(TARGET).elf @rm -f $(GDBINITFILE) @@ -120,4 +139,4 @@ $(GDBINITFILE): $(TARGET).elf @echo "Use 'avr-gdb -x $(GDBINITFILE)'" -.PHONY: clean cycle +.PHONY: clean cycle target diff --git a/apps/shell/app.c b/apps/shell/app.c new file mode 100644 index 0000000..eb85e4e --- /dev/null +++ b/apps/shell/app.c @@ -0,0 +1,15 @@ +#include "init.h" +#include "mux/sched.h" +#include "mcu/context.h" + +void setup() { + +} + +void task1(char args) { + +} + +void task2(char args) { + +} \ No newline at end of file diff --git a/apps/shell/app.mk b/apps/shell/app.mk new file mode 100644 index 0000000..b1bfae3 --- /dev/null +++ b/apps/shell/app.mk @@ -0,0 +1 @@ +MODULES=tshield \ No newline at end of file diff --git a/kernel/bug/include/bug/debug.h b/kernel/bug/include/bug/debug.h deleted file mode 100644 index 854f4c6..0000000 --- a/kernel/bug/include/bug/debug.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DEBUG_H -#define DEBUG_H - -void debug_led(int led, int value); - -#endif \ No newline at end of file diff --git a/kernel/bug/include/bug/panic.h b/kernel/bug/include/bug/panic.h deleted file mode 100644 index 2a39076..0000000 --- a/kernel/bug/include/bug/panic.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef PANIC_H -#define PANIC_H - -void panic(); - -#endif \ No newline at end of file diff --git a/kernel/collection/include/collection/list.h b/kernel/collection/include/collection/list.h deleted file mode 100644 index 3a76885..0000000 --- a/kernel/collection/include/collection/list.h +++ /dev/null @@ -1,244 +0,0 @@ -#ifndef __LIST_H -#define __LIST_H - -/* This file is from Linux Kernel (include/linux/list.h) - * and modified by simply removing hardware prefetching of list items. - * Here by copyright, credits attributed to wherever they belong. - * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu) - */ - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head *prev, struct list_head *next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = (void *) 0; - entry->prev = (void *) 0; -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(struct list_head *head) -{ - return head->next == head; -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next) -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); \ - pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - - -#endif diff --git a/kernel/collection/include/collection/rbuffer.h b/kernel/collection/include/collection/rbuffer.h deleted file mode 100644 index dceaeb0..0000000 --- a/kernel/collection/include/collection/rbuffer.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef RBUFFER_H -#define RBUFFER_H - -#include - -struct rbuffer_t { - char* address_begin; - char* address_end; - char* volatile head; - char* volatile tail; -}; - -#define RBUFFER_INIT(array, length) \ - { \ - .address_begin = array, \ - .address_end = array + length, \ - .head = array, \ - .tail = array \ - } - -#define INIT_RBUFFER(buffer, array, length) \ - (buffer)->address_begin = (array); \ - (buffer)->address_end = (array) + (length); \ - (buffer)->head = (array); \ - (buffer)->tail = (array) - -static inline int rbuffer_empty(struct rbuffer_t* const rb) { - return rb->head == rb->tail; -} - -static inline int rbuffer_write(struct rbuffer_t* const rb, char data) { - char* next_head = rb->head + 1; - if(next_head >= rb->address_end) next_head = rb->address_begin; - if (rb->tail == next_head) return -1; - *rb->head = data; - rb->head = next_head; - return 0; -} - -static inline int rbuffer_read(struct rbuffer_t* const rb, char* const data) { - if (rbuffer_empty(rb)) return -1; - *data = *rb->tail; - rb->tail += 1; - if(rb->tail >= rb->address_end) rb->tail = rb->address_begin; - return 0; -} - -#endif diff --git a/kernel/include/init.h b/kernel/include/init.h new file mode 100644 index 0000000..8df22f5 --- /dev/null +++ b/kernel/include/init.h @@ -0,0 +1,10 @@ +#ifndef MUX_INIT_H +#define MUX_INIT_H + +#include + +void setup(); +void task1(char args); +void task2(char args); + +#endif \ No newline at end of file diff --git a/kernel/include/mux/clock.h b/kernel/include/mux/clock.h new file mode 100644 index 0000000..429a00d --- /dev/null +++ b/kernel/include/mux/clock.h @@ -0,0 +1,21 @@ +#ifndef MUX_CLOCK_H +#define MUX_CLOCK_H + +/** + * Initializes main system clock. + * @ms time between each tick in milliseconds + * @tick function to run every tick + */ +void clock_init(int ms, void (*tick)()); + +/** + * Starts main system clock. + */ +void clock_start(); + +/** + * Stops main system clock. + */ +void clock_stop(); + +#endif \ No newline at end of file diff --git a/kernel/include/mux/debug.h b/kernel/include/mux/debug.h new file mode 100644 index 0000000..7119c35 --- /dev/null +++ b/kernel/include/mux/debug.h @@ -0,0 +1,7 @@ +#ifndef MUX_DEBUG_H +#define MUX_DEBUG_H + +void panic(); +void debug_led(int led, int value); + +#endif \ No newline at end of file diff --git a/kernel/include/mux/idle.h b/kernel/include/mux/idle.h new file mode 100644 index 0000000..0d94a9a --- /dev/null +++ b/kernel/include/mux/idle.h @@ -0,0 +1,6 @@ +#ifndef MUX_IDLE_H +#define MUX_IDLE_H + +void idle_entry(char args); + +#endif \ No newline at end of file diff --git a/kernel/include/mux/io.h b/kernel/include/mux/io.h new file mode 100644 index 0000000..4ec45f5 --- /dev/null +++ b/kernel/include/mux/io.h @@ -0,0 +1,30 @@ +#ifndef MUX_IO_H +#define MUX_IO_H + +#include + +typedef long ssize_t; + +struct file; +struct file_operations; + +struct file { + struct file_operations* const fops; + void* private_data; +}; + +struct file_operations { + int (*open)(struct file* file); + int (*ioctl)(struct file* file, int cmd, long args); + ssize_t (*read)(struct file* file, char* const buffer, size_t size); + ssize_t (*write)(struct file* file, const char* const buffer, size_t size); + int (*close)(struct file* file); +}; + +int open(struct file* file); +int ioctl(struct file* file, int cmd, long args); +ssize_t read(struct file* file, char* const buffer, size_t size); +ssize_t write(struct file* file, const char* const buffer, size_t size); +int close(struct file* file); + +#endif \ No newline at end of file diff --git a/kernel/include/mux/list.h b/kernel/include/mux/list.h new file mode 100644 index 0000000..98ea766 --- /dev/null +++ b/kernel/include/mux/list.h @@ -0,0 +1,244 @@ +#ifndef MUX_LIST_H +#define MUX_LIST_H + +/* This file is from Linux Kernel (include/linux/list.h) + * and modified by simply removing hardware prefetching of list items. + * Here by copyright, credits attributed to wherever they belong. + * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu) + */ + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (void *) 0; + entry->prev = (void *) 0; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next) +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + + +#endif diff --git a/kernel/include/mux/lock.h b/kernel/include/mux/lock.h new file mode 100644 index 0000000..b5ac4d9 --- /dev/null +++ b/kernel/include/mux/lock.h @@ -0,0 +1,24 @@ +#ifndef MUX_LOCK_H +#define MUX_LOCK_H + +#include "mux/sched.h" + +typedef volatile char spin_lock_t; + +#define SPIN_LOCK_UNLOCKED 0 +#define SPIN_LOCK_LOCKED 0 + +static inline void spin_lock(spin_lock_t* lock) { + while(*lock != SPIN_LOCK_UNLOCKED) {yield();}; + cli(); + *lock = SPIN_LOCK_LOCKED; + sei(); +} + +static inline void spin_unlock(spin_lock_t* lock) { + cli(); + *lock = SPIN_LOCK_UNLOCKED; + sei(); +} + +#endif \ No newline at end of file diff --git a/kernel/include/mux/rbuffer.h b/kernel/include/mux/rbuffer.h new file mode 100644 index 0000000..dceaeb0 --- /dev/null +++ b/kernel/include/mux/rbuffer.h @@ -0,0 +1,48 @@ +#ifndef RBUFFER_H +#define RBUFFER_H + +#include + +struct rbuffer_t { + char* address_begin; + char* address_end; + char* volatile head; + char* volatile tail; +}; + +#define RBUFFER_INIT(array, length) \ + { \ + .address_begin = array, \ + .address_end = array + length, \ + .head = array, \ + .tail = array \ + } + +#define INIT_RBUFFER(buffer, array, length) \ + (buffer)->address_begin = (array); \ + (buffer)->address_end = (array) + (length); \ + (buffer)->head = (array); \ + (buffer)->tail = (array) + +static inline int rbuffer_empty(struct rbuffer_t* const rb) { + return rb->head == rb->tail; +} + +static inline int rbuffer_write(struct rbuffer_t* const rb, char data) { + char* next_head = rb->head + 1; + if(next_head >= rb->address_end) next_head = rb->address_begin; + if (rb->tail == next_head) return -1; + *rb->head = data; + rb->head = next_head; + return 0; +} + +static inline int rbuffer_read(struct rbuffer_t* const rb, char* const data) { + if (rbuffer_empty(rb)) return -1; + *data = *rb->tail; + rb->tail += 1; + if(rb->tail >= rb->address_end) rb->tail = rb->address_begin; + return 0; +} + +#endif diff --git a/kernel/include/mux/sched.h b/kernel/include/mux/sched.h new file mode 100644 index 0000000..de50f98 --- /dev/null +++ b/kernel/include/mux/sched.h @@ -0,0 +1,101 @@ +#ifndef MUX_SCHED_H +#define MUX_SCHED_H + +#include "mux/list.h" + +/** + * Task control block, contains runtime + * information about tasks. + */ +struct tcb_t { + /** Stack pointer of this task. (must be first in structure) */ + char* volatile sp; + + /** Lowest address of this task's memory (inclusive). */ + char* mem_low; + + /** Highest address of this task's memory (inclusive). */ + char* mem_high; + + /** Entry function of this task. */ + void (*entry)(char); + + /** Current wait queue that this task is in.*/ + struct list_head queue; + + /** ID of task. */ + char id; + +}; + +/** + * Utility for declaring a task with statically allocated memory. + * Note: for a task to be scheduled, it must first be spawned (see spawn()). +*/ +#define DECLARE_TASK(name, stack_size, entry_function) \ + static char _declared_stack_##name[stack_size]; \ + static struct tcb_t name = { \ + .sp = 0, \ + .mem_low = _declared_stack_##name, \ + .mem_high = _declared_stack_##name + stack_size - 1, \ + .entry = entry_function, \ + .queue = {} \ + }; + + +/** + * Points to currently executing task. If no scheduling has been enabled, + * this points to NULL + */ +extern struct tcb_t* volatile current; + +/** + * Queue that contains all tasks that are ready to be run, awaiting their + * turn from the scheduler. + */ +extern struct list_head ready; + +/** + * Makes the current task sleep on a specific queue. + * This moves the current task to the given queue's tail. + */ +static inline void sleep_queue(struct list_head* queue) { + list_move_tail(¤t->queue, queue); +} + +/** + * Wakes all tasks waiting in the given queue. + * This moves all tasks contained in the queue to the ready queue. + */ +static inline void wake_all_queue(struct list_head* queue) { + list_splice_init(queue, ready.prev); +} + +/** + * Initializes a given task and adds it to the ready queue. + */ +void spawn(struct tcb_t* const tcb, char id); + +/** + * Spawns the idle task + */ +void spawn_idle(struct tcb_t* const tcb, char id); + +/** + * Voluntarily relinquishes control of the CPU from the current task to the scheduler. + */ +void yield() __attribute__ ( ( naked ) ); + + +/** + * Initializes the scheduler by setting up kstack, initializing the idle task + * and selecting the first task to run. + */ +void sched_init(); + +/** + * Enters the scheduler, setting current to the next runnable task. + */ +void schedule(); + +#endif diff --git a/kernel/init.c b/kernel/init.c new file mode 100644 index 0000000..5a9a2e9 --- /dev/null +++ b/kernel/init.c @@ -0,0 +1,29 @@ +#include "init.h" +#include "mux/debug.h" +#include "mux/sched.h" +#include "mux/idle.h" +#include "mux/clock.h" +#include "mcu/context.h" + +#define HZ 100 + +DECLARE_TASK(task_idle, IDLE_STACK_SIZE, idle_entry); +DECLARE_TASK(tcb1, DEFAULT_STACK_SIZE, task1); +DECLARE_TASK(tcb2, DEFAULT_STACK_SIZE, task2); + +int main(int argc, char *argv[]) { + cli(); + + setup(); + + spawn_idle(&task_idle, 0); + spawn(&tcb1, 1); + spawn(&tcb2, 2); + + sei(); + clock_init(1000/HZ, schedule); + clock_start(); + sched_init(); + panic(); //should never reach here + while(1){} +} \ No newline at end of file diff --git a/kernel/io/include/io/io.h b/kernel/io/include/io/io.h deleted file mode 100644 index 3c83cdc..0000000 --- a/kernel/io/include/io/io.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef IO_H -#define IO_H - -#include - -typedef long ssize_t; - -struct file; -struct file_operations; - -struct file { - struct file_operations* const fops; - void* private_data; -}; - -struct file_operations { - int (*open)(struct file* file); - int (*ioctl)(struct file* file, int cmd, long args); - ssize_t (*read)(struct file* file, char* const buffer, size_t size); - ssize_t (*write)(struct file* file, const char* const buffer, size_t size); - int (*close)(struct file* file); -}; - -int open(struct file* file); -int ioctl(struct file* file, int cmd, long args); -ssize_t read(struct file* file, char* const buffer, size_t size); -ssize_t write(struct file* file, const char* const buffer, size_t size); -int close(struct file* file); - -#endif \ No newline at end of file diff --git a/kernel/io/io.c b/kernel/io/io.c index f39168b..63e9669 100644 --- a/kernel/io/io.c +++ b/kernel/io/io.c @@ -1,25 +1,25 @@ -#include "io/io.h" +#include "mux/io.h" int open(struct file* file) { - file->fops->open(file); + return file->fops->open(file); } int ioctl(struct file* file, int cmd, long args) { - file->fops->ioctl(file, cmd, args); + return file->fops->ioctl(file, cmd, args); } ssize_t read(struct file* file, char* const buffer, size_t size) { struct file_operations* fops = file->fops; if (fops->read == NULL) return -1; - else fops->read(file, buffer, size); + else return fops->read(file, buffer, size); } ssize_t write(struct file* file, const char* const buffer, size_t size) { struct file_operations* fops = file->fops; if (fops->write == NULL) return -1; - else fops->write(file, buffer, size); + else return fops->write(file, buffer, size); } int close(struct file* file) { - file->fops->close(file); + return file->fops->close(file); } \ No newline at end of file diff --git a/kernel/io/mcu/atmega2560/include/mcu/io/usart.h b/kernel/io/mcu/atmega2560/include/mcu/io/usart.h deleted file mode 100644 index 6b210fe..0000000 --- a/kernel/io/mcu/atmega2560/include/mcu/io/usart.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef MCU_USART -#define MCU_USART - -#include "io/io.h" - -#define USART_BUFFER_SIZE 64 -#define IOCTL_SET_BAUD 0 - -extern struct file usart0; - - -#endif \ No newline at end of file diff --git a/kernel/io/mcu/atmega2560/usart.c b/kernel/io/mcu/atmega2560/usart.c deleted file mode 100644 index 6f59787..0000000 --- a/kernel/io/mcu/atmega2560/usart.c +++ /dev/null @@ -1,148 +0,0 @@ -#include "io/io.h" -#include "collection/list.h" -#include "collection/rbuffer.h" -#include "task/sched.h" -#include "mcu/io/usart.h" -#include "mcu/task/context.h" -#include -#include - -struct usart_private { - char __rx_buffer[USART_BUFFER_SIZE]; - char __tx_buffer[USART_BUFFER_SIZE]; - - struct rbuffer_t rx_buffer; - struct rbuffer_t tx_buffer; - - struct list_head rx_queue; - struct list_head tx_queue; - - volatile unsigned char* const ucsrxa; - volatile unsigned char* const ubrrxh; - volatile unsigned char* const ubrrxl; - volatile unsigned char* const ucsrxb; - char u2xx; - char rxenx; - char txenx; - char rxciex; - char udriex; -}; - -int usart_open(struct file* usart) { - struct usart_private* priv = (struct usart_private*) usart->private_data; - - INIT_LIST_HEAD(&priv->rx_queue); - INIT_LIST_HEAD(&priv->tx_queue); - INIT_RBUFFER(&priv->rx_buffer, priv->__rx_buffer, USART_BUFFER_SIZE); - INIT_RBUFFER(&priv->tx_buffer, priv->__tx_buffer, USART_BUFFER_SIZE); - - return 0; -} - -int usart_ioctl(struct file* usart, int cmd, long args) { - struct usart_private* priv = (struct usart_private*) usart->private_data; - - switch (cmd) { - case IOCTL_SET_BAUD: { - long baud = args; - (*priv->ucsrxa) |= (1 << priv->u2xx); - long baud_setting = (F_CPU / 4 / baud - 1) / 2; - (*priv->ubrrxh) = baud_setting >> 8; - (*priv->ubrrxl) = baud_setting; - (*priv->ucsrxb) |= (1 << priv->rxenx) | (1 << priv->txenx) | (1 << priv->rxciex); - (*priv->ucsrxb) &= ~(1 << priv->udriex); - return 0; - } - default: - return -1; - } -} - -ssize_t usart_write(struct file* usart, const char* const buffer, size_t length) { - struct usart_private* priv = (struct usart_private*) usart->private_data; - volatile unsigned char* ucsrxb = (priv->ucsrxb); - char write_enable = (1 << priv->udriex); - - ssize_t wrote = 0; - int r = 0; - do { - cli(); - r = rbuffer_write(&priv->tx_buffer, buffer[wrote]); - wrote += 1; - sei(); - *ucsrxb |= write_enable; - } while (r == 0 && wrote < length); - return wrote; -} - -ssize_t usart_read(struct file* usart, char* const buffer, size_t length) { - struct usart_private* priv = (struct usart_private*) usart->private_data; - while (rbuffer_empty(&priv->rx_buffer)) { - sleep_queue(&priv->rx_queue); - yield(); - } - size_t read = 0; - size_t r = 0; - while (!rbuffer_empty(&priv->rx_buffer) && read < length && r == 0) { - cli(); - r = rbuffer_read(&priv->rx_buffer, buffer + read); - read += 1; - sei(); - } - return read; -} - -int usart_close(struct file* usart) { - return 0; -} - -struct file_operations usart_fops = { - .open = usart_open, - .ioctl = usart_ioctl, - .read = usart_read, - .write = usart_write, - .close = usart_close -}; - -struct usart_private _usart0 = { - .ucsrxa = &UCSR0A, - .ubrrxh = &UBRR0H, - .ubrrxl = &UBRR0L, - .ucsrxb = &UCSR0B, - .u2xx = U2X0, - .rxenx = RXEN0, - .txenx = TXEN0, - .rxciex = RXCIE0, - .udriex = UDRIE0 -}; - -struct file usart0 = { - .fops = &usart_fops, - .private_data = &_usart0 -}; - -//called when data register is empty -ISR(USART0_UDRE_vect) { - struct usart_private* priv = (struct usart_private*) usart0.private_data; - char c; - - if (rbuffer_read(&priv->tx_buffer, &c) == 0) { - UDR0 = c; - } else { - UCSR0B &= ~(1 << UDRIE0); //buffer empty, disable interruot - } -} - -//called when byte is received -ISR(USART0_RX_vect) { - //context_save(); - - struct usart_private* priv = (struct usart_private*) usart0.private_data; - - char c = UDR0; - rbuffer_write(&priv->rx_buffer, c); - wake_all_queue(&priv->rx_queue); - - //context_restore(); - //asm volatile ("reti"); -} \ No newline at end of file diff --git a/kernel/mcu/atmega2560/clock.c b/kernel/mcu/atmega2560/clock.c new file mode 100644 index 0000000..4f53372 --- /dev/null +++ b/kernel/mcu/atmega2560/clock.c @@ -0,0 +1,37 @@ +#include +#include "mux/clock.h" +#include "mux/sched.h" +#include "mcu/context.h" + +static void (*on_tick)(); + +void clock_init(int ms, void (*tick)()) { + TCCR3A = 0; + TCCR3B = 0; + TCCR3C = 0; + + TCCR3B = (1 << WGM32); // turn on CTC mode: + TCCR3B |= (1 << CS32) | (0 << CS31) | (1 << CS30); // set to 1024 prescaler + + unsigned long int fcpu = (unsigned long int) F_CPU; + unsigned long int hz = 1000l / ((unsigned long int) ms); + + unsigned long int hz_counter = fcpu / (1024l * (hz)) - 1; + OCR3A = hz_counter; + on_tick = tick; +} + +void clock_start() { + TIMSK3 |= (1 << OCIE3A); +} + +void clock_stop() { + TIMSK3 &= ~(1 << OCIE3A); +} + +ISR(TIMER3_COMPA_vect, ISR_NAKED) { + context_save(); + on_tick(); + context_restore(); + reti(); +} diff --git a/kernel/mcu/atmega2560/context.c b/kernel/mcu/atmega2560/context.c new file mode 100644 index 0000000..137a985 --- /dev/null +++ b/kernel/mcu/atmega2560/context.c @@ -0,0 +1,98 @@ +#include "mcu/context.h" + +char* stack_init(const char* const mem_low, const char* const mem_high, void (*entry)(char), char args) { + char* sp = (char*) mem_high; + unsigned long address = (unsigned long) entry; + + // pattern for debugging purposes + *sp = (char) 0x1; + sp--; + *sp = (char) 0x2; + sp--; + *sp = (char) 0x1; + sp--; + *sp = (char) 0x2; + sp--; + + // put return address on stack + *sp = (char) ( address & (unsigned short) 0x00ff ); + sp--; + + *sp = (char) ( (address >> 8) & ( unsigned short ) 0x00ff ); + sp--; + + *sp = (char) ( (address >> 16) & ( unsigned short ) 0x00ff ); + sp--; + + // save registers + *sp = (char) 0x00; //r0 + sp--; + *sp = (char) 0x80; //SREG, enable interrupts when task starts + sp--; + *sp = ( char ) 0x00; //r1 + sp--; + *sp = ( char ) 0x00; //r2 + sp--; + *sp = ( char ) 0x00; //r3 + sp--; + *sp = ( char ) 0x00; //r4 + sp--; + *sp = ( char ) 0x00; //r5 + sp--; + *sp = ( char ) 0x00; //r6 + sp--; + *sp = ( char ) 0x00; //r7 + sp--; + *sp = ( char ) 0x00; //r8 + sp--; + *sp = ( char ) 0x00; //r9 + sp--; + *sp = ( char ) 0x00; //r10 + sp--; + *sp = ( char ) 0x00; //r11 + sp--; + *sp = ( char ) 0x00; //r12 + sp--; + *sp = ( char ) 0x00; //r13 + sp--; + *sp = ( char ) 0x00; //r14 + sp--; + *sp = ( char ) 0x00; //r15 + sp--; + *sp = ( char ) 0x00; //r16 + sp--; + *sp = ( char ) 0x00; //r17 + sp--; + *sp = ( char ) 0x00; //r18 + sp--; + *sp = ( char ) 0x00; //r19 + sp--; + *sp = ( char ) 0x00; //r20 + sp--; + *sp = ( char ) 0x00; //r21 + sp--; + *sp = ( char ) 0x00; //r22 + sp--; + *sp = ( char ) 0x00; //r23 + sp--; + + *sp = (char) ( args ); //place first argument in register 24 + sp--; + + *sp = ( char ) 0x00; //r25 + sp--; + *sp = ( char ) 0x00; //r26 + sp--; + *sp = ( char ) 0x00; //r27 + sp--; + *sp = ( char ) 0x00; //r28 + sp--; + *sp = ( char ) 0x00; //r29 + sp--; + *sp = ( char ) 0x00; //r30 + sp--; + *sp = ( char ) 0x00; //r31 + sp--; + + return sp; +} diff --git a/kernel/mcu/atmega2560/include/mcu/context.h b/kernel/mcu/atmega2560/include/mcu/context.h new file mode 100644 index 0000000..5f6e947 --- /dev/null +++ b/kernel/mcu/atmega2560/include/mcu/context.h @@ -0,0 +1,123 @@ +#ifndef MCU_CONTEXT_H +#define MCU_CONTEXT_H + +#include +#define ret() asm volatile ( "ret" ) + +/** Default stack size, you may use this definition for declaring tasks. */ +#define DEFAULT_STACK_SIZE 256 + +/** Stack size to be allocated for the idle task. */ +#define IDLE_STACK_SIZE 64 + +/* + * The macros save_context(), restore_context() as well as the code contained in + * init_stack is adapted from the FreeRTOS kernel (http://www.freertos.org/). + * Here by copyright, credits attributed to wherever they belong. + */ + +/** + * Save context to memory location specified by first two chars of + * a symbol named 'current' (this is why 'sp' has to be the first element of + * of task control blocks). After executing this macro, the stack pointer will + * be set to the address contained in 'kstack'. + */ +#define context_save() \ + asm volatile ( \ + "push r0 \n\t" \ + "in r0, __SREG__ \n\t" \ + "cli \n\t" \ + "push r0 \n\t" \ + "push r1 \n\t" \ + "clr r1 \n\t" \ + "push r2 \n\t" \ + "push r3 \n\t" \ + "push r4 \n\t" \ + "push r5 \n\t" \ + "push r6 \n\t" \ + "push r7 \n\t" \ + "push r8 \n\t" \ + "push r9 \n\t" \ + "push r10 \n\t" \ + "push r11 \n\t" \ + "push r12 \n\t" \ + "push r13 \n\t" \ + "push r14 \n\t" \ + "push r15 \n\t" \ + "push r16 \n\t" \ + "push r17 \n\t" \ + "push r18 \n\t" \ + "push r19 \n\t" \ + "push r20 \n\t" \ + "push r21 \n\t" \ + "push r22 \n\t" \ + "push r23 \n\t" \ + "push r24 \n\t" \ + "push r25 \n\t" \ + "push r26 \n\t" \ + "push r27 \n\t" \ + "push r28 \n\t" \ + "push r29 \n\t" \ + "push r30 \n\t" \ + "push r31 \n\t" \ + "lds r26, current \n\t" \ + "lds r27, current +1 \n\t" \ + "in r0, __SP_L__ \n\t" \ + "st x+, r0 \n\t" \ + "in r0, __SP_H__ \n\t" \ + "st x+, r0 \n\t" \ + ) + + +/** + * Restore context to memory location specified by first two chars of + * a symbol named 'current'. + */ +#define context_restore() \ + asm volatile ( \ + "lds r26, current \n\t" \ + "lds r27, current + 1 \n\t" \ + "ld r28, x+ \n\t" \ + "out __SP_L__, r28 \n\t" \ + "ld r29, x+ \n\t" \ + "out __SP_H__, r29 \n\t" \ + "pop r31 \n\t" \ + "pop r30 \n\t" \ + "pop r29 \n\t" \ + "pop r28 \n\t" \ + "pop r27 \n\t" \ + "pop r26 \n\t" \ + "pop r25 \n\t" \ + "pop r24 \n\t" \ + "pop r23 \n\t" \ + "pop r22 \n\t" \ + "pop r21 \n\t" \ + "pop r20 \n\t" \ + "pop r19 \n\t" \ + "pop r18 \n\t" \ + "pop r17 \n\t" \ + "pop r16 \n\t" \ + "pop r15 \n\t" \ + "pop r14 \n\t" \ + "pop r13 \n\t" \ + "pop r12 \n\t" \ + "pop r11 \n\t" \ + "pop r10 \n\t" \ + "pop r9 \n\t" \ + "pop r8 \n\t" \ + "pop r7 \n\t" \ + "pop r6 \n\t" \ + "pop r5 \n\t" \ + "pop r4 \n\t" \ + "pop r3 \n\t" \ + "pop r2 \n\t" \ + "pop r1 \n\t" \ + "pop r0 \n\t" \ + "out __SREG__, r0 \n\t" \ + "pop r0 \n\t" \ + ) + +/** Initialize the given memory addresses to contain a valid, initial stackframe. */ +char* stack_init(const char* const mem_low, const char* const mem_high, void (*entry)(char), char args); + +#endif diff --git a/kernel/mcu/atmega2560/include/mcu/usart.h b/kernel/mcu/atmega2560/include/mcu/usart.h new file mode 100644 index 0000000..e06f0cf --- /dev/null +++ b/kernel/mcu/atmega2560/include/mcu/usart.h @@ -0,0 +1,12 @@ +#ifndef MCU_USART +#define MCU_USART + +#include "mux/io.h" + +#define USART_BUFFER_SIZE 64 +#define IOCTL_SET_BAUD 0 + +extern struct file usart0; + + +#endif \ No newline at end of file diff --git a/kernel/mcu/atmega2560/usart.c b/kernel/mcu/atmega2560/usart.c new file mode 100644 index 0000000..f07e137 --- /dev/null +++ b/kernel/mcu/atmega2560/usart.c @@ -0,0 +1,148 @@ +#include "mux/io.h" +#include "mux/list.h" +#include "mux/rbuffer.h" +#include "mux/sched.h" +#include "mcu/usart.h" +#include "mcu/context.h" +#include +#include + +struct usart_private { + char __rx_buffer[USART_BUFFER_SIZE]; + char __tx_buffer[USART_BUFFER_SIZE]; + + struct rbuffer_t rx_buffer; + struct rbuffer_t tx_buffer; + + struct list_head rx_queue; + struct list_head tx_queue; + + volatile unsigned char* const ucsrxa; + volatile unsigned char* const ubrrxh; + volatile unsigned char* const ubrrxl; + volatile unsigned char* const ucsrxb; + char u2xx; + char rxenx; + char txenx; + char rxciex; + char udriex; +}; + +int usart_open(struct file* usart) { + struct usart_private* priv = (struct usart_private*) usart->private_data; + + INIT_LIST_HEAD(&priv->rx_queue); + INIT_LIST_HEAD(&priv->tx_queue); + INIT_RBUFFER(&priv->rx_buffer, priv->__rx_buffer, USART_BUFFER_SIZE); + INIT_RBUFFER(&priv->tx_buffer, priv->__tx_buffer, USART_BUFFER_SIZE); + + return 0; +} + +int usart_ioctl(struct file* usart, int cmd, long args) { + struct usart_private* priv = (struct usart_private*) usart->private_data; + + switch (cmd) { + case IOCTL_SET_BAUD: { + long baud = args; + (*priv->ucsrxa) |= (1 << priv->u2xx); + long baud_setting = (F_CPU / 4 / baud - 1) / 2; + (*priv->ubrrxh) = baud_setting >> 8; + (*priv->ubrrxl) = baud_setting; + (*priv->ucsrxb) |= (1 << priv->rxenx) | (1 << priv->txenx) | (1 << priv->rxciex); + (*priv->ucsrxb) &= ~(1 << priv->udriex); + return 0; + } + default: + return -1; + } +} + +ssize_t usart_write(struct file* usart, const char* const buffer, size_t length) { + struct usart_private* priv = (struct usart_private*) usart->private_data; + volatile unsigned char* ucsrxb = (priv->ucsrxb); + char write_enable = (1 << priv->udriex); + + ssize_t wrote = 0; + int r = 0; + do { + cli(); + r = rbuffer_write(&priv->tx_buffer, buffer[wrote]); + wrote += 1; + sei(); + *ucsrxb |= write_enable; + } while (r == 0 && wrote < length); + return wrote; +} + +ssize_t usart_read(struct file* usart, char* const buffer, size_t length) { + struct usart_private* priv = (struct usart_private*) usart->private_data; + while (rbuffer_empty(&priv->rx_buffer)) { + sleep_queue(&priv->rx_queue); + yield(); + } + size_t read = 0; + size_t r = 0; + while (!rbuffer_empty(&priv->rx_buffer) && read < length && r == 0) { + cli(); + r = rbuffer_read(&priv->rx_buffer, buffer + read); + read += 1; + sei(); + } + return read; +} + +int usart_close(struct file* usart) { + return 0; +} + +struct file_operations usart_fops = { + .open = usart_open, + .ioctl = usart_ioctl, + .read = usart_read, + .write = usart_write, + .close = usart_close +}; + +struct usart_private _usart0 = { + .ucsrxa = &UCSR0A, + .ubrrxh = &UBRR0H, + .ubrrxl = &UBRR0L, + .ucsrxb = &UCSR0B, + .u2xx = U2X0, + .rxenx = RXEN0, + .txenx = TXEN0, + .rxciex = RXCIE0, + .udriex = UDRIE0 +}; + +struct file usart0 = { + .fops = &usart_fops, + .private_data = &_usart0 +}; + +//called when data register is empty +ISR(USART0_UDRE_vect) { + struct usart_private* priv = (struct usart_private*) usart0.private_data; + char c; + + if (rbuffer_read(&priv->tx_buffer, &c) == 0) { + UDR0 = c; + } else { + UCSR0B &= ~(1 << UDRIE0); //buffer empty, disable interruot + } +} + +//called when byte is received +ISR(USART0_RX_vect) { + //context_save(); + + struct usart_private* priv = (struct usart_private*) usart0.private_data; + + char c = UDR0; + rbuffer_write(&priv->rx_buffer, c); + wake_all_queue(&priv->rx_queue); + + //context_restore(); + //asm volatile ("reti"); +} \ No newline at end of file diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c new file mode 100644 index 0000000..aaf4337 --- /dev/null +++ b/kernel/sched/idle.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include "mux/idle.h" +#include "mux/sched.h" + + +void idle_entry(char args) { + while(1) { + set_sleep_mode(SLEEP_MODE_IDLE); + cli(); + sleep_enable(); + sei(); + sleep_cpu(); + sleep_disable(); + }; +} + diff --git a/kernel/sched/sched.c b/kernel/sched/sched.c new file mode 100644 index 0000000..4b36f03 --- /dev/null +++ b/kernel/sched/sched.c @@ -0,0 +1,57 @@ +#include "mux/sched.h" +#include "mcu/context.h" + + +struct tcb_t* volatile current = 0; + +static struct tcb_t* volatile idle = 0; + +struct list_head ready = LIST_HEAD_INIT(ready); + +static void _spawn(struct tcb_t* const tcb, char id) { + tcb->id = id; + tcb->sp = stack_init(tcb->mem_low, tcb->mem_high, tcb->entry, tcb->id); + INIT_LIST_HEAD(&tcb->queue); +} + +void spawn(struct tcb_t* const tcb, char id) { + _spawn(tcb, id); + list_add_tail(&tcb->queue, &ready); +} + +void spawn_idle(struct tcb_t* const tcb, char id) { + _spawn(tcb, id); + idle = tcb; +} + +void yield(void) { + context_save(); + schedule(); + context_restore(); + ret(); +} + +void sched_init() { + schedule(); + context_restore(); + sei(); + ret(); +} + +#include +void toggle_led() { + DDRB |= (1 << 7); + PORTB ^= (1 << 7); +} + +void schedule() { + toggle_led(); + if(!list_empty(&ready)) { + current = list_entry(ready.next, struct tcb_t, queue); + list_move_tail(ready.next, &ready); + debug_led(0,1); + } else { + current = idle; + debug_led(0,0); + } +} \ No newline at end of file diff --git a/kernel/task/idle.c b/kernel/task/idle.c deleted file mode 100644 index 7d6576d..0000000 --- a/kernel/task/idle.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include -#include -#include "task/idle.h" -#include "task/task.h" - - -void idle_entry(char args) { - while(1) { - set_sleep_mode(SLEEP_MODE_IDLE); - cli(); - sleep_enable(); - sei(); - sleep_cpu(); - sleep_disable(); - }; -} - diff --git a/kernel/task/include/task/idle.h b/kernel/task/include/task/idle.h deleted file mode 100644 index 3b6e40a..0000000 --- a/kernel/task/include/task/idle.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef IDLE_H -#define IDLE_H - -void idle_entry(char args); - -#endif \ No newline at end of file diff --git a/kernel/task/include/task/lock.h b/kernel/task/include/task/lock.h deleted file mode 100644 index 47246b2..0000000 --- a/kernel/task/include/task/lock.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef LOCK_H -#define LOCK_H - -#include "task/sched.h" - -typedef volatile char spin_lock_t; - -#define SPIN_LOCK_UNLOCKED 0 -#define SPIN_LOCK_LOCKED 0 - -static inline void spin_lock(spin_lock_t* lock) { - while(*lock != SPIN_LOCK_UNLOCKED) {yield();}; - cli(); - *lock = SPIN_LOCK_LOCKED; - sei(); -} - -static inline void spin_unlock(spin_lock_t* lock) { - cli(); - *lock = SPIN_LOCK_UNLOCKED; - sei(); -} - -#endif \ No newline at end of file diff --git a/kernel/task/include/task/sched.h b/kernel/task/include/task/sched.h deleted file mode 100644 index b8946db..0000000 --- a/kernel/task/include/task/sched.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SCHED_H -#define SCHED_H - -#include "collection/list.h" -#include "task/task.h" -#include "mcu/task/task.h" - -/** - * Points to currently executing task. If no scheduling has been enabled, - * this points to NULL - */ -extern struct tcb_t* volatile current; - -/** - * Queue that contains all tasks that are ready to be run, awaiting their - * turn from the scheduler. - */ -extern struct list_head ready; - -/** - * Makes the current task sleep on a specific queue. - * This moves the current task to the given queue's tail. - */ -static inline void sleep_queue(struct list_head* queue) { - list_move_tail(¤t->queue, queue); -} - -/** - * Wakes all tasks waiting in the given queue. - * This moves all tasks contained in the queue to the ready queue. - */ -static inline void wake_all_queue(struct list_head* queue) { - list_splice_init(queue, ready.prev); -} - -/** - * Initializes a given task and adds it to the ready queue. - */ -void spawn(struct tcb_t* const tcb); - -/** - * Voluntarily relinquishes control of the CPU from the current task to the scheduler. - */ -void yield() __attribute__ ( ( naked ) ); - - -/** - * Initializes the scheduler by setting up kstack, initializing the idle task - * and selecting the first task to run. - */ -void sched_init(); - -/** - * Enters the scheduler, setting current to the next runnable task. - */ -void schedule(); - -#endif diff --git a/kernel/task/include/task/task.h b/kernel/task/include/task/task.h deleted file mode 100644 index 120bda4..0000000 --- a/kernel/task/include/task/task.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef TASK_H -#define TASK_H - -#include "collection/list.h" - -/** - * Task control block, contains runtime - * information about tasks. - */ -struct tcb_t { - /** Stack pointer of this task. (must be first in structure) */ - char* volatile sp; - - /** Lowest address of this task's memory (inclusive). */ - char* mem_low; - - /** Highest address of this task's memory (inclusive). */ - char* mem_high; - - /** Entry function of this task. */ - void (*entry)(char); - - /** Current wait queue that this task is in.*/ - struct list_head queue; - - /** ID of task. */ - char id; - -}; - -/** - * Utility for declaring a task with statically allocated memory. - * Note: for a task to be scheduled, it must first be spawned (see spawn()). -*/ -#define DECLARE_TASK(name, stack_size, entry_function, pid) \ - static char _declared_stack_##name[stack_size]; \ - static struct tcb_t name = { \ - .sp = 0, \ - .mem_low = _declared_stack_##name, \ - .mem_high = _declared_stack_##name + stack_size - 1, \ - .entry = entry_function, \ - .queue = {}, \ - .id = pid \ - }; - -#endif \ No newline at end of file diff --git a/kernel/task/mcu/atmega2560/context.c b/kernel/task/mcu/atmega2560/context.c deleted file mode 100644 index 9bb7036..0000000 --- a/kernel/task/mcu/atmega2560/context.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "mcu/task/context.h" - -char* stack_init(const char* const mem_low, const char* const mem_high, void (*entry)(char), char args) { - char* sp = (char*) mem_high; - unsigned long address = (unsigned long) entry; - - // pattern for debugging purposes - *sp = (char) 0x1; - sp--; - *sp = (char) 0x2; - sp--; - *sp = (char) 0x1; - sp--; - *sp = (char) 0x2; - sp--; - - // put return address on stack - *sp = (char) ( address & (unsigned short) 0x00ff ); - sp--; - - *sp = (char) ( (address >> 8) & ( unsigned short ) 0x00ff ); - sp--; - - *sp = (char) ( (address >> 16) & ( unsigned short ) 0x00ff ); - sp--; - - // save registers - *sp = (char) 0x00; //r0 - sp--; - *sp = (char) 0x80; //SREG, enable interrupts when task starts - sp--; - *sp = ( char ) 0x00; //r1 - sp--; - *sp = ( char ) 0x00; //r2 - sp--; - *sp = ( char ) 0x00; //r3 - sp--; - *sp = ( char ) 0x00; //r4 - sp--; - *sp = ( char ) 0x00; //r5 - sp--; - *sp = ( char ) 0x00; //r6 - sp--; - *sp = ( char ) 0x00; //r7 - sp--; - *sp = ( char ) 0x00; //r8 - sp--; - *sp = ( char ) 0x00; //r9 - sp--; - *sp = ( char ) 0x00; //r10 - sp--; - *sp = ( char ) 0x00; //r11 - sp--; - *sp = ( char ) 0x00; //r12 - sp--; - *sp = ( char ) 0x00; //r13 - sp--; - *sp = ( char ) 0x00; //r14 - sp--; - *sp = ( char ) 0x00; //r15 - sp--; - *sp = ( char ) 0x00; //r16 - sp--; - *sp = ( char ) 0x00; //r17 - sp--; - *sp = ( char ) 0x00; //r18 - sp--; - *sp = ( char ) 0x00; //r19 - sp--; - *sp = ( char ) 0x00; //r20 - sp--; - *sp = ( char ) 0x00; //r21 - sp--; - *sp = ( char ) 0x00; //r22 - sp--; - *sp = ( char ) 0x00; //r23 - sp--; - - *sp = (char) ( args ); //place first argument in register 24 - sp--; - - *sp = ( char ) 0x00; //r25 - sp--; - *sp = ( char ) 0x00; //r26 - sp--; - *sp = ( char ) 0x00; //r27 - sp--; - *sp = ( char ) 0x00; //r28 - sp--; - *sp = ( char ) 0x00; //r29 - sp--; - *sp = ( char ) 0x00; //r30 - sp--; - *sp = ( char ) 0x00; //r31 - sp--; - - return sp; -} diff --git a/kernel/task/mcu/atmega2560/include/mcu/task/context.h b/kernel/task/mcu/atmega2560/include/mcu/task/context.h deleted file mode 100644 index 0de1fb4..0000000 --- a/kernel/task/mcu/atmega2560/include/mcu/task/context.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef MCU_CONTEXT_H -#define MCU_CONTEXT_H - -#include -#define ret() asm volatile ( "ret" ) - -/* - * The macros save_context(), restore_context() as well as the code contained in - * init_stack is adapted from the FreeRTOS kernel (http://www.freertos.org/). - * Here by copyright, credits attributed to wherever they belong. - */ - -/** - * Save context to memory location specified by first two chars of - * a symbol named 'current' (this is why 'sp' has to be the first element of - * of task control blocks). After executing this macro, the stack pointer will - * be set to the address contained in 'kstack'. - */ -#define context_save() \ - asm volatile ( \ - "push r0 \n\t" \ - "in r0, __SREG__ \n\t" \ - "cli \n\t" \ - "push r0 \n\t" \ - "push r1 \n\t" \ - "clr r1 \n\t" \ - "push r2 \n\t" \ - "push r3 \n\t" \ - "push r4 \n\t" \ - "push r5 \n\t" \ - "push r6 \n\t" \ - "push r7 \n\t" \ - "push r8 \n\t" \ - "push r9 \n\t" \ - "push r10 \n\t" \ - "push r11 \n\t" \ - "push r12 \n\t" \ - "push r13 \n\t" \ - "push r14 \n\t" \ - "push r15 \n\t" \ - "push r16 \n\t" \ - "push r17 \n\t" \ - "push r18 \n\t" \ - "push r19 \n\t" \ - "push r20 \n\t" \ - "push r21 \n\t" \ - "push r22 \n\t" \ - "push r23 \n\t" \ - "push r24 \n\t" \ - "push r25 \n\t" \ - "push r26 \n\t" \ - "push r27 \n\t" \ - "push r28 \n\t" \ - "push r29 \n\t" \ - "push r30 \n\t" \ - "push r31 \n\t" \ - "lds r26, current \n\t" \ - "lds r27, current +1 \n\t" \ - "in r0, __SP_L__ \n\t" \ - "st x+, r0 \n\t" \ - "in r0, __SP_H__ \n\t" \ - "st x+, r0 \n\t" \ - ) - - -/** - * Restore context to memory location specified by first two chars of - * a symbol named 'current'. - */ -#define context_restore() \ - asm volatile ( \ - "lds r26, current \n\t" \ - "lds r27, current + 1 \n\t" \ - "ld r28, x+ \n\t" \ - "out __SP_L__, r28 \n\t" \ - "ld r29, x+ \n\t" \ - "out __SP_H__, r29 \n\t" \ - "pop r31 \n\t" \ - "pop r30 \n\t" \ - "pop r29 \n\t" \ - "pop r28 \n\t" \ - "pop r27 \n\t" \ - "pop r26 \n\t" \ - "pop r25 \n\t" \ - "pop r24 \n\t" \ - "pop r23 \n\t" \ - "pop r22 \n\t" \ - "pop r21 \n\t" \ - "pop r20 \n\t" \ - "pop r19 \n\t" \ - "pop r18 \n\t" \ - "pop r17 \n\t" \ - "pop r16 \n\t" \ - "pop r15 \n\t" \ - "pop r14 \n\t" \ - "pop r13 \n\t" \ - "pop r12 \n\t" \ - "pop r11 \n\t" \ - "pop r10 \n\t" \ - "pop r9 \n\t" \ - "pop r8 \n\t" \ - "pop r7 \n\t" \ - "pop r6 \n\t" \ - "pop r5 \n\t" \ - "pop r4 \n\t" \ - "pop r3 \n\t" \ - "pop r2 \n\t" \ - "pop r1 \n\t" \ - "pop r0 \n\t" \ - "out __SREG__, r0 \n\t" \ - "pop r0 \n\t" \ - ) - -/** Initialize the given memory addresses to contain a valid, initial stackframe. */ -char* stack_init(const char* const mem_low, const char* const mem_high, void (*entry)(char), char args); - -#endif diff --git a/kernel/task/mcu/atmega2560/include/mcu/task/task.h b/kernel/task/mcu/atmega2560/include/mcu/task/task.h deleted file mode 100644 index d9823af..0000000 --- a/kernel/task/mcu/atmega2560/include/mcu/task/task.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef MCU_TASK_H -#define MACU_TASK_H - - -/** Default stack size, you may use this definition for declaring tasks. */ -#define DEFAULT_STACK_SIZE 256 - -/** Stack size to be allocated for the idle task. */ -#define IDLE_STACK_SIZE 64 - -#endif \ No newline at end of file diff --git a/kernel/task/sched.c b/kernel/task/sched.c deleted file mode 100644 index 5989136..0000000 --- a/kernel/task/sched.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "bug/panic.h" -#include "task/task.h" -#include "task/sched.h" -#include "mcu/task/context.h" - - -struct tcb_t* volatile current = 0; - -static struct tcb_t* volatile idle = 0; - -struct list_head ready = LIST_HEAD_INIT(ready); - -void spawn(struct tcb_t* const tcb) { - tcb->sp = stack_init(tcb->mem_low, tcb->mem_high, tcb->entry, tcb->id); - INIT_LIST_HEAD(&tcb->queue); - list_add_tail(&tcb->queue, &ready); -} - -void spawn_idle(struct tcb_t* const tcb) { - spawn(tcb); - list_del(&tcb->queue); - idle = tcb; -} - -void yield(void) { - context_save(); - schedule(); - context_restore(); - ret(); -} - -void sched_init() { - schedule(); - context_restore(); - sei(); - ret(); -} - -#include -void toggle_led() { - DDRB |= (1 << 7); - PORTB ^= (1 << 7); -} - -void schedule() { - toggle_led(); - if(!list_empty(&ready)) { - current = list_entry(ready.next, struct tcb_t, queue); - list_move_tail(ready.next, &ready); - debug_led(0,1); - } else { - current = idle; - debug_led(0,0); - } -} \ No newline at end of file diff --git a/kernel/time/include/time/clock.h b/kernel/time/include/time/clock.h deleted file mode 100644 index 0a247a8..0000000 --- a/kernel/time/include/time/clock.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef CLOCK_H -#define CLOCK_H - -/** - * Initializes main system clock. - * @ms time between each tick in milliseconds - * @tick function to run every tick - */ -void clock_init(int ms, void (*tick)()); - -/** - * Starts main system clock. - */ -void clock_start(); - -/** - * Stops main system clock. - */ -void clock_stop(); - -#endif \ No newline at end of file diff --git a/kernel/time/mcu/atmega2560/clock.c b/kernel/time/mcu/atmega2560/clock.c deleted file mode 100644 index 95622dc..0000000 --- a/kernel/time/mcu/atmega2560/clock.c +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include "time/clock.h" -#include "task/sched.h" -#include "mcu/task/context.h" - -static void (*on_tick)(); - -void clock_init(int ms, void (*tick)()) { - TCCR3A = 0; - TCCR3B = 0; - TCCR3C = 0; - - TCCR3B = (1 << WGM32); // turn on CTC mode: - TCCR3B |= (1 << CS32) | (0 << CS31) | (1 << CS30); // set to 1024 prescaler - - unsigned long int fcpu = (unsigned long int) F_CPU; - unsigned long int hz = 1000l / ((unsigned long int) ms); - - unsigned long int hz_counter = fcpu / (1024l * (hz)) - 1; - OCR3A = hz_counter; - on_tick = tick; -} - -void clock_start() { - TIMSK3 |= (1 << OCIE3A); -} - -void clock_stop() { - TIMSK3 &= ~(1 << OCIE3A); -} - -ISR(TIMER3_COMPA_vect, ISR_NAKED) { - context_save(); - on_tick(); - context_restore(); - reti(); -} diff --git a/kernel/tshield/include/tshield/tshield.h b/kernel/tshield/include/tshield/tshield.h deleted file mode 100644 index b485ad2..0000000 --- a/kernel/tshield/include/tshield/tshield.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef TSHIElD_H -#define TSHIELD_H - -/* - * Custom test shield - * Pin mappings - * - * Leds (from left to right) - * ===== - * Color | Arduino pin | atmega2560 - * ---------------------------------- - * Green D6 PH3 - * Yellow D7 PH4 - * Red D5 PE3 - * Red D4 PG5 - * - * - * Buttons (from left to right) - * ===== - * Number | Arduino pin | atmega2560 - * --------------------------------- - * 0 D2 PE4 (INT4) - * 1 D8 PH5 - * 2 D10 PB4 - * - * Outputs (from top to bottom) - * ===== - * Type | Arduino pin | atmega2560 - * ------------------------------------------------------ - * Servo 11, Vcc, GND PB5 - * Diode protected (max 200mA) 12 PB6 - * - */ - -#define DEBUG_LEDS 4 -#define DEBUG_LED_IDLE 0 - -void tshield_init(); - -void tshield_test(); - -unsigned char tshield_read(); - -void tshield_led(unsigned char led, unsigned char value); - -void tshield_pp(unsigned char value); - -void tshield_servo(unsigned char angle); - - -#endif diff --git a/kernel/tshield/mcu/atmega2560/tshield.c b/kernel/tshield/mcu/atmega2560/tshield.c deleted file mode 100644 index 7cc6e58..0000000 --- a/kernel/tshield/mcu/atmega2560/tshield.c +++ /dev/null @@ -1,140 +0,0 @@ -#include -#include -#include "tshield/tshield.h" -#include "bug/panic.h" - -static void tshield_init_servo(); - -void tshield_init() { - - DDRH |= (1 << 3) | (1 << 4); //leds - PORTH &= ~( (1 << 3) | (1 << 4)); - DDRE |= (1 << 3); - PORTE &= ~(1 << 3); - DDRG |= (1 << 5); - PORTG &= ~(1 << 5); - - DDRE &= ~(1 << 4); // buttons - PORTE |= (1 << 4); - DDRH &= ~(1 << 5); - PORTH |= (1 << 5); - DDRB &= ~(1 << 4); - PORTB |= (1 << 4); - - DDRB |= (1 << 6); - PORTB &= ~(1 << 6); - - tshield_init_servo(); -} - -#define WAIT_VALUE 20000 -#define WAIT() \ - for (volatile long x = 0; x < WAIT_VALUE; ++x){} - -void tshield_test() { - while(1) { - PORTG |= (1 << 5); - WAIT(); - PORTG &= ~(1 << 5); - PORTE |= (1 << 3); - WAIT(); - PORTE &= ~(1 << 3); - PORTH |= (1 << 3); - WAIT(); - PORTH &= ~(1 << 3); - PORTH |= (1 << 4); - WAIT(); - PORTH &= ~(1 << 4); - } - -} - -unsigned char tshield_read() { - return ((PINE & (1 << 4) ? 0 : 1) << 2 ) | - ((PINH & (1 << 5) ? 0 : 1) << 1 ) | - (PINB & (1 << 4) ? 0 : 1); -} - -void tshield_led(unsigned char led, unsigned char value) { - volatile unsigned char* port; - unsigned char bit; - switch (led) { - case 0: - port = &PORTG; - bit = 5; - break; - case 1: - port = &PORTE; - bit = 3; - break; - case 2: - port = &PORTH; - bit = 3; - break; - case 3: - port = &PORTH; - bit = 4; - break; - default: - return; - } - - if (value) { - *port |= (1 << bit); - } else { - *port &= ~(1 << bit); - } - -} - -void tshield_pp(unsigned char value) { - if (value) { - PORTB |= (1 << 6); - } else { - PORTB &= ~(1 << 6); - } -} - -void tshield_init_servo() { - - TCCR1A |= (1<= 0; --i) { - debug_led((i + 1) % DEBUG_LEDS, 0); - debug_led(i, 1); - _wait(); - } - } -} \ No newline at end of file diff --git a/main.c b/main.c deleted file mode 100644 index 703bbb5..0000000 --- a/main.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include -#include -#include "bug/panic.h" -#include "bug/debug.h" -#include "task/task.h" -#include "task/sched.h" -#include "task/idle.h" -#include "task/lock.h" -#include "task/idle.h" -#include "time/clock.h" -#include "io/io.h" -#include "mcu/io/usart.h" -#include "tshield/tshield.h" -#define IN_LENGTH 64 - -#define WAIT_CYCLES(cycles) for (volatile unsigned long i = 0; i < cycles; ++i) {} - -void worker() { - char buffer[64]; - - while(1) { - int length = read(&usart0, buffer, 64); - - int led; - int value; - if (sscanf(buffer, "leds/%d:%d", &led, &value) == 2) { - debug_led(led, value); - } else { - debug_led(0,1); - WAIT_CYCLES(300000); - debug_led(0,0); - } - } -} - - -DECLARE_TASK(task_idle, IDLE_STACK_SIZE, idle_entry, 0); -DECLARE_TASK(task1, DEFAULT_STACK_SIZE, worker, 1); - -int main(int argc, char *argv[]) { - cli(); - tshield_init(); - - open(&usart0); - ioctl(&usart0, IOCTL_SET_BAUD, 115200); - - spawn_idle(&task_idle); - spawn(&task1); - - sei(); - clock_init(10, schedule); - clock_start(); - sched_init(); - panic(); //should never reach here - while(1){} -} diff --git a/modules/tshield/include/tshield/tshield.h b/modules/tshield/include/tshield/tshield.h new file mode 100644 index 0000000..b485ad2 --- /dev/null +++ b/modules/tshield/include/tshield/tshield.h @@ -0,0 +1,51 @@ +#ifndef TSHIElD_H +#define TSHIELD_H + +/* + * Custom test shield + * Pin mappings + * + * Leds (from left to right) + * ===== + * Color | Arduino pin | atmega2560 + * ---------------------------------- + * Green D6 PH3 + * Yellow D7 PH4 + * Red D5 PE3 + * Red D4 PG5 + * + * + * Buttons (from left to right) + * ===== + * Number | Arduino pin | atmega2560 + * --------------------------------- + * 0 D2 PE4 (INT4) + * 1 D8 PH5 + * 2 D10 PB4 + * + * Outputs (from top to bottom) + * ===== + * Type | Arduino pin | atmega2560 + * ------------------------------------------------------ + * Servo 11, Vcc, GND PB5 + * Diode protected (max 200mA) 12 PB6 + * + */ + +#define DEBUG_LEDS 4 +#define DEBUG_LED_IDLE 0 + +void tshield_init(); + +void tshield_test(); + +unsigned char tshield_read(); + +void tshield_led(unsigned char led, unsigned char value); + +void tshield_pp(unsigned char value); + +void tshield_servo(unsigned char angle); + + +#endif diff --git a/modules/tshield/mcu/atmega2560/tshield.c b/modules/tshield/mcu/atmega2560/tshield.c new file mode 100644 index 0000000..59877ec --- /dev/null +++ b/modules/tshield/mcu/atmega2560/tshield.c @@ -0,0 +1,140 @@ +#include +#include +#include "tshield/tshield.h" +#include "mux/debug.h" + +static void tshield_init_servo(); + +void tshield_init() { + + DDRH |= (1 << 3) | (1 << 4); //leds + PORTH &= ~( (1 << 3) | (1 << 4)); + DDRE |= (1 << 3); + PORTE &= ~(1 << 3); + DDRG |= (1 << 5); + PORTG &= ~(1 << 5); + + DDRE &= ~(1 << 4); // buttons + PORTE |= (1 << 4); + DDRH &= ~(1 << 5); + PORTH |= (1 << 5); + DDRB &= ~(1 << 4); + PORTB |= (1 << 4); + + DDRB |= (1 << 6); + PORTB &= ~(1 << 6); + + tshield_init_servo(); +} + +#define WAIT_VALUE 20000 +#define WAIT() \ + for (volatile long x = 0; x < WAIT_VALUE; ++x){} + +void tshield_test() { + while(1) { + PORTG |= (1 << 5); + WAIT(); + PORTG &= ~(1 << 5); + PORTE |= (1 << 3); + WAIT(); + PORTE &= ~(1 << 3); + PORTH |= (1 << 3); + WAIT(); + PORTH &= ~(1 << 3); + PORTH |= (1 << 4); + WAIT(); + PORTH &= ~(1 << 4); + } + +} + +unsigned char tshield_read() { + return ((PINE & (1 << 4) ? 0 : 1) << 2 ) | + ((PINH & (1 << 5) ? 0 : 1) << 1 ) | + (PINB & (1 << 4) ? 0 : 1); +} + +void tshield_led(unsigned char led, unsigned char value) { + volatile unsigned char* port; + unsigned char bit; + switch (led) { + case 0: + port = &PORTG; + bit = 5; + break; + case 1: + port = &PORTE; + bit = 3; + break; + case 2: + port = &PORTH; + bit = 3; + break; + case 3: + port = &PORTH; + bit = 4; + break; + default: + return; + } + + if (value) { + *port |= (1 << bit); + } else { + *port &= ~(1 << bit); + } + +} + +void tshield_pp(unsigned char value) { + if (value) { + PORTB |= (1 << 6); + } else { + PORTB &= ~(1 << 6); + } +} + +void tshield_init_servo() { + + TCCR1A |= (1<= 0; --i) { + debug_led((i + 1) % DEBUG_LEDS, 0); + debug_led(i, 1); + _wait(); + } + } +} \ No newline at end of file -- cgit v1.2.3