📄 myapp_ex06b.c
字号:
* The App_HandleScanActiveConfirm(nwkMessage_t *pMsg) function will handle the
* Active Scan confirm message received from the MLME when the Active scan has
* completed. The message contains a list of PAN descriptors. Based on link
* quality inforamtion in the pan descriptors the nearest coordinator is chosen.
* The corresponding pan descriptor is stored in the global variable coordInfo.
*
* The function may return either of the following values:
* errorNoError: A suitable pan descriptor was found.
* errorNoScanResults: No scan results were present in the confirm message.
*
******************************************************************************/
uint8_t App_HandleScanActiveConfirm(nwkMessage_t *pMsg)
{
uint8_t panDescListSize = pMsg->msgData.scanCnf.resultListSize;
panDescriptor_t *pPanDesc = pMsg->msgData.scanCnf.resList.pPanDescriptorList;
uint8_t rc = errorNoScanResults;
/* Check if the scan resulted in any coordinator responses. */
if(panDescListSize != 0)
{
/* Initialize link quality to very poor. */
uint8_t i, bestLinkQuality = 0;
/* Check all PAN descriptors. */
for(i=0; i<panDescListSize; i++, pPanDesc++)
{
/* Only attempt to associate if the coordinator
accepts associations and is non-beacon. */
if( ( pPanDesc->superFrameSpec[1] & gSuperFrameSpecMsbAssocPermit_c) &&
((pPanDesc->superFrameSpec[0] & gSuperFrameSpecLsbBO_c) == 0x0F) )
{
/* Find the nearest coordinator using the link quality measure. */
if(pPanDesc->linkQuality > bestLinkQuality)
{
/* Save the information of the coordinator candidate. If we
find a better candiate, the information will be replaced. */
memcpy(&coordInfo, pPanDesc, sizeof(panDescriptor_t));
bestLinkQuality = pPanDesc->linkQuality;
rc = errorNoError;
}
}
}
}
/* ALWAYS free the PAN descriptor list */
MSG_Free(pMsg->msgData.scanCnf.resList.pPanDescriptorList);
return rc;
}
/******************************************************************************
* The App_SendAssociateRequest(void) will create an Associate Request message
* and send it to the coordinator it wishes to associate to. The function uses
* information gained about the coordinator during the scan procedure.
*
* The function may return either of the following values:
* errorNoError: The Associate Request message was sent successfully.
* errorInvalidParameter: The MLME service access point rejected the
* message due to an invalid parameter.
* errorAllocFailed: A message buffer could not be allocated.
*
******************************************************************************/
uint8_t App_SendAssociateRequest(void)
{
mlmeMessage_t *pMsg;
mlmeAssociateReq_t *pAssocReq;
Uart_Print("Sending the MLME-Associate Request message to the MAC...");
/* Allocate a message for the MLME message. */
pMsg = MSG_AllocType(mlmeMessage_t);
if(pMsg != NULL)
{
/* This is a MLME-ASSOCIATE.req command. */
pMsg->msgType = gMlmeAssociateReq_c;
/* Create the Associate request message data. */
pAssocReq = &pMsg->msgData.associateReq;
/* Use the coordinator info we got from the Active Scan. */
memcpy(pAssocReq->coordAddress, coordInfo.coordAddress, 8);
memcpy(pAssocReq->coordPanId, coordInfo.coordPanId, 2);
pAssocReq->coordAddrMode = coordInfo.coordAddrMode;
pAssocReq->logicalChannel = coordInfo.logicalChannel;
pAssocReq->securityEnable = FALSE;
/* We want the coordinator to assign a short address to us. */
pAssocReq->capabilityInfo = gCapInfoAllocAddr_c;
/* Send the Associate Request to the MLME. */
if(MSG_Send(NWK_MLME, pMsg) == gSuccess_c)
{
Uart_Print("Done\n");
return errorNoError;
}
else
{
/* One or more parameters in the message were invalid. */
Uart_Print("Invalid parameter!\n");
return errorInvalidParameter;
}
}
else
{
/* Allocation of a message buffer failed. */
Uart_Print("Message allocation failed!\n");
return errorAllocFailed;
}
}
/******************************************************************************
* The App_HandleAssociateConfirm(nwkMessage_t *pMsg) function will handle the
* Associate confirm message received from the MLME when the Association
* procedure has completed. The message contains the short address that the
* coordinator has assigned to us. This address is 0xfffe if we did not specify
* the gCapInfoAllocAddr_c flag in the capability info field of the Associate
* request. The address and address mode are saved in global variables. They
* will be used in the next demo application when sending data.
*
******************************************************************************/
void App_HandleAssociateConfirm(nwkMessage_t *pMsg)
{
/* This is our own extended address (MAC address). It cannot be modified. */
extern const uint8_t aExtendedAddress[8];
/* If the coordinator assigns a short address of 0xfffe then,
that means we must use our own extended address in all
communications with the coordinator. Otherwise, we use
the short address assigned to us. */
if( (pMsg->msgData.associateCnf.assocShortAddress[0] >= 0xFE) &&
(pMsg->msgData.associateCnf.assocShortAddress[1] == 0xFF) )
{
myAddrMode = gAddrModeLong_c;
memcpy(myAddress, (void *)aExtendedAddress, 8);
}
else
{
myAddrMode = gAddrModeShort_c;
memcpy(myAddress, pMsg->msgData.associateCnf.assocShortAddress, 2);
}
}
/******************************************************************************
* The App_HandleMlmeInput(nwkMessage_t *pMsg) function will handle various
* messages from the MLME, e.g. poll confirm.
*
* The function may return either of the following values:
* errorNoError: The message was processed.
* errorNoMessage: The message pointer is NULL.
******************************************************************************/
uint8_t App_HandleMlmeInput(nwkMessage_t *pMsg)
{
if(pMsg == NULL)
return errorNoMessage;
/* Handle the incoming message. The type determines the sort of processing.*/
switch(pMsg->msgType) {
case gNwkPollCnf_c:
if(pMsg->msgData.pollCnf.status != gSuccess_c)
{
/* The Poll Confirm status was not successful. Usually this happens if
no data was available at the coordinator. In this case we start
polling at a lower rate to conserve power. */
pollInterval = POLL_INTERVAL_SLOW;
/* If we get to this point, then no data was available, and we
allow a new poll request. Otherwise, we wait for the data
indication before allowing the next poll request. */
waitPollConfirm = FALSE;
}
break;
}
return errorNoError;
}
/******************************************************************************
* The App_HandleMcpsInput(mcpsToNwkMessage_t *pMsgIn) function will handle
* messages from the MCPS, e.g. Data Confirm, and Data Indication.
*
******************************************************************************/
void App_HandleMcpsInput(mcpsToNwkMessage_t *pMsgIn)
{
switch(pMsgIn->msgType)
{
/* The MCPS-Data confirm is sent by the MAC to the network
or application layer when data has been sent. */
case gMcpsDataCnf_c:
if(numPendingPackets)
numPendingPackets--;
break;
case gMcpsDataInd_c:
/* Copy the received data to the UART. */
Uart_Tx(pMsgIn->msgData.dataInd.msdu, pMsgIn->msgData.dataInd.msduLength);
/* Since we received data, the coordinator might have more to send. We
reduce the polling interval to raise the throughput while data is
available. */
pollInterval = POLL_INTERVAL_FAST;
/* Allow another MLME-Poll request. */
waitPollConfirm = FALSE;
break;
}
}
/******************************************************************************
* The App_WaitMsg(nwkMessage_t *pMsg, uint8_t msgType) function does not, as
* the name implies, wait for a message, thus blocking the execution of the
* state machine. Instead the function analyzes the supplied message to
* determine whether or not the message is of the expected type.
* The function may return either of the following values:
* errorNoError: The message was of the expected type.
* errorNoMessage: The message pointer is NULL.
* errorWrongConfirm: The message is not of the expected type.
*
******************************************************************************/
uint8_t App_WaitMsg(nwkMessage_t *pMsg, uint8_t msgType)
{
/* Do we have a message? If not, the exit with error code */
if(pMsg == NULL)
return errorNoMessage;
/* Is it the expected message type? If not then exit with error code */
if(pMsg->msgType != msgType)
return errorWrongConfirm;
/* Found the expected message. Return with success code */
return errorNoError;
}
/******************************************************************************
* The App_TransmitUartData() function will perform (single/multi buffered)
* data transmissions of data received by the UART. Data could also come from
* other sources such as sensors etc. This is completely determined by the
* application. The constant MAX_PENDING_DATA_PACKETS determine the maximum
* number of packets pending for transmission in the MAC. A global variable
* is incremented each time a data packet is sent to the MCPS, and decremented
* when the corresponding MCPS-Data Confirm message is received. If the counter
* reaches the defined maximum no more data buffers are allocated until the
* counter is decreased below the maximum number of pending packets.
*
* The function uses the coordinator information gained during the Active Scan,
* and the short address assigned to us by coordinator, for building an MCPS-
* Data Request message. The message is sent to the MCPS service access point
* in the MAC.
******************************************************************************/
void App_TransmitUartData(void)
{
/* Use multi buffering for increased TX performance. It does not really
have any effect at a UART baud rate of 19200bps but serves as an
example of how the throughput may be improved in a real-world
application where the data rate is of concern. */
if( (numPendingPackets < MAX_PENDING_DATA_PACKETS) && (pPacket == NULL) )
{
/* If the maximum number of pending data buffes is below maximum limit
and we do not have a data buffer already then allocate one. */
pPacket = MSG_Alloc(sizeof(nwkToMcpsMessage_t) - 1 + DEFAULT_DATA_LENGTH);
}
if(pPacket != NULL)
{
/* If we have a buffer, then get data from the UART. */
uint8_t msduLength = Uart_Poll(pPacket->msgData.dataReq.msdu);
if(msduLength)
{
/* Data was available in the UART receive buffer. Now create an
MCPS-Data Request message containing the UART data. */
pPacket->msgType = gMcpsDataReq_c;
/* Create the header using coordinator information gained during
the scan procedure. Also use the short address we were assigned
by the coordinator during association. */
memcpy(pPacket->msgData.dataReq.dstAddr, coordInfo.coordAddress, 8);
memcpy(pPacket->msgData.dataReq.srcAddr, myAddress, 8);
memcpy(pPacket->msgData.dataReq.dstPanId, coordInfo.coordPanId, 2);
memcpy(pPacket->msgData.dataReq.srcPanId, coordInfo.coordPanId, 2);
pPacket->msgData.dataReq.dstAddrMode = coordInfo.coordAddrMode;
pPacket->msgData.dataReq.srcAddrMode = myAddrMode;
pPacket->msgData.dataReq.msduLength = msduLength;
/* Request MAC level acknowledgement of the data packet */
pPacket->msgData.dataReq.txOptions = gTxOptsAck_c;
/* Give the data packet a handle. The handle is
returned in the MCPS-Data Confirm message. */
pPacket->msgData.dataReq.msduHandle = msduHandle++;
/* Send the Data Request to the MCPS */
NR MSG_Send(NWK_MCPS, pPacket);
/* Prepare for another data buffer */
pPacket = NULL;
numPendingPackets++;
}
}
}
/******************************************************************************
* The App_ReceiveUartData() function will check if it is time to send out an
* MLME-Poll request in order to receive data from the coordinator. If its time,
* and we are permitted then a poll request is created and sent.
*
* The function uses the coordinator information gained during the Active Scan
* for building the MLME-Poll Request message. The message is sent to the MLME
* service access point in the MAC.
******************************************************************************/
void App_ReceiveUartData(void)
{
/* Check if we are permitted, and if it is time to send a poll request.
The poll interval is adjusted dynamically to the current band-width
requirements. */
if( (waitPollConfirm == FALSE) && (Timer_Get() > pollInterval) )
{
/* This is an MLME-POLL.req command. */
mlmeMessage_t *pMlmeMsg = MSG_AllocType(mlmeMessage_t);
if(pMlmeMsg)
{
/* Create the Poll Request message data. */
pMlmeMsg->msgType = gMlmePollReq_c;
/* Use the coordinator information we got from the Active Scan. */
memcpy(pMlmeMsg->msgData.pollReq.coordAddress, coordInfo.coordAddress, 8);
memcpy(pMlmeMsg->msgData.pollReq.coordPanId, coordInfo.coordPanId, 2);
pMlmeMsg->msgData.pollReq.coordAddrMode = coordInfo.coordAddrMode;
pMlmeMsg->msgData.pollReq.securityEnable = FALSE;
/* Send the Poll Request to the MLME. */
if(MSG_Send(NWK_MLME, pMlmeMsg) == gSuccess_c)
{
/* Do not allow another Poll request before the confirm is received. */
waitPollConfirm = TRUE;
/* Restart timer. */
Timer_Reset();
}
}
}
}
/******************************************************************************
* The following functions are called by the MAC to put messages into the
* Application's queue. They need to be defined even if they are not used
* in order to avoid linker errors.
******************************************************************************/
uint8_t MLME_NWK_SapHandler(nwkMessage_t * pMsg)
{
/* Put the incoming MLME message in the applications input queue. */
MSG_Queue(&mMlmeNwkInputQueue, pMsg);
return gSuccess_c;
}
uint8_t MCPS_NWK_SapHandler(mcpsToNwkMessage_t *pMsg)
{
/* Put the incoming MCPS message in the applications input queue. */
MSG_Queue(&mMcpsNwkInputQueue, pMsg);
return gSuccess_c;
}
uint8_t ASP_APP_SapHandler(aspToAppMsg_t *pMsg)
{
/* If the message is not handled anywhere it must be freed. */
MSG_Free(pMsg);
return gSuccess_c;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -