Skip to content

Commit

Permalink
Merge branch 'newkiss'
Browse files Browse the repository at this point in the history
  • Loading branch information
johandc committed Oct 25, 2013
2 parents 3f2b2e8 + 31f76a1 commit 6d593f9
Show file tree
Hide file tree
Showing 16 changed files with 409 additions and 317 deletions.
38 changes: 34 additions & 4 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
libcsp 1.x, xxxx-xx-xx
libcsp 1.2, 25-10-2013
----------------------
- Feature release
- New: CMP service for peek and poke of memory
- New: CMP interface statistics struct is now packed
- New: Faster O(1) buffer system with reference counting and automatic alignment
- New: Thread safe KISS driver with support for multiple interfaces
- New: CSP interface struct now holds an opaque pointer to driver handle
- New: removed TXBUF from KISS driver entirely to minimize stack usage, added TX lock instead
- New: Pre-calculated CRC table .romem or PROGMEM on __avr__
- New: Added buffer overflow protection to KISS interface
- New: Allow posting null pointers on conn RX queues
- New: Lower memory usage on AVR8
- New: csp_route_save and csp_route_load functions
- New: option --disable-verbose to disable filenames and linenumber on debug
- Protocol: KISS uses csp_crc32 instead of it own embedded crc32
- Improvement: Use buffer clone function to copy promisc packets
- Bugfix: Fix pointer size (32/16bit) in cmp_peek/poke
- Bugfix: Issue with double free in KISS fixed
- Bugfix: Change rdp_send timeout from packet to connection timeout to make sending task block longer
- Bugfix: Fix conn pool leak when using security check and discarding new packets
- Bugfix: Add packet too short check for CRC32
- Bugfix: Accept CRC32 responses from nodes without CRC support
- Bugfix: Ensure csp_ping works for packets > 256 bytes
- Bugfix: Cleanup printf inside ISR functions
- Bugfix: Do not add forwarded packets to promisc queue twice
- Bugfix: Fix return value bug of csp_buffer_get when out of buffers
- Bugfix: Always post null pointer with lowest priority, not highest
- Bugfix: Add check on debug level before calling do_csp_debug, fixes #35
- Other: Export csp/arch include files
- Other: Remove the use of bool type from csp_debug
- Other: Moved csp debug functions to csp_debug.h instead of csp.h
- Other: Ensure assignment of id happens using the uint32_t .ext value of the union, quenches warning

libcsp 1.1, 2012-08-24
libcsp 1.1, 24-08-2012
----------------------
- Feature release
- Defacto stable since Feb 2012
Expand All @@ -29,12 +59,12 @@ libcsp 1.1, 2012-08-24
- Bugfix: Fixed problem in csp_if_kiss when out of buffers
- Bigfix: Handle bus-off CAN IRQ for AT90CAN128

libcsp 1.0.1, 2011-10-30
libcsp 1.0.1, 30-10-2011
------------------------
- Hotfix release
- Bugfix: missing extern in csp_if_lo.h

libcsp 1.0, 2011-10-24
libcsp 1.0, 24-10-2011
----------------------
- First official release
- New: CSP 32-bit header 1.0
Expand Down
14 changes: 10 additions & 4 deletions include/csp/csp.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,15 @@ typedef struct __attribute__((__packed__)) {
};
} csp_packet_t;

/** Next hop function prototype */
typedef int (*nexthop_t)(csp_packet_t *packet, uint32_t timeout);
/** Interface TX function */
typedef struct csp_iface_s csp_iface_t;
typedef int (*nexthop_t)(struct csp_iface_s * interface, csp_packet_t *packet, uint32_t timeout);

/** Interface struct */
typedef struct csp_iface_s {
const char *name; /**< Interface name (keep below 10 bytes)*/
nexthop_t nexthop; /**< Next hop function */
const char *name; /**< Interface name (keep below 10 bytes) */
void * driver; /**< Pointer to interface handler structure */
nexthop_t nexthop; /**< Next hop function */
uint8_t promisc; /**< Promiscuous mode enabled */
uint16_t mtu; /**< Maximum Transmission Unit of interface */
uint8_t split_horizon_off; /**< Disable the route-loop prevention on if */
Expand All @@ -219,6 +221,10 @@ typedef struct csp_iface_s {
struct csp_iface_s *next; /**< Next interface */
} csp_iface_t;

/* Nexthop typedef:
* Note this has to match the nexthop type in the iface structure */
typedef int (*nexthop_t)(csp_iface_t * interface, csp_packet_t *packet, uint32_t timeout);

/**
* This define must be equal to the size of the packet overhead in csp_packet_t.
* It is used in csp_buffer_get() to check the allocated buffer size against
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions include/csp/drivers/usart.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,6 @@ void usart_putstr(char *buf, int len);
*/
char usart_getc(void);

int usart_messages_waiting(int handle);

#endif /* USART_H_ */
46 changes: 29 additions & 17 deletions include/csp/interfaces/csp_if_kiss.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,33 @@ extern "C" {
#include <csp/csp.h>
#include <csp/csp_interface.h>

extern csp_iface_t csp_if_kiss;

/**
* The KISS interface relies on the USART callback in order to parse incoming
* messaged from the serial interface. This csp_kiss_rx should match the
* usart_callback_t as implemented in your driver.
* messaged from the serial interface. The USART callback however does not
* support passing the handle number of the responding USART, so you need to implement
* a USART callback for each handle and then call kiss_rx subsequently.
*
* In order to initialize the KISS interface. Fist call kiss_init() and then
* setup your usart to call csp_kiss_rx when new data is available.
*
* When a byte is not a part of a kiss packet, it will be returned to your
* usart driver using the usart_insert funtion that you provide.
*
* @param csp_iface pointer to interface
* @param buf pointer to incoming data
* @param len length of incoming data
* @param pxTaskWoken NULL if task context, pointer to variable if ISR
*/
void csp_kiss_rx(uint8_t *buf, int len, void *pxTaskWoken);
void csp_kiss_rx(csp_iface_t * interface, uint8_t *buf, int len, void *pxTaskWoken);

/**
* The putstr function is used by the kiss interface to send
* The putc function is used by the kiss interface to send
* a string of data to the serial port. This function must
* be implemented by the user, and passed to the kiss
* interface through the kiss_init function.
* @param buf pointer to data
* @param len length of data
* @param buf byte to push
*/
typedef void (*csp_kiss_putstr_f)(char *buf, int len);
typedef void (*csp_kiss_putc_f)(char buf);

/**
* The characters not accepted by the kiss interface, are discarded
Expand All @@ -73,16 +72,29 @@ typedef void (*csp_kiss_putstr_f)(char *buf, int len);
*/
typedef void (*csp_kiss_discard_f)(char c, void *pxTaskWoken);

typedef enum {
KISS_MODE_NOT_STARTED,
KISS_MODE_STARTED,
KISS_MODE_ESCAPED,
KISS_MODE_SKIP_FRAME,
} kiss_mode_e;

/**
* Initialise kiss interface.
* This function stores the function pointers for the putstr and discard functions,
* which must adhere to the above function specifications. This ensures that the
* kiss interface can use a multiple of different USART drivers.
* @param kiss_putstr kiss uses this function to send KISS frames
* @param kiss_discard non-kiss characters are sent to this function (set to NULL to discard)
* @return CSP_ERR_NONE
* This structure should be statically allocated by the user
* and passed to the kiss interface during the init function
* no member information should be changed
*/
int csp_kiss_init(csp_kiss_putstr_f kiss_putstr, csp_kiss_discard_f kiss_discard);
typedef struct csp_kiss_handle_s {
csp_kiss_putc_f kiss_putc;
csp_kiss_discard_f kiss_discard;
unsigned int rx_length;
kiss_mode_e rx_mode;
unsigned int rx_first;
volatile unsigned char *rx_cbuf;
csp_packet_t * rx_packet;
} csp_kiss_handle_t;

void csp_kiss_init(csp_iface_t * csp_iface, csp_kiss_handle_t * csp_kiss_handle, csp_kiss_putc_f kiss_putc_f, csp_kiss_discard_f kiss_discard_f, const char * name);

#ifdef __cplusplus
} /* extern "C" */
Expand Down
117 changes: 98 additions & 19 deletions src/csp_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,33 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <csp/arch/csp_malloc.h>
#include <csp/arch/csp_semaphore.h>

#define CSP_BUFFER_ALIGN (sizeof(int *))

typedef struct csp_skbf_s {
unsigned int refcount;
void * skbf_addr;
char skbf_data[];
} csp_skbf_t;

static csp_queue_handle_t csp_buffers;
static void *csp_buffer_list;
static char * csp_buffer_pool;
static unsigned int count, size;

CSP_DEFINE_CRITICAL(csp_critical_lock);

int csp_buffer_init(int buf_count, int buf_size) {

unsigned int i;
void *element;
csp_skbf_t * buf;

count = buf_count;
size = buf_size;
unsigned int skbfsize = (sizeof(csp_skbf_t) + size);
skbfsize = CSP_BUFFER_ALIGN * ((skbfsize + CSP_BUFFER_ALIGN - 1) / CSP_BUFFER_ALIGN);
unsigned int poolsize = count * skbfsize;

csp_buffer_list = csp_malloc(count * size);
if (csp_buffer_list == NULL)
csp_buffer_pool = csp_malloc(poolsize);
if (csp_buffer_pool == NULL)
goto fail_malloc;

csp_buffers = csp_queue_create(count, sizeof(void *));
Expand All @@ -54,69 +65,137 @@ int csp_buffer_init(int buf_count, int buf_size) {
if (CSP_INIT_CRITICAL(csp_critical_lock) != CSP_ERR_NONE)
goto fail_critical;

memset(csp_buffer_list, 0, count * size);
memset(csp_buffer_pool, 0, poolsize);

for (i = 0; i < count; i++) {
element = csp_buffer_list + i * size;
csp_queue_enqueue(csp_buffers, &element, 0);

/* We have already taken care of pointer alignment since
* skbfsize is an integer multiple of sizeof(int *)
* but the explicit cast to a void * is still necessary
* to tell the compiler so.
*/
buf = (void *) &csp_buffer_pool[i * skbfsize];
buf->refcount = 0;
buf->skbf_addr = buf;

csp_queue_enqueue(csp_buffers, &buf, 0);

}

return CSP_ERR_NONE;

fail_critical:
csp_queue_remove(csp_buffers);
fail_queue:
csp_free(csp_buffer_list);
csp_free(csp_buffer_pool);
fail_malloc:
return CSP_ERR_NOMEM;

}

void *csp_buffer_get_isr(size_t buf_size) {
void *buffer = NULL;

csp_skbf_t * buffer = NULL;
CSP_BASE_TYPE task_woken = 0;

if (buf_size + CSP_BUFFER_PACKET_OVERHEAD > size)
return NULL;

csp_queue_dequeue_isr(csp_buffers, &buffer, &task_woken);
if (buffer == NULL)
return NULL;

//csp_log_buffer("GET ISR: %p %p\r\n", buffer, buffer->skbf_addr);

if (buffer != buffer->skbf_addr) {
//csp_log_error("Corrupt CSP buffer\r\n");
return NULL;
}

buffer->refcount++;
return buffer->skbf_data;

return buffer;
}

void *csp_buffer_get(size_t buf_size) {
void *buffer = NULL;

csp_skbf_t * buffer = NULL;

if (buf_size + CSP_BUFFER_PACKET_OVERHEAD > size) {
csp_log_error("Attempt to allocate too large block %u\r\n", buf_size);
return NULL;
}

csp_queue_dequeue(csp_buffers, &buffer, 0);

if (buffer != NULL) {
csp_log_buffer("BUFFER: Using element at %p\r\n", buffer);
} else {
if (buffer == NULL) {
csp_log_error("Out of buffers\r\n");
return NULL;
}

csp_log_buffer("GET: %p %p\r\n", buffer, buffer->skbf_addr);

if (buffer != buffer->skbf_addr) {
csp_log_error("Corrupt CSP buffer\r\n");
return NULL;
}

return buffer;
buffer->refcount++;
return buffer->skbf_data;
}

void csp_buffer_free_isr(void *packet) {
CSP_BASE_TYPE task_woken = 0;
if (!packet)
return;
csp_queue_enqueue_isr(csp_buffers, &packet, &task_woken);

csp_skbf_t * buf = packet - sizeof(csp_skbf_t);

if (buf->skbf_addr != buf) {
//csp_log_error("FREE ISR: Invalid CSP buffer pointer %p\r\n", packet);
return;
}

if (buf->refcount == 0) {
//csp_log_error("FREE ISR: Buffer already free %p\r\n", buf);
return;
} else if (buf->refcount > 1) {
buf->refcount--;
//csp_log_error("FREE ISR: Buffer %p in use by %u users\r\n", buf, buf->refcount);
return;
} else {
buf->refcount = 0;
//csp_log_buffer("FREE: %p\r\n", buf);
csp_queue_enqueue_isr(csp_buffers, &buf, &task_woken);
}

}

void csp_buffer_free(void *packet) {
if (!packet) {
csp_log_error("Attempt to free null pointer\r\n");
return;
}
csp_log_buffer("BUFFER: Free element at %p\r\n", packet);
csp_queue_enqueue(csp_buffers, &packet, 0);

csp_skbf_t * buf = packet - sizeof(csp_skbf_t);

if (buf->skbf_addr != buf) {
csp_log_error("FREE: Invalid CSP buffer pointer %p\r\n", packet);
return;
}

if (buf->refcount == 0) {
csp_log_error("FREE: Buffer already free %p\r\n", buf);
return;
} else if (buf->refcount > 1) {
buf->refcount--;
csp_log_error("FREE: Buffer %p in use by %u users\r\n", buf, buf->refcount);
return;
} else {
buf->refcount = 0;
csp_log_buffer("FREE: %p\r\n", buf);
csp_queue_enqueue(csp_buffers, &buf, 0);
}

}

void *csp_buffer_clone(void *buffer) {
Expand Down
8 changes: 6 additions & 2 deletions src/csp_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,17 @@ int csp_conn_enqueue_packet(csp_conn_t * conn, csp_packet_t * packet) {
rxq = CSP_RX_QUEUES - 1;
}

if (csp_queue_enqueue(conn->rx_queue[rxq], &packet, 0) != CSP_QUEUE_OK)
if (csp_queue_enqueue(conn->rx_queue[rxq], &packet, 0) != CSP_QUEUE_OK) {
csp_log_error("RX queue %p full with %u items\r\n", conn->rx_queue[rxq], csp_queue_size(conn->rx_queue[rxq]));
return CSP_ERR_NOMEM;
}

#ifdef CSP_USE_QOS
int event = 0;
if (csp_queue_enqueue(conn->rx_event, &event, 0) != CSP_QUEUE_OK)
if (csp_queue_enqueue(conn->rx_event, &event, 0) != CSP_QUEUE_OK) {
csp_log_error("QOS event queue full\r\n");
return CSP_ERR_NOMEM;
}
#endif

return CSP_ERR_NONE;
Expand Down
Loading

0 comments on commit 6d593f9

Please sign in to comment.