Пример #1
0
/**@brief Function for updating the Capture Compare register.
 */
static void compare_reg_update(app_timer_id_t timer_id_head_old)
{
    // Setup the timeout for timers on the head of the list 
    if (m_timer_id_head != TIMER_NULL)
    {
        uint32_t ticks_to_expire = mp_nodes[m_timer_id_head].ticks_to_expire;
        uint32_t counter         = rtc1_counter_get();
        uint32_t cc              = m_ticks_latest;
        uint32_t ticks_elapsed   = ticks_diff_get(counter, cc) + RTC_COMPARE_OFFSET_MIN;

        if (timer_id_head_old == TIMER_NULL)
        {
            // No timers were already running, start RTC
            rtc1_start();
        }

        cc += (ticks_elapsed < ticks_to_expire) ? ticks_to_expire : ticks_elapsed;
        cc &= MAX_RTC_CNT;
        
        rtc1_compare0_set(cc);

        if (ticks_diff_get(rtc1_counter_get(), counter) > ticks_diff_get(cc, counter))
        {
            timer_timeouts_check_sched();
        }
    }
    else
    {
        // No timers are running, stop RTC
        rtc1_stop();
    }
}
Пример #2
0
uint32_t app_timer_cnt_diff_compute(uint32_t   ticks_to,
                                    uint32_t   ticks_from,
                                    uint32_t * p_ticks_diff)
{
    *p_ticks_diff = ticks_diff_get(ticks_to, ticks_from);
    return NRF_SUCCESS;
}
Пример #3
0
/**@brief Function for updating the Capture Compare register.
 */
static void compare_reg_update(timer_node_t * p_timer_id_head_old)
{
    // Setup the timeout for timers on the head of the list
    if (mp_timer_id_head != NULL)
    {
        uint32_t ticks_to_expire = mp_timer_id_head->ticks_to_expire;
        uint32_t pre_counter_val = rtc1_counter_get();
        uint32_t cc              = m_ticks_latest;
        uint32_t ticks_elapsed   = ticks_diff_get(pre_counter_val, cc) + RTC_COMPARE_OFFSET_MIN;

        if (!m_rtc1_running)
        {
            // No timers were already running, start RTC
            rtc1_start();
        }

        cc += (ticks_elapsed < ticks_to_expire) ? ticks_to_expire : ticks_elapsed;
        cc &= MAX_RTC_COUNTER_VAL;

        rtc1_compare0_set(cc);

        uint32_t post_counter_val = rtc1_counter_get();

        if (
            (ticks_diff_get(post_counter_val, pre_counter_val) + RTC_COMPARE_OFFSET_MIN)
            >
            ticks_diff_get(cc, pre_counter_val)
           )
        {
            // When this happens the COMPARE event may not be triggered by the RTC.
            // The nRF51 Series User Specification states that if the COUNTER value is N
            // (i.e post_counter_val = N), writing N or N + 1 to a CC register may not trigger a
            // COMPARE event. Hence the RTC interrupt is forcefully pended by calling the following
            // function.
            rtc1_compare0_set(rtc1_counter_get());  // this should prevent CC to fire again in the background while the code is in RTC-ISR
            nrf_delay_us(MAX_RTC_TASKS_DELAY);
            timer_timeouts_check_sched();
        }
    }
    else
    {
#if (APP_TIMER_KEEPS_RTC_ACTIVE == 0)
        // No timers are running, stop RTC
        rtc1_stop();
#endif //(APP_TIMER_KEEPS_RTC_ACTIVE == 0)
    }
}
Пример #4
0
/**@brief Function for updating the Capture Compare register.
 */
static void compare_reg_update(app_timer_id_t timer_id_head_old)
{
    // Setup the timeout for timers on the head of the list 
    if (m_timer_id_head != TIMER_NULL)
    {
        uint32_t ticks_to_expire = mp_nodes[m_timer_id_head].ticks_to_expire;
        uint32_t pre_counter_val = rtc1_counter_get();
        uint32_t cc              = m_ticks_latest;
        uint32_t ticks_elapsed   = ticks_diff_get(pre_counter_val, cc) + RTC_COMPARE_OFFSET_MIN;

        if (timer_id_head_old == TIMER_NULL)
        {
            // No timers were already running, start RTC
            rtc1_start();
        }

        cc += (ticks_elapsed < ticks_to_expire) ? ticks_to_expire : ticks_elapsed;
        cc &= MAX_RTC_COUNTER_VAL;
        
        rtc1_compare0_set(cc);

        uint32_t post_counter_val = rtc1_counter_get();

        if (
            (ticks_diff_get(post_counter_val, pre_counter_val) + RTC_COMPARE_OFFSET_MIN)
            >
            ticks_diff_get(cc, pre_counter_val)
           )
        {
            // When this happens the COMPARE event may not be triggered by the RTC.
            // The nRF51 Series User Specification states that if the COUNTER value is N
            // (i.e post_counter_val = N), writing N or N+1 to a CC register may not trigger a
            // COMPARE event. Hence the RTC interrupt is forcefully pended by calling the following
            // function.
            timer_timeouts_check_sched();
        }
    }
    else
    {
        // No timers are running, stop RTC
        rtc1_stop();
    }
}
Пример #5
0
/**@brief Function for handling timer list insertions.
 *
 * @param[in]  p_restart_list_head   List of repeating timers to be restarted.
 *
 * @return     TRUE if Capture Compare register must be updated, FALSE otherwise.
 */
static bool list_insertions_handler(timer_node_t * p_restart_list_head)
{
    timer_node_t * p_timer_id_old_head;
    uint8_t        user_id;

    // Remember the old head, so as to decide if new compare needs to be set.
    p_timer_id_old_head = mp_timer_id_head;

    user_id = m_user_array_size;
    while (user_id--)
    {
        timer_user_t * p_user = &mp_users[user_id];

        // Handle insertions of timers.
        while ((p_restart_list_head != NULL) || (p_user->first != p_user->last))
        {
            timer_node_t * p_timer;

            if (p_restart_list_head != NULL)
            {
                p_timer           = p_restart_list_head;
                p_restart_list_head = p_timer->next;
            }
            else
            {
                timer_user_op_t * p_user_op = &p_user->p_user_op_queue[p_user->first];

                p_user->first++;
                if (p_user->first == p_user->user_op_queue_size)
                {
                    p_user->first = 0;
                }

                p_timer = p_user_op->p_node;

                if ((p_user_op->op_type != TIMER_USER_OP_TYPE_START) || p_timer->is_running)
                {
                    continue;
                }

                p_timer->ticks_at_start          = p_user_op->params.start.ticks_at_start;
                p_timer->ticks_first_interval    = p_user_op->params.start.ticks_first_interval;
                p_timer->ticks_periodic_interval = p_user_op->params.start.ticks_periodic_interval;
                p_timer->p_context               = p_user_op->params.start.p_context;

                if (m_rtc1_reset)
                {
                    p_timer->ticks_at_start = 0;
                }
            }

            // Prepare the node to be inserted.
            if (
                 ((p_timer->ticks_at_start - m_ticks_latest) & MAX_RTC_COUNTER_VAL)
                 <
                 (MAX_RTC_COUNTER_VAL / 2)
                )
            {
                p_timer->ticks_to_expire = ticks_diff_get(p_timer->ticks_at_start, m_ticks_latest) + 
                                           p_timer->ticks_first_interval;
            }
            else
            {
                uint32_t delta_current_start;

                delta_current_start = ticks_diff_get(m_ticks_latest, p_timer->ticks_at_start);
                if (p_timer->ticks_first_interval > delta_current_start)
                {
                    p_timer->ticks_to_expire = p_timer->ticks_first_interval - delta_current_start;
                }
                else
                {
                    p_timer->ticks_to_expire = 0;
                }
            }

            p_timer->ticks_at_start       = 0;
            p_timer->ticks_first_interval = 0;
            p_timer->is_running           = true;
            p_timer->next                 = NULL;

            // Insert into list 
            timer_list_insert(p_timer);
        }
    }
    
    return (mp_timer_id_head != p_timer_id_old_head);
}
Пример #6
0
/**@brief Function for checking for expired timers.
 */
static void timer_timeouts_check(void)
{
    // Handle expired of timer 
    if (mp_timer_id_head != NULL)
    {
        timer_node_t *  p_timer;
        timer_node_t *  p_previous_timer;
        uint32_t        ticks_elapsed;
        uint32_t        ticks_expired;

        // Initialize actual elapsed ticks being consumed to 0.
        ticks_expired = 0;

        // ticks_elapsed is collected here, job will use it.
        ticks_elapsed = ticks_diff_get(rtc1_counter_get(), m_ticks_latest);

        // Auto variable containing the head of timers expiring.
        p_timer = mp_timer_id_head;

        // Expire all timers within ticks_elapsed and collect ticks_expired.
        while (p_timer != NULL)
        {
            // Do nothing if timer did not expire.
            if (ticks_elapsed < p_timer->ticks_to_expire)
            {
                break;
            }

            // Decrement ticks_elapsed and collect expired ticks.
            ticks_elapsed -= p_timer->ticks_to_expire;
            ticks_expired += p_timer->ticks_to_expire;

            // Move to next timer.
            p_previous_timer = p_timer;
            p_timer = p_timer->next;

            // Execute Task.
            timeout_handler_exec(p_previous_timer);
        }

        // Prepare to queue the ticks expired in the m_ticks_elapsed queue.
        if (m_ticks_elapsed_q_read_ind == m_ticks_elapsed_q_write_ind)
        {
            // The read index of the queue is equal to the write index. This means the new
            // value of ticks_expired should be stored at a new location in the m_ticks_elapsed
            // queue (which is implemented as a double buffer).

            // Check if there will be a queue overflow.
            if (++m_ticks_elapsed_q_write_ind == CONTEXT_QUEUE_SIZE_MAX)
            {
                // There will be a queue overflow. Hence the write index should point to the start
                // of the queue.
                m_ticks_elapsed_q_write_ind = 0;
            }
        }

        // Queue the ticks expired.
        m_ticks_elapsed[m_ticks_elapsed_q_write_ind] = ticks_expired;

        timer_list_handler_sched();
    }
}
Пример #7
0
/**@brief Function for checking for expired timers.
 */
static void timer_timeouts_check(void)
{
    // Handle expired of timer 
    if (m_timer_id_head != TIMER_NULL)
    {
        uint32_t ticks_expired;
        uint8_t  ticks_elapsed_last;

        // Initialize actual elapsed ticks being consumed to 0 
        ticks_expired = 0;

        // Queue the ticks elapsed (to make the value context safe)
        ticks_elapsed_last = m_ticks_elapsed_last + 1;
        if (ticks_elapsed_last == CONTEXT_QUEUE_SIZE_MAX)
        {
            ticks_elapsed_last = 0;
        }

        if (ticks_elapsed_last != m_ticks_elapsed_first)
        {
            app_timer_id_t timer_id;
            uint32_t       ticks_elapsed;

            // Ticks_elapsed is collected here, job will use it
            ticks_elapsed = ticks_diff_get(rtc1_counter_get(), m_ticks_latest);

            // Auto variable containing the head of timers expiring 
            timer_id = m_timer_id_head;

            // Expire all timers within ticks_elapsed and collect ticks_expired 
            while (timer_id != TIMER_NULL)
            {
                timer_node_t * p_timer;

                // Auto variable for current timer node 
                p_timer = &mp_nodes[timer_id];

                // Do nothing if timer did not expire 
                if (ticks_elapsed < p_timer->ticks_to_expire)
                {
                    break;
                }

                // Decrement ticks_elapsed and collect expired ticks 
                ticks_elapsed -= p_timer->ticks_to_expire;
                ticks_expired += p_timer->ticks_to_expire;

                // Move to next timer 
                timer_id = p_timer->next;

                // Execute Task 
                timeout_handler_exec(p_timer);
            }
        }

        // Queue the elapsed value 
        m_ticks_elapsed[m_ticks_elapsed_last] = ticks_expired;
        m_ticks_elapsed_last                  = ticks_elapsed_last;

        timer_list_handler_sched();
    }
}