freeRTOS操作系统机器人实现
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

390 lines
13 KiB

3 days ago
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: com.c
: 稿
: Radkil
: 2026327
:
:
:
1. : 2026327
: Radkil
:
******************************************************************************/
#include "com.h"
#include "rd_time.h"
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
static const UT_icd g_mutidev_ptr = {sizeof(void*), NULL, NULL, NULL};
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*****************************************************************************
: rd_ComCreate
:
: cbk_ComDecode _pfDecode
cbk_ComSend _pfSend
int _iSize
void *_pUserData
:
: TComCtrl *
:
:
:
1. : 2026424
: radkil
:
*****************************************************************************/
TComCtrl *rd_ComCreate(cbk_ComCheck _pfCheck, cbk_ComDecode _pfDecode, cbk_ComSend _pfSend, int _iSize, void *_pUserData)
{
TComCtrl *ptComCtrl = RD_CALLOC(1, sizeof(TComCtrl));
if (NULL == ptComCtrl) return NULL;
ptComCtrl->m_iBufferSize = _iSize;
ptComCtrl->m_pUserData = _pUserData;
//Rd_SemInit(&ptComCtrl->m_stComBuf.m_sem_Recv, 0, 0);
Rd_SemInit(&ptComCtrl->m_stComBuf.m_sem_Send, 0, 0);
ptComCtrl->m_stComBuf.m_ptRecv = rd_RingbufferCreate(_iSize);
rd_RingbufferReset(ptComCtrl->m_stComBuf.m_ptRecv);
ptComCtrl->m_stComBuf.m_ptSend = rd_RingbufferCreate(_iSize);
rd_RingbufferReset(ptComCtrl->m_stComBuf.m_ptSend);
ptComCtrl->m_pfSend = _pfSend;
ptComCtrl->m_iDevIndex = -1;
TMutiDev *ptMutiDev = RD_CALLOC(1, sizeof(TMutiDev));
ptMutiDev->m_pfCheck = _pfCheck;
ptMutiDev->m_pfDecode = _pfDecode;
utarray_new(ptComCtrl->m_pMutiDevArray, &g_mutidev_ptr);
utarray_push_back(ptComCtrl->m_pMutiDevArray, &ptMutiDev);
return ptComCtrl;
}
void rd_ComAddDev(TComCtrl *_ptComCtrl, cbk_ComCheck _pfCheck, cbk_ComDecode _pfDecode)
{
TMutiDev *ptMutiDev = RD_CALLOC(1, sizeof(TMutiDev));
ptMutiDev->m_pfCheck = _pfCheck;
ptMutiDev->m_pfDecode = _pfDecode;
utarray_push_back(_ptComCtrl->m_pMutiDevArray, &ptMutiDev);
}
int rd_ComDelete(TComCtrl *_ptComCtrl)
{
if (NULL == _ptComCtrl) return RD_FAILURE;
if (_ptComCtrl->m_pMutiDevArray != NULL)
{
for(int i=0; i < utarray_len(_ptComCtrl->m_pMutiDevArray); i++)
{
TMutiDev **ppDev = (TMutiDev**)utarray_eltptr(_ptComCtrl->m_pMutiDevArray, i);
if (*ppDev != NULL)
{
RD_FREE(*ppDev);
}
}
utarray_free(_ptComCtrl->m_pMutiDevArray);
}
//Rd_SemDestroy(&_ptComCtrl->m_stComBuf.m_sem_Recv);
Rd_SemDestroy(&_ptComCtrl->m_stComBuf.m_sem_Send);
rd_RingbufferDestroy(_ptComCtrl->m_stComBuf.m_ptRecv);
rd_RingbufferDestroy(_ptComCtrl->m_stComBuf.m_ptSend);
RD_FREE(_ptComCtrl);
return RD_SUCCESS;
}
/*****************************************************************************
: rd_ComSend
: rd_ComSendProc同时使用
: TComCtrl *_ptComCtrl
char *_pBuffer
uint32_t _iSize
:
: int
:
:
:
1. : 2026424
: radkil
:
*****************************************************************************/
int rd_ComSend(TComCtrl *_ptComCtrl, char *_pBuffer, uint32_t _iSize)
{
if (NULL == _ptComCtrl || NULL == _ptComCtrl->m_pfSend) return RD_NULL;
return _ptComCtrl->m_pfSend(_pBuffer, _iSize);
}
/*****************************************************************************
: rd_ComSendProc
: rd_ComSend同时使用-
: TComCtrl *_ptComCtrl
:
: void
:
:
:
1. : 2026424
: radkil
:
*****************************************************************************/
void rd_ComSendProc(TComCtrl *_ptComCtrl)
{
if (NULL == _ptComCtrl) return;
char *pcBuffer = RD_CALLOC(1, _ptComCtrl->m_iBufferSize);;
int iRet = 0;
Rd_SemWait(&_ptComCtrl->m_stComBuf.m_sem_Send, __func__, NULL);
iRet = rd_RingbufferGet(_ptComCtrl->m_stComBuf.m_ptSend, pcBuffer, _ptComCtrl->m_iBufferSize);
if (iRet > 0)
{
rd_ComSend(_ptComCtrl, pcBuffer, iRet);
}
RD_FREE(pcBuffer);
}
void rd_ComRecvProc(TComCtrl *_ptComCtrl, const char *_pBuffer, uint32_t _iSize)
{
if (NULL == _ptComCtrl) return;
int iRet = rd_RingbufferPutForce(_ptComCtrl->m_stComBuf.m_ptRecv, _pBuffer, _iSize);
if (iRet > 0)
{
Rd_SemPost(&_ptComCtrl->m_stComBuf.m_sem_Recv, __func__, NULL);
}
}
int rd_ComWrite(TComCtrl *_ptComCtrl, char *_pBuffer, uint32_t _iSize)
{
if (NULL == _ptComCtrl) return RD_INVALUE;
int iRet = rd_RingbufferPutForce(_ptComCtrl->m_stComBuf.m_ptSend, _pBuffer, _iSize);
if (iRet > 0)
{
Rd_SemPost(&_ptComCtrl->m_stComBuf.m_sem_Send, __func__, NULL);
}
return iRet;
}
//static int rd_MutiDevIsconflict(TComCtrl *_ptComCtrl, char *_pBuffer, uint32_t _iSize, int _MyIdx)
//{
// int iArrlen = utarray_len(_ptComCtrl->m_pMutiDevArray);
// for(int i = 0; i < iArrlen; i++)
// {
// TMutiDev **ppMutiDev = (TMutiDev**)utarray_eltptr(_ptComCtrl->m_pMutiDevArray, i);
// TMutiDev *ptMutiDev = *ppMutiDev;
// if (i == _MyIdx) continue;
//
// int result = ptMutiDev->m_pfCheck(_pBuffer, _iSize);
// if (result > 0)
// {
// return i;
// }
// }
// return RD_NULL;
//}
/*****************************************************************************
: rd_ComRead
: buffer实际大小
buffer用于存放一包数据
decode里做逻辑
: TComCtrl *_ptComCtrl
char *_pBuffer
uint32_t _iSize
:
: int 0
:
:
:
1. : 2026424
: radkil
:
*****************************************************************************/
int rd_ComRead(TComCtrl *_ptComCtrl, char *_pBuffer, uint32_t _iSize)
{
if (NULL == _ptComCtrl || NULL == _pBuffer || 0 == _iSize)
{
return RD_INVALUE;
}
uint32_t u32CurrentTime = Rd_GetTime();
Rd_SemWait(&_ptComCtrl->m_stComBuf.m_sem_Recv, __func__, NULL);
char *pPeakData = NULL;
int iPeakLen = rd_RingbufferPeak(_ptComCtrl->m_stComBuf.m_ptRecv, &pPeakData);
if (iPeakLen < 0)
{
return RD_FAILURE;
}
else if (0 == iPeakLen)
{
return 0;
}
int iPackLen = 1;
int iArrlen = utarray_len(_ptComCtrl->m_pMutiDevArray);
if (_ptComCtrl->m_iDevIndex < 0)
{
int bFound = 0; // 标记是否找到
int bDataValid = 0; // 标记数据是否有效(即使不完整,只要有协议认领,就不能丢)
for(int i = 0; i < iArrlen; i++)
{
TMutiDev **ppMutiDev = (TMutiDev**)utarray_eltptr(_ptComCtrl->m_pMutiDevArray, i);
TMutiDev *ptMutiDev = *ppMutiDev;
if (NULL != ptMutiDev->m_pfCheck)
{
iPackLen = ptMutiDev->m_pfCheck(pPeakData, iPeakLen);
}
if (iPackLen > 0 && iPackLen <= iPeakLen)
{
_ptComCtrl->m_iDevIndex = i;
bFound = 1;
bDataValid = 1;
break; // 找到了就退出循环,去下面处理
}
else if(0 == iPackLen)
{
if (ptMutiDev->m_uiLastRecvTime == 0)
{
ptMutiDev->m_uiLastRecvTime = u32CurrentTime;
}
if ((u32CurrentTime - ptMutiDev->m_uiLastRecvTime) > RECV_TIMEOUT)
{
char temp[1];
rd_RingbufferGet(_ptComCtrl->m_stComBuf.m_ptRecv, temp, 1); // 丢弃旧数据
// 重置该设备的时间戳,准备迎接下一次可能的通信
ptMutiDev->m_uiLastRecvTime = 0;
bDataValid = 0;
}
else
{
bDataValid = 1;
}
}
}
// 如果遍历完所有设备都没找到包头
if (!bFound)
{
// 只有当所有协议都觉得这个字节没用 (bDataValid == 0) 时,才丢弃
if (!bDataValid)
{
char temp[1];
rd_RingbufferGet(_ptComCtrl->m_stComBuf.m_ptRecv, temp, 1); // 丢弃无效字节
return RD_FAILURE;
}
else
{
// 有协议认领了数据(返回了0),只是还没收完
// 此时直接返回 0,让主循环稍后重试
return 0;
}
}
}
if (_ptComCtrl->m_iDevIndex >= 0)
{
if (_ptComCtrl->m_iDevIndex >= iArrlen)
{
_ptComCtrl->m_iDevIndex = -1;
return RD_FAILURE;
}
TMutiDev **ppMutiDev = (TMutiDev**)utarray_eltptr(_ptComCtrl->m_pMutiDevArray, _ptComCtrl->m_iDevIndex);
TMutiDev *ptMutiDev = *ppMutiDev;
if (NULL != ptMutiDev->m_pfCheck)
{
iPackLen = ptMutiDev->m_pfCheck(pPeakData, iPeakLen);
}
// if (rd_MutiDevIsconflict(_ptComCtrl, pPeakData, iPeakLen, _ptComCtrl->m_iDevIndex) >= 0)
// {
// _ptComCtrl->m_iDevIndex = -1;
// char temp[1];
// rd_RingbufferGet(_ptComCtrl->m_stComBuf.m_ptRecv, temp, 1);
// return RD_FAILURE;
// }
if (iPackLen > 0 && iPackLen <= iPeakLen)
{
int iLen = (_iSize > iPackLen) ? iPackLen : _iSize;
int iRet = rd_RingbufferGet(_ptComCtrl->m_stComBuf.m_ptRecv, _pBuffer, iLen);
if (iRet > 0)
{
_ptComCtrl->m_iDevIndex = -1;
if(NULL != ptMutiDev->m_pfDecode)
{
ptMutiDev->m_uiLastRecvTime = 0;
ptMutiDev->m_pfDecode(_pBuffer, iLen);
}
return iRet;
}
else
{
_ptComCtrl->m_iDevIndex = -1;
return RD_FAILURE;
}
}
else
{
// 长度错误或异常
char temp[1];
rd_RingbufferGet(_ptComCtrl->m_stComBuf.m_ptRecv, temp, 1);
_ptComCtrl->m_iDevIndex = -1;
return RD_FAILURE;
}
}
return 0;
}