mirror of
https://github.com/drasko/open-ameba.git
synced 2024-12-28 09:05:18 +00:00
574 lines
17 KiB
C
574 lines
17 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
|
|
|
|
#define _MAILBOX_C_
|
|
|
|
#include "mailbox.h"
|
|
|
|
/******************************************************************************
|
|
* Function Prototype Declaration
|
|
******************************************************************************/
|
|
static PRTL_MAILBOX RtlMBoxIdToHdl(
|
|
IN u8 MBoxId
|
|
);
|
|
|
|
PRTL_MAILBOX RtlMailboxCreate(
|
|
IN u8 MboxID,
|
|
IN u32 MboxSize,
|
|
IN _Sema *pWakeSema
|
|
);
|
|
|
|
VOID RtlMailboxDel(
|
|
IN PRTL_MAILBOX MboxHdl
|
|
);
|
|
|
|
u8 RtlMailboxSendToBack(
|
|
IN u8 MboxID,
|
|
IN MSG_BLK *pMsg,
|
|
IN u32 MSToWait,
|
|
IN u8 IsFromISR
|
|
);
|
|
|
|
u8 RtlMailboxSendToFront(
|
|
IN u8 MboxID,
|
|
IN MSG_BLK *pMsg,
|
|
IN u32 MSToWait,
|
|
IN u8 IsFromISR
|
|
);
|
|
|
|
u8 RtlMailboxReceive(
|
|
IN u8 MboxID,
|
|
OUT MSG_BLK *pMsg,
|
|
IN u32 MSToWait,
|
|
IN u8 IsFromISR
|
|
);
|
|
|
|
u8 RtlMailboxPeek(
|
|
IN u8 MboxID,
|
|
OUT MSG_BLK *pMsg,
|
|
IN u32 MSToWait,
|
|
IN u8 IsFromISR
|
|
);
|
|
|
|
u32 RtlMailboxMsgWaiting(
|
|
IN u8 MboxID,
|
|
IN u8 IsFromISR
|
|
);
|
|
|
|
/******************************************************************************
|
|
* Global Variable Declaration
|
|
******************************************************************************/
|
|
static RTL_MBOX_ROOT MBox_Entry;
|
|
|
|
/******************************************************************************
|
|
* External Function & Variable Declaration
|
|
******************************************************************************/
|
|
|
|
|
|
/******************************************************************************
|
|
* Function: RtlMBoxIdToHdl
|
|
* Desc: Map a mailbox ID to the mailbox pointer.
|
|
* Para:
|
|
* MBoxId: The Mailbox ID
|
|
* Return: The pointer of the mailbox. If didn't found match mailbox,
|
|
* return NULL.
|
|
*
|
|
******************************************************************************/
|
|
static PRTL_MAILBOX RtlMBoxIdToHdl(
|
|
IN u8 MBoxId
|
|
)
|
|
{
|
|
RTL_MAILBOX *pMbox=NULL;
|
|
RTL_MAILBOX *pTmpMbox;
|
|
_LIST *pHead;
|
|
_LIST *pList;
|
|
|
|
// if the Mailbox root entry initialed ? if not, initial it
|
|
if (!MBox_Entry.isInitialed) {
|
|
RtlMutexInit(&MBox_Entry.Mutex); // Init the Mutex for the mailbox add/delete procedure protection
|
|
RtlInitListhead(&MBox_Entry.mbox_list); // Init the link list head to chain all created mailbox
|
|
MBox_Entry.isInitialed = 1;
|
|
MSG_MBOX_INFO("MBox Entry Initial...\n");
|
|
}
|
|
|
|
pHead = &MBox_Entry.mbox_list;
|
|
RtlDownMutex(&MBox_Entry.Mutex);
|
|
pList = RtlListGetNext(&MBox_Entry.mbox_list);
|
|
while (pList != pHead) {
|
|
pTmpMbox = CONTAINER_OF(pList, RTL_MAILBOX, mbox_list);
|
|
if (MBoxId == pTmpMbox->mbox_id) {
|
|
pMbox = pTmpMbox;
|
|
break;
|
|
}
|
|
pList = RtlListGetNext(pList);
|
|
}
|
|
RtlUpMutex(&MBox_Entry.Mutex);
|
|
|
|
return pMbox;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: RtlMailboxCreate
|
|
* Desc: To create a mailbox with a given mailbox ID and size
|
|
* Para:
|
|
* MboxID: A number to identify this created mailbox. A message block can
|
|
* be send to a mailbox by a given MboxID. The MboxID must be unique
|
|
* in the whole system. If this MboxID is conflict with a created
|
|
* mailbox, the mailbox creation will fail and return NULL.
|
|
* MboxSize: The size of this mailbox to be created. It means maximum number
|
|
* of message blocks can be stored in this mailbox.
|
|
* pWakeSema: The semaphore to wake up the receiving task to receive the new
|
|
* message. If the receiving task doesn't need a semaphore to wakeup
|
|
* it, then just let this pointer is NULL.
|
|
* Return: The created mailbox pointer. If it failed, return NULL.
|
|
******************************************************************************/
|
|
PRTL_MAILBOX RtlMailboxCreate(
|
|
IN u8 MboxID,
|
|
IN u32 MboxSize,
|
|
IN _Sema *pWakeSema
|
|
)
|
|
{
|
|
PRTL_MAILBOX pMBox=NULL;
|
|
|
|
// if the Mailbox root entry initialed ? if not, initial it
|
|
if (!MBox_Entry.isInitialed) {
|
|
RtlMutexInit(&MBox_Entry.Mutex); // Init the Mutex for the mailbox add/delete procedure protection
|
|
RtlInitListhead(&MBox_Entry.mbox_list); // Init the link list head to chain all created mailbox
|
|
MBox_Entry.isInitialed = 1;
|
|
MSG_MBOX_INFO("MBox Entry Initial...\n");
|
|
}
|
|
|
|
// check if this mailbox ID is ocupied ?
|
|
pMBox = RtlMBoxIdToHdl(MboxID);
|
|
if (NULL != pMBox) {
|
|
MSG_MBOX_ERR("RtlMailboxCreate: The Mailbox ID %d is used by someone!!\n", MboxID);
|
|
return NULL;
|
|
}
|
|
|
|
pMBox = (RTL_MAILBOX *)RtlZmalloc(sizeof(RTL_MAILBOX));
|
|
if (NULL==pMBox) {
|
|
MSG_MBOX_ERR("RtlMailboxCreate: MAlloc Failed\n");
|
|
return NULL;
|
|
}
|
|
|
|
RtlInitListhead(&pMBox->mbox_list); // Init the link list to be chained into the created mailbox list
|
|
pMBox->mbox_id = MboxID;
|
|
pMBox->pWakeSema = pWakeSema;
|
|
#ifdef PLATFORM_FREERTOS
|
|
pMBox->mbox_hdl = xQueueCreate(MboxSize, sizeof(MSG_BLK));
|
|
if (NULL == pMBox->mbox_hdl) {
|
|
MSG_MBOX_ERR("RtlMailboxCreate: xQueueCreate Failed\n");
|
|
RtlMfree((void *)pMBox, sizeof(RTL_MAILBOX));
|
|
return NULL;
|
|
}
|
|
#endif
|
|
#ifdef PLATFORM_ECOS
|
|
// TODO: Create mailbox
|
|
#endif
|
|
|
|
// Add this mailbox to the link list of created mailbox
|
|
RtlDownMutex(&MBox_Entry.Mutex);
|
|
RtlListInsertTail(&pMBox->mbox_list, &MBox_Entry.mbox_list);
|
|
RtlUpMutex(&MBox_Entry.Mutex);
|
|
|
|
MSG_MBOX_INFO("A Mailbox Created: Size=%d\n", MboxSize);
|
|
|
|
return pMBox;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: RtlMailboxDel
|
|
* Desc: To delete a mailbox by a given mailbox handle.
|
|
* Para:
|
|
* MboxHdl: The handle of the mailbox to be deleted.
|
|
* Return: None.
|
|
******************************************************************************/
|
|
VOID RtlMailboxDel(
|
|
IN PRTL_MAILBOX MboxHdl
|
|
)
|
|
{
|
|
if (NULL == MboxHdl) {
|
|
MSG_MBOX_ERR("RtlMailboxDel: Try to delete a NULL mailbox\n");
|
|
return;
|
|
}
|
|
|
|
// Remove this mailbox from the link list of created mailbox
|
|
RtlDownMutex(&MBox_Entry.Mutex);
|
|
RtlListDelete(&MboxHdl->mbox_list);
|
|
RtlUpMutex(&MBox_Entry.Mutex);
|
|
|
|
// delete the Queue/Mailbox
|
|
#ifdef PLATFORM_FREERTOS
|
|
vQueueDelete((xQueueHandle)(MboxHdl->mbox_hdl));
|
|
#endif
|
|
#ifdef PLATFORM_ECOS
|
|
// TODO: Delete mailbox
|
|
#endif
|
|
|
|
RtlMfree((void *)MboxHdl, sizeof(RTL_MAILBOX));
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: RtlMailboxSendToBack
|
|
* Desc: To put a message block to the tail of a given mailbox.
|
|
* Para:
|
|
* MboxID: The identifier of the target mailbox.
|
|
* pMsg: The pointer of the message block to be put into the mailbox.
|
|
* MSToWait: If the mailbox is full, this value gives a time to wait to put
|
|
* this message. The time unit is millisecond.
|
|
* The special values are:
|
|
* 0: no waiting;
|
|
* 0xffffffff: wait without timeout.
|
|
* If the waiting is timeout, the message sending is failed and
|
|
* return _FAIL.
|
|
* IsFromISR: Is this function is called from an ISR ?
|
|
* Return: _SUCCESS or _FAIL.
|
|
******************************************************************************/
|
|
u8 RtlMailboxSendToBack(
|
|
IN u8 MboxID,
|
|
IN MSG_BLK *pMsg,
|
|
IN u32 MSToWait,
|
|
IN u8 IsFromISR
|
|
)
|
|
{
|
|
RTL_MAILBOX *pMbox=NULL;
|
|
u32 wait_ticks;
|
|
#ifdef PLATFORM_FREERTOS
|
|
portBASE_TYPE ret;
|
|
#endif
|
|
|
|
pMbox = RtlMBoxIdToHdl(MboxID);
|
|
|
|
if (NULL == pMbox) {
|
|
MSG_MBOX_ERR("RtlMailboxSendToBack: Didn't find matched MBoxID=%d\n", MboxID);
|
|
return _FAIL;
|
|
}
|
|
|
|
#ifdef PLATFORM_FREERTOS
|
|
if (MBOX_WAIT_NO_TIMEOUT == MSToWait) {
|
|
wait_ticks = portMAX_DELAY;
|
|
}
|
|
else if (MBOX_WAIT_NONE == MSToWait) {
|
|
wait_ticks = 0;
|
|
}
|
|
else {
|
|
wait_ticks = ((MSToWait/portTICK_RATE_MS)>0)?(MSToWait/portTICK_RATE_MS):(1);
|
|
}
|
|
|
|
if (IsFromISR) {
|
|
ret = xQueueSendToBackFromISR(pMbox->mbox_hdl, (void *)pMsg, NULL);//(portTickType) wait_ticks);
|
|
}
|
|
else {
|
|
ret = xQueueSendToBack(pMbox->mbox_hdl, (void *)pMsg, (portTickType) wait_ticks);
|
|
}
|
|
|
|
if(ret != pdPASS ) {
|
|
// send message to the queue failed
|
|
MSG_MBOX_ERR("RtlMailboxSendToBack: Put Msg to Queue Failed, MBoxID=%d\n", MboxID);
|
|
ret = _FAIL;
|
|
}
|
|
else {
|
|
// try to give a semaphore to wake up the receiving task
|
|
if (pMbox->pWakeSema) {
|
|
RtlUpSema(pMbox->pWakeSema);
|
|
}
|
|
ret = _SUCCESS;
|
|
}
|
|
|
|
return ret;
|
|
#endif
|
|
|
|
#ifdef PLATFORM_ECOS
|
|
// TODO: Put the message to a mailbox
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* Function: RtlMailboxSendToFront
|
|
* Desc: To put a message block to the head of a mailbox.
|
|
* Para:
|
|
* MboxID: The identifier of the target mailbox.
|
|
* pMsg: The pointer of the message block to be put into the mailbox.
|
|
* MSToWait: If the mailbox is full, this value gives a time to wait to put
|
|
* this message. The time unit is millisecond.
|
|
* The special values are:
|
|
* 0: no waiting;
|
|
* 0xffffffff: wait without timeout.
|
|
* If the waiting is timeout, the message sending is failed and
|
|
* return _FAIL.
|
|
* IsFromISR: Is this function is called from an ISR ?
|
|
* Return: _SUCCESS or _FAIL.
|
|
******************************************************************************/
|
|
u8 RtlMailboxSendToFront(
|
|
IN u8 MboxID,
|
|
IN MSG_BLK *pMsg,
|
|
IN u32 MSToWait,
|
|
IN u8 IsFromISR
|
|
)
|
|
{
|
|
RTL_MAILBOX *pMbox=NULL;
|
|
u32 wait_ticks;
|
|
#ifdef PLATFORM_FREERTOS
|
|
portBASE_TYPE ret;
|
|
#endif
|
|
|
|
pMbox = RtlMBoxIdToHdl(MboxID);
|
|
|
|
if (NULL == pMbox) {
|
|
MSG_MBOX_ERR("RtlMailboxSendToBack: Didn't find matched MBoxID=%d\n", MboxID);
|
|
return _FAIL;
|
|
}
|
|
|
|
#ifdef PLATFORM_FREERTOS
|
|
if (MBOX_WAIT_NO_TIMEOUT == MSToWait) {
|
|
wait_ticks = portMAX_DELAY;
|
|
}
|
|
else if (MBOX_WAIT_NONE == MSToWait) {
|
|
wait_ticks = 0;
|
|
}
|
|
else {
|
|
wait_ticks = ((MSToWait/portTICK_RATE_MS)>0)?(MSToWait/portTICK_RATE_MS):(1);
|
|
}
|
|
|
|
if (IsFromISR) {
|
|
ret = xQueueSendToFrontFromISR(pMbox->mbox_hdl, (void *)pMsg, NULL);//(portTickType) wait_ticks);
|
|
}
|
|
else {
|
|
ret = xQueueSendToFront(pMbox->mbox_hdl, (void *)pMsg, (portTickType) wait_ticks);
|
|
}
|
|
|
|
if(ret != pdPASS ) {
|
|
// send message to the queue failed
|
|
MSG_MBOX_ERR("RtlMailboxSendToBack: Put Msg to Queue Failed, MBoxID=%d\n", MboxID);
|
|
ret = _FAIL;
|
|
}
|
|
else {
|
|
// try to give a semaphore to wake up the receiving task
|
|
if (pMbox->pWakeSema) {
|
|
RtlUpSema(pMbox->pWakeSema);
|
|
}
|
|
ret = _SUCCESS;
|
|
}
|
|
|
|
return ret;
|
|
#endif
|
|
|
|
#ifdef PLATFORM_ECOS
|
|
// TODO: eCos has no API to put message to the head of a mailbox
|
|
#endif
|
|
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: RtlMailboxSendToFront
|
|
* Desc: To get a message block from a given mailbox.
|
|
* Para:
|
|
* MboxID: The identifier of the target mailbox.
|
|
* pMsg: The message block to store the gotten message.
|
|
* MSToWait: If the mailbox is full, this value gives a time to wait to put
|
|
* this message. The time unit is millisecond.
|
|
* The special values are:
|
|
* 0: no waiting;
|
|
* 0xffffffff: wait without timeout.
|
|
* If the waiting is timeout, the message sending is failed and
|
|
* return _FAIL.
|
|
* IsFromISR: Is this function is called from an ISR ?
|
|
* Return: _SUCCESS or _FAIL.
|
|
******************************************************************************/
|
|
u8 RtlMailboxReceive(
|
|
IN u8 MboxID,
|
|
OUT MSG_BLK *pMsg,
|
|
IN u32 MSToWait,
|
|
IN u8 IsFromISR
|
|
)
|
|
{
|
|
RTL_MAILBOX *pMbox=NULL;
|
|
u32 wait_ticks;
|
|
#ifdef PLATFORM_FREERTOS
|
|
portBASE_TYPE ret;
|
|
#endif
|
|
|
|
pMbox = RtlMBoxIdToHdl(MboxID);
|
|
|
|
if (NULL == pMbox) {
|
|
MSG_MBOX_ERR("RtlMailboxReceive: Didn't find the MBox with ID=%d\n", MboxID);
|
|
return _FAIL;
|
|
}
|
|
|
|
#ifdef PLATFORM_FREERTOS
|
|
if (MBOX_WAIT_NONE == MSToWait) {
|
|
wait_ticks = 0;
|
|
}
|
|
else if (MBOX_WAIT_NO_TIMEOUT == MSToWait) {
|
|
wait_ticks = portMAX_DELAY;
|
|
}
|
|
else {
|
|
wait_ticks = ((MSToWait/portTICK_RATE_MS)>0)?(MSToWait/portTICK_RATE_MS):(1);
|
|
}
|
|
|
|
if (IsFromISR) {
|
|
ret = xQueueReceiveFromISR(pMbox->mbox_hdl, (void *)pMsg, NULL);//( portTickType ) wait_ticks);
|
|
}
|
|
else {
|
|
ret = xQueueReceive(pMbox->mbox_hdl, (void *)pMsg, ( portTickType ) wait_ticks);
|
|
|
|
}
|
|
|
|
if(ret != pdTRUE ) {
|
|
// receive message failed
|
|
if (0 != MSToWait) {
|
|
MSG_MBOX_ERR("RtlMailboxReceive: Receive Msg Failed, MBoxID=%d\n", MboxID);
|
|
}
|
|
ret = _FAIL;
|
|
}
|
|
else {
|
|
ret = _SUCCESS;
|
|
}
|
|
|
|
return ret;
|
|
#endif
|
|
|
|
#ifdef PLATFORM_ECOS
|
|
// TODO: Get a message from the mailbox
|
|
#endif
|
|
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: RtlMailboxPeek
|
|
* Desc: To copy the head message from a given mailbox without move this
|
|
* message block out from the mailbox.
|
|
* Para:
|
|
* MboxID: The identifier of the target mailbox.
|
|
* pMsg: The message block to store the gotten message.
|
|
* MSToWait: If the mailbox is full, this value gives a time to wait to put
|
|
* this message. The time unit is millisecond.
|
|
* The special values are:
|
|
* 0: no waiting;
|
|
* 0xffffffff: wait without timeout.
|
|
* If the waiting is timeout, the message sending is failed and
|
|
* return _FAIL.
|
|
* IsFromISR: Is this function is called from an ISR ?
|
|
* Return: _SUCCESS or _FAIL.
|
|
******************************************************************************/
|
|
u8 RtlMailboxPeek(
|
|
IN u8 MboxID,
|
|
OUT MSG_BLK *pMsg,
|
|
IN u32 MSToWait,
|
|
IN u8 IsFromISR
|
|
)
|
|
{
|
|
RTL_MAILBOX *pMbox=NULL;
|
|
u32 wait_ticks;
|
|
#ifdef PLATFORM_FREERTOS
|
|
portBASE_TYPE ret;
|
|
#endif
|
|
|
|
pMbox = RtlMBoxIdToHdl(MboxID);
|
|
|
|
if (NULL == pMbox) {
|
|
MSG_MBOX_ERR("RtlMailboxPeek: Didn't find the MBox with ID=%d\n", MboxID);
|
|
return _FAIL;
|
|
}
|
|
|
|
#ifdef PLATFORM_FREERTOS
|
|
if (MBOX_WAIT_NONE == MSToWait) {
|
|
wait_ticks = 0;
|
|
}
|
|
else if (MBOX_WAIT_NO_TIMEOUT == MSToWait) {
|
|
wait_ticks = portMAX_DELAY;
|
|
}
|
|
else {
|
|
wait_ticks = ((MSToWait/portTICK_RATE_MS)>0)?(MSToWait/portTICK_RATE_MS):(1);
|
|
}
|
|
|
|
if (IsFromISR) {
|
|
// ret = xQueuePeekFromISR(pMbox->mbox_hdl, (void *)pMsg, ( portTickType ) wait_ticks);
|
|
// TODO: check why we have no "xQueuePeekFromISR"
|
|
MSG_MBOX_ERR("RtlMailboxPeek: Current version has no 'xQueuePeekFromISR'\n");
|
|
ret = pdFALSE;
|
|
}
|
|
else {
|
|
ret = xQueuePeek(pMbox->mbox_hdl, (void *)pMsg, ( portTickType ) wait_ticks);
|
|
|
|
}
|
|
|
|
if(ret != pdTRUE ) {
|
|
// receive message failed
|
|
MSG_MBOX_ERR("RtlMailboxReceive: Receive Msg Failed, MBoxID=%d\n", MboxID);
|
|
ret = _FAIL;
|
|
}
|
|
else {
|
|
ret = _SUCCESS;
|
|
}
|
|
|
|
return ret;
|
|
#endif
|
|
|
|
#ifdef PLATFORM_ECOS
|
|
// TODO: Get a message from the mailbox
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* Function: RtlMailboxMsgWaiting
|
|
* Desc: To get the number of message blocks are storing in a given mailbox.
|
|
* Para:
|
|
* MboxID: The identifier of the target mailbox.
|
|
* IsFromISR: Is this function is called from an ISR ?
|
|
* Return: The number of message blocks are storing in this mailbox.
|
|
******************************************************************************/
|
|
u32 RtlMailboxMsgWaiting(
|
|
IN u8 MboxID,
|
|
IN u8 IsFromISR
|
|
)
|
|
{
|
|
RTL_MAILBOX *pMbox=NULL;
|
|
u32 msg_num=0;
|
|
|
|
pMbox = RtlMBoxIdToHdl(MboxID);
|
|
|
|
if (NULL == pMbox) {
|
|
MSG_MBOX_ERR("RtlMailboxMsgWaiting: Didn't find the MBox with ID=%d\n", MboxID);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef PLATFORM_FREERTOS
|
|
if (IsFromISR) {
|
|
msg_num = uxQueueMessagesWaitingFromISR(pMbox->mbox_hdl);
|
|
}
|
|
else {
|
|
msg_num = uxQueueMessagesWaiting(pMbox->mbox_hdl);
|
|
}
|
|
#endif
|
|
|
|
#ifdef PLATFORM_ECOS
|
|
// TODO: call eCos API to implement this function
|
|
#endif
|
|
|
|
return msg_num;
|
|
|
|
}
|
|
|