Example #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();
    }
}
Example #2
0
uint32_t app_timer_init(uint32_t                      prescaler,
                        uint8_t                       op_queues_size,
                        void *                        p_buffer,
                        app_timer_evt_schedule_func_t evt_schedule_func)
{
    int i;

    // Check that buffer is correctly aligned
    if (!is_word_aligned(p_buffer))
    {
        return NRF_ERROR_INVALID_PARAM;
    }
    // Check for NULL buffer
    if (p_buffer == NULL)
    {
        mp_users = NULL;
        return NRF_ERROR_INVALID_PARAM;
    }
    
    // Stop RTC to prevent any running timers from expiring (in case of reinitialization)
    rtc1_stop();
    
    m_evt_schedule_func = evt_schedule_func;
    
    // Initialize users array
    m_user_array_size = APP_TIMER_INT_LEVELS;
    mp_users          = p_buffer;
    
    // Skip user array
    p_buffer = &((uint8_t *)p_buffer)[APP_TIMER_INT_LEVELS * sizeof(timer_user_t)];

    // Initialize operation queues
    for (i = 0; i < APP_TIMER_INT_LEVELS; i++)
    {
        timer_user_t * p_user = &mp_users[i];
        
        p_user->first              = 0;
        p_user->last               = 0;
        p_user->user_op_queue_size = op_queues_size;
        p_user->p_user_op_queue    = p_buffer;
    
        // Skip operation queue
        p_buffer = &((uint8_t *)p_buffer)[op_queues_size * sizeof(timer_user_op_t)];
    }

    mp_timer_id_head             = NULL;
    m_ticks_elapsed_q_read_ind  = 0;
    m_ticks_elapsed_q_write_ind = 0;

    NVIC_ClearPendingIRQ(SWI_IRQn);
    NVIC_SetPriority(SWI_IRQn, SWI_IRQ_PRI);
    NVIC_EnableIRQ(SWI_IRQn);

    rtc1_init(prescaler);

    m_ticks_latest = rtc1_counter_get();
    
    return NRF_SUCCESS;
}
Example #3
0
/**@brief Function for removing a timer from the timer queue.
 *
 * @param[in]  timer_id   Id of timer to remove.
 */
static void timer_list_remove(app_timer_id_t timer_id)
{
    app_timer_id_t previous;
    app_timer_id_t current;
    uint32_t       timeout;

    // Find the timer's position in timer list.
    previous = m_timer_id_head;
    current  = previous;
    
    while (current != TIMER_NULL)
    {
        if (current == timer_id)
        {
            break;
        }
        previous = current;
        current  = mp_nodes[current].next;
    }

    // Timer not in active list.
    if (current == TIMER_NULL)
    {
        return;
    }

    // Timer is the first in the list
    if (previous == current)
    {
        m_timer_id_head = mp_nodes[m_timer_id_head].next;

        // No more timers in the list. Disable RTC1.
        if (m_timer_id_head == TIMER_NULL)
        {
            rtc1_stop();
        }
    }

    // Remaining timeout between next timeout.
    timeout = mp_nodes[current].ticks_to_expire;

    // Link previous timer with next of this timer, i.e. removing the timer from list.
    mp_nodes[previous].next = mp_nodes[current].next;

    // If this is not the last timer, increment the next timer by this timer timeout.
    current = mp_nodes[previous].next;
    if (current != TIMER_NULL)
    {
        mp_nodes[current].ticks_to_expire += timeout;
    }
}
Example #4
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)
    }
}
Example #5
0
uint32_t app_timer_init(uint32_t                      prescaler,
                        uint8_t                       op_queue_size,
                        void *                        p_buffer,
                        app_timer_evt_schedule_func_t evt_schedule_func)
{
    // Check that buffer is correctly aligned
    if (!is_word_aligned(p_buffer))
    {
        return NRF_ERROR_INVALID_PARAM;
    }
    // Check for NULL buffer
    if (p_buffer == NULL)
    {
        return NRF_ERROR_INVALID_PARAM;
    }

    // Stop RTC to prevent any running timers from expiring (in case of reinitialization)
    rtc1_stop();

    m_evt_schedule_func = evt_schedule_func;

    // Initialize operation queue
    m_op_queue.first           = 0;
    m_op_queue.last            = 0;
    m_op_queue.size            = op_queue_size;
    m_op_queue.p_user_op_queue = p_buffer;

    mp_timer_id_head            = NULL;
    m_ticks_elapsed_q_read_ind  = 0;
    m_ticks_elapsed_q_write_ind = 0;

#if APP_TIMER_WITH_PROFILER
    m_max_user_op_queue_utilization   = 0;
#endif

    NVIC_ClearPendingIRQ(SWI_IRQn);
    NVIC_SetPriority(SWI_IRQn, SWI_IRQ_PRI);
    NVIC_EnableIRQ(SWI_IRQn);

    rtc1_init(prescaler);

    m_ticks_latest = rtc1_counter_get();

    return NRF_SUCCESS;
}
Example #6
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();
    }
}
Example #7
0
uint32_t app_timer_init(uint32_t                      prescaler,
                        uint8_t                       max_timers,
                        uint8_t                       op_queues_size,
                        void *                        p_buffer,
                        app_timer_evt_schedule_func_t evt_schedule_func)
{
    int i;

    // Check that buffer is correctly aligned
    if (!is_word_aligned(p_buffer))
    {
        return NRF_ERROR_INVALID_PARAM;
    }
    // Check for NULL buffer
    if (p_buffer == NULL)
    {
        return NRF_ERROR_INVALID_PARAM;
    }
    
    // Stop RTC to prevent any running timers from expiring (in case of reinitialization)
    rtc1_stop();
    
    m_evt_schedule_func = evt_schedule_func;

    // Initialize timer node array
    m_node_array_size = max_timers;
    mp_nodes          = p_buffer;
    
    for (i = 0; i < max_timers; i++)
    {
        mp_nodes[i].state      = STATE_FREE;
        mp_nodes[i].is_running = false;
    }
    
    // Skip timer node array
    p_buffer = &((uint8_t *)p_buffer)[max_timers * sizeof(timer_node_t)];
    
    // Initialize users array
    m_user_array_size = APP_TIMER_INT_LEVELS;
    mp_users          = p_buffer;
    
    // Skip user array
    p_buffer = &((uint8_t *)p_buffer)[APP_TIMER_INT_LEVELS * sizeof(timer_user_t)];

    // Initialize operation queues
    for (i = 0; i < APP_TIMER_INT_LEVELS; i++)
    {
        timer_user_t * p_user = &mp_users[i];
        
        p_user->first              = 0;
        p_user->last               = 0;
        p_user->user_op_queue_size = op_queues_size;
        p_user->p_user_op_queue    = p_buffer;
    
        // Skip operation queue
        p_buffer = &((uint8_t *)p_buffer)[op_queues_size * sizeof(timer_user_op_t)];
    }

    m_timer_id_head             = TIMER_NULL;
    m_ticks_elapsed_q_read_ind  = 0;
    m_ticks_elapsed_q_write_ind = 0;

		/*
    NVIC_ClearPendingIRQ(SWI0_IRQn);
    NVIC_SetPriority(SWI0_IRQn, SWI0_IRQ_PRI);
    NVIC_EnableIRQ(SWI0_IRQn);
		*/
		
		
		/*--khai-- : temporarily use SWI1 for app_timer so that conflict with event_handler won't occur*/
    NVIC_ClearPendingIRQ(SWI1_IRQn);
    NVIC_SetPriority(SWI1_IRQn, SWI0_IRQ_PRI);
    NVIC_EnableIRQ(SWI1_IRQn);
		
    rtc1_init(prescaler);

    m_ticks_latest = rtc1_counter_get();
    
    return NRF_SUCCESS;
}