/** * \brief Configure the TAL PIB's relevant to the Performance analyzer * application * \ingroup group_app_init */ static void configure_pibs(void) { uint16_t temp_word; pib_value_t pib_value; uint8_t temp_byte; /* Set Default address. */ temp_word = CCPU_ENDIAN_TO_LE16(DEFAULT_ADDR); pib_value.pib_value_16bit = temp_word; tal_pib_set(macShortAddress, &pib_value); /* Set PAN ID. */ temp_word = CCPU_ENDIAN_TO_LE16(SRC_PAN_ID); pib_value.pib_value_16bit = temp_word; tal_pib_set(macPANId, &pib_value); /* Set channel. */ temp_byte = (uint8_t)DEFAULT_CHANNEL; pib_value.pib_value_8bit = temp_byte; tal_pib_set(phyCurrentChannel, &pib_value); /* Set IEEE address - To make sure that trx registers written properly **/ tal_pib_set(macIeeeAddress, (pib_value_t *)&tal_pib.IeeeAddress); }
/** * \brief Configure the frame to be used for Packet Streaming * \param frame_len Length of the frame to be used for Packet Streaming */ void configure_pkt_stream_frames(uint16_t frame_len) { uint8_t index; uint16_t app_frame_length; uint8_t *frame_ptr; uint8_t *temp_frame_ptr; uint16_t fcf = 0; uint16_t temp_value; app_payload_t *tmp; stream_pkt = (frame_info_t *)pkt_buffer; /* * Fill in PHY frame. */ /* Get length of current frame. */ app_frame_length = frame_len - FRAME_OVERHEAD; /* Set payload pointer. */ /* Add 2 octets for FCS. */ frame_ptr = temp_frame_ptr = (uint8_t *)stream_pkt + LARGE_BUFFER_SIZE - app_frame_length - FCS_LEN; tmp = (app_payload_t *)temp_frame_ptr; (tmp->cmd_id) = PKT_STREAM_PKT; temp_frame_ptr++; /* * Assign dummy payload values. * Payload is stored to the end of the buffer avoiding payload copying * by TAL. */ /* 1=> cmd ID*/ for (index = 0; index < (app_frame_length - 1); index++) { *temp_frame_ptr++ = index; /* dummy values */ } /* Source Address */ temp_value = tal_pib.ShortAddress; frame_ptr -= SHORT_ADDR_LEN; convert_16_bit_to_byte_array(temp_value, frame_ptr); /* 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 */ temp_value = 0XFFFF; frame_ptr -= SHORT_ADDR_LEN; convert_16_bit_to_byte_array(temp_value, frame_ptr); /* 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 = (uint8_t)rand(); /* Set the FCF. */ // Reserved frame type so that other apps doesnot receive and process this data fcf |= 0x04 | FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR) | FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR); 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 = (uint8_t)frame_len; /* Finished building of frame. */ stream_pkt->mpdu = frame_ptr; }
/** * @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() */
/* * \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)); }