Add ring buffer for USART.
This commit is contained in:
@@ -121,3 +121,156 @@ usart_config (uint8_t dev_no, uint32_t config_bits)
|
|||||||
dev->BRR = brr_table[i].brr_value;
|
dev->BRR = brr_table[i].brr_value;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ring buffer
|
||||||
|
*/
|
||||||
|
#define MAX_RB_BUF 1024
|
||||||
|
|
||||||
|
struct rb {
|
||||||
|
uint8_t *buf;
|
||||||
|
chopstx_mutex_t m;
|
||||||
|
chopstx_cond_t data_available;
|
||||||
|
chopstx_cond_t space_available;
|
||||||
|
uint32_t head :10;
|
||||||
|
uint32_t tail :10;
|
||||||
|
uint32_t size :10;
|
||||||
|
uint32_t full : 1;
|
||||||
|
uint32_t empty : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: size = 1024 can still work, regardless of the limit of 10-bit.
|
||||||
|
*/
|
||||||
|
static init
|
||||||
|
rb_init (struct rng_rb *rb, uint32_t *p, uint16_t size)
|
||||||
|
{
|
||||||
|
rb->buf = p;
|
||||||
|
rb->size = size;
|
||||||
|
chopstx_mutex_init (&rb->m);
|
||||||
|
chopstx_cond_init (&rb->data_available);
|
||||||
|
chopstx_cond_init (&rb->space_available);
|
||||||
|
rb->head = rb->tail = 0;
|
||||||
|
rb->full = 0;
|
||||||
|
rb->empty = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_add (struct rng_rb *rb, uint8_t v)
|
||||||
|
{
|
||||||
|
rb->buf[rb->tail++] = v;
|
||||||
|
if (rb->tail == rb->size)
|
||||||
|
rb->tail = 0;
|
||||||
|
if (rb->tail == rb->head)
|
||||||
|
rb->full = 1;
|
||||||
|
rb->empty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t
|
||||||
|
rb_del (struct rng_rb *rb)
|
||||||
|
{
|
||||||
|
uint32_t v = rb->buf[rb->head++];
|
||||||
|
|
||||||
|
if (rb->head == rb->size)
|
||||||
|
rb->head = 0;
|
||||||
|
if (rb->head == rb->tail)
|
||||||
|
rb->empty = 1;
|
||||||
|
rb->full = 0;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Application: consumer
|
||||||
|
* Hardware: generator
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rb_ll_put (struct rng_rb *rb, uint8_t v)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
chopstx_mutex_lock (&rb->m);
|
||||||
|
if (rb->full)
|
||||||
|
r = -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = 0;
|
||||||
|
rb_add (rb, v);
|
||||||
|
chopstx_cond_signal (&rb->data_available);
|
||||||
|
}
|
||||||
|
chopstx_mutex_unlock (&rb->m);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Application: generator
|
||||||
|
* Hardware: consumer
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rb_ll_get (struct rng_rb *rb)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
chopstx_mutex_lock (&rb->m);
|
||||||
|
if (rb->empty)
|
||||||
|
r = -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = rb_del (rb);
|
||||||
|
chopstx_cond_signal (&rb->space_available);
|
||||||
|
}
|
||||||
|
chopstx_mutex_unlock (&rb->m);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Application: consumer
|
||||||
|
* Hardware: generator
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
rb_read (struct rng_rb *rb, uint8_t *buf, uint16_t buflen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
chopstx_mutex_lock (&rb->m);
|
||||||
|
while (rb->empty)
|
||||||
|
chopstx_cond_wait (&rb->data_available, &rb->m);
|
||||||
|
|
||||||
|
for (i = 0; i < buflen; i++)
|
||||||
|
{
|
||||||
|
buf[i] = rb_del (rb);
|
||||||
|
if (rb->empty)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
chopstx_cond_signal (&rb->space_available);
|
||||||
|
chopstx_mutex_unlock (&rb->m);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Application: generator
|
||||||
|
* Hardware: consumer
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rb_write (struct rng_rb *rb, uint8_t *buf, uint16_t buflen)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
chopstx_mutex_lock (&rb->m);
|
||||||
|
while (i < buflen)
|
||||||
|
{
|
||||||
|
while (rb->full)
|
||||||
|
chopstx_cond_wait (&rb->space_available, &rb->m);
|
||||||
|
|
||||||
|
while (i < buflen)
|
||||||
|
{
|
||||||
|
rb_add (rb, buf[i++]);
|
||||||
|
if (rb->full)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
chopstx_cond_signal (&rb->data_available);
|
||||||
|
}
|
||||||
|
chopstx_mutex_unlock (&rb->m);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user