Пример #1
0
bool wpan_mlme_associate_req(uint8_t LogicalChannel,
                             uint8_t ChannelPage,
                             wpan_addr_spec_t *CoordAddrSpec,
                             uint8_t CapabilityInformation)
{
    buffer_t *buffer_header;
    mlme_associate_req_t *mlme_associate_req;

    /* Allocate a buffer for mlme associate request */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    /* Check for buffer availability */
    if (NULL == buffer_header) {
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_associate_req = (mlme_associate_req_t *)BMM_BUFFER_POINTER(
                             buffer_header);

    /* Construct mlme_associate_req_t message */
    mlme_associate_req->cmdcode = MLME_ASSOCIATE_REQUEST;

    /* Operating channel */
    mlme_associate_req->LogicalChannel = LogicalChannel;

    /* Coordinator address spec */
    mlme_associate_req->CoordAddrMode = CoordAddrSpec->AddrMode;

#ifdef TEST_HARNESS_BIG_ENDIAN
    mlme_associate_req->CoordPANId
        = CPU_ENDIAN_TO_LE16(CoordAddrSpec->PANId);
#else
    mlme_associate_req->CoordPANId = CoordAddrSpec->PANId;
#endif

    ADDR_COPY_DST_SRC_64(mlme_associate_req->CoordAddress.long_address,
                         CoordAddrSpec->Addr.long_address);

    /* Other fields */
    mlme_associate_req->CapabilityInformation = CapabilityInformation;
    mlme_associate_req->ChannelPage = ChannelPage;

    /* Insert service message into NHLE MLME queue */
#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-ASSOCIATE.request is not appended into NHLE MAC
         * queue, hence free the buffer allocated
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #2
0
/**
 * @brief Cleanup TAL
 *
 * @param trx_id Transceiver identifier
 */
static void cleanup_tal(trx_id_t trx_id)
{
	/* Clear all running TAL timers. */
	ENTER_CRITICAL_REGION();
	stop_tal_timer(trx_id);
	LEAVE_CRITICAL_REGION();

	/* Clear TAL Incoming Frame queue and free used buffers. */
	while (tal_incoming_frame_queue[trx_id].size > 0) {
		buffer_t *frame
			= qmm_queue_remove(
				&tal_incoming_frame_queue[trx_id], NULL);
		if (NULL != frame) {
			bmm_buffer_free(frame);
		}
	}
	/* Get new TAL Rx buffer if necessary */
	if (tal_rx_buffer[trx_id] == NULL) {
		tal_rx_buffer[trx_id] = bmm_buffer_alloc(LARGE_BUFFER_SIZE);
	}

	/* Handle buffer shortage */
	if (tal_rx_buffer[trx_id] == NULL) {
		tal_buf_shortage[trx_id] = true;
	} else {
		tal_buf_shortage[trx_id] = false;
	}
}
Пример #3
0
uint8_t pal_sio_init(uint8_t UARTx) 
{

  buffer_t *buffer_header;
  NWK_DataReq_t *nlde_data_req;

  buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);
  nlde_data_req = (NWK_DataReq_t *)BMM_BUFFER_POINTER(buffer_header);
  uart_0_buffer.rx_buf_head = ((uint8_t *)nlde_data_req) + (LARGE_BUFFER_SIZE - FCS_LEN - TRANSPARENT_IO_BUF_SIZE);
  uart_0_buffer.rx_buf[0] = (uint8_t *)buffer_header;
	UARTx = UARTx;
	return 0;
}
Пример #4
0
void mac_gts_table_update(void)
{
    uint8_t table_index;

    for (table_index = 0; table_index < mac_pan_gts_table_len;
            table_index++) {
        if (mac_pan_gts_table[table_index].ExpiryCount > 0 &&
                --mac_pan_gts_table[table_index].ExpiryCount ==
                0) {
            gts_char_t gts_char;
            uint16_t dev_addr
                = mac_pan_gts_table[table_index].DevShortAddr;
            gts_char.GtsDirection
                = mac_pan_gts_table[table_index].GtsDesc
                  .GtsDirection;
            gts_char.GtsLength
                = mac_pan_gts_table[table_index].GtsDesc
                  .GtsLength;
            gts_char.GtsCharType = GTS_DEALLOCATE;
            gts_char.Reserved = 0;
            if (mac_gts_deallocate(gts_char,
                                   mac_pan_gts_table[table_index].
                                   DevShortAddr, true)) {
                buffer_t *buffer_header;
                mlme_gts_ind_t *mgi;

                buffer_header = bmm_buffer_alloc(
                                    LARGE_BUFFER_SIZE);

                if (NULL == buffer_header) {
                    /* Buffer is not available */
                    return;
                }

                mgi = (mlme_gts_ind_t *)BMM_BUFFER_POINTER(
                          buffer_header);

                mgi->DeviceAddr = dev_addr;

                mgi->GtsChar = gts_char;
                mgi->cmdcode = MLME_GTS_INDICATION;

                /* Append the MLME GTS indication to the
                 *MAC-NHLE queue. */
                qmm_queue_append(&mac_nhle_q, buffer_header);
                --table_index;
            }
        }
    }
}
Пример #5
0
bool wpan_mlme_associate_resp(uint64_t DeviceAddress,
                              uint16_t AssocShortAddress,
                              uint8_t status)
{
    buffer_t *buffer_header;
    mlme_associate_resp_t *mlme_associate_resp;

    /* Allocate a small buffer for association response */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buffer_header) {
        /* Buffer is not available */
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_associate_resp = (mlme_associate_resp_t *)BMM_BUFFER_POINTER(
                              buffer_header);

    /* Construct mlme_associate_resp_t message */
    mlme_associate_resp->cmdcode = MLME_ASSOCIATE_RESPONSE;

    /* Other fields */
#ifdef TEST_HARNESS_BIG_ENDIAN
    mlme_associate_resp->DeviceAddress  = CPU_ENDIAN_TO_LE64(DeviceAddress);
    mlme_associate_resp->AssocShortAddress = CPU_ENDIAN_TO_LE16(
                AssocShortAddress);
#else
    mlme_associate_resp->DeviceAddress  = DeviceAddress;
    mlme_associate_resp->AssocShortAddress = AssocShortAddress;
#endif
    mlme_associate_resp->status = status;

    /* Insert mlme_associate_resp_t into NHLE MAC queue */
#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-ASSOCIATE.response is not appended into NHLE MAC
         * queue, hence free the buffer allocated
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #6
0
bool wpan_mlme_poll_req(wpan_addr_spec_t *CoordAddrSpec)
{
    buffer_t *buffer_header;
    mlme_poll_req_t *mlme_poll_req;

    /* Allocate a small buffer for poll request */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buffer_header) {
        /* Buffer is not available */
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_poll_req = (mlme_poll_req_t *)BMM_BUFFER_POINTER(buffer_header);

    /* construct mlme_poll_req_t message */
    mlme_poll_req->cmdcode = MLME_POLL_REQUEST;

    /* Other fileds. */
    mlme_poll_req->CoordAddrMode = CoordAddrSpec->AddrMode;
#ifdef TEST_HARNESS_BIG_ENDIAN
    mlme_poll_req->CoordPANId = CPU_ENDIAN_TO_LE16(CoordAddrSpec->PANId);
#else
    mlme_poll_req->CoordPANId = CoordAddrSpec->PANId;
#endif
    if (WPAN_ADDRMODE_SHORT == CoordAddrSpec->AddrMode) {
        ADDR_COPY_DST_SRC_16(mlme_poll_req->CoordAddress,
                             CoordAddrSpec->Addr.short_address);
    } else {
        ADDR_COPY_DST_SRC_64(mlme_poll_req->CoordAddress,
                             CoordAddrSpec->Addr.long_address);
    }

#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-POLL.request is not appended into NHLE MAC
         * queue, hence free the buffer allocated and return false
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #7
0
bool wpan_mlme_disassociate_req(wpan_addr_spec_t *DeviceAddrSpec,
                                uint8_t DisassociateReason,
                                bool TxIndirect)
{
    buffer_t *buffer_header;
    mlme_disassociate_req_t *mlme_disassociate_req;

    /* Allocate a small buffer for disassociation request */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buffer_header) {
        /* Buffer is not available */
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_disassociate_req = (mlme_disassociate_req_t *)BMM_BUFFER_POINTER(
                                buffer_header);

    /* Update the disassociate request structure */
    mlme_disassociate_req->cmdcode = MLME_DISASSOCIATE_REQUEST;
    mlme_disassociate_req->DisassociateReason = DisassociateReason;
    mlme_disassociate_req->DeviceAddrMode = DeviceAddrSpec->AddrMode;
#ifdef TEST_HARNESS_BIG_ENDIAN
    mlme_disassociate_req->DevicePANId = CPU_ENDIAN_TO_LE16(
            DeviceAddrSpec->PANId);
#else
    mlme_disassociate_req->DevicePANId = DeviceAddrSpec->PANId;
#endif
    ADDR_COPY_DST_SRC_64(mlme_disassociate_req->DeviceAddress,
                         DeviceAddrSpec->Addr.long_address);
    mlme_disassociate_req->TxIndirect = TxIndirect;

#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-DISASSOCIATE.request is not appended into NHLE MAC
         * queue, hence free the buffer allocated and return false
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #8
0
// Target function to timer, sends ping packet after a delay
void mp(void)
{
   uint8_t* pFrame = bmm_buffer_alloc();

   if(pFrame != NULL)
   {
      ftPing *frame = (ftPing*)(((rx_frame_t*)pFrame)->data);

      frame->fcf = FCF_DATA;
      frame->seq = macConfig.dsn++;
      frame->panid = macConfig.panId;
      frame->srcAddr = macConfig.shortAddress;
      frame->originAddr = macConfig.shortAddress;
      frame->finalDestAddr = pingAddr;
      frame->type = pingType;
      frame->rssi = radioGetSavedRssiValue();
      frame->lqi = radioGetSavedLqiValue();

      ((rx_frame_t*)pFrame)->length = sizeof(ftPing);

      if (NODETYPE == COORD)
      {
         // Find the top parent
         u8 addr = macGetTopParent(pingAddr);
         frame->destAddr = addr;
         // See if the child is sleeping (only the coord sends directly to a child node)
         if (RUMSLEEP && macIsChild(addr) && macIsChildSleeping(addr))
         {
            // Send it later, after child is awake
            macHoldFrame(addr, pFrame);
            // buffer is freed inside macHoldFrame()
            // Don't send frame right now
            return;
         }
      }
      else // End/router nodes
      {
         frame->destAddr = macConfig.parentShortAddress;
      }

      event_object_t event;
      event.event = MAC_EVENT_SEND;
      event.data = pFrame;
      event.callback = 0;

      // save Event
      mac_put_event(&event);
   }
}
Пример #9
0
bool wpan_mlme_orphan_resp(uint64_t OrphanAddress,
                           uint16_t ShortAddress,
                           bool AssociatedMember)
{
    buffer_t *buffer_header;
    mlme_orphan_resp_t *mlme_orphan_resp;

    /* Allocate a small buffer for orphan response */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buffer_header) {
        /* Buffer is not available */
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_orphan_resp = (mlme_orphan_resp_t *)BMM_BUFFER_POINTER(
                           buffer_header);

    /* Update the orphan response structure */
    mlme_orphan_resp->cmdcode = MLME_ORPHAN_RESPONSE;
#ifdef TEST_HARNESS_BIG_ENDIAN
    mlme_orphan_resp->OrphanAddress = CPU_ENDIAN_TO_LE64(OrphanAddress);
    mlme_orphan_resp->ShortAddress  = CPU_ENDIAN_TO_LE16(ShortAddress);
#else
    mlme_orphan_resp->OrphanAddress = OrphanAddress;
    mlme_orphan_resp->ShortAddress  = ShortAddress;
#endif
    mlme_orphan_resp->AssociatedMember = AssociatedMember;

#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-ORPHAN.response is not appended into NHLE MAC
         * queue, hence free the buffer allocated and return false
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #10
0
int32_t wnet_dataframe_send(rcp_txinfo_t *txinfo, 
                           uint8_t *databuf, 
                           uint32_t datalen)
{
    buffer_t *buffer_header;
    uint8_t *nlde_data_req;
    if (uart_0_buffer.rx_buf_head == NULL)
    	return -1;
     AppFrameHeader_t *app = (AppFrameHeader_t *)uart_0_buffer.rx_buf_head;
    *uart_0_buffer.rx_buf_head = 0xF1;
    *(uart_0_buffer.rx_buf_head+1) = 0x00;



    app->AppSequenceNumber = gNwk_nib.sequenceNumber;
    app->DstAddress = 0xFFFF;

    app->length = datalen;
    memcpy(app->AppPayload,databuf,datalen);
    uart_0_buffer.rx_buf_head[app->length +7] = XORSUM((uint8_t *)app,app->length +7);


    wpan_nlde_data_req( NWK_DSTADDRMODE_RESPONSE,
    					app->DstAddress,
    					app->length +8,
                                 uart_0_buffer.rx_buf_head,
                                 uart_0_buffer.rx_buf[0],
    					txinfo->hops,
    					0,
    					true,
    					UART_ALLOC,
    					APP_ROUTE_MESH);
    					
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);
    if (buffer_header == NULL)
		{
			uart_0_buffer.rx_buf_head = NULL;
    	return -1;
		}
    nlde_data_req = BMM_BUFFER_POINTER(buffer_header);
    uart_0_buffer.rx_buf_head = (nlde_data_req) + (LARGE_BUFFER_SIZE - FCS_LEN - TRANSPARENT_IO_BUF_SIZE);
    uart_0_buffer.rx_buf[0] = (uint8_t *)buffer_header;							

    return 1;
}
Пример #11
0
/**
 * @brief Completes Rx transaction
 *
 * @param trx_id Transceiver identifier
 */
void complete_rx_transaction(trx_id_t trx_id)
{
	/* Get energy of received frame */
	uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id;
	uint8_t ed = trx_reg_read(reg_offset + RG_RF09_EDV);
	uint16_t ed_pos = rx_frm_info[trx_id]->len_no_crc + 1 +
			tal_pib[trx_id].FCSLen;
	rx_frm_info[trx_id]->mpdu[ed_pos] = ed; /* PSDU, LQI, ED */

	/* Append received frame to incoming_frame_queue and get new rx buffer.
	 **/
	qmm_queue_append(&tal_incoming_frame_queue[trx_id],
			tal_rx_buffer[trx_id]);
	/* The previous buffer is eaten up and a new buffer is not assigned yet.
	 **/
	tal_rx_buffer[trx_id] = bmm_buffer_alloc(LARGE_BUFFER_SIZE);
	/* Switch to rx again to handle buffer shortage */
	switch_to_rx(trx_id);
}
Пример #12
0
bool wpan_mlme_scan_req(uint8_t ScanType,
                        uint32_t ScanChannels,
                        uint8_t ScanDuration,
                        uint8_t ChannelPage)
{
    buffer_t *buffer_header;
    mlme_scan_req_t *mlme_scan_req;

    /* Allocate a small buffer for scan request */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buffer_header) {
        /* Buffer is not available */
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_scan_req = (mlme_scan_req_t *)BMM_BUFFER_POINTER(buffer_header);

    /* Update the scan request structure */
    mlme_scan_req->cmdcode = MLME_SCAN_REQUEST;
    mlme_scan_req->ScanType = ScanType;
    mlme_scan_req->ScanChannels = ScanChannels;
    mlme_scan_req->ScanDuration = ScanDuration;
    mlme_scan_req->ChannelPage = ChannelPage;

#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-SCAN.request is not appended into NHLE MAC
         * queue, hence free the buffer allocated and return false
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #13
0
bool wpan_mlme_get_req(uint8_t PIBAttribute)
#endif  /* (MAC_SECURITY_ZIP || MAC_SECURITY_2006) */
{
    buffer_t *buffer_header;
    mlme_get_req_t *mlme_get_req;

    /* Allocate a large buffer for get request as maximum beacon payload
     * should be accommodated */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    /* Check for buffer availability */
    if (NULL == buffer_header) {
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_get_req = (mlme_get_req_t *)BMM_BUFFER_POINTER(buffer_header);

    /* Update the get request structure */
    mlme_get_req->cmdcode = MLME_GET_REQUEST;
    mlme_get_req->PIBAttribute = PIBAttribute;
#if ((defined MAC_SECURITY_ZIP)  || (defined MAC_SECURITY_2006))
    mlme_get_req->PIBAttributeIndex = PIBAttributeIndex;
#endif  /* (MAC_SECURITY_ZIP || MAC_SECURITY_2006) */

#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-GET.request is not appended into NHLE MAC
         * queue, hence free the buffer allocated and return false
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #14
0
bool wpan_mlme_rx_enable_req(bool DeferPermit,
                             uint32_t RxOnTime,
                             uint32_t RxOnDuration)
{
    buffer_t *buffer_header;
    mlme_rx_enable_req_t *mlme_rx_enable_req;

    /* Allocate a small buffer for rx enable request */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buffer_header) {
        /* Buffer is not available */
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_rx_enable_req = (mlme_rx_enable_req_t *)BMM_BUFFER_POINTER(
                             buffer_header);

    /* Update the rx enable request structure */
    mlme_rx_enable_req->cmdcode = MLME_RX_ENABLE_REQUEST;
    mlme_rx_enable_req->DeferPermit = DeferPermit;
    mlme_rx_enable_req->RxOnTime = RxOnTime;
    mlme_rx_enable_req->RxOnDuration = RxOnDuration;

#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-RX-ENABLE.request is not appended into NHLE MAC
         * queue, hence free the buffer allocated and return false
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #15
0
bool wpan_mlme_sync_req(uint8_t LogicalChannel,
                        uint8_t ChannelPage,
                        bool TrackBeacon)
{
    buffer_t *buffer_header;
    mlme_sync_req_t *mlme_sync_req;

    /* Allocate a small buffer for sync request */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buffer_header) {
        /* Buffer is not available */
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_sync_req = (mlme_sync_req_t *)BMM_BUFFER_POINTER(buffer_header);

    /* Update the sync request structure */
    mlme_sync_req->cmdcode = MLME_SYNC_REQUEST;
    mlme_sync_req->LogicalChannel = LogicalChannel;
    mlme_sync_req->ChannelPage = ChannelPage;
    mlme_sync_req->TrackBeacon = TrackBeacon;

#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-SYNC.request is not appended into NHLE MAC
         * queue, hence free the buffer allocated and return false
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #16
0
bool wpan_mlme_gts_req(uint16_t DevShortAddr, gts_char_t GtsChar)
{
#ifdef GTS_SUPPORT
    buffer_t *buffer_header;
    mlme_gts_req_t *mlme_gts_req;

    /* Allocate a small buffer for gts request */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buffer_header) {
        /* Buffer is not available */
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_gts_req = (mlme_gts_req_t *)BMM_BUFFER_POINTER(buffer_header);

    /* construct mlme_gts_req_t message */
    mlme_gts_req->cmdcode = MLME_GTS_REQUEST;

    mlme_gts_req->DeviceShortAddr = CPU_ENDIAN_TO_LE16(DevShortAddr);
    /* Other fields. */
    mlme_gts_req->GtsChar = GtsChar;
#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-POLL.request is not appended into NHLE MAC
         * queue, hence free the buffer allocated and return false
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */
    return true;
#endif /* GTS_SUPPORT */
}
Пример #17
0
/**
   Send a frame that has been stored for a child node.  This is meant
   to be called immediately upon receiving a packet from a sleeping child node.
 */
void macSendStoredFrame(u16 addr)
{
   if (NODETYPE != ENDDEVICE && RUMSLEEP && VLP)
   {
      u8 i;

      // See if a frame is stored for this node
      for (i=0;i<STORED_FRAMES;i++)
      {
         if (storedFrames[i].len &&
               storedFrames[i].addr == addr)
         {
            // Send this frame, remove checksum
            uint8_t* pFrame = bmm_buffer_alloc();
            if(pFrame != NULL)
            {
               // restore stored frame
               memcpy(((rx_frame_t*)pFrame)->data, storedFrames[i].buf, storedFrames[i].len);

               ((rx_frame_t*)pFrame)->length = storedFrames[i].len;

               event_object_t event;
               event.event = MAC_EVENT_SEND;
               event.data = pFrame;
               event.callback = 0;

               // save Event
               mac_put_event(&event);

               // Clear out this frame
               storedFrames[i].len = 0;
            }

         }
      }
   }

}
Пример #18
0
bool wpan_mlme_reset_req(bool SetDefaultPib)
{
    buffer_t *buffer_header;
    mlme_reset_req_t *mlme_reset_req;

    /* Allocate a small buffer for reset request */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buffer_header) {
        /* Buffer is not available */
        return false;
    }

    /* Get the buffer body from buffer header */
    mlme_reset_req = (mlme_reset_req_t *)BMM_BUFFER_POINTER(buffer_header);

    /* Update the reset request structure */
    mlme_reset_req->cmdcode = MLME_RESET_REQUEST;
    mlme_reset_req->SetDefaultPIB = SetDefaultPib;

#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MLME-RESET.request is not appended into NHLE MAC
         * queue, hence free the buffer allocated and return false
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #19
0
bool wpan_mcps_purge_req(uint8_t msduHandle)
{
    buffer_t *buffer_header;
    mcps_purge_req_t *mcps_purge_req;

    /* Allocate small buffer for mcps purge request */
    buffer_header = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buffer_header) {
        /* Buffer is not available */
        return false;
    }

    /* Get the buffer body from buffer header */
    mcps_purge_req = (mcps_purge_req_t *)BMM_BUFFER_POINTER(buffer_header);

    /* Update the purge request structure */
    mcps_purge_req->cmdcode = MCPS_PURGE_REQUEST;
    mcps_purge_req->msduHandle = msduHandle;

#ifdef ENABLE_QUEUE_CAPACITY
    if (MAC_SUCCESS != qmm_queue_append(&nhle_mac_q, buffer_header)) {
        /*
         * MCPS-PURGE.request is not appended into NHLE MAC
         * queue, hence free the buffer allocated and return false
         */
        bmm_buffer_free(buffer_header);
        return false;
    }

#else
    qmm_queue_append(&nhle_mac_q, buffer_header);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return true;
}
Пример #20
0
/**
 * @brief Initializes the TAL
 *
 * This function is called to initialize the TAL. The transceiver is
 * initialized, the TAL PIBs are set to their default values, and the TAL state
 * machine is set to TAL_IDLE state.
 *
 * @return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF and the
 *                 current device part number and version number are correct;
 *         FAILURE otherwise
 */
retval_t tal_init(void)
{
    /* Init the PAL and by this means also the transceiver interface */
    if (pal_init() != MAC_SUCCESS)
    {
        return FAILURE;
    }

    if (trx_init() != MAC_SUCCESS)
    {
        return FAILURE;
    }

#if (EXTERN_EEPROM_AVAILABLE == 1)
    pal_ps_get(EXTERN_EEPROM, EE_IEEE_ADDR, 8, &tal_pib.IeeeAddress);
#else
    pal_ps_get(INTERN_EEPROM, EE_IEEE_ADDR, 8, &tal_pib.IeeeAddress);
#endif

    /*
     * Do the reset stuff.
     * Set the default PIBs.
     * Generate random seed.
     */
    if (internal_tal_reset(true) != MAC_SUCCESS)
    {
        return FAILURE;
    }

#ifndef DISABLE_IEEE_ADDR_CHECK
    /* Check if a valid IEEE address is available. */
    /*
     * This while loop is on purpose, since just in the
     * rare case that such an address is randomly
     * generated again, we must repeat this.
     */
    while ((tal_pib.IeeeAddress == 0x0000000000000000) ||
            (tal_pib.IeeeAddress == 0xFFFFFFFFFFFFFFFF)
          )
    {
        /*
         * In case no valid IEEE address is available, a random
         * IEEE address will be generated to be able to run the
         * applications for demonstration purposes.
         * In production code this can be omitted.
         */
        /*
         * The proper seed for function rand() has already been generated
         * in function tal_generate_rand_seed().
         */
        uint8_t *ptr_pib = (uint8_t *)&tal_pib.IeeeAddress;

        for (uint8_t i = 0; i < 8; i++)
        {
            *ptr_pib++ = (uint8_t)rand();
            /*
             * Note:
             * Even if casting the 16 bit rand value back to 8 bit,
             * and running the loop 8 timers (instead of only 4 times)
             * may look cumbersome, it turns out that the code gets
             * smaller using 8-bit here.
             * And timing is not an issue at this place...
             */
        }
    }
#endif  /* #ifndef DISABLE_IEEE_ADDR_CHECK */

    /*
     * Configure interrupt handling.
     * Install handlers for the transceiver interrupts.
     */
    pal_trx_irq_init_rx_end((FUNC_PTR)trx_rx_end_handler_cb);
    pal_trx_irq_init_tx_end((FUNC_PTR)trx_tx_end_handler_cb);
    pal_trx_irq_init_awake((FUNC_PTR)trx_awake_handler_cb);

#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)
    /* Configure time stamp interrupt. */
    pal_trx_irq_init_tstamp((FUNC_PTR)trx_irq_timestamp_handler_cb);
#endif /* (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */

    /* Initialize the buffer management module and get a buffer to store reveived frames. */
    bmm_buffer_init();
    tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    /* Init incoming frame queue */
#ifdef ENABLE_QUEUE_CAPACITY
    qmm_queue_init(&tal_incoming_frame_queue, TAL_INCOMING_FRAME_QUEUE_CAPACITY);
#else
    qmm_queue_init(&tal_incoming_frame_queue);
#endif  /* ENABLE_QUEUE_CAPACITY */

#ifdef ENABLE_TFA
    tfa_init();
#endif

    return MAC_SUCCESS;
} /* tal_init() */
Пример #21
0
/**
 * @brief TAL task handling
 *
 * This function
 * - Checks and allocates the receive buffer.
 * - Processes the TAL incoming frame queue.
 * - Implements the TAL state machine.
 */
void tal_task(void)
{
    /* Check if the receiver needs to be switched on. */
    if (tal_rx_on_required && (tal_state == TAL_IDLE))
    {
        /* Check if a receive buffer has not been available before. */
        if (tal_rx_buffer == NULL)
        {
            tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE);
        }

        /* Check if buffer could be allocated */
        if (NULL != tal_rx_buffer)
        {
            /*
             * Note:
             * This flag needs to be reset BEFORE the received is switched on.
             */
            tal_rx_on_required = false;

#ifdef PROMISCUOUS_MODE
            if (tal_pib.PromiscuousMode)
            {
                set_trx_state(CMD_RX_ON);
            }
            else
            {
                set_trx_state(CMD_RX_AACK_ON);
            }
#else   /* Normal operation */
            set_trx_state(CMD_RX_AACK_ON);
#endif
        }
    }
    else
    {
        /* no free buffer is available; try next time again */
    }

    /*
     * If the transceiver has received a frame and it has been placed
     * into the queue of the TAL, the frame needs to be processed further.
     */
    if (tal_incoming_frame_queue.size > 0)
    {
        buffer_t *rx_frame;

        /* Check if there are any pending data in the incoming_frame_queue. */
        rx_frame = qmm_queue_remove(&tal_incoming_frame_queue, NULL);
        if (NULL != rx_frame)
        {
            process_incoming_frame(rx_frame);
        }
    }

    /* Handle the TAL state machines */
    switch (tal_state)
    {
        case TAL_IDLE:
            /* Do nothing, but fall through... */
        case TAL_TX_AUTO:
            /* Wait until state is changed to TAL_TX_DONE inside tx end ISR */
            break;

        case TAL_TX_DONE:
            tx_done_handling();    // see tal_tx.c
            break;

#ifdef BEACON_SUPPORT
        case TAL_SLOTTED_CSMA:
            slotted_csma_state_handling();  // see tal_slotted_csma.c
            break;
#endif  /* BEACON_SUPPORT */

#if (MAC_SCAN_ED_REQUEST_CONFIRM == 1)
        case TAL_ED_RUNNING:
            /* Do nothing here. Wait until ED is completed. */
            break;

        case TAL_ED_DONE:
            ed_scan_done();
            break;
#endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */
        default:
            ASSERT("tal_state is not handled" == 0);
            break;
    }
} /* tal_task() */
Пример #22
0
/*
 * \brief Handle received frame interrupt
 *
 * This function handles transceiver interrupts for received frames and
 * uploads the frames from the trx.
 */
void handle_received_frame_irq(void)
{
    uint8_t ed_value;
    /* Actual frame length of received frame. */
    uint8_t phy_frame_len;
    /* Extended frame length appended by LQI and ED. */
    uint8_t ext_frame_length;
    frame_info_t *receive_frame;
    uint8_t *frame_ptr;

    if (tal_rx_buffer == NULL)
    {
        Assert("no tal_rx_buffer available" == 0);
        /*
         * Although the buffer protection mode is enabled and the receiver has
         * been switched to PLL_ON, the next incoming frame was faster.
         * It cannot be handled and is discarded.
         */
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_DISABLE);  /* Disable buffer protection mode */
        pal_timer_delay(2); // Allow pin change to get effective
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE);  /* Enable buffer protection mode */
        return;
    }

    receive_frame = (frame_info_t *)BMM_BUFFER_POINTER(tal_rx_buffer);

#ifdef PROMISCUOUS_MODE
    if (tal_pib.PromiscuousMode)
    {
        /* Check for valid FCS */
        if (pal_trx_bit_read(SR_RX_CRC_VALID) == CRC16_NOT_VALID)
        {
            return;
        }
    }
#endif

    /* Get ED value; needed to normalize LQI. */
    ed_value = pal_trx_reg_read(RG_PHY_ED_LEVEL);

    /* Get frame length from transceiver. */
    phy_frame_len = ext_frame_length = pal_trx_reg_read(RG_TST_RX_LENGTH);

    /* Check for valid frame length. */
    if (phy_frame_len > 127)
    {
        return;
    }

    /*
     * The PHY header is also included in the frame (length field), hence the frame length
     * is incremented.
     * In addition to that, the LQI and ED value are uploaded, too.
     */
    ext_frame_length += LQI_LEN + ED_VAL_LEN;

    /* Update payload pointer to store received frame. */
    frame_ptr = (uint8_t *)receive_frame + LARGE_BUFFER_SIZE - ext_frame_length;

    /*
     * Note: The following code is different from other non-single chip
     * transceivers, where reading the frame via SPI contains the length field
     * in the first octet.
     */
    pal_trx_frame_read(frame_ptr, phy_frame_len + LQI_LEN);
    frame_ptr--;
    *frame_ptr = phy_frame_len;
    receive_frame->mpdu = frame_ptr;
    /* Add ED value at the end of the frame buffer. */
    receive_frame->mpdu[phy_frame_len + LQI_LEN + ED_VAL_LEN] = ed_value;


#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)
    /*
     * Store the timestamp.
     * The timestamping is only required for beaconing networks
     * or if timestamping is explicitly enabled.
     */
    receive_frame->time_stamp = tal_rx_timestamp;
#endif  /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */

    /* Append received frame to incoming_frame_queue and get new rx buffer. */
    qmm_queue_append(&tal_incoming_frame_queue, tal_rx_buffer);

    /* The previous buffer is eaten up and a new buffer is not assigned yet. */
    tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    /* Check if receive buffer is available */
    if (NULL == tal_rx_buffer)
    {
        /*
         * Turn off the receiver until a buffer is available again.
         * tal_task() will take care of eventually reactivating it.
         * Due to ongoing ACK transmission do not force to switch it off.
         */

        /* Do not change the state since buffer protection mode is not re-enabled yet.
         * Buffer protection will be re-enabled after buffer becomes available
         */
        //set_trx_state(CMD_PLL_ON);
        tal_rx_on_required = true;
    }
    else
    {
        /*
         * Trx returns to RX_AACK_ON automatically, if this was its previous state.
         * Keep the following as a reminder, if receiver is used with RX_ON instead.
         */
        //pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
        /*
         * Release the protected buffer and set it again for further protection since
         * the buffer is available
         */
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_DISABLE);  /* Disable buffer protection mode */
        pal_timer_delay(2); // Allow pin change to get effective
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE);  /* Enable buffer protection mode */
    }

    /*
     * Clear pending TX_END IRQ: The TX_END IRQ is envoked for the transmission
     * end of an automatically sent ACK frame. This implementation does not use
     * this feature.
     */
    pal_trx_irq_flag_clr_tx_end();
}
Пример #23
0
/*
 * @brief Continues handling of MLME_SCAN.request once the radio is awake
 *
 * @param scan_buf Pointer to Scan request buffer.
 */
static void mac_awake_scan(buffer_t *scan_buf)
{
	mlme_scan_conf_t *msc;
	msc = (mlme_scan_conf_t *)BMM_BUFFER_POINTER(scan_buf);

	/* Set the first channel at which the scan is started */
	scan_curr_channel = MIN_CHANNEL;

	switch (scan_type) {
#if (MAC_SCAN_ED_REQUEST_CONFIRM == 1)
	case MLME_SCAN_TYPE_ED:
		msc->scan_result_list[0].ed_value[1] = 0; /* First channel's
		                                           * accumulated energy
		                                           * level */
		mac_scan_state = MAC_SCAN_ED;
		scan_proceed(MLME_SCAN_TYPE_ED, (buffer_t *)scan_buf);
		break;
#endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */

#if ((MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1) || \
		(MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1))
	case MLME_SCAN_TYPE_ACTIVE:
	case MLME_SCAN_TYPE_PASSIVE:
	{
		/*
		 * Before commencing an active or passive scan, the MAC sublayer
		 * shall store the value of macPANId and then set it to 0cFFFF
		 * for
		 * the duration of the scan. This enables the receive filter to
		 * accept all beacons rather than just the beacons from its
		 * current PAN (see 7.5.6.2). On completion of the scan, the
		 * MAC sublayer shall restore the value of macPANId to the
		 * value stored before the scan began.
		 */
		uint16_t broadcast_panid = BROADCAST;

		mac_scan_orig_panid = tal_pib.PANId;

#if (_DEBUG_ > 0)
		retval_t set_status =
#endif
		set_tal_pib_internal(macPANId, (void *)&broadcast_panid);

#if (_DEBUG_ > 0)
		Assert(MAC_SUCCESS == set_status);
		set_status = set_status;
#endif
		if (MLME_SCAN_TYPE_ACTIVE == scan_type) {
			/*
			 * In active scan reuse the scan request buffer for
			 * sending beacon request.
			 */
			mac_scan_cmd_buf_ptr = (uint8_t *)scan_buf;
		}

		/* Allocate a large size buffer for scan confirm. */
		mac_conf_buf_ptr
			= (uint8_t *)bmm_buffer_alloc(LARGE_BUFFER_SIZE);

		if (NULL == mac_conf_buf_ptr) {
			/*
			 * Large buffer is not available for sending scan
			 * confirmation,
			 * hence the scan request buffer (small buffer) is used
			 * to send
			 * the scan confirmation.
			 */
			msc->status = MAC_INVALID_PARAMETER;

			/* Append scan confirm message to the MAC-NHLE queue */
			qmm_queue_append(&mac_nhle_q, scan_buf);

			/* Set radio to sleep if allowed */
			mac_sleep_trans();
			return;
		}

		if (MLME_SCAN_TYPE_PASSIVE == scan_type) {
			/* Free the scan request buffer when in passive scan. */
			bmm_buffer_free(scan_buf);
		}

		msc = (mlme_scan_conf_t *)BMM_BUFFER_POINTER(
				(buffer_t *)mac_conf_buf_ptr);

		msc->cmdcode = MLME_SCAN_CONFIRM;
		msc->ScanType = scan_type;
		msc->ChannelPage = scan_curr_page;
		msc->UnscannedChannels = scan_channels;
		msc->ResultListSize = 0;
		msc->scan_result_list[0].ed_value[0] = 0;

		scan_proceed(scan_type, (buffer_t *)mac_conf_buf_ptr);
		break;
	}
#endif /* ((MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1) ||
		 *(MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1)) */

#if (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1)
	case MLME_SCAN_TYPE_ORPHAN:
		/* Buffer allocated for orphan notification command */
		mac_scan_cmd_buf_ptr
			= (uint8_t *)bmm_buffer_alloc(LARGE_BUFFER_SIZE);

		if (NULL == mac_scan_cmd_buf_ptr) {
			msc->status = MAC_INVALID_PARAMETER;

			/* Append scan confirm message to the MAC-NHLE queue */
			qmm_queue_append(&mac_nhle_q, scan_buf);

			/* Set radio to sleep if allowed */
			mac_sleep_trans();
			return;
		}

		scan_proceed(MLME_SCAN_TYPE_ORPHAN,
				(buffer_t *)mac_conf_buf_ptr);
		break;
#endif /* (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1) */

	default:
		msc->status = MAC_INVALID_PARAMETER;
		/* Append scan confirm message to the MAC-NHLE queue */
		qmm_queue_append(&mac_nhle_q, scan_buf);

		/* Set radio to sleep if allowed */
		mac_sleep_trans();
		break;
	}
} /* mac_awake_scan() */
Пример #24
0
/*
 * @brief Constructs a null data frame
 *
 * @return Pointer to the created null data frame, NULL otherwise.
 */
static buffer_t *build_null_data_frame(void)
{
    bool use_long_addr_dest;
    frame_info_t *transmit_frame;
    uint8_t frame_len;
    uint8_t *frame_ptr;
    uint16_t fcf = 0;
    buffer_t *buf_ptr = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buf_ptr)
    {
        return NULL;
    }

    transmit_frame = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr);

    /* No data payload, this is a null packet.*/
    transmit_frame->msg_type = NULL_FRAME;
    transmit_frame->buffer_header = buf_ptr;

    /* No indirect transmission. */
    transmit_frame->indirect_in_transit = false;

    /* Update the payload length. */
    frame_len = 2 +  // Add 2 octets for FCS
                2 +  // 2 octets for short Destination Address
                2 +  // 2 octets for Destination PAN-Id
                2 +  // 2 octets for short Source Address
                3;   // 3 octets DSN and FCF

    /* Get the payload pointer. */
    frame_ptr = (uint8_t *)transmit_frame + LARGE_BUFFER_SIZE - 2;  /* Add 2 octets for FCS. */

    /*
     * Set Source Address.
     */
    if ((BROADCAST == tal_pib.ShortAddress) ||
        (MAC_NO_SHORT_ADDR_VALUE == tal_pib.ShortAddress)
       )
    {
        /* Use long address as source address. */
        frame_ptr -= 8;
        frame_len += 6;
        convert_64_bit_to_byte_array(tal_pib.IeeeAddress, frame_ptr);
        fcf |= FCF_SET_SOURCE_ADDR_MODE(FCF_LONG_ADDR);
    }
    else
    {
        /* Use short address as source address. */
        frame_ptr -= 2;
        convert_16_bit_to_byte_array(tal_pib.ShortAddress, frame_ptr);
        fcf |= FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR);
    }

    /* Shall the Intra-PAN bit set? */
    if (tal_pib.PANId == mac_parse_data.src_panid)
    {
        /*
         * Both PAN-Ids are identical.
         * Set intra-PAN bit.
         */
        fcf |= FCF_PAN_ID_COMPRESSION;
    }
    else
    {
        /* Set Source PAN-Id. */
        frame_ptr -= 2;
        frame_len += 2;
        convert_16_bit_to_byte_array(tal_pib.PANId, frame_ptr);
    }


    /* Set Destination Address. */
    use_long_addr_dest = (FCF_LONG_ADDR == mac_parse_data.src_addr_mode);

    /* Destination address is set from source address of received frame. */
    if (use_long_addr_dest)
    {
        frame_ptr -= 8;
        frame_len += 6;
        convert_64_bit_to_byte_array(mac_parse_data.src_addr.long_address, frame_ptr);

        fcf |= FCF_SET_DEST_ADDR_MODE(FCF_LONG_ADDR) |
              FCF_SET_FRAMETYPE(FCF_FRAMETYPE_DATA);
    }
    else
    {
        frame_ptr -= 2;
        convert_16_bit_to_byte_array(mac_parse_data.src_addr.short_address, frame_ptr);
        fcf |= FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR) |
              FCF_SET_FRAMETYPE(FCF_FRAMETYPE_DATA);
    }


    /* Destination PANId is set from source PANId of received frame. */
    frame_ptr -= 2;
    convert_16_bit_to_byte_array(mac_parse_data.src_panid, frame_ptr);


    /* Set DSN. */
    frame_ptr--;
    *frame_ptr = mac_pib.mac_DSN++;


    /* Set the FCF. */
    frame_ptr -= 2;
    convert_spec_16_bit_to_byte_array(fcf, frame_ptr);


    /* First element shall be length of PHY frame. */
    frame_ptr--;
    *frame_ptr = frame_len;

    /* Finished building of frame. */
    transmit_frame->mpdu = frame_ptr;

    return buf_ptr;
} /* build_null_data_frame() */
Пример #25
0
/**
 * @brief Build and transmits data request command frame
 *
 * This function builds and tranmits a data request command frame.
 *
 *
 * @param expl_poll Data request due to explicit MLME poll request
 * @param force_own_long_addr Forces the usage of the Extended Address as
 *                            Source Address. This a allows for implicitly
 *                            poll for pending data at the coordinator if
 *                            the Extended Address was used in the Beacon frame.
 * @param expl_dest_addr_mode Mode of subsequent destination address to be used
 *                            explicitly (0/2/3).
 *                            0: No explicit destination address attached,
 *                               use either macCoordShortAddress or
 *                               macCoordExtendedAddress
 *                            2: Use explicitly attached address in parameter
 *                               expl_dest_addr as destination address as
 *                               short address
 *                            3: Use explicitly attached address in parameter
 *                               expl_dest_addr as destination address as
 *                               extended address
 * @param expl_dest_addr Explicitly attached destination address for data
 *                       request frame. This is to be treated as either not
 *                       present, short or extended address, depending on
 *                       parameter expl_dest_addr_mode.
 * @param expl_dest_pan_id Explicitly attached destination PAN-Id (Coordinator
 *                         PAN-Id) for data request frame.
 *                         This is to be treated only as present, depending on
 *                         parameter expl_dest_addr_mode.
 *
 * @return True if data request command frame was created and sent to
 *         the TAL successfully, false otherwise.
 */
bool mac_build_and_tx_data_req(bool expl_poll,
                               bool force_own_long_addr,
                               uint8_t expl_dest_addr_mode,
                               address_field_t *expl_dest_addr,
                               uint16_t expl_dest_pan_id)
{
    retval_t tal_tx_status;
    bool intrabit = false;
    uint8_t frame_len;
    uint8_t *frame_ptr;
    uint16_t fcf;
    buffer_t *buf_ptr = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    if (NULL == buf_ptr)
    {
        return false;
    }

    frame_info_t *transmit_frame = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr);

    /*
     * If this data request cmd frame was initiated by a device due to implicit
     * poll, set msgtype to DATAREQUEST_IMPL_POLL.
     * If this data request cmd frame was initiated by a MLME poll request,
     * set msgtype to DATAREQUEST.
     */
    if (expl_poll)
    {
        transmit_frame->msg_type = DATAREQUEST;
    }
    else
    {
        transmit_frame->msg_type = DATAREQUEST_IMPL_POLL;
    }

    /*
     * The buffer header is stored as a part of frame_info_t structure before the
     * frame is given to the TAL. After the transmission of the frame, reuse
     * the buffer using this pointer.
     */
    transmit_frame->buffer_header = buf_ptr;

    /* Update the payload length. */
    frame_len = DATA_REQ_PAYLOAD_LEN +
                2 + // Add 2 octets for FCS
                2 + // 2 octets for short Source Address
                2 + // 2 octets for short Destination Address
                2 + // 2 octets for Destination PAN-Id
                3;  // 3 octets DSN and FCF

    /* Get the payload pointer. */
    frame_ptr = (uint8_t *)transmit_frame +
                LARGE_BUFFER_SIZE -
                DATA_REQ_PAYLOAD_LEN - 2;   /* Add 2 octets for FCS. */

    /*
     * Build the command frame id.
     * This is actually being written into "transmit_frame->layload[0]".
     */
    *frame_ptr = DATAREQUEST;

    /* Source Address */
    /*
     * Long address needs to be used if a short address is not present
     * or if we are forced to use the long address.
     *
     * This is used for example in cases where the coordinator indicates
     * pending data for us using our extended address.
     *
     * This is also used for transmitting a data request frame
     * during association, since here we always need to use our
     * extended address.
     */
    if ((BROADCAST == tal_pib.ShortAddress) ||
        (CCPU_ENDIAN_TO_LE16(MAC_NO_SHORT_ADDR_VALUE) == tal_pib.ShortAddress) ||
        force_own_long_addr)
    {
        frame_ptr -= 8;
        frame_len += 6; // Add further 6 octets for long Source Address

        /* Build the Source address. */
        convert_64_bit_to_byte_array(tal_pib.IeeeAddress, frame_ptr);
        fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) |
              FCF_SET_SOURCE_ADDR_MODE(FCF_LONG_ADDR) |
              FCF_ACK_REQUEST;
    }
    else
    {
        frame_ptr -= 2;

        /* Build the Source address. */
        convert_16_bit_to_byte_array(tal_pib.ShortAddress, frame_ptr);

        fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) |
              FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR) |
              FCF_ACK_REQUEST;
    }


    /* Source PAN-Id */
    /*
     * In IEEE 802.15.4 the PAN ID Compression bit may always be set.
     * See page 154:
     * If the data request command is being sent in response to the receipt
     * of a beacon frame indicating that data are pending for that device,
     * the Destination Addressing Mode subfield of the Frame Control field
     * may be set to zero ..."
     * In order to keep the implementation simple the address info is also in
     * this case 2 or 3, i.e. the destination address info is present.
     * This in return means that the PAN ID Compression bit is always set for
     * data request frames, except the expl_dest_pan_id parameter is different from
     * our own PAN-Id PIB attribute.
     */
     if ((expl_dest_addr_mode != FCF_NO_ADDR) &&
        (expl_dest_pan_id != tal_pib.PANId)
       )
     {
        frame_ptr -= 2;
        frame_len += 2;  // Add further 6 octets for long Source Pan-Id

        convert_16_bit_to_byte_array(tal_pib.PANId, frame_ptr);
     }
     else
     {
    /*
     * The source PAN Id is not present since the PAN ID
     * Compression bit is set.
     */
        /* Set intra-PAN bit. */
        intrabit = true;
        fcf |= FCF_PAN_ID_COMPRESSION;
    }


    /* Destination Address */
    if (FCF_SHORT_ADDR == expl_dest_addr_mode)
    {
        /* An explicit short destination address is requested. */
        fcf |= FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR);

        frame_ptr -= 2;
        convert_16_bit_to_byte_array(expl_dest_addr->short_address, frame_ptr);
    }
    else if (FCF_LONG_ADDR == expl_dest_addr_mode)
    {
        /* An explicit long destination address is requested. */
        fcf |= FCF_SET_DEST_ADDR_MODE(FCF_LONG_ADDR);

        frame_ptr -= 8;
        frame_len += 6; // Add further 6 octets for long Destination Address
        convert_64_bit_to_byte_array(expl_dest_addr->long_address, frame_ptr);
    }
    else
    {
        /* No explicit destination address is requested. */
        if (CCPU_ENDIAN_TO_LE16(MAC_NO_SHORT_ADDR_VALUE) != mac_pib.mac_CoordShortAddress)
        {
            /*
             * If current value of short address for coordinator PIB is
             * NOT 0xFFFE, the current value of the short address for
             * coordinator shall be used as desination address.
             */
            fcf |= FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR);

            frame_ptr -= 2;
            convert_16_bit_to_byte_array(mac_pib.mac_CoordShortAddress, frame_ptr);
        }
        else
        {
            /*
             * If current value of short address for coordinator PIB is 0xFFFE,
             * the current value of the extended address for coordinator
             * shall be used as desination address.
             */
            fcf |= FCF_SET_DEST_ADDR_MODE(FCF_LONG_ADDR);

            frame_ptr -= 8;
            frame_len += 6; // Add further 6 octets for long Destination Address
            convert_64_bit_to_byte_array(mac_pib.mac_CoordExtendedAddress, frame_ptr);
        }
    }


    /* Destination PAN-Id */
    frame_ptr -= 2;

    if (intrabit)
    {
        /* Add our PAN-Id. */
        convert_16_bit_to_byte_array(tal_pib.PANId, frame_ptr);
    }
    else
    {
    /*
         * There is an expclicit destination address present AND
         * the destination PAN-Id is different from our own PAN-ID,
         * so include the source PAN-id into the frame.
     */
        convert_16_bit_to_byte_array(expl_dest_pan_id, frame_ptr);
    }


    /* Set DSN. */
    frame_ptr--;
    *frame_ptr = mac_pib.mac_DSN++;


    /* Set the FCF. */
    frame_ptr -= 2;
    convert_spec_16_bit_to_byte_array(fcf, frame_ptr);


    /* First element shall be length of PHY frame. */
    frame_ptr--;
    *frame_ptr = frame_len;

    /* Finished building of frame. */
    transmit_frame->mpdu = frame_ptr;


    /* Transmission should be done with CSMA-CA and frame retries. */
#ifdef BEACON_SUPPORT
    /*
     * Now it gets tricky:
     * In Beacon network the frame is sent with slotted CSMA-CA only if:
     * 1) the node is associated, or
     * 2) the node is idle, but synced before association,
     * 3) the node is a Coordinator (we assume, that coordinators are always
     *    in sync with their parents).
     *
     * In all other cases, the frame has to be sent using unslotted CSMA-CA.
     */
    csma_mode_t cur_csma_mode;

    if (NON_BEACON_NWK != tal_pib.BeaconOrder)
    {
        if (
            ((MAC_IDLE == mac_state) && (MAC_SYNC_BEFORE_ASSOC == mac_sync_state)) ||
#if (MAC_START_REQUEST_CONFIRM == 1)
            (MAC_ASSOCIATED == mac_state) ||
            (MAC_COORDINATOR == mac_state)
#else
            (MAC_ASSOCIATED == mac_state)
#endif /* MAC_START_REQUEST_CONFIRM */
           )
        {
            cur_csma_mode = CSMA_SLOTTED;
        }
        else
        {
            cur_csma_mode = CSMA_UNSLOTTED;
        }
    }
    else
    {
        /* In Nonbeacon network the frame is sent with unslotted CSMA-CA. */
        cur_csma_mode = CSMA_UNSLOTTED;
    }

    tal_tx_status = tal_tx_frame(transmit_frame, cur_csma_mode, true);
#else   /* No BEACON_SUPPORT */
    /* In Nonbeacon build the frame is sent with unslotted CSMA-CA. */
    tal_tx_status = tal_tx_frame(transmit_frame, CSMA_UNSLOTTED, true);
#endif  /* BEACON_SUPPORT */

    if (MAC_SUCCESS == tal_tx_status)
    {
        MAKE_MAC_BUSY();
        return true;
    }
    else
    {
        /* TAL is busy, hence the data request could not be transmitted */
        bmm_buffer_free(buf_ptr);

        return false;
    }
} /* mac_build_and_tx_data_req() */
Пример #26
0
/*
 * \brief Handle received frame interrupt
 *
 * This function handles transceiver interrupts for received frames and
 * uploads the frames from the trx.
 */
void handle_received_frame_irq(void)
{
	/* Actual frame length of received frame. */
	uint8_t phy_frame_len;
	/* Extended frame length appended by LQI and ED. */
	uint8_t ext_frame_length;
	frame_info_t *receive_frame;
	uint8_t *frame_ptr;

	if (tal_rx_buffer == NULL) {
		Assert("no tal_rx_buffer available" == 0);

		/*
		 * Although the buffer protection mode is enabled and the
		 *receiver has
		 * been switched to PLL_ON, the next incoming frame was faster.
		 * It cannot be handled and is discarded. Reading anything from
		 *the
		 * frame resets the buffer protection mode.
		 */
		uint8_t dummy;
		trx_frame_read(&dummy, 1);
		return;
	}

	receive_frame = (frame_info_t *)BMM_BUFFER_POINTER(tal_rx_buffer);

#ifdef PROMISCUOUS_MODE
	if (tal_pib.PromiscuousMode) {
		/* Check for valid FCS */
		if (trx_bit_read(SR_RX_CRC_VALID) == CRC16_NOT_VALID) {
			return;
		}
	}

#endif

#if (defined ENABLE_TRX_SRAM) || defined(ENABLE_TRX_SRAM_READ)
	/* Use SRAM read to keep rx safe mode armed. */
	trx_sram_read(0x00, &phy_frame_len, LENGTH_FIELD_LEN); /* 0x00: SRAM
	                                                        * offset address */
#else
	/* Get frame length from transceiver. */
	trx_frame_read(&phy_frame_len, LENGTH_FIELD_LEN);
#endif

	/* Check for valid frame length. */
	if (phy_frame_len > 127) {
		return;
	}

	/*
	 * The PHY header is also included in the frame (length field), hence
	 *the frame length
	 * is incremented.
	 * In addition to that, the LQI and ED value are uploaded, too.
	 */
	ext_frame_length = phy_frame_len + LENGTH_FIELD_LEN + LQI_LEN +
			ED_VAL_LEN;

	/* Update payload pointer to store received frame. */
	frame_ptr = (uint8_t *)receive_frame + LARGE_BUFFER_SIZE -
			ext_frame_length;

	/*
	 * Note: The following code is different from single chip
	 * transceivers, since reading the frame via SPI contains the length
	 *field
	 * in the first octet. RF232's frame buffer includes ED value too.
	 */
	trx_frame_read(frame_ptr,
			LENGTH_FIELD_LEN + phy_frame_len + LQI_LEN +
			ED_VAL_LEN);
	receive_frame->mpdu = frame_ptr;

#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)

	/*
	 * Store the timestamp.
	 * The timestamping is only required for beaconing networks
	 * or if timestamping is explicitly enabled.
	 */
	receive_frame->time_stamp = tal_timestamp;
#endif  /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */

	/* Append received frame to incoming_frame_queue and get new rx buffer.
	 **/
	qmm_queue_append(&tal_incoming_frame_queue, tal_rx_buffer);

	/* The previous buffer is eaten up and a new buffer is not assigned yet.
	 **/
	tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

	/* Check if receive buffer is available */
	if (NULL == tal_rx_buffer) {
		/*
		 * Turn off the receiver until a buffer is available again.
		 * tal_task() will take care of eventually reactivating it.
		 * Due to ongoing ACK transmission do not force to switch it
		 *off.
		 */
		set_trx_state(CMD_PLL_ON);
		tal_rx_on_required = true;
	} else {
		/*
		 * Trx returns to RX_AACK_ON automatically, if this was its
		 *previous state.
		 * Keep the following as a reminder, if receiver is used with
		 *RX_ON instead.
		 */
		/* trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON); */
	}
}
Пример #27
0
/**
 * @brief Initializes the TAL
 *
 * This function is called to initialize the TAL. The transceiver is
 * initialized, the TAL PIBs are set to their default values, and the TAL state
 * machine is set to TAL_IDLE state.
 *
 * @return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF and the
 *                 current device part number and version number are correct;
 *         FAILURE otherwise
 */
retval_t tal_init(void)
{
    /* Init the PAL and by this means also the transceiver interface */
#ifdef ENABLE_RP
    /*
     * The ranging processor (RP) only performs a minimalistic
     * initialization here.
     */
    pal_basic_init();
#else  /* !ENABLE_RP */
    if (pal_init() != MAC_SUCCESS)
    {
        return FAILURE;
    }

    if (trx_init() != MAC_SUCCESS)
    {
        return FAILURE;
    }

#if (EXTERN_EEPROM_AVAILABLE == 1)
    pal_ps_get(EXTERN_EEPROM, EE_IEEE_ADDR, 8, &tal_pib.IeeeAddress);
#else
    #if (USER_SIGN_AVAILABLE == 1)
        pal_ps_get(USER_SIGNATURE, USER_SIGNATURES_START + 2, 8, &tal_pib.IeeeAddress);
        //http://www.atmel.com/Images/Atmel-42172-Wireless-ZigBit-ATZB-X0-256-3-0-C_Datasheet.pdf
    #else
        pal_ps_get(INTERN_EEPROM, EE_IEEE_ADDR, 8, &tal_pib.IeeeAddress);
    #endif
#endif

    /*
     * Do the reset stuff.
     * Set the default PIBs.
     * Generate random seed.
     */
    if (internal_tal_reset(true) != MAC_SUCCESS)
    {
        return FAILURE;
    }

#ifndef DISABLE_IEEE_ADDR_CHECK
    /* Check if a valid IEEE address is available. */
    /*
     * This while loop is on purpose, since just in the
     * rare case that such an address is randomly
     * generated again, we must repeat this.
     */
    while ((tal_pib.IeeeAddress == 0x0000000000000000) ||
           (tal_pib.IeeeAddress == 0xFFFFFFFFFFFFFFFF))
    {
        /*
         * In case no valid IEEE address is available, a random
         * IEEE address will be generated to be able to run the
         * applications for demonstration purposes.
         * In production code this can be omitted.
         */
        /*
         * The proper seed for function rand() has already been generated
         * in function tal_generate_rand_seed().
         */
        uint8_t *ptr_pib = (uint8_t *)&tal_pib.IeeeAddress;

        for (uint8_t i = 0; i < 8; i++)
        {
            *ptr_pib++ = (uint8_t)rand();
            /*
             * Note:
             * Even if casting the 16 bit rand value back to 8 bit,
             * and running the loop 8 timers (instead of only 4 times)
             * may look cumbersome, it turns out that the code gets
             * smaller using 8-bit here.
             * And timing is not an issue at this place...
             */
        }
    }
#endif  /* #ifndef DISABLE_IEEE_ADDR_CHECK */
#endif  /* ENABLE_RP */

    /*
     * Configure interrupt handling.
     * Install a handler for the transceiver interrupt.
     */
    pal_trx_irq_init(trx_irq_handler_cb);
#ifndef ENABLE_RP
    pal_trx_irq_en();   /* Enable transceiver main interrupt. */
#endif

#if ((defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)) && (DISABLE_TSTAMP_IRQ == 0)
    /* Configure time stamp interrupt. */
    pal_trx_irq_init_tstamp(trx_irq_timestamp_handler_cb);
#ifndef ENABLE_RP
    pal_trx_irq_en_tstamp();    /* Enable timestamp interrupt. */
#endif
#endif

    /* Initialize the buffer management module and get a buffer to store received frames. */
    bmm_buffer_init();
    tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE);
#if DEBUG > 0
    if (tal_rx_buffer == NULL)
    {
        return FAILURE;
    }
#endif

    /* Init incoming frame queue */
#ifdef ENABLE_QUEUE_CAPACITY
    qmm_queue_init(&tal_incoming_frame_queue, TAL_INCOMING_FRAME_QUEUE_CAPACITY);
#else
    qmm_queue_init(&tal_incoming_frame_queue);
#endif  /* ENABLE_QUEUE_CAPACITY */

#ifdef ENABLE_TFA
    tfa_init();
#endif

    return MAC_SUCCESS;
} /* tal_init() */
Пример #28
0
/*! \brief  This function will upload a frame from the radio transceiver's frame
 *          buffer.
 *
 *          If the frame currently available in the radio transceiver's frame buffer
 *          is out of the defined bounds. Then the frame length, lqi value and crc
 *          be set to zero. This is done to indicate an error.
 *
 */
uint8_t* hal_frame_read(void)
{
   uint8_t* pFrame = bmm_buffer_alloc();

   if(pFrame != NULL)
   {
      rx_frame_t *rx_frame = (rx_frame_t*)pFrame;

#ifdef SINGLE_CHIP
      AVR_ENTER_CRITICAL_REGION();

      volatile uint8_t *pSrc = (volatile uint8_t *)0x180;
      uint8_t frame_length = hal_register_read(RG_TST_RX_LENGTH);
      if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH))
      {
         // read length and save frame content -> lqi is NOT included in frame length byte
         rx_frame->length = frame_length;
         //memcpy(rx_data, (void *)pSrc, frame_length);
         memcpy(rx_frame->data, (void *)pSrc, frame_length-1);
         // save LQI /
         //rx_frame->lqi = *(pSrc + (frame_length + 1));
         rx_frame->lqi = *(pSrc + frame_length);
      }
      else
      {
         rx_frame->length = 0;
         rx_frame->lqi    = 0;
         rx_frame->crc    = false;
         bmm_buffer_free(pFrame); // free allcoated buffer
         pFrame = NULL; // set buffer pointer to NULL, that next app do not use it
      }
      AVR_LEAVE_CRITICAL_REGION();
#else
      uint8_t* rx_data = &rx_frame->data[0];

      AVR_ENTER_CRITICAL_REGION();

      HAL_SS_LOW();

      //Send frame read command.
      SPDR = HAL_TRX_CMD_FR;
      while ((SPSR & (1 << SPIF)) == 0) {;}
      u8 frame_length = SPDR;

      //Read frame length.
      SPDR = frame_length;
      while ((SPSR & (1 << SPIF)) == 0) {;}
      frame_length = SPDR;

      //Check for correct frame length.
      if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH))
      {
         rx_frame->length = frame_length; //Store frame length.

         //Upload frame buffer to data pointer. Calculate CRC.
         SPDR = frame_length;
         while ((SPSR & (1 << SPIF)) == 0)
            ;

         do
         {
            u8 tempData = SPDR;
            SPDR = 0;       // dummy write

            //*rx_data++ = tempData;
            *rx_data = tempData;
            rx_data++;
            while ((SPSR & (1 << SPIF)) == 0)
               ;
         } while (--frame_length > 0);

         //Read LQI value for this frame.
         rx_frame->lqi = SPDR;

         HAL_SS_HIGH();
      }
      else
      {
         HAL_SS_HIGH();

         if (rx_frame)
         {
            rx_frame->length = 0;
            rx_frame->lqi    = 0;
            rx_frame->crc    = false;
            bmm_buffer_free(pFrame); // free allocated buffer
            pFrame = NULL; // set buffer pointer to NULL, that next app do not use it
         }
      }

      AVR_LEAVE_CRITICAL_REGION();

#endif // SINGLE_CHIP
   }
   return pFrame;
}
Пример #29
0
/*
 * \brief Initializes the TAL
 *
 * This function is called to initialize the TAL. The transceiver is
 * initialized, the TAL PIBs are set to their default values, and the TAL state
 * machine is set to TAL_IDLE state.
 *
 * \return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF and the
 *                 current device part number and version number are correct;
 *         FAILURE otherwise
 */
retval_t tal_init(void)
{
    /* Init the PAL and by this means also the transceiver interface */
    if (pal_init() != MAC_SUCCESS) {
        return FAILURE;
    }

    if (trx_init() != MAC_SUCCESS) {
        return FAILURE;
    }

    if (tal_timer_init() != MAC_SUCCESS) {
        return FAILURE;
    }

#ifdef ENABLE_STACK_NVM
    pal_ps_get(INTERN_EEPROM, EE_IEEE_ADDR, 8, &tal_pib.IeeeAddress);
#endif

    /*
     * For systems including the AT86RF230B the random seed generation
     * cannot be done using a dedicated hardware feature.
     * Therefore all random seed generation needs to be done by special
     * means (e.g. utilization of ADC) that generate a random value only
     * within a certain range.
     *
     * In case the node already has a valid IEEE address (i.e. an IEEE
     * address which is different from 0x0000000000000000 or
     * 0xFFFFFFFFFFFFFFFF), this IEEE address (the lower 16 bit)
     * shall be used as seed for srand(), since each node should have a
     *unique
     * IEEE address.
     * In this case srand() is called directly and function
     *tal_generate_rand_seed()
     * is not called.
     *
     * Note: This behaviour is different in all other TALs, since in these
     * cases the seed for srand() is always generated based on transceiver
     * hardware support.
     */

#ifndef DISABLE_IEEE_ADDR_CHECK
    if ((tal_pib.IeeeAddress == 0x0000000000000000) ||
            (tal_pib.IeeeAddress == 0xFFFFFFFFFFFFFFFF)
       ) {
        /*
         * Generate a seed for the random number generator in function
         *rand().
         * This is required (for example) as seed for the CSMA-CA
         *algorithm.
         */
        tal_generate_rand_seed();

        /*
         * Now that we have generated a random seed, we can generate a
         *random
         * IEEE address for this node.
         */
        do {
            /*
             * In case no valid IEEE address is available, a random
             * IEEE address will be generated to be able to run the
             * applications for demonstration purposes.
             * In production code this can be omitted.
             */

            /*
             * The proper seed for function rand() has already been
             *generated
             * in function tal_generate_rand_seed().
             */
            uint8_t *ptr_pib = (uint8_t *)&tal_pib.IeeeAddress;

            for (uint8_t i = 0; i < 8; i++) {
                *ptr_pib++ = (uint8_t)rand();

                /*
                 * Note:
                 * Even if casting the 16 bit rand value back to
                 *8 bit,
                 * and running the loop 8 timers (instead of
                 *only 4 times)
                 * may look cumbersome, it turns out that the
                 *code gets
                 * smaller using 8-bit here.
                 * And timing is not an issue at this place...
                 */
            }
        }
        /* Check if a valid IEEE address is available. */
        while ((tal_pib.IeeeAddress == 0x0000000000000000) ||
                (tal_pib.IeeeAddress == 0xFFFFFFFFFFFFFFFF)
              );
    } else {
        /* Valid IEEE address, so no need to generate a new random seed.
         **/
        uint16_t cur_rand_seed = (uint16_t)tal_pib.IeeeAddress;
        srand(cur_rand_seed);
    }

#else

    /*
     * No check for a valid IEEE address done, so directly create a seed
     * for srand().
     */
    tal_generate_rand_seed();
#endif

    /*
     * Do the reset stuff.
     * Set the default PIBs.
     */
    if (internal_tal_reset(true) != MAC_SUCCESS) {
        return FAILURE;
    }

    pal_trx_reg_read(RG_IRQ_STATUS); /* clear pending irqs, dummy read */

    /*
     * Configure interrupt handling.
     * Install a handler for the transceiver interrupt.
     */
    pal_trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
    pal_trx_irq_en(); /* Enable transceiver main interrupt. */

    /* Initialize the buffer management module and get a buffer to store
     *reveived frames. */
    bmm_buffer_init();
    tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    /* Init incoming frame queue */
#ifdef ENABLE_QUEUE_CAPACITY
    qmm_queue_init(&tal_incoming_frame_queue,
                   TAL_INCOMING_FRAME_QUEUE_CAPACITY);
#else
    qmm_queue_init(&tal_incoming_frame_queue);
#endif  /* ENABLE_QUEUE_CAPACITY */

    return MAC_SUCCESS;
} /* tal_init() */
Пример #30
0
/**
    @brief The macsixlowpanDataRequest function is used to send a frame over
    the air to another node.  Any node type can call this function.

    @param addr Short address of the destination node.

    @param len The length of the packet in bytes.

    @param data Pointer to the data to be sent.

    @param type Type of frame to be sent
 */
static void macDataRequestInt(u16 addr, u8 len, u8 * data, u8 type)
{
   u8 rpSent; // Was a routing packet sent?

   // Don't send to self
   if (addr == macConfig.shortAddress || addr == BROADCASTADDR)
   {
      return;
   }

   // This node has no short address
   if (!macConfig.associated)
   {
      return;
   }

   uint8_t* pFrame = bmm_buffer_alloc();

   if(pFrame != NULL)
   {
      // Create a struct pointer to the global variable...
      //ftData *data_frame = (ftData*)(mac_buffer_tx+1);

      ftData *data_frame = (ftData*)(((rx_frame_t*)pFrame)->data);

      // Build the frame.
      data_frame->fcf = FCF_DATA;
      data_frame->seq = macConfig.dsn++;
      data_frame->panid = macConfig.panId;
      data_frame->srcAddr = macConfig.shortAddress;
      data_frame->finalDestAddr = addr;
      data_frame->originAddr = macConfig.shortAddress;

      // send a routing packet if necessary
      rpSent = macSendRoutingPacket(addr);

      if (NODETYPE == COORD)
      {
         // Find the child node that can route this packet
         u16 child = addr;
         u16 parent = macGetParent(child);
         while (parent != DEFAULT_COORD_ADDR)
         {
            child = parent;
            parent = macGetParent(child);
         }
         // send to child node that can route this packet
         data_frame->destAddr = child;
      }
      else
         // All data is send to parent, unless this is a wakeup frame
         if (type == WAKE_NODE)
            data_frame->destAddr = addr;
         else
            data_frame->destAddr = macConfig.parentShortAddress;

      // Frame type is data
      if (macConfig.sleeping && NODETYPE == ENDDEVICE && RUMSLEEP)
      {
         type |= 0x80; // Set high bit of type if we're sleeping
      }

      data_frame->type = type;

      // Copy the payload data to frame. (note: this creates smaller code than using memcpy!!)
      u8 i;
      for(i=0; i<len; i++){
         ((u8*)&data_frame->payload)[i] = *data++;
      }

      // Check addresses again - addr will be different now -> Don't send to self
      if (data_frame->destAddr == macConfig.shortAddress || data_frame->destAddr == BROADCASTADDR)
      {
         bmm_buffer_free(pFrame);
         return;
      }

      ((rx_frame_t*)pFrame)->length = len + ftDataHeaderSize; // save length away

      if (NODETYPE == COORD)
      {
         // See if the child is sleeping (only the coord sends directly to a child node)
         if (RUMSLEEP && macIsChild(addr) && macIsChildSleeping(addr) && VLP) // Send it later, after child is awake
         {
            macHoldFrame(addr, pFrame);
            // buffer is freed inside macHoldFrame()
         }
         else // Node is not sleeping child, send it now.
         {
            event_object_t event;
            event.event = MAC_EVENT_SEND;
            event.data = pFrame;
            event.callback = 0;

            // save Event
            mac_put_event(&event);
         }
      }
      else
      {
         event_object_t event;
         event.event = MAC_EVENT_SEND;
         event.data = pFrame;
         event.callback = 0;

         // save Event
         mac_put_event(&event);
      }
      macConfig.busy = true;
   }
}