MAILBOX函数的使用

上官斌
2023-12-01

TI雷达开发板的Mailbox的使用

DSS端的初始化内容

进入端口: dss_main.c

Task_Params_init(&taskParams);
taskParams.stackSize = 3*1024;
Task_create(MmwDemo_dssInitTask, &taskParams, NULL);
static void MmwDemo_dssInitTask(UArg arg0, UArg arg1)
{
    int32_t             errCode;
    MMWave_InitCfg      initCfg;
    Task_Params         taskParams;
    Semaphore_Params    semParams; // 信号量关于处理资源调度问题,我在我的另一个文章中有讲解
    Mailbox_Config      mboxCfg;//放置着配置mailbox的初始化所有变量,是一个声明的作用
    Error_Block         eb;


    /* Initialize the Mailbox */
    Mailbox_init(MAILBOX_TYPE_DSS);

    /*****************************************************************************
     * Open & configure the drivers:
     *****************************************************************************/
  
    /*****************************************************************************
     * Create mailbox Semaphore:
     *****************************************************************************/
    /* Create a binary semaphore which is used to handle mailbox interrupt. */
    Semaphore_Params_init(&semParams);
    semParams.mode             = Semaphore_Mode_BINARY;
    gMmwDssMCB.mboxSemHandle = Semaphore_create(0, &semParams, NULL);

    /* Setup the default mailbox configuration */
    Mailbox_Config_init(&mboxCfg);

    /* Setup the configuration: */
    mboxCfg.chType       = MAILBOX_CHTYPE_MULTI;
    mboxCfg.chId         = MAILBOX_CH_ID_0;
    mboxCfg.writeMode    = MAILBOX_MODE_BLOCKING;
    mboxCfg.readMode     = MAILBOX_MODE_CALLBACK;
    mboxCfg.readCallback = &MmwDemo_mboxCallback;

    gMmwDssMCB.peerMailbox = Mailbox_open(MAILBOX_TYPE_MSS, &mboxCfg, &errCode);
    if (gMmwDssMCB.peerMailbox == NULL)
    {
        /* Error: Unable to open the mailbox */
        System_printf("Error: Unable to open the Mailbox to the DSS [Error code %d]\n", errCode);
        return;
    }

    /* Debug Message: */
    /*System_printf("Debug: DSS Mailbox Handle %p\n", gMmwDssMCB.peerMailbox);*/

    /* Create task to handle mailbox messges */
    Task_Params_init(&taskParams);
    Task_create(MmwDemo_mboxReadTask, &taskParams, NULL);
    
    /* Initialize LVDS streaming components */
    if ((errCode = MmwDemo_LVDSStreamInit()) < 0 )
    {
        System_printf ("Error: MMWDemoDSS LVDS stream init failed with Error[%d]\n",errCode);
        return;
    }

一、函数初始化函数Mailbox_init(MAILBOX_TYPE_DSS);

int32_t Mailbox_init(Mailbox_Type localEndpoint)
{
    int32_t    retVal = 0;
    int32_t    i;
    uintptr_t  key;

    #ifdef SOC_XWR14XX 
    if (localEndpoint != MAILBOX_TYPE_MSS)
    #else
    if ((localEndpoint != MAILBOX_TYPE_MSS) && (localEndpoint != MAILBOX_TYPE_DSS))
    #endif
    {
        DebugP_log1 ("MAILBOX: Mailbox_init error! Invalid localEndpoint = %d\n",localEndpoint);
        /* Error: Invalid argument or usage */
        retVal = MAILBOX_EINVAL;
    }
    else
    {
        /* Critical Section Protection*/
        key = HwiP_disable();
        if (gMailboxMCB.initFlag == 0) 
		{            
            /* Initialize global variables */
            gMailboxMCB.bssInstCount         = 0;
            gMailboxMCB.mssDssInstCount      = 0;
            /* Set local endpoint which is the same for all instances of the driver in this processor */
            gMailboxMCB.localEndpoint        = localEndpoint;
            gMailboxMCB.mssDssChType         = MAILBOX_CHTYPE_SINGLE;
            gMailboxMCB.lastMsgSentHandle    = NULL;
            gMailboxMCB.mssDssHwCfgPtr       = NULL;    
            gMailboxMCB.mssDssReadChIDInUse  = MAILBOX_UNUSED_CHANNEL_ID;    
            gMailboxMCB.mssDssWriteChIDInUse = MAILBOX_UNUSED_CHANNEL_ID;    
            
            memset ((void *)&(gMailboxMCB.errCnt), 0, sizeof(gMailboxMCB.errCnt));
            memset ((void *)&(gMailboxMCB.hwiHandles), 0, sizeof(gMailboxMCB.hwiHandles));            
            for(i=0; i <= MAILBOX_CH_ID_MAX; i++)
			{
                gMailboxMCB.handleArray[i] = NULL;  
            }				

            gMailboxMCB.initFlag = 1;                
        }
        else
        {
            DebugP_log0 ("MAILBOX: Mailbox_init error! Mailbox Driver has already been initialized\n");
            retVal = MAILBOX_EINITIALIZED;
        }
        /* Release the critical section: */
        HwiP_restore(key);
    }    
    
    return retVal;
}

/*

四、手动配置一些变量

/* Setup the configuration: */
    mboxCfg.chType       = MAILBOX_CHTYPE_MULTI;
    mboxCfg.chId         = MAILBOX_CH_ID_0;
    mboxCfg.writeMode    = MAILBOX_MODE_BLOCKING;
    mboxCfg.readMode     = MAILBOX_MODE_CALLBACK;
    mboxCfg.readCallback = &MmwDemo_mboxCallback;

五、打开mailbox

  gMmwDssMCB.peerMailbox = Mailbox_open(MAILBOX_TYPE_MSS, &mboxCfg, &errCode);
    if (gMmwDssMCB.peerMailbox == NULL)
    {
        /* Error: Unable to open the mailbox */
        System_printf("Error: Unable to open the Mailbox to the DSS [Error code %d]\n", errCode);
        return;
    }//进行一个简单的判断,然后我们就进入open函数


open函数

```c
Mbox_Handle Mailbox_open(Mailbox_Type remoteEndpoint, const Mailbox_Config *cfg,  int32_t* errCode)//从这里我们就可以看出,我们的remoteEndpoint是MAILBOX_TYPE_MSS,也就是说我们的目标地址是MSS
{
    Mailbox_Driver*     mailboxDriver;//这里将会初始化handle和硬件终端和信号量
    Mbox_Handle      retHandle = NULL;
    HwiP_Params         hwiParams;
    SemaphoreP_Params   semParams;
    uintptr_t           key;

    *errCode = 0;

    /* Critical Section Protection*/
    key = HwiP_disable();//停止硬件中断
    
    /* Sanity Check: Validate the arguments */
    #ifdef SOC_XWR14XX 
    if ((gMailboxMCB.initFlag == 0) ||(cfg == NULL) || (remoteEndpoint != MAILBOX_TYPE_BSS))
    #else
    if ((gMailboxMCB.initFlag == 0) ||(cfg == NULL) || (remoteEndpoint == gMailboxMCB.localEndpoint) || (remoteEndpoint > MAILBOX_TYPE_LAST))
    #endif
    {
        DebugP_log0 ("MAILBOX: Mailbox_open error! Mailbox Driver open failed due to bad input argument.\n");
        /* Error: Invalid argument or usage */
        *errCode = MAILBOX_EINVAL;
        goto exit;
    }//以上的代码分别核验了芯片的型号,是否初始化完成,是否没有完成cfg配置,是否是配置的remotpoint有问题,并且报错
    
    if((remoteEndpoint == MAILBOX_TYPE_BSS) && (gMailboxMCB.bssInstCount > 0))
    {
        DebugP_log0 ("MAILBOX: Mailbox_open error! Mailbox Driver open failed. BSS driver instance already open.\n");
        /* Error: Invalid argument or usage */
        *errCode = MAILBOX_EINVAL;
        goto exit;
    }//这里判断其目标地址是否为BSS,这时候应该已经将BSS的初始化完成了
    
    #ifdef SOC_XWR16XX 
    /* If this is MSS<->DSS communication, check if this is a valid open of a new instance
       of the driver. Only MSS<->DSS can have multiple instances of the driver. Because the driver
       can only run on MSS or DSS, we just need to check the remoteEndpoint to see if this is a
       driver instance between MSS<->DSS.*/
       //上面这一段话告诉我们只有MSS和DSS的通信可以有多个通道实例,并且要新开启一个instance
    if(remoteEndpoint != MAILBOX_TYPE_BSS)
    {
        /*Check if the channel type is valid*/
        if(cfg->chType > MAILBOX_CHTYPE_MULTI)
        {
            DebugP_log1 ("MAILBOX: Mailbox_open error! Mailbox Driver open failed with bad Channle type parameter (%d).\n",cfg->chType);
            /* Error: Invalid configuration */
            *errCode = MAILBOX_EBADCHTYPE;
            goto exit;
        }//这一段是如果其实BSS的通信端但是却使用的多通道,那么就报错。
    
        /*Check if channel type is consistent*/
        if(gMailboxMCB.mssDssInstCount == 0)
        {
            /*First mss/dss instance. Set global variable to store channel type that must be used for all mss-dss instances.*/
            gMailboxMCB.mssDssChType = cfg->chType;
        }
        else
        {
            /*Multiple mss-dss instances. Therefore, must use mss-dss multi-channels for all instances.*/
            if((gMailboxMCB.mssDssChType != MAILBOX_CHTYPE_MULTI) || (cfg->chType != MAILBOX_CHTYPE_MULTI))
            {
                DebugP_log1 ("MAILBOX: Mailbox_open error! Mailbox Driver open failed with bad Channle type parameter (%d).\n",cfg->chType);
                DebugP_log0 ("MAILBOX: When using multiple mss-dss instances all channels must be of type MAILBOX_CHTYPE_MULTI.\n");
                /* Error: Invalid configuration */
                *errCode = MAILBOX_EBADCHTYPE;
                goto exit;
            }
        }
        
        /*Check if channel ID is consistent. Note that chId is only used for multi-channel.
          Single-channel does not use header or channel ID.*/
        if(cfg->chType == MAILBOX_CHTYPE_MULTI)
        {
            /*For multi-channel need to check ID value*/
            /*Check if the ID is valid*/
            if(cfg->chId > MAILBOX_CH_ID_MAX)
            {
                DebugP_log1 ("MAILBOX: Mailbox_open error! Mailbox Driver open failed with bad Channle ID parameter (%d).\n",cfg->chId);
                /* Error: Invalid configuration */
                *errCode = MAILBOX_EBADCHID;
                goto exit;
            }
            
            /*Check if the ID is already in use*/        
            if(gMailboxMCB.handleArray[cfg->chId] != NULL)
            {
                DebugP_log1 ("MAILBOX: Mailbox_open error! Mailbox Driver open failed. Channel ID (%d) is already in use.\n",cfg->chId);
                /* Error: Invalid configuration */
                *errCode = MAILBOX_EBADCHID;
                goto exit;
            }
        }    
    }
    #endif    
    
    /* Check if configuration is valid */
    if( (cfg->writeMode        == MAILBOX_MODE_CALLBACK) ||
        (cfg->opMode           != MAILBOX_OPERATION_MODE_PARTIAL_READ_ALLOWED) ||
        (cfg->dataTransferMode != MAILBOX_DATA_TRANSFER_MEMCPY) )
    {
        DebugP_log0 ("MAILBOX: Mailbox_open error! Mailbox Driver open failed with bad configuration.\n");
        /* Error: Invalid configuration */
        *errCode = MAILBOX_EINVALCFG;
        goto exit;
    }

    /* Allocate memory for the Mailbox Driver */
    mailboxDriver = MemoryP_ctrlAlloc ((uint32_t)sizeof(Mailbox_Driver), 0);
    if (mailboxDriver == NULL)
    {
        DebugP_log0 ("MAILBOX: Mailbox_open error! Mailbox Driver memory allocation failed.\n");
        /* Error: No memory available. */
        *errCode = MAILBOX_ENOMEM;
        goto exit;
    }
    
    /* Initialize the allocated memory: */
    memset ((void *)mailboxDriver, 0, sizeof(Mailbox_Driver));

    /* Populate the driver with initial configuration */
    memcpy ((void *)&mailboxDriver->cfg, (const void *)cfg, sizeof(Mailbox_Config));
    
    mailboxDriver->remoteEndpoint = remoteEndpoint;
    mailboxDriver->localEndpoint  = gMailboxMCB.localEndpoint;
    
    /* Setup the return handle: */
    retHandle = (Mbox_Handle)mailboxDriver;

    /* Populate hardware configuration */
    Mailbox_hwCfg(mailboxDriver);

    if((remoteEndpoint == MAILBOX_TYPE_BSS) || (gMailboxMCB.mssDssInstCount == 0))
    {        
        /* Clear status register */
        ((mailboxDriver->hwCfg)->baseLocalToRemote.reg)->INT_STS_CLR = CSL_FINSR (((mailboxDriver->hwCfg)->baseLocalToRemote.reg)->INT_STS_CLR, 0U, 0U, 1U);
    
        /* Register the Interrupt Handler: Every mailbox has 2 interrupts: "mailbox full" and "mailbox empty"*/
        /************** Mailbox full ***********/
        HwiP_Params_init(&hwiParams);
        if(remoteEndpoint == MAILBOX_TYPE_BSS)
        {
            hwiParams.name = "MAILBOX_FULL_BSS";
            hwiParams.arg  = (uintptr_t)retHandle;
            gMailboxMCB.hwiHandles.bssFull = HwiP_create((mailboxDriver->hwCfg)->boxFullIntNum, Mailbox_boxFullISRBss, &hwiParams);
            /* Debug Message: */
            DebugP_log2 ("MAILBOX: Mailbox Driver Registering Mailbox Full to BSS HWI ISR [%p] for Interrupt %d\n",
                          gMailboxMCB.hwiHandles.bssFull, (mailboxDriver->hwCfg)->boxFullIntNum);
        }
	    #ifdef SOC_XWR16XX 
        else
        {
            hwiParams.name = "MAILBOX_FULL_MSSDSS";
            /*If the remote endpoint is MSS or DSS, we may have multiple instances of the driver but only one interrupt.
             In case of multiple instances (multi-channel):
             Argument is NULL and interrupt will have to check hash array to find handle based on the channel ID.
             In case of single channel, there is no header to recover the channel ID, so need to pass the handle in the argument.
            */
            if(cfg->chType == MAILBOX_CHTYPE_SINGLE)
            {
                hwiParams.arg  = (uintptr_t)retHandle;
            }
            else
            {
                hwiParams.arg  = NULL;
            }    
            gMailboxMCB.hwiHandles.mssDssFull = HwiP_create((mailboxDriver->hwCfg)->boxFullIntNum, Mailbox_boxFullISRMssDss, &hwiParams);
            /* Debug Message: */
            DebugP_log2 ("MAILBOX: Mailbox Driver Registering Mailbox Full to MSS or DSS HWI ISR [%p] for Interrupt %d\n",
                          gMailboxMCB.hwiHandles.mssDssFull, (mailboxDriver->hwCfg)->boxFullIntNum);
        }
        #endif		

        /************** Mailbox empty ***********/
        HwiP_Params_init(&hwiParams);
        if(remoteEndpoint == MAILBOX_TYPE_BSS)
        {
            hwiParams.name = "MAILBOX_EMPTY_BSS";
            hwiParams.arg  = (uintptr_t)retHandle;
            gMailboxMCB.hwiHandles.bssEmpty = HwiP_create((mailboxDriver->hwCfg)->boxEmptyIntNum, Mailbox_boxEmptyISRBss, &hwiParams);
            /* Debug Message: */
            DebugP_log2 ("MAILBOX: Mailbox Driver Registering Mailbox Empty to BSS HWI ISR [%p] for Interrupt %d\n",
                          gMailboxMCB.hwiHandles.bssEmpty, (mailboxDriver->hwCfg)->boxEmptyIntNum);
        }
        #ifdef SOC_XWR16XX 
        else
        {
            hwiParams.name = "MAILBOX_EMPTY_MSSDSS";
            /*If the remote endpoint is MSS or DSS, we may have multiple instances of the driver but only one interrupt.
             In case of multiple instances (multi-channel):
             Argument is NULL and interrupt will have to check hash array to find handle based on the channel ID.
             In case of single channel, there is no header to recover the channel ID, so need to pass the handle in the argument.
            */
            if(cfg->chType == MAILBOX_CHTYPE_SINGLE)
            {
                hwiParams.arg  = (uintptr_t)retHandle;
            }
            else
            {
                hwiParams.arg  = NULL;
            }    
            gMailboxMCB.hwiHandles.mssDssEmpty = HwiP_create((mailboxDriver->hwCfg)->boxEmptyIntNum, Mailbox_boxEmptyISRMssDss, &hwiParams);
            /* Debug Message: */
            DebugP_log2 ("MAILBOX: Mailbox Driver Registering Mailbox Empty to MSS or DSS HWI ISR [%p] for Interrupt %d\n",
                          gMailboxMCB.hwiHandles.mssDssEmpty, (mailboxDriver->hwCfg)->boxEmptyIntNum);
        }
		#endif
    }                  
        
    /* Is the write mode blocking? */
    if (mailboxDriver->cfg.writeMode == MAILBOX_MODE_BLOCKING)
    {
        /* YES: Create a binary semaphore which is used to handle the Blocking operation. */
        SemaphoreP_Params_init(&semParams);
        semParams.mode          = SemaphoreP_Mode_BINARY;
        mailboxDriver->writeSem = SemaphoreP_create(0, &semParams);
    }

    /* Is the read mode blocking? */
    if (mailboxDriver->cfg.readMode == MAILBOX_MODE_BLOCKING)
    {
        /* YES: Create a binary semaphore which is used to handle the Blocking operation. */
        SemaphoreP_Params_init(&semParams);
        semParams.mode         = SemaphoreP_Mode_BINARY;
        mailboxDriver->readSem = SemaphoreP_create(0, &semParams);
    }

    /* Instance of the driver for the specific endpoint is created */
    if(remoteEndpoint == MAILBOX_TYPE_BSS)
    {
        /* If this is an instance of the driver to talk to BSS, increment count.*/
        gMailboxMCB.bssInstCount++;
    }
    #ifdef SOC_XWR16XX 
    else
    {
        gMailboxMCB.mssDssInstCount++;
        /* Store handle of driver into hash array */
        gMailboxMCB.handleArray[cfg->chId] = retHandle;
    }
	#endif
    
    DebugP_log1 ("MAILBOX: Mailbox Driver (%p) open successful.\n", mailboxDriver);

exit:    
    /* Release the critical section: */
    HwiP_restore(key);
    return retHandle;
}    

这个函数只要正常使用TI的初始化参数,就一般不会出问题,所以我们可以略读

六、 gMmwDssMCB.peerMailbox = Mailbox_open(MAILBOX_TYPE_MSS, &mboxCfg, &errCode);、

这个是将返回的handle将起赋予peerMailbox变量,这时候我们的函数初始化就已经完成的,所以我们接下里就是使用了。

七、Mailbox函数的使用

下面我们就开始讲解写函数和读函数

八、mailboxwrite函数

int32_t Mailbox_write(Mbox_Handle handle, const uint8_t *buffer, uint32_t size)//三个参数,一个是handle,一个是地址,一个是大小
{
    Mailbox_Driver*     driver;
    SemaphoreP_Status   status;
    int32_t             retVal = 0;
    uint32_t            header = 0;
    uintptr_t           key;

    driver = (Mailbox_Driver*)handle;

    /* Sanity Check: Validate the arguments */
    if ((size == 0) || (size > MAILBOX_DATA_BUFFER_SIZE) || (buffer == NULL) || (handle == NULL) || (driver->hwCfg == NULL))
    {
        /* Error: Invalid Arguments */
        DebugP_log4 ("MAILBOX: Mailbox_write Error! Invalid param. Size=%d Buffer=(%p) handle=(%p) hwCfgPtr=(%p)\n", size, buffer, handle, driver->hwCfg);
        retVal = MAILBOX_EINVAL;
        goto exit;
    }	//核对大小
    
    if((driver->remoteEndpoint != MAILBOX_TYPE_BSS) && (driver->cfg.chType == MAILBOX_CHTYPE_MULTI))//判断这两个条件,我们这里是MSS并且确实是多通道
    {
        /* Critical Section Protection*/
        key = HwiP_disable();//停止硬件中断
        if(gMailboxMCB.mssDssWriteChIDInUse == MAILBOX_UNUSED_CHANNEL_ID)//做出标记
        {
            /* Mark that the TX mailbox is now in use*/
            gMailboxMCB.mssDssWriteChIDInUse = driver->cfg.chId;
            /* Release the critical section: */
            HwiP_restore(key);//恢复硬件中断
        }
        else
        {
            /* Error: TX mailbox is being used by another mailbox instance*/
            DebugP_log2 ("MAILBOX: Mailbox_write Error! handle=(%p). Write attempt with TX box in use by channel ID %d\n",driver, gMailboxMCB.mssDssWriteChIDInUse);
            retVal = MAILBOX_ECHINUSE;
            /* Release the critical section: */
            HwiP_restore(key);
            goto exit;
        }
    }    
    
    if(driver->txBoxStatus == MAILBOX_TX_BOX_FULL)//我猜测这个变量会在下方里面进行赋值
    {
        /* Error: TX mailbox is full, can not write new message until acknowledge is received from remote endpoint */
        /* Note that this should take care that the DMA has been completed as well because this flag is cleaned only after
           copy is done */
        DebugP_log1 ("MAILBOX: Mailbox_write Error! handle=(%p). Write attempt with txBoxStatus == MAILBOX_TX_BOX_FULL\n", handle);
        retVal = MAILBOX_ETXFULL;
        goto exit;
    }
    
    /* A write operation is starting, need to set TXbox flag to full to block any other write to this instance of mailbox*/
    driver->txBoxStatus = MAILBOX_TX_BOX_FULL;//这里就开始了,先把传输状态设置为慢,看来是不需要到read函数里面了
    
    /* Copy data from application buffer to mailbox buffer */
    if(driver->cfg.dataTransferMode == MAILBOX_DATA_TRANSFER_MEMCPY)//判断其位memcpy函数实现模式
    {
        if((driver->remoteEndpoint != MAILBOX_TYPE_BSS) && (driver->cfg.chType == MAILBOX_CHTYPE_MULTI))//我们都满足
        {
            /*Write internal header*/
            header = driver->cfg.chId;使用这个ID
            memcpy ((void *)(driver->hwCfg)->baseLocalToRemote.data, (void *)(&header), sizeof(header));先把头发过去
            /*Write message. Need to account for internal header size*/
            memcpy ((void *)((uint8_t *)((driver->hwCfg)->baseLocalToRemote.data) + MAILBOX_MULTI_CH_HEADER_SIZE), (const void *)buffer, size);再把数据发过去
        }
        else
        {
            /*Write message.*/
            memcpy ((void *)(driver->hwCfg)->baseLocalToRemote.data, (const void *)buffer, size);否则就直接发数据不发头
        }
        
        #ifdef SUBSYS_MSS
        MEM_BARRIER();
        #endif
    }
    else
    {
        DebugP_log0 ("MAILBOX: Mailbox_write Error! Only memcpy dataTransferMode is supported\n");这里说明了mailbox只支持memcpy模式
        retVal = MAILBOX_EINVALCFG;
        goto exit;
    }
    
    下面是两种模式,一种是blocking,一种是writepolling
    /* Store handle of instance in case this is a MSS/DSS driver instance*/
    if(driver->remoteEndpoint != MAILBOX_TYPE_BSS)//发数据的时候我们不是这样的
    {
        gMailboxMCB.lastMsgSentHandle = handle;
    }
    
    /* Trigger "mailbox full" interrupt to remote endpoint*/
    ((driver->hwCfg)->baseLocalToRemote.reg)->INT_TRIG = CSL_FINSR (((driver->hwCfg)->baseLocalToRemote.reg)->INT_TRIG, 0U, 0U, 1U);
    
    /* Next action depends on the mailbox write mode*/
    if(driver->cfg.writeMode == MAILBOX_MODE_BLOCKING)
    {
        /* Pend on semaphore until acknowledge ("mailbox_empty" interrupt) from remote endpoint is received*/
        status = SemaphoreP_pend (driver->writeSem, driver->cfg.writeTimeout);
        if (status == SemaphoreP_TIMEOUT)
        {
            /* Set error code */
            retVal = MAILBOX_ETXACKTIMEDOUT;

            /* Report the error condition: */
            DebugP_log2 ("MAILBOX:(%p) Write acknowledge timed out. Ack was never received. Number of received TX messages = %d.\n",
                         driver, driver->txCount);
        }
    }
    
    /* If write is blocking mode and semaphore did not timeout, write succeeded and ack received.
       If write is polling mode and we reached this point, write was done but not sure if ack has been received. */
    if( ((driver->cfg.writeMode == MAILBOX_MODE_BLOCKING) && (status != SemaphoreP_TIMEOUT)) ||
        (driver->cfg.writeMode == MAILBOX_MODE_POLLING) )
    {        
        /* Increment TX count */
        driver->txCount++;
        
        /* Set return value */
        retVal = (int32_t)size;            
    }
    
exit:    
    return retVal;
}

九、Mailboxread函数

首先我们来看MSSmain.c的邮箱读取函数,因为我们是从DSS到MSS发数据的,所以我们需要到MSS的mailboxwrite函数中去看他是如何接收的,下面附上我所使用的工程的代码

static void MmwDemo_mboxReadTask(UArg arg0, UArg arg1)
{
    MmwDemo_message      message;
    int32_t              retVal = 0;
    uint32_t totalPacketLen;
    uint32_t numPaddingBytes;
    uint32_t itemIdx;
    uint8_t a[2] = {0x0d, 0x0a};

    /* wait for new message and process all the messages received from the peer */
    while(1)
    {
        Semaphore_pend(gMmwMssMCB.mboxSemHandle, BIOS_WAIT_FOREVER);//我通过搜索这个变量gMmwMssMCB这个变量,我发现她是一个全局变量,在函数定义之外使用所以他这里,这个pend函数不需要担心他没有声明而找不到变量,我们这里传入的这个句柄我们可以返回去查看是在main,C中初始化的,不知道是否为和DSS共用一个我觉得应该是一个,他这里挂起这个函数,并且永久等待
        
        /* Read the message from the peer mailbox: We are not trying to protect the read
         * from the peer mailbox because this is only being invoked from a single thread */
        retVal = Mailbox_read(gMmwMssMCB.peerMailbox, (uint8_t*)&message, sizeof(MmwDemo_message));/往下翻,我们就可以去解析read函数,我们下面转到下面来看
        if (retVal < 0)
        {
            /* Error: Unable to read the message. Setup the error code and return values */
            System_printf ("Error: Mailbox read failed [Error code %d]\n", retVal);
        }
        else if (retVal == 0)
        {
            /* We are done: There are no messages available from the peer execution domain. */
            continue;
        }
        else
        {
            /* Flush out the contents of the mailbox to indicate that we are done with the message. This will
             * allow us to receive another message in the mailbox while we process the received message. */
            Mailbox_readFlush (gMmwMssMCB.peerMailbox);

这个就是邮箱read函数

int32_t Mailbox_read(Mbox_Handle handle, uint8_t *buffer, uint32_t size)
//可以看出他传输的是就是这个message结构体,我们后面可以查看这个结构体的定义来查看其是否为全局变量。
{
    Mailbox_Driver*     driver;
    SemaphoreP_Status   status;
    int32_t             retVal = 0;

    driver = (Mailbox_Driver*)handle;//赋予handle:peermailbox
    
    /* Sanity Check: Validate the arguments */
    if ((size == 0) || (buffer == NULL) || (handle == NULL))
    {
        /* Error: Invalid Arguments */
        DebugP_log3 ("MAILBOX: Mailbox_read Error! Invalid param. Size=%d Buffer=(%p) handle=(%p)\n", size, buffer, handle);
        retVal = MAILBOX_EINVAL;
    }
    else
    {    
        /* If the size is bigger than maximum mailbox buffer size, read/copy the max available size */
        if(size + driver->numBytesRead > MAILBOX_DATA_BUFFER_SIZE)
        {
            size = MAILBOX_DATA_BUFFER_SIZE - driver->numBytesRead;
        }
        
        /* First check if this is the first message because it will only block if this is a first message */
        if(driver->numBytesRead == 0)
        {            
            /* If mailbox read mode is "blocking", need to pend on semaphore*/
            if(driver->cfg.readMode == MAILBOX_MODE_BLOCKING)
            {
                /* Pend on semaphore until message arrives in mailbox ("mailbox_full" interrupt is received)*/
                status = SemaphoreP_pend (driver->readSem, driver->cfg.readTimeout);
                if (status == SemaphoreP_TIMEOUT)
                {
                    /* Set error code */
                    retVal = MAILBOX_EREADTIMEDOUT;

                    /* Report the error condition: */
                    DebugP_log2 ("MAILBOX:(%p) Mailbox_read timed out. Number of RX messages = %d.\n",
                                 driver, driver->rxCount);
                }
            }
            
            /* In polling or callback mode the newMessageFlag indicates that a message was received.在polling模式中,这个newMessageFlag表明新的信息已经收到
               In blocking mode, a posted semaphore indicates that a new message was received.在blocking模式中,这个信号量表示其收到新的信息,我们在开始的初始化变量时候发现其,写入模式为blocking,其读的模式为callbak,所以我们使用flag来判断的,不是用的信号量。
               If any of these are true, the driver should read the new message.*/
            if( ((driver->cfg.readMode == MAILBOX_MODE_POLLING)  && (driver->newMessageFlag == MAILBOX_NEW_MESSAGE_RECEIVED)) ||
                ((driver->cfg.readMode == MAILBOX_MODE_CALLBACK) && (driver->newMessageFlag == MAILBOX_NEW_MESSAGE_RECEIVED)) ||
                ((driver->cfg.readMode == MAILBOX_MODE_BLOCKING) && (status != SemaphoreP_TIMEOUT)) )//我们符合第二个参数的数值所以进去这个函数
            {
                driver->newMessageFlag = MAILBOX_NEW_MESSAGE_NOT_RECEIVED;         //首先把flag设置为没有收到       
                /* Increment RX count */
                driver->rxCount++;增加收到的数目
                
                /* Copy data from mailbox buffer into application buffer */
                if(driver->cfg.dataTransferMode == MAILBOX_DATA_TRANSFER_MEMCPY)	//我们也是这个memcpy,我们这个设备只支持这个memcpy,可能是TI对其他的设备还有新的支持功能
                {
                    if((driver->remoteEndpoint != MAILBOX_TYPE_BSS) && (driver->cfg.chType == MAILBOX_CHTYPE_MULTI))	//我们的remoteendpoint是MSS并且我们的就是多个
                    {
                        /*Read message. Need to account for internal header*/
                        memcpy ((void *)buffer, (void *)((uint8_t *)((driver->hwCfg)->baseRemoteToLocal.data) + driver->numBytesRead + MAILBOX_MULTI_CH_HEADER_SIZE), size); 读数据,还有头的信息
                    }
                    else
                    {
                        /*Read message.*/
                        memcpy ((void *)buffer, (void *)((uint8_t *)((driver->hwCfg)->baseRemoteToLocal.data) + driver->numBytesRead), size); //这里不执行
                    }    
                }
                else
                {
                    DebugP_log0 ("MAILBOX: Mailbox_read Error! Only memcpy dataTransferMode is supported\n");
                    retVal = MAILBOX_EINVALCFG;
                    goto exit;
                }//如果都不是,则不支持其他模式

                /* Set return value */
                retVal = (int32_t)size;
                
                /* Update number of bytes read for this message*/
                driver->numBytesRead = driver->numBytesRead + size;
            }    //更新数据接受个数
        }
        else
        {
            /* This is a subsequent read for a message that is already in the mailbox buffer */     第一个数据不会进行blocking,所以他是两个翻版跟第一次memcpy对应       
            /* Copy data from mailbox buffer into application buffer */
            if(driver->cfg.dataTransferMode == MAILBOX_DATA_TRANSFER_MEMCPY)
            {
                if((driver->remoteEndpoint != MAILBOX_TYPE_BSS) && (driver->cfg.chType == MAILBOX_CHTYPE_MULTI))
                {
                    /*Read message. Need to account for internal header*/
                    memcpy ((void *)buffer, (void *)((uint8_t *)((driver->hwCfg)->baseRemoteToLocal.data) + driver->numBytesRead + MAILBOX_MULTI_CH_HEADER_SIZE), size); 
                }
                else
                {
                    /*Read message.*/
                    memcpy ((void *)buffer, (void *)((uint8_t *)((driver->hwCfg)->baseRemoteToLocal.data) + driver->numBytesRead), size); 
                }    
            }
            else
            {
                DebugP_log0 ("MAILBOX: Mailbox_read Error! Only memcpy dataTransferMode is supported\n");
                retVal = MAILBOX_EINVALCFG;
                goto exit;
            }
            
            /* Set return value */
            retVal = (int32_t)size;
            
            /* Update number of bytes read for this message*/
            driver->numBytesRead = driver->numBytesRead + size;
        }
    }
exit:    
    return retVal;
}

十、冲刷函数Mailbox_readFlush (gMmwDssMCB.peerMailbox);

这个函数的出现,是为了告诉系统我已经接受完成了信息,可以开始处理了
下面我们来进入其原函数

int32_t Mailbox_readFlush(Mbox_Handle handle)
{
    Mailbox_Driver*     driver;
    int32_t             retVal = 0;
    uintptr_t           key;
    

    /* Sanity Check: Validate the arguments */
    if (handle == NULL)
    {
        /* Error: Invalid Arguments */
        DebugP_log0 ("MAILBOX: Mailbox_readFlush Error! Null handle\n");
        retVal = MAILBOX_EINVAL;
    }//确认传输成功
    else
    {
        driver = (Mailbox_Driver*)handle;

        /* If this is MSS-DSS multi-channel, make sure mailbox is not being used by another instance */
        if((driver->remoteEndpoint != MAILBOX_TYPE_BSS) && (driver->cfg.chType == MAILBOX_CHTYPE_MULTI))//我们是MSS和multi
        {
            /* Critical Section Protection*/
            key = HwiP_disable();关闭硬件中断
            if(gMailboxMCB.mssDssReadChIDInUse != driver->cfg.chId)
            {
                retVal = MAILBOX_ECHINUSE;
                /* Release the critical section: */
                HwiP_restore(key);打开中断
                goto exit;
            }
            else
            {
                /* Indicate that channel is no longer in use */
                gMailboxMCB.mssDssReadChIDInUse = MAILBOX_UNUSED_CHANNEL_ID;
                /* Release the critical section: */
                HwiP_restore(key);
            }
        }
        
        driver->readFlushCount++;//flush次数加一
        
        /* Reset number of bytes read*/
        driver->numBytesRead = 0;重置numbytesread
            
        if(driver->hwCfg != NULL)将信息告诉已经接受到了
        {
            /* Send acknowledgement to remote endpoint */
            ((driver->hwCfg)->baseLocalToRemote.reg)->INT_TRIG = CSL_FINSR (((driver->hwCfg)->baseLocalToRemote.reg)->INT_TRIG, 1U, 1U, 1U);
        }
        else
        {
            /* Error: Invalid Arguments */
            DebugP_log0 ("MAILBOX: Mailbox_readFlush Error! Null hardware configuration.\n");
            retVal = MAILBOX_EINVAL;
        }
    }    

exit:    
    return retVal;    
}    

十一、 处理接收到的信息

switch (message.type)
        {
            case MMWDEMO_MSS2DSS_GUIMON_CFG:
            {
                /* Save guimon configuration */
                MmwDemo_cfgUpdate((void *)&message.body.guiMonSel,
                                     offsetof(MmwDemo_CliCfg_t, guiMonSel),
                                     sizeof(MmwDemo_GuiMonSel), subFrameNum);
                break;
            }

到这里所有的函数就已经结束了。感谢大家有耐心能看到这里,如果有需要帮助的地方欢迎加我的QQ1103871467付费咨询。

 类似资料: