Beispiel #1
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;
	}
}
Beispiel #2
0
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;
}
Beispiel #4
0
/**
 * @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;
}
Beispiel #5
0
/**
 * @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);
	}
}
Beispiel #6
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() */
Beispiel #7
0
/**
 * @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;
}