Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't register the same timer again at the timeout handle function #17

Open
simonccn opened this issue Mar 23, 2016 · 1 comment
Open

Comments

@simonccn
Copy link
Contributor

static void led_flash_timer_handle(POINTER param)
{
       LED_RED_TOGGLE();    
       led_timer.cb_ticks = 300
        led_timer.cb_func = led_flash_timer_handle;
        led_timer.cb_data = NULL;        
        atomTimerRegister(&lock_led_timer);    
}
void led_flash(uint8_t led, uint32_t interval, uint8_t flash_times)
{
    atomTimerCancel(&lock_led_timer);

     LED_RED_ON();

    lock_led_timer.cb_ticks = 300;
    lock_led_timer.cb_func = led_flash_timer_handle;
    lock_led_timer.cb_data = NULL;

    atomTimerRegister(&lock_led_timer);    
}

The callback list in atomTimerCallbacks() will be changed if the timer register again in led_flash_timer_handle. This limit the application of timers.

@br-rhrbacek
Copy link

I successfully fixed this issue by modifying the ATOM_TIMER structure:

/* Timer descriptor */
typedef struct atom_timer
{
    TIMER_CB_FUNC   cb_func;    /* Callback function */
    POINTER         cb_data;    /* Pointer to callback parameter/data */
    uint32_t        cb_ticks;   /* Ticks until callback */

    /* Internal data */
    struct atom_timer *next_timer;      /* Next timer in doubly-linked list */
    struct atom_timer *next_timer_call; /* Next timer that should be called */

} ATOM_TIMER;

Then I modified the atomTimerCallbacks() function:

/**
 * \b atomTimerCallbacks
 *
 * This is an internal function not for use by application code.
 *
 * Find any callbacks that are due and call them up.
 *
 * @return None
 */
static void atomTimerCallbacks (void)
{
    ATOM_TIMER *prev_ptr, *next_ptr, *saved_next_ptr;
    ATOM_TIMER *callback_list_tail = NULL, *callback_list_head = NULL;

    /*
     * Walk the list decrementing each timer's remaining ticks count and
     * looking for due callbacks.
     */
    prev_ptr = next_ptr = timer_queue;
    while (next_ptr)
    {
        /* Save the next timer in the list (we adjust next_ptr for callbacks) */
        saved_next_ptr = next_ptr->next_timer;

        /* Is this entry due? */
        if (--(next_ptr->cb_ticks) == 0)
        {
            /* Remove the entry from the timer list */
            if (next_ptr == timer_queue)
            {
                /* We're removing the list head */
                timer_queue = next_ptr->next_timer;
            }
            else
            {
                /* We're removing a mid or tail timer */
                prev_ptr->next_timer = next_ptr->next_timer;
            }

            /*
             * Add this timer to the list of callbacks to run later when
             * we've finished walking the list (we shouldn't call callbacks
             * now in case they want to register new timers and hence walk
             * the timer list.
             *
             * We use the ATOM_TIMER structure's next_timer_call to maintain the
             * callback list.
             */
            if (callback_list_head == NULL)
            {
                /* First callback request in the list */
                callback_list_head = callback_list_tail = next_ptr;
                callback_list_head->next_timer_call = NULL;
            }
            else
            {
                /* Add callback request to the list tail */
                callback_list_tail->next_timer_call = next_ptr;
                callback_list_tail = next_ptr;
            }

            /* Mark this timer as the end of the callback list */
            next_ptr->next_timer_call = NULL;

            /* Do not update prev_ptr, we have just removed this one */

        }

        /* Entry is not due, leave it in there with its count decremented */
        else
        {
            /*
             * Update prev_ptr to this entry. We will need it if we want
             * to remove a mid or tail timer.
             */
            prev_ptr = next_ptr;
        }

        /* Move on to the next in the list */
        next_ptr = saved_next_ptr;
    }

    /*
     * Check if any callbacks were due. We call them after we walk the list
     * in case they want to register new timers (and hence walk the list).
     */
    if (callback_list_head)
    {
        /* Walk the callback list */
        next_ptr = callback_list_head;
        while (next_ptr)
        {
            /* Call the registered callback */
            if (next_ptr->cb_func)
            {
                next_ptr->cb_func (next_ptr->cb_data);
            }

            /* Move on to the next callback in the list */
            next_ptr = next_ptr->next_timer_call;
        }
    }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants