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:
parent
5e1494dd32
commit
da44d15132
|
@ -5,6 +5,44 @@
|
|||
|
||||
#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
|
||||
#include "drivers/spi.h"
|
||||
#endif
|
||||
|
|
|
@ -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')
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue