diff options
author | Jakob Odersky <jodersky@gmail.com> | 2014-01-24 20:10:45 +0100 |
---|---|---|
committer | Jakob Odersky <jodersky@gmail.com> | 2014-01-24 20:10:45 +0100 |
commit | 6cdf34b0e87bc915de39a6d5817980a825a720da (patch) | |
tree | 1b8710106c0201ecad5e199099b4f084795b96ea /kernel/serial.disabled/serial.c | |
download | mux-6cdf34b0e87bc915de39a6d5817980a825a720da.tar.gz mux-6cdf34b0e87bc915de39a6d5817980a825a720da.tar.bz2 mux-6cdf34b0e87bc915de39a6d5817980a825a720da.zip |
initial commit
Diffstat (limited to 'kernel/serial.disabled/serial.c')
-rw-r--r-- | kernel/serial.disabled/serial.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/kernel/serial.disabled/serial.c b/kernel/serial.disabled/serial.c new file mode 100644 index 0000000..1f66174 --- /dev/null +++ b/kernel/serial.disabled/serial.c @@ -0,0 +1,109 @@ +#include <avr/interrupt.h> +#include "collection/list.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); + +void serial_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); + + //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; +} + +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(); + yield(); + return serial_read(data, max_size); + } +} + + +//called when byte is received +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(); + 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); + } +} + +//called when data register is empty +ISR(USART0_UDRE_vect) { + char c; + if (rbuffer_read(&serial.tx_buffer, &c) == 0) { + UDR0 = c; + } else { + UCSR0B &= ~(1 << UDRIE0); //buffer empty, disable interruot + } +} +/* +void serial_read() { + ENTER_CRITICAL(); + list_move_tail(¤t->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"); +} +*/ |