//! \file uart.c //! \author tkl //! \date Jul 15, 2012 //! \brief Source file of the architecture independent uart implementation. #include #include #include "driver.h" #include "ringbuffer.h" #include "irq.h" #include "stack.h" #include "queue.h" #include "thread.h" #include "schedule.h" #include "uart.h" extern volatile struct thread_context *current_thread; static const void *uart_it_callback(const void *param); int uart_open(const struct uart *this) { if(NULL == this) return (-1); int ret = this->fp->set_cb(this->arch_dep_device, uart_it_callback, this); ret |= this->fp->open(this->arch_dep_device); return (ret); } int uart_close(const struct uart *this) { if(NULL == this) return (-1); blocking_read_wakeup((const void *)this); return (this->fp->close(this->arch_dep_device)); } int uart_read(const struct uart *this, char *buffer, int len) { int ret = -1; unsigned int irq; if(NULL == this) return (-1); irq = disable_irq(); if(ringbuffer_is_empty(this->buffer)) { current_thread->status = THREAD_STATUS_BLOCKING; current_thread->wakeup_blocking_source = (void*) this; restore_irq(irq); schedule(); } ret = ringbuffer_read(this->buffer, buffer, len); restore_irq(irq); return ret; } int uart_write(const struct uart *this, const char *buffer, int len) { if(NULL == this) return (-1); return (this->fp->write(this->arch_dep_device, buffer, len)); } static const void *uart_it_callback(const void *param) { if(NULL == param) return (NULL); char c = 0; struct uart *uart = (struct uart *)param; uart->fp->read((const void *)uart->arch_dep_device, &c, 1); if(!ringbuffer_is_full(uart->buffer)) ringbuffer_write(uart->buffer, &c, 1); blocking_read_wakeup(param); return (param); }