diff options
author | Jakob Odersky <jodersky@gmail.com> | 2014-01-25 14:47:07 +0100 |
---|---|---|
committer | Jakob Odersky <jodersky@gmail.com> | 2014-01-25 14:47:07 +0100 |
commit | 7dd00b2267d991a102f18eacf3e2afacb570a299 (patch) | |
tree | 9138bc7ce4feba262a20063f94aceaba3ec30788 /kernel | |
parent | 9453a44cfc475b57319d1051c74f72753ca4f64c (diff) | |
download | mux-7dd00b2267d991a102f18eacf3e2afacb570a299.tar.gz mux-7dd00b2267d991a102f18eacf3e2afacb570a299.tar.bz2 mux-7dd00b2267d991a102f18eacf3e2afacb570a299.zip |
implement serial
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/collection/include/collection/rbuffer.h | 83 | ||||
-rw-r--r-- | kernel/collection/rbuffer.c | 8 | ||||
-rw-r--r-- | kernel/sched/include/sched/sched.h | 3 | ||||
-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(¤t->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 |