/** * @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; } }
bool wpan_task(void) { bool event_processed; uint8_t *event = NULL; /* mac_task returns true if a request was processed completely */ event_processed = mac_task(); /* * MAC to NHLE event queue should be dispatched * irrespective of the dispatcher state. */ event = (uint8_t *)qmm_queue_remove(&mac_nhle_q, NULL); /* If an event has been detected, handle it. */ if (NULL != event) { dispatch_event(event); event_processed = true; } #ifdef ENABLE_RTB rtb_task(); #endif /* ENABLE_RTB */ tal_task(); pal_task(); return (event_processed); }
/** * @brief Allocates a buffer * * This function allocates a buffer and returns a pointer to the buffer. * The same pointer should be used while freeing the buffer.User should * call BMM_BUFFER_POINTER(buf) to get the pointer to buffer user area. * * @param size size of buffer to be allocated. * * @return pointer to the buffer allocated, * NULL if buffer not available. */ buffer_t *bmm_buffer_alloc(uint8_t size) { buffer_t *pfree_buffer = NULL; #if (TOTAL_NUMBER_OF_SMALL_BUFS > 0) /* * Allocate buffer only if size requested is less than or equal to * maximum * size that can be allocated. */ if (size <= LARGE_BUFFER_SIZE) { /* * Allocate small buffer if size is less than small buffer size * and if * small buffer is available allocate from small buffer pool. */ if ((size <= SMALL_BUFFER_SIZE)) { /* Allocate buffer from free small buffer queue */ pfree_buffer = qmm_queue_remove(&free_small_buffer_q, NULL); } /* * If size is greater than small buffer size or no free small * buffer is * available, allocate a buffer from large buffer pool if * avialable */ if (NULL == pfree_buffer) { /* Allocate buffer from free large buffer queue */ pfree_buffer = qmm_queue_remove(&free_large_buffer_q, NULL); } } #else /* no small buffers available at all */ /* Allocate buffer from free large buffer queue */ pfree_buffer = qmm_queue_remove(&free_large_buffer_q, NULL); size = size; /* Keep compiler happy. */ #endif return pfree_buffer; }
/** * @brief Runs the MAC scheduler * * This function runs the MAC scheduler. * * MLME and MCPS queues are removed alternately, starting with MLME queue. * * @return true if event is dispatched, false if no event to dispatch. */ bool mac_task(void) { uint8_t *event = NULL; bool processed_event = false; if (!mac_busy) { /* Check whether queue is empty */ if (nhle_mac_q.size != 0) { event = (uint8_t *)qmm_queue_remove(&nhle_mac_q, NULL); /* If an event has been detected, handle it. */ if (NULL != event) { /* Process event due to NHLE requests */ dispatch_event(event); processed_event = true; } } } /* * Internal event queue should be dispatched * irrespective of the dispatcher state. */ /* Check whether queue is empty */ if (tal_mac_q.size != 0) { event = (uint8_t *)qmm_queue_remove(&tal_mac_q, NULL); /* If an event has been detected, handle it. */ if (NULL != event) { dispatch_event(event); processed_event = true; } } return processed_event; }
/** * @brief Internal function for flushing a specific queue * * @param q Queue to be flushed */ void qmm_queue_flush(queue_t *q) { buffer_t *buf_to_free; while (q->size > 0) { /* Remove the buffer from the queue and free it */ buf_to_free = qmm_queue_remove(q, NULL); if (NULL == buf_to_free) { #if (_DEBUG_ > 0) ABORT("Corrupted queue"); #endif q->size = 0; return; } bmm_buffer_free(buf_to_free); } }
/** * @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() */
/** * @brief Resets TAL state machine and sets the default PIB values if requested * * @param set_default_pib Defines whether PIB values need to be set * to its default values * * @return MAC_SUCCESS if the transceiver state is changed to TRX_OFF * FAILURE otherwise */ retval_t tal_reset(bool set_default_pib) { /* * Do the reset stuff. * Set the default PIBs depending on the given parameter set_default_pib. * Do NOT generate random seed again. */ if (internal_tal_reset(set_default_pib) != MAC_SUCCESS) { return FAILURE; } #if (NUMBER_OF_TAL_TIMERS > 0) /* Clear all running TAL timers. */ { uint8_t timer_id; ENTER_CRITICAL_REGION(); for (timer_id = TAL_FIRST_TIMER_ID; timer_id <= TAL_LAST_TIMER_ID; timer_id++) { pal_timer_stop(timer_id); } LEAVE_CRITICAL_REGION(); } #endif /* Clear TAL Incoming Frame queue and free used buffers. */ while (tal_incoming_frame_queue.size > 0) { buffer_t *frame = qmm_queue_remove(&tal_incoming_frame_queue, NULL); if (NULL != frame) { bmm_buffer_free(frame); } } #ifdef ENABLE_TFA tfa_reset(set_default_pib); #endif /* * Configure interrupt handling. Clear all pending interrupts. * Handlers have been installed in tal_init(), and are never * uninstalled. */ pal_trx_irq_flag_clr_rx_end(); pal_trx_irq_flag_clr_tx_end(); #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) pal_trx_irq_flag_clr_tstamp(); #endif /* (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ pal_trx_irq_flag_clr_awake(); /* * To make sure that the CSMA seed is properly set within the transceiver, * put the trx to sleep briefly and wake it up again. */ tal_trx_sleep(SLEEP_MODE_1); tal_trx_wakeup(); #ifdef ENABLE_FTN_PLL_CALIBRATION { /* Handle PLL calibration and filter tuning. */ retval_t timer_status; /* Calibration timer has already been stopped within this function. */ /* Start periodic calibration timer.*/ timer_status = pal_timer_start(TAL_CALIBRATION, TAL_CALIBRATION_TIMEOUT_US, TIMEOUT_RELATIVE, (FUNC_PTR)calibration_timer_handler_cb, NULL); if (timer_status != MAC_SUCCESS) { ASSERT("PLL calibration timer start problem" == 0); } } #endif /* ENABLE_FTN_PLL_CALIBRATION */ #ifdef STB_ON_SAL stb_restart(); #endif return MAC_SUCCESS; }
/* * \brief Resets TAL state machine and sets the default PIB values if requested * * \param set_default_pib Defines whether PIB values need to be set * to its default values * * \return MAC_SUCCESS if the transceiver state is changed to TRX_OFF * FAILURE otherwise */ retval_t tal_reset(bool set_default_pib) { /* * Do the reset stuff. * Set the default PIBs depending on the given parameter * set_default_pib. * Do NOT generate random seed again. */ if (internal_tal_reset(set_default_pib) != MAC_SUCCESS) { return FAILURE; } ENTER_CRITICAL_REGION(); tal_timers_stop(); LEAVE_CRITICAL_REGION(); /* Clear TAL Incoming Frame queue and free used buffers. */ while (tal_incoming_frame_queue.size > 0) { buffer_t *frame = qmm_queue_remove(&tal_incoming_frame_queue, NULL); if (NULL != frame) { bmm_buffer_free(frame); } } #ifdef ENABLE_TFA tfa_reset(set_default_pib); #endif /* * Configure interrupt handling. * Install a handler for the transceiver interrupt. */ trx_irq_init((FUNC_PTR)trx_irq_handler_cb); /* The pending transceiver interrupts on the microcontroller are * cleared. */ pal_trx_irq_flag_clr(); pal_trx_irq_en(); /* Enable transceiver main interrupt. */ #ifdef ENABLE_FTN_PLL_CALIBRATION { /* Handle PLL calibration and filter tuning. */ retval_t timer_status; /* Calibration timer has already been stopped within this * function. */ /* Start periodic calibration timer.*/ timer_status = pal_timer_start(TAL_CALIBRATION, TAL_CALIBRATION_TIMEOUT_US, TIMEOUT_RELATIVE, (FUNC_PTR)calibration_timer_handler_cb, NULL); if (timer_status != MAC_SUCCESS) { Assert("PLL calibration timer start problem" == 0); } } #endif /* ENABLE_FTN_PLL_CALIBRATION */ return MAC_SUCCESS; }