aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jodersky@gmail.com>2014-04-03 18:48:59 +0200
committerJakob Odersky <jodersky@gmail.com>2014-04-03 18:48:59 +0200
commitb6181e4a21b1bc3b5615604e175c6a297b661687 (patch)
treeb9b47c10159eef591c6085ab49bee34e2b284b71
parentf93ab955074e213ad6f2bf60522cc86952d57d83 (diff)
downloadmux-b6181e4a21b1bc3b5615604e175c6a297b661687.tar.gz
mux-b6181e4a21b1bc3b5615604e175c6a297b661687.tar.bz2
mux-b6181e4a21b1bc3b5615604e175c6a297b661687.zip
add uniform io interface
-rw-r--r--kernel/collection/include/collection/rbuffer.h84
-rw-r--r--kernel/io/include/io/io.h30
-rw-r--r--kernel/io/include/io/usart.h31
-rw-r--r--kernel/io/io.c25
-rw-r--r--kernel/io/mcu/atmega2560/include/mcu/io/usart.h12
-rw-r--r--kernel/io/mcu/atmega2560/usart.c148
-rw-r--r--kernel/io/usart.c103
-rw-r--r--kernel/task/include/task/sched.h6
-rw-r--r--kernel/task/include/task/task.h18
-rw-r--r--kernel/task/mcu/atmega2560/context.c48
-rw-r--r--kernel/task/mcu/atmega2560/include/mcu/task/context.h26
-rw-r--r--kernel/task/sched.c10
-rw-r--r--kernel/time/include/time/clock.h13
-rw-r--r--main.c43
-rw-r--r--test/read-write/main.c70
15 files changed, 394 insertions, 273 deletions
diff --git a/kernel/collection/include/collection/rbuffer.h b/kernel/collection/include/collection/rbuffer.h
index 01d5418..dceaeb0 100644
--- a/kernel/collection/include/collection/rbuffer.h
+++ b/kernel/collection/include/collection/rbuffer.h
@@ -4,67 +4,45 @@
#include <stddef.h>
struct rbuffer_t {
- char* address_begin;
- char* address_end;
- char* volatile head;
- char* volatile tail;
+ char* address_begin;
+ char* address_end;
+ char* volatile head;
+ char* volatile tail;
};
-#define RBUFFER_ARRAY_INIT(array, length) \
- { \
- .address_begin = array, \
- .address_end = array + length, \
- .head=array, \
- .tail=array \
- }
+#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;
+ return rb->head == rb->tail;
}
-#define __rbuffer_overlap(rb, ptr) \
- if (ptr >= rb->address_end) ptr = rb->address_begin
-
-static inline int rbuffer_write_char(struct rbuffer_t* const rb, char data) {
- char* next_head = rb->head + 1;
- __rbuffer_overlap(rb, next_head);
- if (rb->tail == next_head) return 0;
- *rb->head = data;
- rb->head = next_head;
- return 1;
+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_char(struct rbuffer_t* const rb, char* const data) {
- if (rbuffer_empty(rb)) return 0;
- *data = *rb->tail;
- rb->tail += 1;
- __rbuffer_overlap(rb, rb->tail);
- return 1;
+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;
}
-static inline size_t rbuffer_write(struct rbuffer_t* const rb, const char* const data, size_t size) {
- size_t wrote = 0;
- for (size_t i = 0; i < size; ++i) {
- if (rbuffer_write_char(rb, data[i])) {
- wrote += 1;
- } else {
- return wrote;
- }
- }
- return wrote;
-}
-
-static inline size_t rbuffer_read(struct rbuffer_t* const rb, char* const data, size_t size) {
- size_t read = 0;
- for (size_t i = 0; i < size; ++i) {
- if (rbuffer_read_char(rb, &data[i])) {
- read += 1;
- } else {
- return read;
- }
- }
- return read;
-}
-
-
#endif
diff --git a/kernel/io/include/io/io.h b/kernel/io/include/io/io.h
new file mode 100644
index 0000000..a715f1b
--- /dev/null
+++ b/kernel/io/include/io/io.h
@@ -0,0 +1,30 @@
+#ifndef IO_H
+#define IO_H
+
+#include <stddef.h>
+
+typedef long ssize_t;
+
+struct file;
+struct file_operations;
+
+struct file {
+ struct file_operations* 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/include/io/usart.h b/kernel/io/include/io/usart.h
deleted file mode 100644
index 62e2768..0000000
--- a/kernel/io/include/io/usart.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef SERIAL_H
-#define SERIAL_H
-
-#include "collection/rbuffer.h"
-#include "collection/list.h"
-
-#define USARTS 1
-#define USART_BUFFER_SIZE 64
-
-struct usart_device_t {
- volatile char __rx_buffer[USART_BUFFER_SIZE];
- volatile 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;
-};
-
-#define USART_DEVICE_INIT(name) \
- { \
- .rx_buffer = RBUFFER_ARRAY_INIT(name.__rx_buffer, USART_BUFFER_SIZE), \
- .tx_buffer = RBUFFER_ARRAY_INIT(name.__tx_buffer, USART_BUFFER_SIZE), \
- .rx_queue = LIST_HEAD_INIT(name.rx_queue), \
- .tx_queue = LIST_HEAD_INIT(name.tx_queue) \
- }
-
-void usart_init(unsigned long baud);
-
-#endif \ No newline at end of file
diff --git a/kernel/io/io.c b/kernel/io/io.c
new file mode 100644
index 0000000..f39168b
--- /dev/null
+++ b/kernel/io/io.c
@@ -0,0 +1,25 @@
+#include "io/io.h"
+
+int open(struct file* file) {
+ file->fops->open(file);
+}
+
+int ioctl(struct file* file, int cmd, long args) {
+ 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);
+}
+
+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);
+}
+
+int close(struct file* file) {
+ 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
new file mode 100644
index 0000000..6b210fe
--- /dev/null
+++ b/kernel/io/mcu/atmega2560/include/mcu/io/usart.h
@@ -0,0 +1,12 @@
+#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
new file mode 100644
index 0000000..381f403
--- /dev/null
+++ b/kernel/io/mcu/atmega2560/usart.c
@@ -0,0 +1,148 @@
+#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 <avr/interrupt.h>
+#include <avr/io.h>
+
+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, ISR_NAKED) {
+ 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/io/usart.c b/kernel/io/usart.c
deleted file mode 100644
index 2046630..0000000
--- a/kernel/io/usart.c
+++ /dev/null
@@ -1,103 +0,0 @@
-
-#include <stddef.h>
-#include <stdio.h>
-#include <avr/interrupt.h>
-#include "task/sched.h"
-#include "io/usart.h"
-#include "bug/debug.h"
-#include "mcu/task/context.h"
-
-static struct usart_device_t umain = USART_DEVICE_INIT(umain);
-static int umain_putc(char c);
-static int umain_getc();
-
-FILE umain_out = FDEV_SETUP_STREAM(umain_putc, NULL, _FDEV_SETUP_WRITE);
-FILE umain_in = FDEV_SETUP_STREAM(NULL, umain_getc, _FDEV_SETUP_READ);
-
-void usart_init(unsigned long baud) {
- UCSR0A |= (1 << U2X0); //enable double speed transmission
- uint16_t baud_setting = (F_CPU / 4 / baud - 1) / 2;
- UBRR0H = baud_setting >> 8;
- UBRR0L = baud_setting;
- UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); // 8-bit, no parity, 1 stop bit
- UCSR0B &= ~(1 << UDRIE0);
- stdout = &umain_out;
- stdin = &umain_in;
-}
-
-int umain_putc(char c) {
- if (c == '\n') umain_putc('\r');
- int r = 0;
- do {
- cli();
- r = rbuffer_write_char(&umain.tx_buffer, c);
- sei();
- UCSR0B |= (1 << UDRIE0);
- } while (r != 1);
- return c;
-}
-
-int umain_getc() {
- while (rbuffer_empty(&umain.rx_buffer)) {
- cli();
- sleep_queue(&umain.rx_queue);
- yield();
- }
- cli();
- char c = 0;
- size_t r = rbuffer_read_char(&umain.rx_buffer, &c);
- sei();
- if (r) return (int) c;
- else return EOF;
-}
-
-//called when byte is received
-ISR(USART0_RX_vect, ISR_NAKED) {
- context_save();
- char c = UDR0;
- rbuffer_write_char(&umain.rx_buffer, c);
- wake_all_queue(&umain.rx_queue);
- context_restore();
- asm volatile ("reti");
-}
-
-//called when data register is empty
-ISR(USART0_UDRE_vect) {
- char c;
- if (rbuffer_read_char(&umain.tx_buffer, &c)) {
- UDR0 = c;
- } else {
- UCSR0B &= ~(1 << UDRIE0); //buffer empty, disable interruot
- }
-}
-
-/*
-void serial_read() {
- ENTER_CRITICAL();
- list_move_tail(&current->list, &serial_rx_q);
- EXIT_CRITICAL();
- yield();
-}
-*/
-/*
-void serial_write_str(const char* const str) {
- for (size_t i = 0; str[i] != '\0'; ++i) {
- ENTER_CRITICAL();
- rbuffer_write(&serial_dev.tx_buffer, str[i]);
- EXIT_CRITICAL();
- UCSR0B |= (1 << UDRIE0);
- }
-}*/
-
-
-/*
-ISR(INT3_vect, ISR_NAKED) {
- SAVE_CONTEXT();
- if (!list_empty(&serial_rx_q)) {
- list_move_tail(serial_rx_q.next, &ready);
- }
- schedule();
- RESTORE_CONTEXT();
- asm volatile ("reti");
-}
-*/
diff --git a/kernel/task/include/task/sched.h b/kernel/task/include/task/sched.h
index 6dcd67c..b8946db 100644
--- a/kernel/task/include/task/sched.h
+++ b/kernel/task/include/task/sched.h
@@ -17,12 +17,6 @@ extern struct tcb_t* volatile current;
*/
extern struct list_head ready;
-/**
- * Stack pointer for operations performed out of task context, including any
- * calls made after context save.
- */
-extern void* volatile kstack;
-
/**
* Makes the current task sleep on a specific queue.
* This moves the current task to the given queue's tail.
diff --git a/kernel/task/include/task/task.h b/kernel/task/include/task/task.h
index 99f16dc..120bda4 100644
--- a/kernel/task/include/task/task.h
+++ b/kernel/task/include/task/task.h
@@ -4,18 +4,6 @@
#include "collection/list.h"
/**
- * Wakeup sources define the minimum power level
- * at which a task that is waiting in a queue
- * can be woken up
- */
-enum wakeup_src {
- WAKEUP_SRC_OFF = 0, //processor off, external interrupts may trigger this source
- WAKEUP_SRC_CLOCK = 1, //main clock required
- WAKEUP_SRC_IDLE = 2, //processor can be put in idle state
- WAKEUP_SRC_ON = 3 //processor must stay on
-};
-
-/**
* Task control block, contains runtime
* information about tasks.
*/
@@ -38,9 +26,6 @@ struct tcb_t {
/** ID of task. */
char id;
-
- enum wakeup_src wakeup_src;
-
};
/**
@@ -55,8 +40,7 @@ struct tcb_t {
.mem_high = _declared_stack_##name + stack_size - 1, \
.entry = entry_function, \
.queue = {}, \
- .id = pid, \
- .wakeup_src = WAKEUP_SRC_ON \
+ .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
index bcc2130..9bb7036 100644
--- a/kernel/task/mcu/atmega2560/context.c
+++ b/kernel/task/mcu/atmega2560/context.c
@@ -5,26 +5,26 @@ char* stack_init(const char* const mem_low, const char* const mem_high, void (*e
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--;
+ *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 );
+ // 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 = (char) ( (address >> 16) & ( unsigned short ) 0x00ff );
sp--;
- // save registers
+ // save registers
*sp = (char) 0x00; //r0
sp--;
*sp = (char) 0x80; //SREG, enable interrupts when task starts
@@ -69,30 +69,30 @@ char* stack_init(const char* const mem_low, const char* const mem_high, void (*e
sp--;
*sp = ( char ) 0x00; //r20
sp--;
- *sp = ( char ) 0x00; //r21
+ *sp = ( char ) 0x00; //r21
sp--;
- *sp = ( char ) 0x00; //r22
+ *sp = ( char ) 0x00; //r22
sp--;
- *sp = ( char ) 0x00; //r23
+ *sp = ( char ) 0x00; //r23
sp--;
- *sp = (char) ( args ); //place first argument in register 24
+ *sp = (char) ( args ); //place first argument in register 24
sp--;
- *sp = ( char ) 0x00; //r25
+ *sp = ( char ) 0x00; //r25
sp--;
- *sp = ( char ) 0x00; //r26
+ *sp = ( char ) 0x00; //r26
sp--;
- *sp = ( char ) 0x00; //r27
+ *sp = ( char ) 0x00; //r27
sp--;
- *sp = ( char ) 0x00; //r28
+ *sp = ( char ) 0x00; //r28
sp--;
- *sp = ( char ) 0x00; //r29
+ *sp = ( char ) 0x00; //r29
sp--;
- *sp = ( char ) 0x00; //r30
+ *sp = ( char ) 0x00; //r30
sp--;
- *sp = ( char ) 0x00; //r31
+ *sp = ( char ) 0x00; //r31
sp--;
- return 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
index b717991..0de1fb4 100644
--- a/kernel/task/mcu/atmega2560/include/mcu/task/context.h
+++ b/kernel/task/mcu/atmega2560/include/mcu/task/context.h
@@ -1,5 +1,5 @@
-#ifndef CONTEXT_H
-#define CONTEXT_H
+#ifndef MCU_CONTEXT_H
+#define MCU_CONTEXT_H
#include <avr/interrupt.h>
#define ret() asm volatile ( "ret" )
@@ -20,6 +20,7 @@
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" \
@@ -59,12 +60,6 @@
"st x+, r0 \n\t" \
"in r0, __SP_H__ \n\t" \
"st x+, r0 \n\t" \
- "lds r26, kstack \n\t" \
- "lds r27, kstack + 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" \
)
@@ -74,12 +69,6 @@
*/
#define context_restore() \
asm volatile ( \
- "lds r26, kstack \n\t" \
- "lds r27, kstack +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" \
"lds r26, current \n\t" \
"lds r27, current + 1 \n\t" \
"ld r28, x+ \n\t" \
@@ -125,13 +114,4 @@
/** 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);
-/** Initialize the given memory addresses to contain a valid, initial stackframe. */
-static inline void kstack_init(void **kstack) {
- //this sets the kernel stack to the default stack location
- //of this mcu, namely the top (stacks of tasks will typically
- //be contained in memory allocated on the head and thus should
- //overflow with the kernel stack)
- *kstack = (void*) SP;
-}
-
#endif
diff --git a/kernel/task/sched.c b/kernel/task/sched.c
index 1ffd369..da7b59d 100644
--- a/kernel/task/sched.c
+++ b/kernel/task/sched.c
@@ -2,7 +2,6 @@
#include "task/task.h"
#include "task/sched.h"
#include "mcu/task/context.h"
-#include "mcu/task/context.h"
struct tcb_t* volatile current = 0;
@@ -11,8 +10,6 @@ static struct tcb_t* volatile idle = 0;
struct list_head ready = LIST_HEAD_INIT(ready);
-void* volatile kstack;
-
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);
@@ -26,32 +23,25 @@ void spawn_idle(struct tcb_t* const tcb) {
}
void yield(void) {
- cli();
context_save();
schedule();
context_restore();
- sei();
ret();
}
-
void sched_init() {
- kstack_init(&kstack);
schedule();
context_restore();
sei();
ret();
}
-
#include <avr/io.h>
void toggle_led() {
DDRB |= (1 << 7);
PORTB ^= (1 << 7);
}
-
-
void schedule() {
toggle_led();
if(!list_empty(&ready)) {
diff --git a/kernel/time/include/time/clock.h b/kernel/time/include/time/clock.h
index 3d90cf0..0a247a8 100644
--- a/kernel/time/include/time/clock.h
+++ b/kernel/time/include/time/clock.h
@@ -1,8 +1,21 @@
#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/main.c b/main.c
index f8dde1e..0ed45da 100644
--- a/main.c
+++ b/main.c
@@ -9,26 +9,57 @@
#include "task/lock.h"
#include "task/idle.h"
#include "time/clock.h"
-#include "io/usart.h"
+#include "io/io.h"
+#include "mcu/io/usart.h"
#include "tshield/tshield.h"
-#include "mcu/task/context.h"
-#include "shell.h"
-
#define IN_LENGTH 64
#define WAIT_CYCLES(cycles) for (volatile unsigned long i = 0; i < cycles; ++i) {}
+void writer() {
+
+ char* buffer = "hello world";
+ size_t length = 11;
+
+
+ while(1) {
+ debug_led(1, 0);
+ WAIT_CYCLES(300000);
+ debug_led(1, 1);
+ write(&usart0, buffer, length);
+ }
+}
+
+void reader() {
+ char in;
+
+ while(1) {
+ debug_led(2, 0);
+ debug_led(3, 0);
+ if (read(&usart0, &in, 1) >= 0) {
+ debug_led(2, 1);
+ } else {
+ debug_led(3, 1);
+ WAIT_CYCLES(30000);
+ }
+
+ }
+}
DECLARE_TASK(task_idle, IDLE_STACK_SIZE, idle_entry, 0);
-DECLARE_TASK(task1, DEFAULT_STACK_SIZE, shell, 1);
+DECLARE_TASK(task1, DEFAULT_STACK_SIZE, writer, 1);
+DECLARE_TASK(task2, DEFAULT_STACK_SIZE, reader, 2);
int main(int argc, char *argv[]) {
cli();
tshield_init();
- usart_init(115200);
+
+ open(&usart0);
+ ioctl(&usart0, IOCTL_SET_BAUD, 115200);
spawn_idle(&task_idle);
spawn(&task1);
+ spawn(&task2);
sei();
clock_init(10, schedule);
diff --git a/test/read-write/main.c b/test/read-write/main.c
new file mode 100644
index 0000000..0ed45da
--- /dev/null
+++ b/test/read-write/main.c
@@ -0,0 +1,70 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include "bug/panic.h"
+#include "bug/debug.h"
+#include "task/task.h"
+#include "task/sched.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 writer() {
+
+ char* buffer = "hello world";
+ size_t length = 11;
+
+
+ while(1) {
+ debug_led(1, 0);
+ WAIT_CYCLES(300000);
+ debug_led(1, 1);
+ write(&usart0, buffer, length);
+ }
+}
+
+void reader() {
+ char in;
+
+ while(1) {
+ debug_led(2, 0);
+ debug_led(3, 0);
+ if (read(&usart0, &in, 1) >= 0) {
+ debug_led(2, 1);
+ } else {
+ debug_led(3, 1);
+ WAIT_CYCLES(30000);
+ }
+
+ }
+}
+
+DECLARE_TASK(task_idle, IDLE_STACK_SIZE, idle_entry, 0);
+DECLARE_TASK(task1, DEFAULT_STACK_SIZE, writer, 1);
+DECLARE_TASK(task2, DEFAULT_STACK_SIZE, reader, 2);
+
+int main(int argc, char *argv[]) {
+ cli();
+ tshield_init();
+
+ open(&usart0);
+ ioctl(&usart0, IOCTL_SET_BAUD, 115200);
+
+ spawn_idle(&task_idle);
+ spawn(&task1);
+ spawn(&task2);
+
+ sei();
+ clock_init(10, schedule);
+ clock_start();
+ sched_init();
+ panic(); //should never reach here
+ while(1){}
+}