an old afLib which supports both SPI and UART
af_queue.cpp
- Committer:
- Rhyme
- Date:
- 2018-03-20
- Revision:
- 0:6f371c791202
File content as of revision 0:6f371c791202:
/*
* af_queue.c
*
* Created on: Apr 27, 2015
* Author: chrisatkiban
*/
#include <stddef.h>
#include <stdbool.h>
#include "af_queue.h"
static Stream *_theLog = NULL;
static uint8_t (*m_p_preemption_disable)(void);
static void (*m_p_preemption_enable)(uint8_t is_nested);
static void __af_queue_put(queue_t *p_q, af_queue_elem_desc_t *p_desc)
{
if (p_q->p_head == NULL) {
p_q->p_tail = p_q->p_head = p_desc;
} else {
p_q->p_tail->p_next_alloc = p_desc;
p_q->p_tail = p_desc;
}
}
static void _af_queue_put(queue_t *p_q, af_queue_elem_desc_t *p_desc, bool interrupt_context)
{
if (!interrupt_context) {
uint8_t is_nested;
is_nested = m_p_preemption_disable();
{
__af_queue_put( p_q, p_desc );
}
m_p_preemption_enable(is_nested);
} else {
__af_queue_put( p_q, p_desc );
}
}
static af_queue_elem_desc_t *__af_queue_elem_alloc(queue_t *p_q)
{
af_queue_elem_desc_t *p_desc = NULL;
if (p_q->p_free_head != NULL) {
p_desc = p_q->p_free_head;
p_q->p_free_head = p_desc->p_next_free;
p_desc->p_next_alloc = NULL;
}
return p_desc;
}
static void *_af_queue_elem_alloc(queue_t *p_q, bool interrupt_context)
{
af_queue_elem_desc_t *p_desc;
if (!interrupt_context) {
uint8_t is_nested;
is_nested = m_p_preemption_disable();
{
p_desc = __af_queue_elem_alloc(p_q);
}
m_p_preemption_enable(is_nested);
} else {
p_desc = __af_queue_elem_alloc(p_q);
}
return p_desc ? p_desc->data : NULL;
}
static af_queue_elem_desc_t *__af_queue_get(queue_t *p_q)
{
af_queue_elem_desc_t *p_desc = p_q->p_head;
if (p_desc != NULL) {
p_q->p_head = p_desc->p_next_alloc;
p_desc->p_next_alloc = NULL;
}
if (p_q->p_head == NULL) {
p_q->p_tail = NULL;
}
return p_desc;
}
static void *_af_queue_get(queue_t *p_q, bool interrupt_context)
{
af_queue_elem_desc_t *p_desc;
if (!interrupt_context) {
uint8_t is_nested;
is_nested = m_p_preemption_disable();
{
p_desc = __af_queue_get(p_q);
}
m_p_preemption_enable(is_nested);
} else {
p_desc = __af_queue_get(p_q);
}
return p_desc ? p_desc->data : NULL;
}
static void __af_queue_elem_free(queue_t *p_q, void *p_data)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
af_queue_elem_desc_t *p_desc = (af_queue_elem_desc_t *)((uint8_t *)p_data - __builtin_offsetof(struct af_queue_elem_desc_s, data));
#pragma GCC diagnostic push
af_queue_elem_desc_t *p_tmp_desc;
p_tmp_desc = p_q->p_free_head;
p_q->p_free_head = p_desc;
p_desc->p_next_free = p_tmp_desc;
}
static void _af_queue_elem_free(queue_t *p_q, void *p_data, bool interrupt_context)
{
if (!interrupt_context) {
uint8_t is_nested;
is_nested = m_p_preemption_disable();
{
__af_queue_elem_free(p_q, p_data);
}
m_p_preemption_enable(is_nested);
} else {
__af_queue_elem_free(p_q, p_data);
}
}
static void *_af_queue_peek(queue_t *p_q, bool interrupt_context)
{
return p_q->p_head ? p_q->p_head->data : NULL;
}
static void *_af_queue_peek_tail(queue_t *p_q, bool interrupt_context)
{
return p_q->p_tail ? p_q->p_tail->data : NULL;
}
void af_queue_put(queue_t *p_q, void *p_data)
{
af_queue_elem_desc_t *p_desc = (af_queue_elem_desc_t *)((uint8_t *)p_data - __builtin_offsetof(struct af_queue_elem_desc_s, data));
_af_queue_put(p_q, p_desc, false);
}
void af_queue_put_from_interrupt(queue_t *p_q, void *p_data)
{
af_queue_elem_desc_t *p_desc = (af_queue_elem_desc_t *)((uint8_t *)p_data - __builtin_offsetof(struct af_queue_elem_desc_s, data));
_af_queue_put(p_q, p_desc, true);
}
void *af_queue_elem_alloc(queue_t *p_q)
{
return _af_queue_elem_alloc(p_q, false);
}
void *af_queue_elem_alloc_from_interrupt(queue_t *p_q)
{
return _af_queue_elem_alloc(p_q, true);
}
void *af_queue_get(queue_t *p_q)
{
return _af_queue_get(p_q, false);
}
void *af_queue_get_from_interrupt(queue_t *p_q)
{
return _af_queue_get(p_q, true);
}
void *af_queue_peek(queue_t *p_q)
{
return _af_queue_peek(p_q, false);
}
void *af_queue_peek_from_interrupt(queue_t *p_q)
{
return _af_queue_peek(p_q, true);
}
void *af_queue_peek_tail(queue_t *p_q)
{
return _af_queue_peek_tail(p_q, false);
}
void *af_queue_peek_tail_from_interrupt(queue_t *p_q)
{
return _af_queue_peek_tail(p_q, true);
}
void af_queue_elem_free(queue_t *p_q, void *p_data)
{
_af_queue_elem_free(p_q, p_data, false);
}
void af_queue_elem_free_from_interrupt(queue_t *p_q, void *p_data)
{
_af_queue_elem_free(p_q, p_data, true);
}
void af_queue_init(queue_t *p_q, int elem_size, int max_elem, uint8_t *p_mem)
{
af_queue_elem_desc_t *p_desc;
af_queue_elem_desc_t *p_desc_next;
int offset;
int i = 0;
p_q->p_head = NULL;
p_q->p_tail = NULL;
// string all elements together and onto the null-terminated free list to start
p_q->p_free_head = (af_queue_elem_desc_t *)p_mem;
for (i = 0; i < max_elem - 1; ++i) {
offset = i * (ALIGN_SIZE(sizeof(af_queue_elem_desc_t), 4) + ALIGN_SIZE(elem_size, 4));
p_desc = (af_queue_elem_desc_t *)(p_mem + offset);
offset = (i + 1) * (ALIGN_SIZE(sizeof(af_queue_elem_desc_t), 4) + ALIGN_SIZE(elem_size, 4));
p_desc_next = (af_queue_elem_desc_t *)(p_mem + offset);
p_desc->p_next_free = p_desc_next;
}
offset = (max_elem - 1) * (ALIGN_SIZE(sizeof(af_queue_elem_desc_t), 4) + ALIGN_SIZE(elem_size, 4));
p_desc = (af_queue_elem_desc_t *)(p_mem + offset);
p_desc->p_next_free = NULL;
}
void af_queue_init_system(uint8_t (*p_preemption_disable)(void), void (*p_preemption_enable)(uint8_t is_nested), Stream *theLog)
{
m_p_preemption_disable = p_preemption_disable;
m_p_preemption_enable = p_preemption_enable;
_theLog = theLog;
}
void af_queue_dump(queue_t *p_q)
{
af_queue_elem_desc_t *p_elem;
if (_theLog != NULL) {
_theLog->printf("Q %X", (int)p_q);
_theLog->printf(" free_head %X", (int)p_q->p_free_head);
_theLog->printf(" head %X", (int)p_q->p_head);
_theLog->printf(" tail %X", (int)p_q->p_tail);
_theLog->printf("In Queue: \n"); // Not all allocated are in queue (until af_queue_put)
p_elem = p_q->p_head;
while (p_elem) {
_theLog->printf("%X\n", (int) p_elem);
p_elem = p_elem->p_next_alloc;
}
_theLog->printf("Free:\n");
p_elem = p_q->p_free_head;
while (p_elem) {
_theLog->printf("%X\n", (int) p_elem);
p_elem = p_elem->p_next_free;
}
}
}