serialapp.c

来自「一些基于IRA环境开发的zigbee实例程序」· C语言 代码 · 共 790 行 · 第 1/2 页

C
790
字号
  }

#if SERIAL_APP_LOOPBACK
  if ( events & SERIALAPP_TX_RTRY_EVT )
  {
    if ( rxLen )
    {
      if ( !HalUARTWrite( SERIAL_APP_PORT, rxBuf, rxLen ) )
      {
        osal_start_timerEx( SerialApp_TaskID, SERIALAPP_TX_RTRY_EVT,
                                              SERIALAPP_TX_RTRY_TIMEOUT );
      }
      else
      {
        rxLen = 0;
      }
    }

    return ( events ^ SERIALAPP_TX_RTRY_EVT );
  }
#endif

  return ( 0 );  // Discard unknown events.
}

/*********************************************************************
 * @fn      SerialApp_ProcessZDOMsgs()
 *
 * @brief   Process response messages
 *
 * @param   none
 *
 * @return  none
 */
static void SerialApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
{
  switch( inMsg->clusterID )
  {
    case End_Device_Bind_rsp:
      if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
      {
        // Light LED
        HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
      }
#if defined(BLINK_LEDS)
      else
      {
        // Flash LED to show failure
        HalLedSet ( HAL_LED_4, HAL_LED_MODE_FLASH );
      }
#endif
      break;

    case Match_Desc_rsp:
      {
        ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
        if ( pRsp )
        {
          if ( pRsp->status == ZSuccess && pRsp->cnt )
          {
            SerialApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
            SerialApp_DstAddr.addr.shortAddr = pRsp->nwkAddr;
            // Take the first endpoint, Can be changed to search through endpoints
            SerialApp_DstAddr.endPoint = pRsp->epList[0];

            // Light LED
            HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
          }
          osal_mem_free( pRsp );
        }
      }
      break;
  }
}

/*********************************************************************
 * @fn      SerialApp_HandleKeys
 *
 * @brief   Handles all key events for this device.
 *
 * @param   shift - true if in shift/alt.
 * @param   keys  - bit field for key events.
 *
 * @return  none
 */

static void SerialApp_HandleKeys( uint8 shift, uint8 keys )
{
  zAddrType_t dstAddr;

  /*if ( shift )
  {
    if ( keys & HAL_KEY_SW_1 )
    {
    }
    if ( keys & HAL_KEY_SW_2 )
    {
    }
    if ( keys & HAL_KEY_SW_3 )
    {
    }
    if ( keys & HAL_KEY_SW_4 )
    {
    }
  }
  else   */
  {
    if ( keys & HAL_KEY_SW_1 )
    {
    }

    if ( keys & HAL_KEY_SW_2 )
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );

      // Initiate an End Device Bind Request for the mandatory endpoint
      dstAddr.addrMode = Addr16Bit;
      dstAddr.addr.shortAddr = 0x0000; // Coordinator
      ZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(),
                            SerialApp_epDesc.endPoint,
                            SERIALAPP_PROFID,
                            SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
                            SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
                            FALSE );
    }

    if ( keys & HAL_KEY_SW_3 )
    {
    }

    if ( keys & HAL_KEY_SW_4 )
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );

      // Initiate a Match Description Request (Service Discovery)
      dstAddr.addrMode = AddrBroadcast;
      dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
      ZDP_MatchDescReq( &dstAddr, NWK_BROADCAST_SHORTADDR,
                        SERIALAPP_PROFID,
                        SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
                        SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
                        FALSE );
    }
  }
}

/*********************************************************************
 * @fn      SerialApp_ProcessMSGCmd
 *
 * @brief   Data message processor callback. This function processes
 *          any incoming data - probably from other devices. Based
 *          on the cluster ID, perform the intended action.
 *
 * @param   pkt - pointer to the incoming message packet
 *
 * @return  TRUE if the 'pkt' parameter is being used and will be freed later,
 *          FALSE otherwise.
 */
void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt )
{
  uint8 stat;
  uint8 seqnb;
  uint8 delay;

  switch ( pkt->clusterId )
  {
  // A message with a serial data block to be transmitted on the serial port.
  case SERIALAPP_CLUSTERID1:
    seqnb = pkt->cmd.Data[0];

    // Keep message if not a repeat packet
    if ( (seqnb > SerialApp_SeqRx) ||                    // Normal
        ((seqnb < 0x80 ) && ( SerialApp_SeqRx > 0x80)) ) // Wrap-around
    {
      // Transmit the data on the serial port.
      if ( HalUARTWrite( SERIAL_APP_PORT, pkt->cmd.Data+1,
                                         (pkt->cmd.DataLength-1) ) )
      {
        // Save for next incoming message
        SerialApp_SeqRx = seqnb;

        stat = OTA_SUCCESS;
      }
      else
      {
        stat = OTA_SER_BUSY;
      }
    }
    else
    {
      stat = OTA_DUP_MSG;
    }

    // Select approproiate OTA flow-control delay.
    delay = (stat == OTA_SER_BUSY) ? SERIALAPP_NAK_DELAY : SERIALAPP_ACK_DELAY;

    // Build & send OTA response message.
    rspBuf[0] = stat;
    rspBuf[1] = seqnb;
    rspBuf[2] = LO_UINT16( delay );
    rspBuf[3] = HI_UINT16( delay );
    stat = AF_DataRequest( &(pkt->srcAddr), (endPointDesc_t*)&SerialApp_epDesc,
                            SERIALAPP_CLUSTERID2, SERIAL_APP_RSP_CNT , rspBuf,
                           &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS );

    if ( stat != afStatus_SUCCESS )
    {
      osal_start_timerEx( SerialApp_TaskID, SERIALAPP_RSP_RTRY_EVT,
                                            SERIALAPP_RSP_RTRY_TIMEOUT );

      // Store the address for the timeout retry.
      osal_memcpy(&SerialApp_RspDstAddr, &(pkt->srcAddr), sizeof( afAddrType_t ));
    }
    break;

  // A response to a received serial data block.
  case SERIALAPP_CLUSTERID2:
    if ( (pkt->cmd.Data[1] == SerialApp_SeqTx) &&
        ((pkt->cmd.Data[0] == OTA_SUCCESS) ||
         (pkt->cmd.Data[0] == OTA_DUP_MSG)) )
    {
      // Remove timeout waiting for response from other device.
      osal_stop_timerEx( SerialApp_TaskID, SERIALAPP_MSG_RTRY_EVT );
      FREE_OTABUF();
    }
    else
    {
      delay = BUILD_UINT16( pkt->cmd.Data[2], pkt->cmd.Data[3] );
      // Re-start timeout according to delay sent from other device.
      osal_start_timerEx( SerialApp_TaskID, SERIALAPP_MSG_RTRY_EVT, delay );
    }
    break;

    default:
      break;
  }
}

/*********************************************************************
 * @fn      SerialApp_SendData
 *
 * @brief   Send data OTA.
 *
 * @param   none
 *
 * @return  none
 */
static void SerialApp_SendData( uint8 *buf, uint8 len )
{
  afStatus_t stat;

  // Pre-pend sequence number to the start of the Rx buffer.
  *buf = ++SerialApp_SeqTx;

  otaBuf = buf;
  otaLen = len+1;

  stat = AF_DataRequest( &SerialApp_DstAddr,
                         (endPointDesc_t *)&SerialApp_epDesc,
                          SERIALAPP_CLUSTERID1,
                          otaLen, otaBuf,
                          &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS );

  if ( (stat == afStatus_SUCCESS) || (stat == afStatus_MEM_FAIL) )
  {
    osal_start_timerEx( SerialApp_TaskID, SERIALAPP_MSG_RTRY_EVT,
                      SERIALAPP_MSG_RTRY_TIMEOUT );
    rtryCnt = SERIALAPP_MAX_RETRIES;
  }
  else
  {
    FREE_OTABUF();
  }
}

#if SERIAL_APP_LOOPBACK
/*********************************************************************
 * @fn      rxCB_Loopback
 *
 * @brief   Process UART Rx event handling.
 *          May be triggered by an Rx timer expiration - less than max
 *          Rx bytes have arrived within the Rx max age time.
 *          May be set by failure to alloc max Rx byte-buffer for the DMA Rx -
 *          system resources are too low, so set flow control?
 *
 * @param   none
 *
 * @return  none
 */
static void rxCB_Loopback( uint8 port, uint8 event )
{

  if ( rxLen )
  {
    if ( !HalUARTWrite( SERIAL_APP_PORT, rxBuf, rxLen ) )
    {
      osal_start_timerEx( SerialApp_TaskID, SERIALAPP_TX_RTRY_EVT,
                                            SERIALAPP_TX_RTRY_TIMEOUT );
      return;
    }
    else
    {
      osal_stop_timerEx( SerialApp_TaskID, SERIALAPP_TX_RTRY_EVT );
    }
  }

  // HAL UART Manager will turn flow control back on if it can after read.
  if ( !(rxLen = HalUARTRead( port, rxBuf, SERIAL_APP_RX_CNT )) )
  {
    return;
  }

  if ( HalUARTWrite( SERIAL_APP_PORT, rxBuf, rxLen ) )
  {
    rxLen = 0;
  }
  else
  {
    osal_start_timerEx( SerialApp_TaskID, SERIALAPP_TX_RTRY_EVT,
                                          SERIALAPP_TX_RTRY_TIMEOUT );
  }
}

#else

/*********************************************************************
 * @fn      rxCB
 *
 * @brief   Process UART Rx event handling.
 *          May be triggered by an Rx timer expiration - less than max
 *          Rx bytes have arrived within the Rx max age time.
 *          May be set by failure to alloc max Rx byte-buffer for the DMA Rx -
 *          system resources are too low, so set flow control?
 *
 * @param   none
 *
 * @return  none
 */
static void rxCB( uint8 port, uint8 event )
{
  uint8 *buf, len;

  /* While awaiting retries/response, only buffer 1 next buffer: otaBuf2.
   * If allow the DMA Rx to continue to run, allocating Rx buffers, the heap
   * will become so depleted that an incoming OTA response cannot be received.
   * When the Rx data available is not read, the DMA Rx Machine automatically
   * sets flow control off - it is automatically re-enabled upon Rx data read.
   * When the back-logged otaBuf2 is sent OTA, an Rx data read is scheduled.
   */
  if ( otaBuf2 )
  {
    return;
  }

  if ( !(buf = osal_mem_alloc( SERIAL_APP_RX_CNT )) )
  {
    return;
  }

  /* HAL UART Manager will turn flow control back on if it can after read.
   * Reserve 1 byte for the 'sequence number'.
   */
  len = HalUARTRead( port, buf+1, SERIAL_APP_RX_CNT-1 );

  if ( !len )  // Length is not expected to ever be zero.
  {
    osal_mem_free( buf );
    return;
  }

  /* If the local global otaBuf is in use, then either the response handshake
   * is being awaited or retries are being attempted. When the wait/retries
   * process has been exhausted, the next OTA msg will be attempted from
   * otaBuf2, if it is not NULL.
   */
  if ( otaBuf )
  {
    otaBuf2 = buf;
    otaLen2 = len;
  }
  else
  {
    otaBuf = buf;
    otaLen = len;
    /* Don't call SerialApp_SendData() from here in the callback function.
     * Set the event so SerialApp_SendData() runs during this task's time slot.
     */
    osal_set_event( SerialApp_TaskID, SERIALAPP_MSG_SEND_EVT );
  }
}
#endif

/*********************************************************************
*********************************************************************/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?