/** * @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); } }
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; }
/* * @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); } } }
/* * @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; }
/** * @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 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() */
/* * \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)); }
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(); } }
/** * @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() */