kosmos/source/firmware/kernel/driver/uart._c

81 lines
1.8 KiB
Plaintext
Raw Normal View History

2016-07-28 19:02:54 +00:00
//! \file uart.c
//! \author tkl
//! \date Jul 15, 2012
//! \brief Source file of the architecture independent uart implementation.
#include <stddef.h>
#include <stdbool.h>
#include "driver.h"
#include "ringbuffer.h"
#include "irq.h"
#include "stack.h"
#include "queue.h"
#include "thread.h"
#include "schedule.h"
#include "kernel.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);
}