Added device driver's IPC.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2098 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
bernard.xiong@gmail.com 2012-04-23 06:02:28 +00:00
parent 5e1494dd32
commit da44d15132
4 changed files with 307 additions and 0 deletions

View File

@ -5,6 +5,44 @@
#define RT_DEVICE(device) ((rt_device_t)device) #define RT_DEVICE(device) ((rt_device_t)device)
/* completion flag */
struct rt_completion
{
rt_uint32_t flag;
/* suspended list */
rt_list_t suspended_list;
};
/* ring buffer */
struct rt_ringbuffer
{
rt_uint16_t read_index, write_index;
rt_uint8_t *buffer_ptr;
rt_uint16_t buffer_size;
};
/**
* Completion
*/
void rt_completion_init(struct rt_completion* completion);
rt_err_t rt_completion_wait(struct rt_completion* completion, rt_int32_t timeout);
void rt_completion_done(struct rt_completion* completion);
/**
* DataLink for DeviceDriver
*/
/**
* RingBuffer for DeviceDriver
*/
void rt_ringbuffer_init(struct rt_ringbuffer* rb, rt_uint8_t *pool, rt_uint16_t size);
rt_size_t rt_ringbuffer_put(struct rt_ringbuffer* rb, const rt_uint8_t *ptr, rt_uint16_t length);
rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer* rb, const rt_uint8_t ch);
rt_size_t rt_ringbuffer_get(struct rt_ringbuffer* rb, rt_uint8_t *ptr, rt_uint16_t length);
rt_size_t rt_ringbuffer_available_size(struct rt_ringbuffer* rb);
rt_size_t rt_ringbuffer_emptry_size(struct rt_ringbuffer* rb);
#ifdef RT_USING_SPI #ifdef RT_USING_SPI
#include "drivers/spi.h" #include "drivers/spi.h"
#endif #endif

View File

@ -0,0 +1,8 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd + '/../include']
group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_DEVICE_IPC'], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,107 @@
/**
* Complete implementation in Device Drivers
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#define RT_COMPLETED 1
#define RT_UNCOMPLETED 0
void rt_completion_init(struct rt_completion* completion)
{
rt_base_t level;
RT_ASSERT(completion != RT_NULL);
level = rt_hw_interrupt_disable();
completion->flag = RT_UNCOMPLETED;
rt_list_init(&completion->suspended_list);
rt_hw_interrupt_enable(level);
}
rt_err_t rt_completion_wait(struct rt_completion* completion, rt_int32_t timeout)
{
rt_err_t result;
rt_base_t level;
rt_thread_t thread;
RT_ASSERT(completion != RT_NULL);
result = RT_EOK;
thread = rt_thread_self();
level = rt_hw_interrupt_disable();
if (completion->flag != RT_COMPLETED)
{
/* only one thread can suspend on complete */
RT_ASSERT(rt_list_isempty(&(completion->suspended_list)));
if (timeout == 0)
{
result = -RT_ETIMEOUT;
goto __exit;
}
else
{
/* suspend thread */
rt_thread_suspend(thread);
/* add to suspended list */
rt_list_insert_before(&(completion->suspended_list), &(thread->tlist));
/* current context checking */
RT_DEBUG_NOT_IN_INTERRUPT;
/* start timer */
if (timeout > 0)
{
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout);
rt_timer_start(&(thread->thread_timer));
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
/* do schedule */
rt_schedule();
/* thread is waked up */
result = thread->error;
level = rt_hw_interrupt_disable();
/* clean completed flag */
completion->flag = RT_UNCOMPLETED;
}
}
__exit:
rt_hw_interrupt_enable(level);
return result;
}
void rt_completion_done(struct rt_completion* completion)
{
rt_base_t level;
RT_ASSERT(completion != RT_NULL);
level = rt_hw_interrupt_disable();
completion->flag = RT_COMPLETED;
if (!rt_list_isempty(&(completion->suspended_list)))
{
/* there is one thread in suspended list */
struct rt_thread *thread;
/* get thread entry */
thread = rt_list_entry(completion->suspended_list.next, struct rt_thread, tlist);
/* resume it */
rt_thread_resume(thread);
rt_hw_interrupt_enable(level);
/* perform a schedule */
rt_schedule();
}
else
{
rt_hw_interrupt_enable(level);
}
}

View File

@ -0,0 +1,154 @@
#include <rtthread.h>
#include <rtdevice.h>
void rt_ringbuffer_init(struct rt_ringbuffer* rb, rt_uint8_t *pool, rt_uint16_t size)
{
RT_ASSERT(rb != RT_NULL);
/* initialize read and write index */
rb->read_index = rb->write_index = 0;
/* set buffer pool and size */
rb->buffer_ptr = pool;
rb->buffer_size = size;
}
rt_size_t rt_ringbuffer_put(struct rt_ringbuffer* rb, const rt_uint8_t *ptr, rt_uint16_t length)
{
rt_size_t size;
RT_ASSERT(rb != RT_NULL);
/* whether has enough space */
if (rb->read_index > rb->write_index)
size = rb->read_index - rb->write_index;
else
size = rb->buffer_size - rb->write_index + rb->read_index;
/* no space */
if (size == 0) return 0;
/* drop some data */
if (size < length) length = size;
if (rb->read_index > rb->write_index)
{
/* read_index - write_index = empty space */
rt_memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
rb->write_index += length;
}
else
{
if (rb->buffer_size - rb->write_index > length)
{
/* there is enough space after write_index */
rt_memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
rb->write_index += length;
}
else
{
rt_memcpy(&rb->buffer_ptr[rb->write_index], ptr,
rb->buffer_size - rb->write_index);
rt_memcpy(&rb->buffer_ptr[0], &ptr[rb->buffer_size - rb->write_index],
length - (rb->buffer_size - rb->write_index));
rb->write_index = length - (rb->buffer_size - rb->write_index);
}
}
return length;
}
/**
* put a character into ring buffer
*/
rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer* rb, const rt_uint8_t ch)
{
rt_uint16_t next;
RT_ASSERT(rb != RT_NULL);
/* whether has enough space */
next = rb->write_index + 1;
if (next >= rb->buffer_size) next = 0;
if (next == rb->read_index) return 0;
/* put character */
rb->buffer_ptr[rb->write_index] = ch;
rb->write_index = next;
return 1;
}
/**
* get data from ring buffer
*/
rt_size_t rt_ringbuffer_get(struct rt_ringbuffer* rb, rt_uint8_t *ptr, rt_uint16_t length)
{
rt_size_t size;
RT_ASSERT(rb != RT_NULL);
/* whether has enough data */
if (rb->read_index > rb->write_index)
size = rb->buffer_size - rb->read_index + rb->write_index;
else
size = rb->write_index - rb->read_index;
/* no data */
if (size == 0) return 0;
/* less data */
if (size < length) length = size;
if (rb->read_index > rb->write_index)
{
if (rb->buffer_size - rb->read_index > length)
{
/* copy directly */
rt_memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
rb->read_index += length;
}
else
{
/* copy first and second */
rt_memcpy(ptr, &rb->buffer_ptr[rb->read_index],
rb->buffer_size - rb->read_index);
rt_memcpy(&ptr[rb->buffer_size - rb->read_index], &rb->buffer_ptr[0],
length - rb->buffer_size + rb->read_index);
rb->read_index = length - rb->buffer_size + rb->read_index;
}
}
else
{
rt_memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
rb->read_index += length;
}
return length;
}
/**
* get available data size
*/
rt_size_t rt_ringbuffer_available_size(struct rt_ringbuffer* rb)
{
rt_size_t size;
RT_ASSERT(rb != RT_NULL);
if (rb->read_index > rb->write_index)
size = rb->buffer_size - rb->read_index + rb->write_index;
else
size = rb->write_index - rb->read_index;
/* return the available size */
return size;
}
/**
* get empty space size
*/
rt_size_t rt_ringbuffer_emptry_size(struct rt_ringbuffer* rb)
{
RT_ASSERT(rb != RT_NULL);
return rb->buffer_size - rt_ringbuffer_available_size(rb);
}