81 lines
1.8 KiB
Plaintext
81 lines
1.8 KiB
Plaintext
|
//! \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);
|
||
|
}
|