serial line ringbuf implementation + increased default buffer size to 128 bytes
This commit is contained in:
parent
edd94c00b0
commit
6f4a537aa0
1 changed files with 64 additions and 25 deletions
|
@ -28,23 +28,29 @@
|
||||||
*
|
*
|
||||||
* This file is part of the Contiki operating system.
|
* This file is part of the Contiki operating system.
|
||||||
*
|
*
|
||||||
* @(#)$Id: serial-line.c,v 1.1 2009/03/17 15:56:33 adamdunkels Exp $
|
* @(#)$Id: serial-line.c,v 1.2 2009/10/27 16:20:31 fros4943 Exp $
|
||||||
*/
|
*/
|
||||||
#include "dev/serial-line.h"
|
#include "dev/serial-line.h"
|
||||||
#include <string.h> /* for memcpy() */
|
#include <string.h> /* for memcpy() */
|
||||||
|
|
||||||
|
#include "lib/ringbuf.h"
|
||||||
|
|
||||||
#ifdef SERIAL_LINE_CONF_BUFSIZE
|
#ifdef SERIAL_LINE_CONF_BUFSIZE
|
||||||
#define BUFSIZE SERIAL_LINE_CONF_BUFSIZE
|
#define BUFSIZE SERIAL_LINE_CONF_BUFSIZE
|
||||||
#else /* SERIAL_LINE_CONF_BUFSIZE */
|
#else /* SERIAL_LINE_CONF_BUFSIZE */
|
||||||
#define BUFSIZE 80
|
#define BUFSIZE 128
|
||||||
#endif /* SERIAL_LINE_CONF_BUFSIZE */
|
#endif /* SERIAL_LINE_CONF_BUFSIZE */
|
||||||
|
|
||||||
|
#if (BUFSIZE & (BUFSIZE - 1)) != 0
|
||||||
|
#error SERIAL_LINE_CONF_BUFSIZE must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...).
|
||||||
|
#error Change SERIAL_LINE_CONF_BUFSIZE in contiki-conf.h.
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IGNORE_CHAR(c) (c == 0x0d)
|
#define IGNORE_CHAR(c) (c == 0x0d)
|
||||||
#define END 0x0a
|
#define END 0x0a
|
||||||
|
|
||||||
static char buffer[BUFSIZE], appbuffer[BUFSIZE];
|
static struct ringbuf rxbuf;
|
||||||
static volatile unsigned char bufwptr;
|
static uint8_t rxbuf_data[BUFSIZE];
|
||||||
static volatile char buffer_full = 0;
|
|
||||||
|
|
||||||
PROCESS(serial_line_process, "Serial driver");
|
PROCESS(serial_line_process, "Serial driver");
|
||||||
|
|
||||||
|
@ -55,18 +61,31 @@ process_event_t serial_line_event_message;
|
||||||
int
|
int
|
||||||
serial_line_input_byte(unsigned char c)
|
serial_line_input_byte(unsigned char c)
|
||||||
{
|
{
|
||||||
if(!buffer_full && !IGNORE_CHAR(c)) {
|
static uint8_t overflow = 0; /* Buffer overflow: ignore until END */
|
||||||
if(c == END) {
|
|
||||||
/* terminate the string */
|
if(!IGNORE_CHAR(c)) {
|
||||||
buffer[bufwptr++] = '\0';
|
if(!overflow) {
|
||||||
buffer_full++;
|
/* Add character */
|
||||||
|
if(ringbuf_put(&rxbuf, c) == 0) {
|
||||||
|
/* Buffer overflow: ignore the rest of the line */
|
||||||
|
overflow = 1;
|
||||||
process_poll(&serial_line_process);
|
process_poll(&serial_line_process);
|
||||||
return 1;
|
}
|
||||||
|
} else {
|
||||||
|
/* Buffer overflowed:
|
||||||
|
* Only (try to) add terminator characters, otherwise skip */
|
||||||
|
if(c == END && ringbuf_put(&rxbuf, c) != 0) {
|
||||||
|
overflow = 0;
|
||||||
|
} else {
|
||||||
|
process_poll(&serial_line_process);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reserve space for the terminating zero character */
|
if(c == END && !overflow) {
|
||||||
if(bufwptr < (BUFSIZE - 1)) {
|
/* Tell process at least one (potentially cropped due to overflow)
|
||||||
buffer[bufwptr++] = c;
|
* line exists in the buffer */
|
||||||
|
process_poll(&serial_line_process);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -74,21 +93,40 @@ serial_line_input_byte(unsigned char c)
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
PROCESS_THREAD(serial_line_process, ev, data)
|
PROCESS_THREAD(serial_line_process, ev, data)
|
||||||
{
|
{
|
||||||
|
static char buf[128];
|
||||||
|
static int ptr;
|
||||||
|
|
||||||
PROCESS_BEGIN();
|
PROCESS_BEGIN();
|
||||||
|
|
||||||
bufwptr = 0;
|
|
||||||
buffer_full = 0;
|
|
||||||
|
|
||||||
serial_line_event_message = process_alloc_event();
|
serial_line_event_message = process_alloc_event();
|
||||||
|
ptr=0;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
PROCESS_YIELD();
|
|
||||||
|
|
||||||
if(buffer_full) {
|
/* Fill application buffer until newline or empty */
|
||||||
memcpy(appbuffer, buffer, bufwptr);
|
int c = ringbuf_get(&rxbuf);
|
||||||
process_post(PROCESS_BROADCAST, serial_line_event_message, appbuffer);
|
if(c == -1) {
|
||||||
bufwptr = 0;
|
/* Buffer empty, wait for poll */
|
||||||
buffer_full = 0;
|
PROCESS_YIELD();
|
||||||
|
} else {
|
||||||
|
if(c != END) {
|
||||||
|
buf[ptr++] = (uint8_t)c;
|
||||||
|
} else {
|
||||||
|
/* Terminate */
|
||||||
|
buf[ptr++] = (uint8_t)'\0';
|
||||||
|
|
||||||
|
if (ptr > 1) {
|
||||||
|
/* Broadcast event */
|
||||||
|
process_post(PROCESS_BROADCAST, serial_line_event_message, buf);
|
||||||
|
|
||||||
|
/* Wait until all processes have handled the serial line event */
|
||||||
|
if(PROCESS_ERR_OK ==
|
||||||
|
process_post(PROCESS_CURRENT(), PROCESS_EVENT_CONTINUE, NULL)) {
|
||||||
|
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_CONTINUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +136,7 @@ PROCESS_THREAD(serial_line_process, ev, data)
|
||||||
void
|
void
|
||||||
serial_line_init(void)
|
serial_line_init(void)
|
||||||
{
|
{
|
||||||
|
ringbuf_init(&rxbuf, rxbuf_data, sizeof(rxbuf_data));
|
||||||
process_start(&serial_line_process, NULL);
|
process_start(&serial_line_process, NULL);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
Loading…
Reference in a new issue