Example #1
0
/**
 * @brief Application task
 */
static void app_task(void)
{
    uint8_t number_of_bytes_to_be_transmitted;

    if (tx_state == TX_IDLE)
    {
        number_of_bytes_to_be_transmitted = pal_sio_rx(SIO_CHANNEL, sio_rx_data, MAX_APP_DATA_LENGTH);

        // If bytes are received via UART/USB, transmit the bytes.
        if (number_of_bytes_to_be_transmitted > 0)
        {
            pal_led(LED_START, LED_TOGGLE);        // indicate data processing
            tx_state = TX_ONGOING;

            tx_buffer[PL_POS_SEQ_NUM]++;

            /* Check for maximum allowed IEEE 802.15.4 frame length. */
            if (number_of_bytes_to_be_transmitted > aMaxMACSafePayloadSize)
            {
                number_of_bytes_to_be_transmitted = aMaxMACSafePayloadSize;
            }

            /* Update mpdu length within frame. */
            tx_buffer[0] = number_of_bytes_to_be_transmitted + FRAME_OVERHEAD;

            /* Copy MSDU (actual MAC payload) into frame. */
            /*
             * Note: Usually the MSDU is copied beginning from the end of
             * the frame. Since the header is always the same for this
             * application, the start of the MSDU is always the same position.
             * Therefore the payload copying is done from the beginning.
             */
            memcpy(&tx_buffer[LENGTH_FIELD_LEN + FRAME_OVERHEAD  - FCS_LEN],
                    sio_rx_data,
                    number_of_bytes_to_be_transmitted);

            tal_tx_frame(tx_buffer, CSMA_UNSLOTTED, true);
        }
    }
    else if (tx_state == TX_RETRY)
    {
        tx_state = TX_ONGOING;

        /* Retransmit the previous frame until frame transmission was successful. */
        tal_tx_frame(tx_buffer, CSMA_UNSLOTTED, true);
    }
}
Example #2
0
void bc_delay_cb(frame_info_t *transmit_frame)
{
	retval_t status;

	status = tal_tx_frame(nwkBroadDelay[minBroadDelayIndex].transmit_frame, CSMA_UNSLOTTED, true);
	broadDelayBitmap &= ~(1<<minBroadDelayIndex);
	nwkBroadDelay[minBroadDelayIndex].transmit_frame = NULL;
	nwkBroadDelay[minBroadDelayIndex].delayCount = 0xFFFFFFFF;
	broadDelayCount--;

	if (MAC_SUCCESS == status)
	{
		MAKE_MAC_BUSY();
	}
	else
	{
       // NwkState = NwkState;
        //bmm_buffer_free(nwkBroadDelay[minBroadDelayIndex].transmit_frame->buffer_header);//TODO 要多考虑,如果后面还有数据,需要再启动
        mac_sleep_trans();
	}



	if (broadDelayCount > 0)
	{
		//bubble_sort_broad();

		do
		{
			status = pal_timer_start(APP_TIMER_UART_TIMEOUT,
					nwkBroadDelay[++minBroadDelayIndex].delayCount,
					TIMEOUT_ABSOLUTE, (FUNC_PTR) bc_delay_cb,
					NULL);
			if (MAC_SUCCESS != status)
			{
				broadDelayBitmap &= ~(1<<minBroadDelayIndex);
				nwkBroadDelay[minBroadDelayIndex].transmit_frame = NULL;
				nwkBroadDelay[minBroadDelayIndex].delayCount = 0xFFFFFFFF;
				broadDelayCount--;
			}
		} while (MAC_SUCCESS != status && nwkBroadDelay[minBroadDelayIndex+1].transmit_frame != NULL);
	}
    
    if (broadDelayCount == 0)
      minBroadDelayIndex = 0;
}
Example #3
0
/*
 * @brief Creates and transmits a Null Data frame
 *
 * This function creates and transmits a Null Data frame in case the
 * coordinator does not have pending data to be transmitted.
 */
void mac_handle_tx_null_data_frame(void)
{
    frame_info_t *tx_frame;
    retval_t tal_tx_status;
    buffer_t *buf_ptr;

    /*
     * No matching pending item in the queue,
     * so a Null Data frame is created.
     */
    buf_ptr = build_null_data_frame();

    if (NULL != buf_ptr)
    {
        tx_frame = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr);

        /*
         * Transmission should be done with CSMA-CA or
         * quickly after the ACK of the data request command.
         * Here it's done quickly after the ACK w/o CSMA.
         */
        tal_tx_status = tal_tx_frame(tx_frame, NO_CSMA_WITH_IFS, false);

        if (MAC_SUCCESS == tal_tx_status)
        {
            MAKE_MAC_BUSY();
        }
        else
        {
            /*
             * Transmission to TAL failed, free up the buffer used to create
             * Null Data frame.
             */
            bmm_buffer_free(buf_ptr);
        }
    }
    }
Example #4
0
/*
 * @brief The MLME-GTS.request primitive makes a request for device to
 * request for GTS or on PANC to allocate or deallocate a GTS for itself
 * or other devices
 *
 * 802.15.4. Section 7.1.7.1.
 *
 * @param m The MLME-GTS.request message.
 */
void mlme_gts_request(uint8_t *m)
{
    mlme_gts_req_t mgr;
    memcpy(&mgr, BMM_BUFFER_POINTER((buffer_t *)m),
           sizeof(mlme_gts_req_t));

    if (MAC_NO_SHORT_ADDR_VALUE <= tal_pib.ShortAddress ||
            (MAC_NO_SHORT_ADDR_VALUE <=
             mac_pib.mac_CoordShortAddress &&
             MAC_PAN_COORD_STARTED != mac_state)) {
        mac_gen_mlme_gts_conf((buffer_t *)m, MAC_NO_SHORT_ADDRESS,
                              mgr.GtsChar);
        return;
    } else if (true != mac_pib.mac_GTSPermit    ||
               (0 == mgr.GtsChar.GtsLength) ||
               (MAC_ASSOCIATED == mac_state &&
                (mgr.DeviceShortAddr != tal_pib.ShortAddress ||
                 MAC_SYNC_TRACKING_BEACON != mac_sync_state ||
                 (mgr.GtsChar.GtsCharType == GTS_DEALLOCATE &&
                  (!mac_dev_gts_table[mgr.GtsChar.GtsDirection].
                   GtsStartingSlot ||
                   mgr.GtsChar.GtsLength !=
                   mac_dev_gts_table[mgr.GtsChar.GtsDirection].GtsLength))
                )
               )
              ) {
        mac_gen_mlme_gts_conf((buffer_t *)m, MAC_INVALID_PARAMETER,
                              mgr.GtsChar);
        return;
    }

#ifdef FFD
    else if (MAC_PAN_COORD_STARTED == mac_state) {
        if (GTS_ALLOCATE & mgr.GtsChar.GtsCharType) {
            if (mac_gts_allocate(mgr.GtsChar,
                                 mgr.DeviceShortAddr)) {
                mac_gen_mlme_gts_conf((buffer_t *)m,
                                      MAC_SUCCESS,
                                      mgr.GtsChar);
                return;
            } else {
                mac_gen_mlme_gts_conf((buffer_t *)m,
                                      MAC_NO_DATA,
                                      mgr.GtsChar);
                return;
            }
        } else {
            if (mac_gts_deallocate(mgr.GtsChar, mgr.DeviceShortAddr,
                                   true)) {
                mac_gen_mlme_gts_conf((buffer_t *)m,
                                      MAC_SUCCESS,
                                      mgr.GtsChar);
                return;
            } else {
                mac_gen_mlme_gts_conf((buffer_t *)m,
                                      MAC_NO_DATA,
                                      mgr.GtsChar);
                return;
            }
        }
    }
#endif /* FFD */
    else if (MAC_ASSOCIATED == mac_state) {
        frame_info_t *transmit_frame
            = (frame_info_t *)BMM_BUFFER_POINTER((buffer_t *)m);

        mac_trx_wakeup();

        /* Build the GTS Request command frame. */
        uint8_t tal_tx_status;
        uint8_t frame_len;
        uint8_t *frame_ptr;
        uint8_t *temp_frame_ptr;
        uint16_t fcf;

        /*
         * Use the mlme gts request buffer for transmitting
         * gts request frame.
         */
        frame_info_t *gts_req_frame
            = (frame_info_t *)(BMM_BUFFER_POINTER((buffer_t *)m));

        gts_req_frame->msg_type = GTSREQUEST;
        gts_req_frame->buffer_header = (buffer_t *)m;

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

        /* Update the payload field. */
        *frame_ptr++ = GTSREQUEST;
        /* Build the GTS characteristics info. */
        *frame_ptr = *((uint8_t *)&mgr.GtsChar);

        /* Get the payload pointer again to add the MHR. */
        frame_ptr = temp_frame_ptr;

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

        /* Source address */
        frame_ptr -= 2;

        convert_16_bit_to_byte_array(tal_pib.ShortAddress, frame_ptr);

        frame_ptr -= 2;
        convert_16_bit_to_byte_array(mac_pib.mac_CoordShortAddress,
                                     frame_ptr);

        fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) |
              FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR) |
              FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR) |
              FCF_ACK_REQUEST | FCF_PAN_ID_COMPRESSION;

        /* Destination PAN-Id */
        frame_ptr -= 2;
        convert_16_bit_to_byte_array(tal_pib.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. */
        gts_req_frame->mpdu = frame_ptr;

        tal_tx_status
            = tal_tx_frame(transmit_frame, CSMA_SLOTTED, true);

        if (MAC_SUCCESS == tal_tx_status) {
            uint8_t update_index = mgr.GtsChar.GtsDirection;

            if (mgr.DeviceShortAddr ==
                    mac_pib.mac_CoordShortAddress) {
                update_index |= 0x02;
            }

            if (GTS_DEALLOCATE == mgr.GtsChar.GtsCharType) {
                mac_dev_gts_table[update_index].GtsLength
                    = 0;
                mac_dev_gts_table[update_index].GtsStartingSlot
                    = 0;
                mac_dev_gts_table[update_index].GtsState
                    = GTS_STATE_IDLE;
                mac_gen_mlme_gts_conf((buffer_t *)m,
                                      MAC_SUCCESS, mgr.GtsChar);
                return;
            } else {
                mac_dev_gts_table[update_index].GtsReq_ptr = m;
                mac_dev_gts_table[update_index].GtsState
                    = GTS_STATE_REQ_SENT;
                mac_dev_gts_table[update_index].GtsPersistCount
                    = aGTSDescPersistenceTime;
                mac_dev_gts_table[update_index].GtsLength
                    = mgr.GtsChar.GtsLength;
                MAKE_MAC_BUSY();
            }
        } else {
            mac_gen_mlme_gts_conf((buffer_t *)m, tal_tx_status,
                                  mgr.GtsChar);
        }
    } else {
        mac_gen_mlme_gts_conf((buffer_t *)m, MAC_INVALID_PARAMETER,
                              mgr.GtsChar);
    }
    return;
}
Example #5
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() */
Example #6
0
/**
 * @brief Processes a received data request command frame
 *
 * This function processes a received data request command frame
 * at the coordinator, searches for pending indirect data frames
 * for the originator and initiates the frame transmission of the
 * data frame with CSMA-CA.
 *
 * @param msg Frame reception buffer pointer
 */
void mac_process_data_request(buffer_t *msg)
{
    /* Buffer pointer to next indirect data frame to be transmitted. */
    buffer_t *buf_ptr_next_data;
    search_t find_buf;
    frame_info_t *transmit_frame;
    retval_t tal_tx_status;

    /* Free the buffer of the received frame. */
    bmm_buffer_free(msg);

    /* Ignore data request if we are not PAN coordinator or coordinator. */
    if ((MAC_IDLE == mac_state) ||
        (MAC_ASSOCIATED == mac_state)
       )
    {
#if (DEBUG > 0)
        ASSERT("Neither PAN coordinator nor coordinator" == 0);
#endif
        return;
    }

    /* Check the addressing mode */
    if (mac_parse_data.src_addr_mode == FCF_SHORT_ADDR)
    {
        /*
         * Look for pending data in the indirect queue for
         * this short address.
         */

        /*
         * Assign the function pointer for searching the
         * data having address of the requested device.
         */
        find_buf.criteria_func = find_short_buffer;

        /* Update the short address to be searched. */
        find_buf.handle = &mac_parse_data.src_addr.short_address;
    }
    else if (mac_parse_data.src_addr_mode == FCF_LONG_ADDR)
    {
        /*
         * Look for pending data in the indirect queue for
         * this long address.
         */

        /*
         * Assign the function pointer for searching the
         * data having address of the requested device.
         */
        find_buf.criteria_func = find_long_buffer;

        /* Update the long address to be searched. */
        find_buf.handle = &mac_parse_data.src_addr.long_address;
    }
    else
    {
#if (DEBUG > 0)
            ASSERT("Unexpected addressing mode" == 0);
#endif
            return;
    }

    /*
     * Read from the indirect queue. The removal of items from this queue
     * will be done after successful transmission of the frame.
     */
    buf_ptr_next_data = qmm_queue_read(&indirect_data_q, &find_buf);
    /* Note: The find_buf structure is reused below, so do not change this. */

    if (NULL == buf_ptr_next_data)
    {
        mac_handle_tx_null_data_frame();
        return;
    }
    else
    {
        /* Indirect data found and to be sent. */
        transmit_frame = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr_next_data);

        /*
         * We need to check whether the source PAN-Id of the previously
         * received data request frame is identical to the destination PAN-Id
         * of the pending frame. If not the frame shall not be transmitted,
         * but a Null Data frame instead.
         */
        if (mac_parse_data.src_panid !=
            convert_byte_array_to_16_bit(&transmit_frame->mpdu[PL_POS_DST_PAN_ID_START])
           )
        {
            mac_handle_tx_null_data_frame();
            return;
        }
        else
        {
            /*
             * The frame to be transmitted next is marked.
             * This is necessary since the queue needs to be traversed again
             * to find other pending indirect data frames for this particular
             * recipient.
             */
            transmit_frame->indirect_in_transit = true;
            transmit_frame->buffer_header = buf_ptr_next_data;

            /*
             * Go through the indirect data queue to find out the frame pending for
             * the device which has requested for the data.
             */
            /*
             * Since the buffer header has already been stored in
             * transmit_frame->buffer_header, it can be reused here for
             * other purpose.
             */
            /*
             * It is assumed that the find_buf struct does still have
             * the original values from above.
             */
            buf_ptr_next_data = qmm_queue_read(&indirect_data_q, &find_buf);
            /*
             * Check whether there is another indirect data available
             * for the same recipient.
             */
            if (NULL != buf_ptr_next_data)
            {
                transmit_frame->mpdu[PL_POS_FCF_1] |= FCF_FRAME_PENDING;
            }
        }

        /*
         * Transmission should be done with CSMA-CA or
         * quickly after the ACK of the data request command.
         * Here it's done quickly after the ACK w/o CSMA.
         */
        tal_tx_status = tal_tx_frame(transmit_frame, NO_CSMA_WITH_IFS, false);

        if (MAC_SUCCESS == tal_tx_status)
        {
            MAKE_MAC_BUSY();
        }
        else
        {
            /*
             * TAL rejects frame transmission, since it's too close to the next
             * beacon transmission. The frame is kept in the indirect queue.
             */
            transmit_frame->indirect_in_transit = false;
        }
    }
} /* mac_process_data_request() */
Example #7
0
/*
 * \brief Function to transmit frames as per 802.15.4 std.
 *
 * \param dst_addr_mode     destination address mode - can be 16 or 64 bit
 * \param dst_addr          destination address
 * \param src_addr_mode     source address mode - can be 16 or 64 bit
 * \param msdu_handle       msdu handle for the upper layers to track packets
 * \param payload           data payload pointer
 * \param payload_length    data length
 * \param ack_req           specifies ack requested for frame if set to 1
 *
 * \return MAC_SUCCESS      if the TAL has accepted the data for frame
 * transmission
 *         TAL_BUSY         if the TAL is busy servicing the previous tx request
 */
retval_t transmit_frame(uint8_t dst_addr_mode,
		uint8_t *dst_addr,
		uint8_t src_addr_mode,
		uint8_t msdu_handle,
		uint8_t *payload,
		uint8_t payload_length,
		uint8_t ack_req)
{
	uint8_t i;
	uint16_t temp_value;
	uint8_t frame_length;
	uint8_t *frame_ptr;
	uint8_t *temp_frame_ptr;
	uint16_t fcf = 0;

	/* Prevent multiple transmissions , this code is not reentrant*/
	if (node_info.transmitting) {
		return FAILURE;
	}

	node_info.transmitting = true;

	/* Get length of current frame. */
	frame_length = (FRAME_OVERHEAD + payload_length);

	/* Set payload pointer. */
	frame_ptr = temp_frame_ptr = (uint8_t *)node_info.tx_frame_info +
					LARGE_BUFFER_SIZE -
					payload_length - FCS_LEN;

	/*
	 * Payload is stored to the end of the buffer avoiding payload
	 * copying by TAL.
	 */
	for (i = 0; i < payload_length; i++) {
		*temp_frame_ptr++ = *(payload + i);
	}

	/* Source address */
	if (FCF_SHORT_ADDR == src_addr_mode) {
		frame_ptr -= SHORT_ADDR_LEN;
		convert_16_bit_to_byte_array(tal_pib.ShortAddress, frame_ptr);

		fcf |= FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR);
	} else {
		frame_ptr -= EXT_ADDR_LEN;
		frame_length += FCF_2_SOURCE_ADDR_OFFSET;

		convert_64_bit_to_byte_array(tal_pib.IeeeAddress, frame_ptr);

		fcf |= FCF_SET_SOURCE_ADDR_MODE(FCF_LONG_ADDR);
	}

	/* Source PAN-Id */
#if (DST_PAN_ID == SRC_PAN_ID)
	/* No source PAN-Id included, but FCF updated. */
	fcf |= FCF_PAN_ID_COMPRESSION;
#else
	frame_ptr -= PAN_ID_LEN;
	temp_value = CCPU_ENDIAN_TO_LE16(SRC_PAN_ID);
	convert_16_bit_to_byte_array(temp_value, frame_ptr);
#endif

	/* Destination address */
	if (FCF_SHORT_ADDR == dst_addr_mode) {
		frame_ptr -= SHORT_ADDR_LEN;
		//convert_16_bit_to_byte_array(*((uint16_t *)dst_addr),
		//		frame_ptr);
	memcpy(frame_ptr, (uint8_t *)dst_addr, sizeof(uint16_t));
		fcf |= FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR);
	} else {
		frame_ptr -= EXT_ADDR_LEN;
		frame_length += PL_POS_DST_ADDR_START;

		//convert_64_bit_to_byte_array(*((uint64_t *)dst_addr),
		//		frame_ptr);
		memcpy(frame_ptr, (uint8_t *)dst_addr, sizeof(uint64_t));
		fcf |= FCF_SET_DEST_ADDR_MODE(FCF_LONG_ADDR);
	}

	/* Destination PAN-Id */
	temp_value = CCPU_ENDIAN_TO_LE16(DST_PAN_ID);
	frame_ptr -= PAN_ID_LEN;
	convert_16_bit_to_byte_array(temp_value, frame_ptr);

	/* Set DSN. */
	frame_ptr--;
	*frame_ptr = node_info.msg_seq_num;
	node_info.msg_seq_num++;

	/* Set the FCF. */
	fcf |= FCF_FRAMETYPE_DATA;
	if (ack_req) {
		fcf |= FCF_ACK_REQUEST;
	}

	frame_ptr -= FCF_LEN;
	convert_16_bit_to_byte_array(CCPU_ENDIAN_TO_LE16(fcf), frame_ptr);

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

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

	/* Place msdu handle for tracking */
	node_info.tx_frame_info->msduHandle = msdu_handle;

	/* transmit the frame */
	return(tal_tx_frame(node_info.tx_frame_info, CSMA_UNSLOTTED, true));
}
Example #8
0
void bc_data_cb(frame_info_t *transmit_frame)
{
	uint8_t index;
	index  = nwkFindPassiveAck(transmit_frame->NwkFrameHeader->srcAddr, transmit_frame->NwkFrameHeader->sequenceNumber);
	if (index != 0xFF)
	{
		if (gNwkPassiveAckTable.table[index].end == false)
		{
			do
			{
				if (gNwkPassiveAckTable.table[index].realyNeighborNum >= neighborTable.size)
					break;

				while (transmit_frame->AppFrameHeader->frameControl.tries != 0)//以后要用这个NWK_MAX_BROADCAST_RETRIES
				{
					transmit_frame->AppFrameHeader->AppPayload[transmit_frame->AppFrameHeader->length] ^= transmit_frame->AppFrameHeader->frameControl.tries;
					transmit_frame->AppFrameHeader->frameControl.tries--;
					transmit_frame->AppFrameHeader->AppPayload[transmit_frame->AppFrameHeader->length] ^= transmit_frame->AppFrameHeader->frameControl.tries;

					//mac_trx_wakeup();
					retval_t status = FAILURE;

					transmit_frame->mpdu[3] = mac_pib.mac_DSN++;
					/* In Nonbeacon build the frame is sent with unslotted CSMA-CA. */
					status = tal_tx_frame(transmit_frame, CSMA_UNSLOTTED, true);

					if (MAC_SUCCESS == status)
					{
						MAKE_MAC_BUSY();

						/* Start timer to initiate next broadcast data transmission. */
						pal_timer_start(gNwkPassiveAckTable.table[index].timerID,
										((uint32_t)NWK_PASSIVE_ACK_TIMEOUT),
										TIMEOUT_RELATIVE,
										(FUNC_PTR)bc_data_cb,
										transmit_frame);
						gNwkPassiveAckTable.table[index].reTryTimes++;
					}
					else
					{
						break;
					}
					return;
				}
			}while(0);
			NwkState = NWK_MODULE_NONE;
			pal_timer_start(gNwkPassiveAckTable.table[index].timerID,
							((uint32_t)	(NWK_BROADCAST_DELIVERY_TIME-(gNwkPassiveAckTable.table[index].reTryTimes+1)*NWK_PASSIVE_ACK_TIMEOUT)),
							TIMEOUT_RELATIVE,
							(FUNC_PTR)bc_data_cb,
							transmit_frame);
			gNwkPassiveAckTable.table[index].end = true;
			return;
		}
		gNwkPassiveAckTable.table[index].end = false;
		gNwkPassiveAckTable.table[index].reTryTimes = 0;
		nwkFreePassiveAck(transmit_frame->NwkFrameHeader->srcAddr, transmit_frame->NwkFrameHeader->sequenceNumber);
		if (transmit_frame != NULL)
			bmm_buffer_free(transmit_frame->buffer_header);
		//NwkState = NWK_MODULE_NONE;
		mac_sleep_trans();
	}
}
Example #9
0
/**
 * @brief Send a beacon request or orphan notification command frame
 *
 * This function sends a beacon request or orphan notification command frame.
 * An MPDU containing either a beacon request or an orphan notification command
 * frame is constructed and sent.
 *
 * @param beacon_req True if a beacon request command frame shall be sent,
 *                   otherwise (false) an orphan notification command frame
 *                   will be sent.
 *
 * @return True if the frame transmission has been initiated, false otherwise.
 */
static bool send_scan_cmd(bool beacon_req)
{
	retval_t tal_tx_status;
	uint8_t frame_len;
	uint8_t *frame_ptr;
	uint16_t fcf;
	uint16_t bc_addr = BROADCAST;

	/*
	 * mac_scan_cmd_buf_ptr holds the buffer allocated for sending beacon
	 * request or orphan notification command. In active scan the scan
	 * request
	 * buffer is used to send a beacon request and in orphan scan new buffer
	 * is
	 * allocated to send an orphan notification.
	 */
	frame_info_t *transmit_frame
		= (frame_info_t *)BMM_BUFFER_POINTER(
			(buffer_t *)mac_scan_cmd_buf_ptr);

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

	transmit_frame->buffer_header = (buffer_t *)mac_scan_cmd_buf_ptr;

	if (beacon_req) {
		fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) |
				FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR) |
				FCF_SET_SOURCE_ADDR_MODE(FCF_NO_ADDR);

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

		/* Build the command frame id. */
		*frame_ptr = transmit_frame->msg_type = BEACONREQUEST;
	} else { /* Orphan Notification command */
		fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) |
				FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR) |
				FCF_SET_SOURCE_ADDR_MODE(FCF_LONG_ADDR) |
				FCF_PAN_ID_COMPRESSION;

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

		/* Build the command frame id. */
		*frame_ptr = transmit_frame->msg_type = ORPHANNOTIFICATION;

		/* Orphan notification contains long source address. */
		frame_ptr -= 8;
		convert_64_bit_to_byte_array(tal_pib.IeeeAddress, frame_ptr);
	}

	/* Destination address */
	frame_ptr -= 2;
	convert_16_bit_to_byte_array(bc_addr, frame_ptr);

	/* Destination PANid */
	frame_ptr -= 2;
	convert_16_bit_to_byte_array(bc_addr, 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;

#if (TAL_TYPE == AT86RF230B)
	/* Transmit data without CSMA-CA and no frame retry. */
	tal_tx_status = tal_tx_frame(transmit_frame, NO_CSMA_NO_IFS, false);
#else
	/* Transmit data with unslotted CSMA-CA and no frame retry. */
	tal_tx_status = tal_tx_frame(transmit_frame, CSMA_UNSLOTTED, false);
#endif

	if (MAC_SUCCESS == tal_tx_status) {
		MAKE_MAC_BUSY();
		return true;
	} else {
		return false;
	}
} /* send_scan_cmd() */