aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorJakob Odersky <jodersky@gmail.com>2014-01-25 14:47:07 +0100
committerJakob Odersky <jodersky@gmail.com>2014-01-25 14:47:07 +0100
commit7dd00b2267d991a102f18eacf3e2afacb570a299 (patch)
tree9138bc7ce4feba262a20063f94aceaba3ec30788 /kernel
parent9453a44cfc475b57319d1051c74f72753ca4f64c (diff)
downloadmux-7dd00b2267d991a102f18eacf3e2afacb570a299.tar.gz
mux-7dd00b2267d991a102f18eacf3e2afacb570a299.tar.bz2
mux-7dd00b2267d991a102f18eacf3e2afacb570a299.zip
implement serial
Diffstat (limited to 'kernel')
-rw-r--r--kernel/collection/include/collection/rbuffer.h83
-rw-r--r--kernel/collection/rbuffer.c8
-rw-r--r--kernel/sched/include/sched/sched.h3
-rw-r--r--kernel/serial/include/serial/serial.h (renamed from kernel/serial.disabled/include/serial/serial.h)13
-rw-r--r--kernel/serial/serial.c (renamed from kernel/serial.disabled/serial.c)61
5 files changed, 83 insertions, 85 deletions
diff --git a/kernel/collection/include/collection/rbuffer.h b/kernel/collection/include/collection/rbuffer.h
index dbdd6ee..01d5418 100644
--- a/kernel/collection/include/collection/rbuffer.h
+++ b/kernel/collection/include/collection/rbuffer.h
@@ -3,45 +3,68 @@
#include <stddef.h>
-#define EEMPTY -1
-#define EFULL -2
-
-typedef char rbuffer_byte_t;
-
struct rbuffer_t {
- rbuffer_byte_t* address;
- size_t size;
- size_t head;
- size_t tail;
+ char* address_begin;
+ char* address_end;
+ char* volatile head;
+ char* volatile tail;
};
-#define RBUFFER_INIT(array, length) \
+#define RBUFFER_ARRAY_INIT(array, length) \
{ \
- .address = array, \
- .size = length, \
- .head=0, \
- .tail=0 \
+ .address_begin = array, \
+ .address_end = array + length, \
+ .head=array, \
+ .tail=array \
}
-void rbuffer_init(struct rbuffer_t* rb, rbuffer_byte_t* address, size_t size);
+static inline int rbuffer_empty(struct rbuffer_t* const rb) {
+ 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;
+}
-/** Read data from ringbuffer. */
-static inline int rbuffer_read(struct rbuffer_t* const rb, rbuffer_byte_t* const data_out) {
- if (rb->head == rb->tail) return EEMPTY;
- *data_out = rb->address[rb->head];
- rb->head = rb->head + 1;
- if (rb->head >= rb->size) rb->head=0;
- 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_write(struct rbuffer_t* const rb, rbuffer_byte_t data_in) {
- size_t next_tail = rb->tail + 1;
- if (next_tail >= rb->size) next_tail = 0;
- if (rb->head == next_tail) return EFULL;
-
- rb->address[rb->tail] = data_in;
- rb->tail = next_tail;
- 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/collection/rbuffer.c b/kernel/collection/rbuffer.c
deleted file mode 100644
index ec11d13..0000000
--- a/kernel/collection/rbuffer.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <collection/rbuffer.h>
-
-void rbuffer_init(struct rbuffer_t* rb, rbuffer_byte_t* address, size_t size) {
- rb->address = address;
- rb->size = size;
- rb->head=0;
- rb->tail=0;
-}
diff --git a/kernel/sched/include/sched/sched.h b/kernel/sched/include/sched/sched.h
index 8838f09..f7bafcd 100644
--- a/kernel/sched/include/sched/sched.h
+++ b/kernel/sched/include/sched/sched.h
@@ -5,7 +5,7 @@
#include "mcu/sched/context.h"
/** Proposed default stack size, you may use this definition for declaring tasks. */
-#define STACK_SIZE 64
+#define STACK_SIZE 256
/** Stack size to be allocated for the idle task. */
#define IDLE_STACK_SIZE 64
@@ -67,7 +67,6 @@ extern struct list_head ready;
*/
extern char* 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/serial.disabled/include/serial/serial.h b/kernel/serial/include/serial/serial.h
index c76fe45..f6fcfc5 100644
--- a/kernel/serial.disabled/include/serial/serial.h
+++ b/kernel/serial/include/serial/serial.h
@@ -1,10 +1,9 @@
-#ifndef SERIAL_PRIVATE_H
-#define SERIAL_PRIVATE_H
+#ifndef SERIAL_H
+#define SERIAL_H
#include <stddef.h>
#include "collection/rbuffer.h"
#include "collection/list.h"
-#include "serial/serial.h"
#define USARTS 1
#define SERIAL_BUFFER_SIZE 64
@@ -22,17 +21,17 @@ struct serial_device_t {
#define SERIAL_DEVICE_INIT(name) \
{ \
- .rx_buffer = RBUFFER_INIT(name.__rx_buffer, SERIAL_BUFFER_SIZE), \
- .tx_buffer = RBUFFER_INIT(name.__tx_buffer, SERIAL_BUFFER_SIZE), \
+ .rx_buffer = RBUFFER_ARRAY_INIT(name.__rx_buffer, SERIAL_BUFFER_SIZE), \
+ .tx_buffer = RBUFFER_ARRAY_INIT(name.__tx_buffer, SERIAL_BUFFER_SIZE), \
.rx_q = LIST_HEAD_INIT(name.rx_q), \
.tx_q = LIST_HEAD_INIT(name.tx_q) \
}
void serial_init(unsigned long baud);
-size_t serial_read(char* const data, size_t max_size);
+size_t serial_read(char* const data, size_t size);
-void serial_write(const char* const data, size_t size);
+size_t serial_write(const char* const data, size_t size);
inline void serial_write_str(const char* const str) {
size_t length = 0;
diff --git a/kernel/serial.disabled/serial.c b/kernel/serial/serial.c
index 1f66174..6e88cd6 100644
--- a/kernel/serial.disabled/serial.c
+++ b/kernel/serial/serial.c
@@ -1,9 +1,7 @@
#include <avr/interrupt.h>
-#include "collection/list.h"
+#include "serial/serial.h"
#include "sched/sched.h"
-#include "sched/context.h"
#include "bug/debug.h"
-#include "serial/serial.h"
static struct serial_device_t serial = SERIAL_DEVICE_INIT(serial);
@@ -14,34 +12,25 @@ void serial_init(unsigned long baud) {
UBRR0L = baud_setting;
UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); // 8-bit, no parity, 1 stop bit
UCSR0B &= ~(1 << UDRIE0);
-
- //EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (1 << ISC00);
- //EIMSK |= (1 << INT0);
}
-static inline int rbuffer_safe_read(struct rbuffer_t* const rb, char* d) {
- ENTER_CRITICAL();
- int ret = rbuffer_read(rb, d);
- EXIT_CRITICAL();
- return ret;
+static inline int rbuffer_empty_safe(struct rbuffer_t* const rb) {
+ cli();
+ int r = rbuffer_empty(rb);
+ sei();
+ return r;
}
-size_t serial_read(char* const data, size_t max_size) {
-
- if (rbuffer_safe_read(&serial.rx_buffer, data) == 0) {
- size_t i;
- char d;
- for (i = 1; i < max_size && (rbuffer_safe_read(&serial.rx_buffer, &d) == 0); ++i) {
- data[i] = d;
- }
- return i;
- } else {
- ENTER_CRITICAL();
- list_move_tail(&current->q, &serial.rx_q);
- EXIT_CRITICAL();
+size_t serial_read(char* const data, size_t size) {
+ while (rbuffer_empty_safe(&serial.rx_buffer)) {
+ cli();
+ sleep_on(&serial.rx_q);
yield();
- return serial_read(data, max_size);
}
+ cli();
+ size_t r = rbuffer_read(&serial.rx_buffer, data, size);
+ sei();
+ return r;
}
@@ -49,29 +38,25 @@ size_t serial_read(char* const data, size_t max_size) {
ISR(USART0_RX_vect, ISR_NAKED) {
SAVE_CONTEXT();
char c = UDR0;
- rbuffer_write(&serial.rx_buffer, c);
- if (!list_empty(&serial.rx_q)) {
- list_move_tail(serial.rx_q.next, &ready);
- }
- schedule();
+ rbuffer_write_char(&serial.rx_buffer, c);
+ wake_all(&serial.rx_q);
RESTORE_CONTEXT();
asm volatile ("reti");
}
-void serial_write(const char* const data, size_t size) {
- for (size_t i = 0; i < size; ++i) {
- ENTER_CRITICAL();
- rbuffer_write(&serial.tx_buffer, data[i]);
- EXIT_CRITICAL();
- UCSR0B |= (1 << UDRIE0);
- }
+size_t serial_write(const char* const data, size_t size) {
+ cli();
+ size_t r = rbuffer_write(&serial.tx_buffer, data, size);
+ sei();
+ UCSR0B |= (1 << UDRIE0);
+ return r;
}
//called when data register is empty
ISR(USART0_UDRE_vect) {
char c;
- if (rbuffer_read(&serial.tx_buffer, &c) == 0) {
+ if (rbuffer_read_char(&serial.tx_buffer, &c)) {
UDR0 = c;
} else {
UCSR0B &= ~(1 << UDRIE0); //buffer empty, disable interruot