383 lines
7.8 KiB
C
383 lines
7.8 KiB
C
/***************************************************************************
|
|
*
|
|
* Copyright 2015-2019 BES.
|
|
* All rights reserved. All unpublished rights reserved.
|
|
*
|
|
* No part of this work may be used or reproduced in any form or by any
|
|
* means, or stored in a database or retrieval system, without prior written
|
|
* permission of BES.
|
|
*
|
|
* Use of this work is governed by a license granted by BES.
|
|
* This work contains confidential and proprietary information of
|
|
* BES. which is protected by copyright, trade secret,
|
|
* trademark and other intellectual property rights.
|
|
*
|
|
****************************************************************************/
|
|
/***
|
|
* cqueue.c - c circle queue c file
|
|
*/
|
|
|
|
#include "cqueue.h"
|
|
#include "cmsis.h"
|
|
#include "hal_uart.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
//#define DEBUG_CQUEUE 1
|
|
|
|
CQ_FUNC_ATTR
|
|
int InitCQueue(CQueue *Q, unsigned int size, CQItemType *buf) {
|
|
Q->size = size;
|
|
Q->base = buf;
|
|
Q->len = 0;
|
|
if (!Q->base)
|
|
return CQ_ERR;
|
|
|
|
Q->read = Q->write = 0;
|
|
return CQ_OK;
|
|
}
|
|
|
|
CQ_FUNC_ATTR
|
|
int IsEmptyCQueue(CQueue *Q) {
|
|
if (Q->len == 0)
|
|
return CQ_OK;
|
|
else
|
|
return CQ_ERR;
|
|
}
|
|
|
|
CQ_FUNC_ATTR
|
|
int LengthOfCQueue(CQueue *Q) { return Q->len; }
|
|
|
|
CQ_FUNC_ATTR
|
|
int AvailableOfCQueue(CQueue *Q) { return (Q->size - Q->len); }
|
|
|
|
#if 1
|
|
CQ_FUNC_ATTR
|
|
int EnCQueue(CQueue *Q, CQItemType *e, unsigned int len) {
|
|
if (AvailableOfCQueue(Q) < len) {
|
|
return CQ_ERR;
|
|
}
|
|
|
|
Q->len += len;
|
|
|
|
uint32_t bytesToTheEnd = Q->size - Q->write;
|
|
if (bytesToTheEnd > len) {
|
|
memcpy((uint8_t *)&Q->base[Q->write], (uint8_t *)e, len);
|
|
Q->write += len;
|
|
} else {
|
|
memcpy((uint8_t *)&Q->base[Q->write], (uint8_t *)e, bytesToTheEnd);
|
|
memcpy((uint8_t *)&Q->base[0], (((uint8_t *)e) + bytesToTheEnd),
|
|
len - bytesToTheEnd);
|
|
Q->write = len - bytesToTheEnd;
|
|
}
|
|
|
|
return CQ_OK;
|
|
}
|
|
|
|
int EnCQueue_AI(CQueue *Q, CQItemType *e, unsigned int len) {
|
|
uint32_t bytesToTheEnd = Q->size - Q->write;
|
|
uint32_t readBytesToTheEnd = Q->size - Q->read;
|
|
|
|
if (AvailableOfCQueue(Q) < len) {
|
|
if (readBytesToTheEnd > len) {
|
|
Q->read += len;
|
|
} else {
|
|
Q->read = len - readBytesToTheEnd;
|
|
}
|
|
} else {
|
|
Q->len += len;
|
|
}
|
|
|
|
if (bytesToTheEnd > len) {
|
|
memcpy((uint8_t *)&Q->base[Q->write], (uint8_t *)e, len);
|
|
Q->write += len;
|
|
} else {
|
|
memcpy((uint8_t *)&Q->base[Q->write], (uint8_t *)e, bytesToTheEnd);
|
|
memcpy((uint8_t *)&Q->base[0], (((uint8_t *)e) + bytesToTheEnd),
|
|
len - bytesToTheEnd);
|
|
Q->write = len - bytesToTheEnd;
|
|
}
|
|
|
|
return CQ_OK;
|
|
}
|
|
|
|
#else
|
|
static inline void memcpy_u8(void *dst, void *src, unsigned int len) {
|
|
unsigned int i = 0;
|
|
unsigned int *d8, *s8;
|
|
d8 = dst;
|
|
s8 = src;
|
|
for (i = 0; i < len; i++)
|
|
d8[i] = s8[i];
|
|
}
|
|
|
|
static inline void memcpy_u32(void *dst, void *src, unsigned int len) {
|
|
unsigned int i = 0;
|
|
unsigned int *d32, *s32;
|
|
d32 = dst;
|
|
s32 = src;
|
|
for (i = 0; i < len; i++)
|
|
d32[i] = s32[i];
|
|
}
|
|
|
|
CQ_FUNC_ATTR
|
|
int EnCQueue(CQueue *Q, CQItemType *e, unsigned int len) {
|
|
unsigned char *src = e;
|
|
unsigned char *dst = &(Q->base[Q->write]);
|
|
|
|
unsigned int cnt_u8;
|
|
unsigned int cnt_u32;
|
|
unsigned int cnt_u32_res;
|
|
|
|
unsigned int front_u8;
|
|
unsigned int front_u32;
|
|
unsigned int front_u32_res;
|
|
|
|
unsigned int end_u8;
|
|
unsigned int end_u32;
|
|
unsigned int end_u32_res;
|
|
|
|
bool unaligned_en;
|
|
|
|
if (AvailableOfCQueue(Q) < len) {
|
|
return CQ_ERR;
|
|
}
|
|
|
|
Q->len += len;
|
|
|
|
end_u8 = Q->size - Q->write;
|
|
end_u32 = end_u8 / 4;
|
|
end_u32_res = end_u8 % 4;
|
|
|
|
cnt_u8 = len;
|
|
cnt_u32 = cnt_u8 / 4;
|
|
cnt_u32_res = cnt_u8 % 4;
|
|
|
|
unaligned_en = config_unaligned_access(true);
|
|
|
|
if (cnt_u8 <= end_u8) {
|
|
memcpy_u32(dst, src, cnt_u32);
|
|
|
|
if (cnt_u32_res) {
|
|
src += cnt_u32 * 4;
|
|
dst += cnt_u32 * 4;
|
|
memcpy_u8(dst, src, cnt_u32_res);
|
|
}
|
|
|
|
// Deal with Q->write
|
|
Q->write += cnt_u8;
|
|
|
|
} else {
|
|
front_u8 = len - end_u8;
|
|
front_u32 = front_u8 / 4;
|
|
front_u32_res = front_u8 % 4;
|
|
|
|
// Deal with end data
|
|
memcpy_u32(dst, src, end_u32);
|
|
src += end_u32 * 4;
|
|
dst += end_u32 * 4;
|
|
|
|
memcpy_u8(dst, src, end_u32_res);
|
|
src += end_u32_res;
|
|
dst = &(Q->base[0]);
|
|
|
|
// Deal with front data
|
|
memcpy_u32(dst, src, front_u32);
|
|
|
|
if (front_u32_res) {
|
|
src += front_u32 * 4;
|
|
dst += front_u32 * 4;
|
|
|
|
memcpy_u8(dst, src, front_u32_res);
|
|
}
|
|
|
|
// Deal with Q->write
|
|
Q->write = front_u8;
|
|
}
|
|
|
|
config_unaligned_access(unaligned_en);
|
|
|
|
return CQ_OK;
|
|
}
|
|
|
|
void memcpy_fast(char *dst, char *src, unsigned int len) {
|
|
int size = len / 4;
|
|
int mod = len % 4;
|
|
|
|
int *Dst = (int *)dst;
|
|
int *Src = (int *)src;
|
|
|
|
int dst_offset = (int)Dst - (int)dst;
|
|
int src_offset = (int)Src - (int)src;
|
|
|
|
if (!dst_offset && !src_offset) {
|
|
memcpy_u32(Dst, Src, size);
|
|
if (mod) {
|
|
memcpy_u8(Dst + size, Src + size, mod);
|
|
}
|
|
} else {
|
|
memcpy_u8(dst, src, len);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
CQ_FUNC_ATTR
|
|
int EnCQueueFront(CQueue *Q, CQItemType *e, unsigned int len) {
|
|
if (AvailableOfCQueue(Q) < len) {
|
|
return CQ_ERR;
|
|
}
|
|
|
|
Q->len += len;
|
|
|
|
/* walk to last item , revert write */
|
|
e = e + len - 1;
|
|
|
|
if (Q->read == 0)
|
|
Q->read = Q->size - 1;
|
|
else
|
|
Q->read--;
|
|
|
|
while (len > 0) {
|
|
Q->base[Q->read] = *e;
|
|
|
|
--Q->read;
|
|
--e;
|
|
--len;
|
|
|
|
if (Q->read < 0)
|
|
Q->read = Q->size - 1;
|
|
}
|
|
|
|
/* we walk one more, walk back */
|
|
if (Q->read == Q->size - 1)
|
|
Q->read = 0;
|
|
else
|
|
++Q->read;
|
|
|
|
return CQ_OK;
|
|
}
|
|
|
|
CQ_FUNC_ATTR
|
|
int DeCQueue(CQueue *Q, CQItemType *e, unsigned int len) {
|
|
if (LengthOfCQueue(Q) < len)
|
|
return CQ_ERR;
|
|
|
|
Q->len -= len;
|
|
|
|
if (e != NULL) {
|
|
uint32_t bytesToTheEnd = Q->size - Q->read;
|
|
if (bytesToTheEnd > len) {
|
|
memcpy((uint8_t *)e, (uint8_t *)&Q->base[Q->read], len);
|
|
Q->read += len;
|
|
} else {
|
|
memcpy((uint8_t *)e, (uint8_t *)&Q->base[Q->read], bytesToTheEnd);
|
|
memcpy((((uint8_t *)e) + bytesToTheEnd), (uint8_t *)&Q->base[0],
|
|
len - bytesToTheEnd);
|
|
Q->read = len - bytesToTheEnd;
|
|
}
|
|
} else {
|
|
if (0 < Q->size) {
|
|
Q->read = (Q->read + len) % Q->size;
|
|
} else {
|
|
Q->read = 0;
|
|
}
|
|
}
|
|
|
|
return CQ_OK;
|
|
}
|
|
|
|
CQ_FUNC_ATTR
|
|
int PeekCQueue(CQueue *Q, unsigned int len_want, CQItemType **e1,
|
|
unsigned int *len1, CQItemType **e2, unsigned int *len2) {
|
|
if (LengthOfCQueue(Q) < len_want) {
|
|
return CQ_ERR;
|
|
}
|
|
|
|
*e1 = &(Q->base[Q->read]);
|
|
if ((Q->write > Q->read) || (Q->size - Q->read >= len_want)) {
|
|
*len1 = len_want;
|
|
*e2 = NULL;
|
|
*len2 = 0;
|
|
return CQ_OK;
|
|
} else {
|
|
*len1 = Q->size - Q->read;
|
|
*e2 = &(Q->base[0]);
|
|
*len2 = len_want - *len1;
|
|
return CQ_OK;
|
|
}
|
|
|
|
return CQ_ERR;
|
|
}
|
|
|
|
int PeekCQueueToBuf(CQueue *Q, CQItemType *e, unsigned int len) {
|
|
int status = CQ_OK;
|
|
unsigned char *e1 = NULL, *e2 = NULL;
|
|
unsigned int len1 = 0, len2 = 0;
|
|
|
|
status = PeekCQueue(Q, len, &e1, &len1, &e2, &len2);
|
|
|
|
if (status == CQ_OK) {
|
|
if (len == (len1 + len2)) {
|
|
memcpy(e, e1, len1);
|
|
memcpy(e + len1, e2, len2);
|
|
} else {
|
|
status = CQ_ERR;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
int PullCQueue(CQueue *Q, CQItemType *e, unsigned int len) {
|
|
int status = CQ_OK;
|
|
unsigned char *e1 = NULL, *e2 = NULL;
|
|
unsigned int len1 = 0, len2 = 0;
|
|
|
|
status = PeekCQueue(Q, len, &e1, &len1, &e2, &len2);
|
|
|
|
if (status == CQ_OK) {
|
|
if (len == (len1 + len2)) {
|
|
memcpy(e, e1, len1);
|
|
memcpy(e + len1, e2, len2);
|
|
DeCQueue(Q, 0, len);
|
|
} else {
|
|
status = CQ_ERR;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
#ifdef DEBUG_CQUEUE
|
|
int DumpCQueue(CQueue *Q) {
|
|
CQItemType e;
|
|
int len = 0, i = 0;
|
|
|
|
len = LengthOfCQueue(Q);
|
|
|
|
if (len <= 0)
|
|
return CQ_ERR;
|
|
|
|
i = Q->read;
|
|
while (len > 0) {
|
|
e = Q->base[i];
|
|
|
|
TRACE(stderr, "-0x%x", e);
|
|
TRACE(stderr, "-%c", e);
|
|
|
|
++i;
|
|
--len;
|
|
if (i == Q->size)
|
|
i = 0;
|
|
}
|
|
|
|
return CQ_ERR;
|
|
}
|
|
#endif
|
|
|
|
void ResetCQueue(CQueue *Q) {
|
|
Q->len = 0;
|
|
Q->read = Q->write = 0;
|
|
}
|