diff --git a/inc/pbuf.h b/inc/pbuf.h new file mode 100644 index 0000000..b6dfd5e --- /dev/null +++ b/inc/pbuf.h @@ -0,0 +1,145 @@ +#ifndef _PBUF_H +#define _PBUF_H + + +#include +#include + +#include + + +#define __align4 __attribute__((aligned(4))) + + +typedef void (*pbuf_callback_t)(void); //function pointer that will be called when a pbuf is freed in this pool + +struct pbuf_pool_s; + +typedef struct pbuf_s +{ + uint8_t* payload; + uint32_t length; + + uint32_t capacity; + uint8_t* payload_memory; + + struct pbuf_s *next; //used to link pbufs + struct pbuf_pool_s *pool; + + void *user; +}pbuf_t; + + + +typedef struct pbuf_pool_s +{ + pbuf_t* pbuf_memory; + uint32_t pbuf_count; + + uint8_t* payload_memory; + uint32_t payload_capacity; + + uint32_t pbufs_available; + pbuf_t* free_list; + + pbuf_callback_t free_callback; +}pbuf_pool_t; + + + +#define PBUF_DECLARE_POOL(pool_name, pbuf_count, pbuf_size) \ +static uint8_t pool_name##_payload_memory[(pbuf_count) * (pbuf_size)] __align4; \ +static pbuf_t pool_name##_memory[pbuf_count]; \ +pbuf_pool_t pool_name + + +#define STATIC_PBUF_DECLARE_POOL(pool_name, pbuf_count, pbuf_size) \ +static uint8_t pool_name##_payload_memory[(pbuf_count) * (pbuf_size)] __align4; \ +static pbuf_t pool_name##_memory[pbuf_count]; \ +static pbuf_pool_t pool_name + + + +#define PBUF_INIT_POOL(pool_name) \ + pbuf_pool_create(&pool_name, \ + sizeof(pool_name##_memory) / sizeof(pbuf_t), \ + pool_name##_memory, \ + sizeof(pool_name##_payload_memory) / (sizeof(pool_name##_memory) / sizeof(pbuf_t)), \ + pool_name##_payload_memory) + + +/** + \brief Creates a new pool of pbufs + + \param pool Pointer to a pbuf_pool_t structure that will be initialized + \param pbuf_count Number of pbufs to create in the pbuf pool + \param pbuf_memory Pointer to a statically allocated area of memory for storing the pbuf structures. + \param payload_capacity Size of the pbuf payload. + \param payload_memory Pointer to statically allocated memory that will be used for storing the pbuf attached buffers + + pbuf_memory needs to be a statically allocated memory chunk of size: pbuf_count * sizeof(pbuf_t) (bytes) + payload_memory needs to be a statically allocated memory chunk of size: pbuf_count * pbuf_payload_size (bytes) + +*/ +void pbuf_pool_create(pbuf_pool_t *pool, uint32_t pbuf_count, void *pbuf_memory, uint32_t payload_capacity, void *payload_memory); +void pbuf_pool_reset(pbuf_pool_t *pool); + + +void pbuf_dump_pool(pbuf_pool_t *pool); + + +static inline uint32_t pbuf_pool_get_available(pbuf_pool_t *pool) +{ + return pool->pbufs_available; +} + + +static inline pbuf_t* pbuf_alloc(pbuf_pool_t *pool) +{ + assert(pool); + + pbuf_t* p = pool->free_list; + + if (p) + { + pool->free_list = pool->free_list->next; //remove it from the list + pool->pbufs_available--; + + p->payload = p->payload_memory; + p->capacity = pool->payload_capacity; + } + + return p; +} + + +static inline void pbuf_free(pbuf_t* p) +{ + if (p) + { + p->next = p->pool->free_list; //add it back to the free list + p->pool->free_list = p; + p->pool->pbufs_available++; + + if (p->pool->free_callback) //call the hook if we have one + p->pool->free_callback(); + } +} + +/* +inline void pbuf_free_queue(pbuf_t *queue) +{ + while(queue) + { + pbuf_t *p = queue; + queue = queue->next; + + //free the pbuf + p->next = p->pool->free_list; //add it back to the free list + p->pool->free_list = p; + } +} +*/ + +#endif + diff --git a/pbuf.mk b/pbuf.mk new file mode 100644 index 0000000..224077c --- /dev/null +++ b/pbuf.mk @@ -0,0 +1,4 @@ +PBUF_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))). + +CSRCS += $(PBUF_PATH)/src/pbuf.c +INCDIRS += $(PBUF_PATH)/inc diff --git a/src/pbuf.c b/src/pbuf.c new file mode 100644 index 0000000..1c4255d --- /dev/null +++ b/src/pbuf.c @@ -0,0 +1,68 @@ +#include + +#include + + +void pbuf_pool_create(pbuf_pool_t *pool, uint32_t pbuf_count, void *pbuf_memory, uint32_t pbuf_payload_capacity, void *pbuf_payload_memory) +{ + assert(pool); + assert(pbuf_count); + assert(pbuf_memory); + assert(pbuf_payload_capacity); + assert(pbuf_payload_memory); + + pool->pbuf_memory = (pbuf_t*)pbuf_memory; + pool->pbuf_count = pbuf_count; + + pool->payload_capacity = pbuf_payload_capacity; + pool->payload_memory = (uint8_t*)pbuf_payload_memory; + + pool->free_callback = NULL; + + pbuf_pool_reset(pool); +} + + + +void pbuf_pool_reset(pbuf_pool_t *pool) +{ + assert(pool); + + //initialize pbuf structures + uint8_t *payload = pool->payload_memory; + + pbuf_t *p = pool->free_list = pool->pbuf_memory; + for(uint32_t i = 0; i < pool->pbuf_count - 1; i++) + { + p->payload_memory = payload; + payload += pool->payload_capacity; + + p->pool = pool; + p->next = p + 1; + + p++; + } + + p->payload_memory = payload; + p->pool = pool; + p->next = 0; + + pool->pbufs_available = pool->pbuf_count; +} + + + +void pbuf_dump_pool(pbuf_pool_t *pool) +{ + debug_printf("\r\nPool %x, %u pbufs available\r\n", pool, pool->pbufs_available); + + pbuf_t *p = pool->free_list; + while(p) + { + debug_printf("\r\n%x", p); + p = p->next; + } + + debug_printf("\r\nEnd of dump\r\n"); +} +