Пример #1
0
/*!
 * \cond DOXYGEN_PRIVATE
 *
 * \brief Interrupt service routine.
 *
 * This ISR is used when every channel has its own vector in vector table.
 * Checks whether callback_func is not NULL,
 * and unless callback is blocked by callback_blocked being non-zero it calls the callback function with callback_data as parameter,
 * otherwise callback_pending is set to non-zero value.
 *
 * \param p[in]   Pointer to hwtimer struct.
 *
 * \return void
 *
 * \see hwtimer_pit_deinit
 * \see hwtimer_pit_set_div
 * \see hwtimer_pit_start
 * \see hwtimer_pit_stop
 * \see hwtimer_pit_get_time
 * \see hwtimer_pit_isr_shared
 */
static void hwtimer_pit_isr(void *p)
{
    HWTIMER_PTR hwtimer     = (HWTIMER_PTR) p;
    PIT_MemMapPtr pit_base  = (PIT_MemMapPtr) hwtimer->ll_context[0];
    uint32_t pit_channel     = GET_PIT_CHANNEL_FROM_PITID(hwtimer->ll_context[1]);

    /* Check if interrupt is enabled for this channel. Cancel spurious interrupt */
    if (!(PIT_TCTRL_TIE_MASK & PIT_TCTRL_REG(pit_base, pit_channel)))
    {
        return;
    }

    /* Clear interrupt flag */
    PIT_TFLG_REG(pit_base, pit_channel) = PIT_TFLG_TIF_MASK;
    /* Errata for OM33Z: e2682: PIT: Does not generate a subsequent interrupt after clearing the interrupt flag */
    /* Workaround: The user must access any PIT register after clearing the interrupt flag in the ISR. */
    PIT_TFLG_REG(pit_base, pit_channel);

    /* Following part of function is typically the same for all low level hwtimer drivers */
    hwtimer->ticks++;

    if (NULL != hwtimer->callback_func)
    {
        if (hwtimer->callback_blocked)
        {
            hwtimer->callback_pending = 1;
        }
        else
        {
            /* Run user function*/
            hwtimer->callback_func(hwtimer->callback_data);
        }
    }
}
Пример #2
0
/*!
 * \cond DOXYGEN_PRIVATE
 *
 * \brief Shared interrupt service routine.
 *
 * This ISR is used when more channels share one vector in vector table.
 * Checks whether callback_func is not NULL,
 * and unless callback is blocked by callback_blocked being non-zero it calls the callback function with callback_data as parameter,
 * otherwise callback_pending is set to non-zero value.
 * \param p[in]   Null pointer.
 *
 * \return void
 *
 * \see hwtimer_pit_deinit
 * \see hwtimer_pit_set_div
 * \see hwtimer_pit_start
 * \see hwtimer_pit_stop
 * \see hwtimer_pit_get_time
 * \see hwtimer_pit_isr
 */
static void hwtimer_pit_isr_shared(void *p)
{
    HWTIMER_PTR * pit_hwtimers_array = NULL;
    uint32_t pit_hwtimers_array_size;
    uint32_t i;
    HWTIMER_PTR hwtimer;
    PIT_MemMapPtr pit_base;
    uint32_t pit_channel;

    pit_hwtimers_array_size = pit_get_hwtimers_array(&pit_hwtimers_array);

    for (i = 0; i < pit_hwtimers_array_size; i++)
    {
        hwtimer =  pit_hwtimers_array[i];
        /* If hwtimer exist*/
        if (NULL != hwtimer)
        {
            pit_base    = (PIT_MemMapPtr) hwtimer->ll_context[0];
            pit_channel =  GET_PIT_CHANNEL_FROM_PITID(hwtimer->ll_context[1]);

            /* Check if interrupt is enabled for this channel. */
            if (!(PIT_TCTRL_TIE_MASK & PIT_TCTRL_REG(pit_base, pit_channel)))
            {
                continue;
            }

            /* If interrupt occur for this pit and channel*/
            if(PIT_TFLG_REG((PIT_MemMapPtr)pit_base, pit_channel) & PIT_TFLG_TIF_MASK)
            {
                /* Clear interrupt flag */
                PIT_TFLG_REG((PIT_MemMapPtr)pit_base, pit_channel) = PIT_TFLG_TIF_MASK;
                /* Errata for OM33Z: e2682: PIT: Does not generate a subsequent interrupt after clearing the interrupt flag */
                /* Workaround: The user must access any PIT register after clearing the interrupt flag in the ISR. */
                PIT_TFLG_REG(pit_base, pit_channel);

                /* Following part of function is typically the same for all low level hwtimer drivers */
                hwtimer->ticks++;

                if (NULL != hwtimer->callback_func)
                {
                    if (hwtimer->callback_blocked)
                    {
                        hwtimer->callback_pending = 1;
                    }
                    else
                    {
                        /* Run user function*/
                        hwtimer->callback_func(hwtimer->callback_data);
                    }
                }
            }
        }
    }
}
Пример #3
0
/*!
 * \cond DOXYGEN_PRIVATE
 *
 * \brief Stop pit timer module
 *
 * Disable timer and interrupt
 *
 * \param hwtimer[in] Pointer to hwtimer structure.
 *
 * \return MQX_OK Success.
 *
 * \see hwtimer_pit_init
 * \see hwtimer_pit_deinit
 * \see hwtimer_pit_set_div
 * \see hwtimer_pit_start
 * \see hwtimer_pit_get_time
 * \see hwtimer_pit_isr
 * \see hwtimer_pit_isr_shared
 */
static _mqx_int hwtimer_pit_stop(HWTIMER_PTR hwtimer)
{
    PIT_MemMapPtr pit_base  = (PIT_MemMapPtr) hwtimer->ll_context[0];
    uint32_t pit_channel     = GET_PIT_CHANNEL_FROM_PITID(hwtimer->ll_context[1]);

    /* Disable timer and interrupt */
    PIT_TCTRL_REG(pit_base, pit_channel) = 0;
    PIT_TFLG_REG(pit_base, pit_channel) = PIT_TFLG_TIF_MASK; // Clear interrupt flag
    /* Errata for OM33Z: e2682: PIT: Does not generate a subsequent interrupt after clearing the interrupt flag */
    /* Workaround: The user must access any PIT register after clearing the interrupt flag in the ISR. */
    PIT_TFLG_REG(pit_base, pit_channel);

    return MQX_OK;
}
Пример #4
0
/*!
 * \cond DOXYGEN_PRIVATE
 *
 * \brief Atomically captures current time into HWTIMER_TIME_STRUCT structure
 *
 * Corrects/normalizes the values if necessary (interrupt pending, etc.)
 *
 * \param hwtimer[in] Pointer to hwtimer structure.
 * \param time[out]   Pointer to time structure. This value is filled with current value of the timer.
 *
 * \return MQX_OK Success.
 *
 * \see hwtimer_pit_init
 * \see hwtimer_pit_deinit
 * \see hwtimer_pit_set_div
 * \see hwtimer_pit_start
 * \see hwtimer_pit_stop
 * \see hwtimer_pit_isr
 * \see hwtimer_pit_isr_shared
 */
static _mqx_int hwtimer_pit_get_time(HWTIMER_PTR hwtimer, HWTIMER_TIME_PTR time)
{
    PIT_MemMapPtr   pit_base    = (PIT_MemMapPtr) hwtimer->ll_context[0];
    uint32_t        pit_channel = GET_PIT_CHANNEL_FROM_PITID(hwtimer->ll_context[1]);
    uint32_t        temp_cval;

    /* Disable interrupt from timer*/
    _int_disable();
    time->TICKS = hwtimer->ticks;

    temp_cval  = PIT_CVAL_REG(pit_base, pit_channel);
    /* Check pending interrupt flag */
    if(PIT_TFLG_REG(pit_base, pit_channel) & PIT_TFLG_TIF_MASK)
    {
        _int_enable();
        time->SUBTICKS = hwtimer->modulo - 1;
    }
    else
    {
        _int_enable();
        time->SUBTICKS = PIT_LDVAL_REG(pit_base, pit_channel) - temp_cval;
    }

    return MQX_OK;
}
Пример #5
0
/*!
 * \cond DOXYGEN_PRIVATE
 *
 * \brief Start pit timer module
 *
 * This function enables the timer and leaves it running, timer is
 * periodically generating interrupts.
 *
 * \param hwtimer[in] Pointer to hwtimer structure.
 *
 * \return MQX_OK Success.
 *
 * \see hwtimer_pit_init
 * \see hwtimer_pit_deinit
 * \see hwtimer_pit_set_div
 * \see hwtimer_pit_stop
 * \see hwtimer_pit_get_time
 * \see hwtimer_pit_isr
 * \see hwtimer_pit_isr_shared
 */
static _mqx_int hwtimer_pit_start(HWTIMER_PTR hwtimer)
{
    PIT_MemMapPtr pit_base  = (PIT_MemMapPtr) hwtimer->ll_context[0];
    uint32_t pit_channel     = GET_PIT_CHANNEL_FROM_PITID(hwtimer->ll_context[1]);

    PIT_TCTRL_REG(pit_base, pit_channel) = 0;  // Stop timer to force reseting the counter
    PIT_TFLG_REG(pit_base, pit_channel)  = PIT_TFLG_TIF_MASK; // Clear flag
    PIT_TCTRL_REG(pit_base, pit_channel) = PIT_TCTRL_TEN_MASK | PIT_TCTRL_TIE_MASK; // Run timer and enable interrupts

    return MQX_OK;
}
Пример #6
0
/*FUNCTION*-----------------------------------------------------------------
*
* Function Name   : _kinetis_timer_init_freq
* Returned Value  : the clock rate for the timer (ns per hw tick)
* Comments        :
*   this function will set up a timer to interrupt
*
*END*---------------------------------------------------------------------*/
void _kinetis_timer_init_freq
   (
      /* [IN] the timer to initialize */
      _mqx_uint timer,

      /* [IN] ticks per second */
      uint_32   tickfreq,
      
      /* [IN] the system clock speed in MHz */
      uint_32   system_clock,

      /* [IN] Unmask the timer after initializing */
      boolean   unmask_timer
   )
{ /* Body */

    if(tickfreq != 0)
    {
        /* Enable PIT Module Clock */
        SIM_SCGC6 |= SIM_SCGC6_PIT_MASK;
        
        /* Configure PIT */
        PIT_MCR = ~(PIT_MCR_FRZ_MASK |PIT_MCR_MDIS_MASK);

        /* Timer counter value */
        PIT_LDVAL_REG(PIT_BASE_PTR,timer) = system_clock/tickfreq;

        /* Enable PIT interrupt */
        PIT_TCTRL_REG(PIT_BASE_PTR,timer) = PIT_TCTRL_TEN_MASK;
        
        /* Mask PIT interrupt flag */
        PIT_TFLG_REG(PIT_BASE_PTR,timer)= PIT_TFLG_TIF_MASK; 
        
    }
    if (unmask_timer) 
    {
        _kinetis_timer_unmask_int(timer);
    } 
}
Пример #7
0
/******************************************************************************
*   @name        _kinetis_timer_clear_int
*
*   @brief       This function clears PIT interrupt flag
*
*   @return      None
*
*   @comment
*    
*******************************************************************************/
void _kinetis_timer_clear_int(uint_32 timer)
{
    PIT_TFLG_REG(PIT_BASE_PTR,timer) |= PIT_TFLG_TIF_MASK;
}
Пример #8
0
/******************************************************************************
*   @name        _pit_clear_int
*
*   @brief       This function clears PIT interrupt flag
*
*   @return      None
*
*   @comment
*    
*******************************************************************************/
void _pit_clear_int(uint_32 timer)
{
   PIT_TFLG_REG(PIT_BASE_PTR,timer) |= PIT_TFLG_TIF_MASK;
}
Пример #9
0
/*!
 * \cond DOXYGEN_PRIVATE
 *
 * \brief This function initializes caller allocated structure according to given
 * numerical identifier of the timer.
 *
 * Called by hwtimer_init().
 * Initializes the HWTIMER structure.
 * Sets interrupt priority and registers ISR.
 *
 * \param hwtimer[in]   Returns initialized hwtimer structure handle.
 * \param pit_id[in]    Determines PIT modul and pit channel.
 * \param isr_prior[in] Interrupt priority for PIT
 *
 * \return MQX_OK                       Success.
 * \return MQX_INVALID_PARAMETER        When channel number does not exist in pit module.
 * \return MQX_INVALID_COMPONENT_HANDLE Doesnt have any interrupt vectors, or pit does not exist.
 * \return -1                           When pit is used byt PE or when _int_install_isr faild.
 *
 * \see hwtimer_pit_deinit
 * \see hwtimer_pit_set_div
 * \see hwtimer_pit_start
 * \see hwtimer_pit_stop
 * \see hwtimer_pit_get_time
 * \see hwtimer_pit_isr
 * \see hwtimer_pit_isr_shared
 */
static _mqx_int hwtimer_pit_init(HWTIMER_PTR hwtimer, uint32_t pit_id, uint32_t isr_prior)
{
    HWTIMER_PTR * pit_hwtimers_array = NULL;
    uint32_t pit_hwtimers_array_size;
    PSP_INTERRUPT_TABLE_INDEX    vector;
    PIT_MemMapPtr pit_base;
    uint32_t pit_number;
    uint32_t pit_channel;
    uint32_t pit_channels_count;
    uint32_t pit_vectors_count;
    _mqx_uint i;
    const _mqx_uint *pit_vectors = NULL;
    PIT_MemMapPtr pit;
    /* Count of chanels is computed, because this information missing in generated iomap file */
    pit_channels_count = sizeof(pit->CHANNEL) / sizeof(pit->CHANNEL[0]);

    #if MQX_CHECK_ERRORS
    if (pit_channels_count <= pit_id)
    {
        return MQX_INVALID_PARAMETER;
    }
    #endif

    /* We need to store pit_id of timer in context struct */
    hwtimer->ll_context[0] = (uint32_t)PIT_BASE_PTR;
    hwtimer->ll_context[1] = pit_id;

    pit_base    = (PIT_MemMapPtr) hwtimer->ll_context[0];
    pit_channel = GET_PIT_CHANNEL_FROM_PITID(hwtimer->ll_context[1]);
    pit_number  = GET_PIT_NUMBER_FROM_PITID(hwtimer->ll_context[1]);
    #if PE_LDD_VERSION
    if (PE_PeripheralUsed((uint32_t)pit_base))
    {
        return -1;
    }
    #endif
    /* Enable PIT Module Clock */
    pit_io_init(0);

    /* workaround, add delay to pit clk gating and pit module enabling */
    for (i = 0; i <= 50; i++) {
    ;
    }

    /* Enable PIT module */
    PIT_MCR_REG(pit_base) =  0;

    #if BSPCFG_HWTIMER_PIT_FREEZE
    /* Allows the timers to be stopped when the device enters the Debug mode. */
    PIT_MCR_REG(pit_base) |= PIT_MCR_FRZ_MASK;
    #endif

    /* Disable timer and interrupt */
    PIT_TCTRL_REG(pit_base, pit_channel) = 0;
    /* Clear any pending interrupt */
    PIT_TFLG_REG(pit_base, pit_channel) = PIT_TFLG_TIF_MASK;

    /* Set isr for timer*/
    pit_vectors_count =  pit_get_vectors(pit_number, &pit_vectors);
    #if MQX_CHECK_ERRORS
    if ((NULL == pit_vectors) || (0 == pit_vectors_count))
    {
        return MQX_INVALID_COMPONENT_HANDLE;  //doesnt have any interrupt vectors, or pit does not exist
    }
    #endif
    if (pit_channels_count <= pit_vectors_count)
    {
        /* Every channel has own interrupt vector */
        vector = (PSP_INTERRUPT_TABLE_INDEX) (pit_vectors[pit_channel]);
        if (NULL == _int_install_isr(vector, (INT_ISR_FPTR) hwtimer_pit_isr, (void *) hwtimer))
        {
            return -1;
        }
        _bsp_int_init(vector, isr_prior, 0, TRUE);
    }
    else
    {
        pit_hwtimers_array_size = pit_get_hwtimers_array(&pit_hwtimers_array);
        #if MQX_CHECK_ERRORS
        if ((NULL == pit_hwtimers_array) || (0 == pit_hwtimers_array_size))
        {
            return MQX_INVALID_COMPONENT_HANDLE;
        }
        #endif
        /* Pit has shared interrupt vectors */
        pit_hwtimers_array[pit_channel] = hwtimer;
        for (i = 0; i < pit_vectors_count; i++)
        {
            vector = (PSP_INTERRUPT_TABLE_INDEX) (pit_vectors[i]);
            if (NULL == _int_install_isr(vector, (INT_ISR_FPTR) hwtimer_pit_isr_shared, NULL))
            {
                return -1;
            }
            _bsp_int_init(vector, isr_prior, 0, TRUE);
        }
    }
    return MQX_OK;
}