timer.c 18.5 KB
Newer Older
1 2 3
/*
 * File      : timer.c
 * This file is part of RT-Thread RTOS
D
dzzxzz 已提交
4
 * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
5
 *
B
Bernard Xiong 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 20 21 22 23 24 25 26
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-03-12     Bernard      first version
 * 2006-04-29     Bernard      implement thread timer
 * 2006-06-04     Bernard      implement rt_timer_control
 * 2006-08-10     Bernard      fix the periodic timer bug
 * 2006-09-03     Bernard      implement rt_timer_detach
27
 * 2009-11-11     LiJin        add soft timer
28
 * 2010-05-12     Bernard      fix the timer check bug.
29
 * 2010-11-02     Charlie      re-implement tick overflow issue
30
 * 2012-12-15     Bernard      fix the next timeout issue in soft timer
31 32
 * 2014-07-12     Bernard      does not lock scheduler when invoking soft-timer 
 *                             timeout function.
33 34 35 36 37
 */

#include <rtthread.h>
#include <rthw.h>

38
/* hard timer list */
39
static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
40

41
#ifdef RT_USING_TIMER_SOFT
42
#ifndef RT_TIMER_THREAD_STACK_SIZE
D
dzzxzz@gmail.com 已提交
43
#define RT_TIMER_THREAD_STACK_SIZE     512
44 45 46
#endif

#ifndef RT_TIMER_THREAD_PRIO
D
dzzxzz@gmail.com 已提交
47
#define RT_TIMER_THREAD_PRIO           0
48 49
#endif

50
/* soft timer list */
51
static rt_list_t rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
52 53 54
static struct rt_thread timer_thread;
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t timer_thread_stack[RT_TIMER_THREAD_STACK_SIZE];
55
#endif
56

57
#ifdef RT_USING_HOOK
D
dzzxzz 已提交
58 59 60
extern void (*rt_object_take_hook)(struct rt_object *object);
extern void (*rt_object_put_hook)(struct rt_object *object);
static void (*rt_timer_timeout_hook)(struct rt_timer *timer);
61 62 63 64

/**
 * @addtogroup Hook
 */
D
dzzxzz 已提交
65

D
dogandog 已提交
66
/**@{*/
67 68 69 70

/**
 * This function will set a hook function, which will be invoked when timer
 * is timeout.
71
 *
72 73
 * @param hook the hook function
 */
D
dzzxzz 已提交
74
void rt_timer_timeout_sethook(void (*hook)(struct rt_timer *timer))
75
{
76
    rt_timer_timeout_hook = hook;
77 78
}

D
dogandog 已提交
79
/**@}*/
80 81
#endif

82
static void _rt_timer_init(rt_timer_t timer,
D
dzzxzz@gmail.com 已提交
83 84 85 86
                           void (*timeout)(void *parameter),
                           void      *parameter,
                           rt_tick_t  time,
                           rt_uint8_t flag)
87
{
88 89
    int i;

90 91
    /* set flag */
    timer->parent.flag  = flag;
92

93 94
    /* set deactivated */
    timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
95

96 97
    timer->timeout_func = timeout;
    timer->parameter    = parameter;
98

99 100
    timer->timeout_tick = 0;
    timer->init_tick    = time;
101

102
    /* initialize timer list */
103 104 105 106
    for (i = 0; i < RT_TIMER_SKIP_LIST_LEVEL; i++)
    {
        rt_list_init(&(timer->row[i]));
    }
107 108
}

109 110
/* the fist timer always in the last row */
static rt_tick_t rt_timer_list_next_timeout(rt_list_t timer_list[])
111
{
112
    struct rt_timer *timer;
D
dzzxzz@gmail.com 已提交
113

114
    if (rt_list_isempty(&timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
115
        return RT_TICK_MAX;
B
Bernard Xiong 已提交
116

117 118
    timer = rt_list_entry(timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
                          struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
D
dzzxzz@gmail.com 已提交
119

120
    return timer->timeout_tick;
121 122
}

123 124 125 126 127 128 129 130 131 132
rt_inline void _rt_timer_remove(rt_timer_t timer)
{
    int i;

    for (i = 0; i < RT_TIMER_SKIP_LIST_LEVEL; i++)
    {
        rt_list_remove(&timer->row[i]);
    }
}

G
Grissiom 已提交
133
#if RT_DEBUG_TIMER
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
static int rt_timer_count_height(struct rt_timer *timer)
{
    int i, cnt = 0;

    for (i = 0; i < RT_TIMER_SKIP_LIST_LEVEL; i++)
    {
        if (!rt_list_isempty(&timer->row[i]))
            cnt++;
    }
    return cnt;
}

void rt_timer_dump(rt_list_t timer_heads[])
{
    rt_list_t *list;

    for (list = timer_heads[RT_TIMER_SKIP_LIST_LEVEL-1].next;
         list != &timer_heads[RT_TIMER_SKIP_LIST_LEVEL-1];
         list = list->next)
    {
        struct rt_timer *timer = rt_list_entry(list,
                                               struct rt_timer,
                                               row[RT_TIMER_SKIP_LIST_LEVEL-1]);
        rt_kprintf("%d", rt_timer_count_height(timer));
    }
    rt_kprintf("\n");
}
161
#endif
162

163 164 165
/**
 * @addtogroup Clock
 */
D
dzzxzz 已提交
166

D
dogandog 已提交
167
/**@{*/
168 169

/**
170 171
 * This function will initialize a timer, normally this function is used to
 * initialize a static timer object.
172 173 174 175 176 177 178 179
 *
 * @param timer the static timer object
 * @param name the name of timer
 * @param timeout the timeout function
 * @param parameter the parameter of timeout function
 * @param time the tick of timer
 * @param flag the flag of timer
 */
D
dzzxzz@gmail.com 已提交
180
void rt_timer_init(rt_timer_t  timer,
181
                   const char *name,
D
dzzxzz@gmail.com 已提交
182 183 184 185
                   void (*timeout)(void *parameter),
                   void       *parameter,
                   rt_tick_t   time,
                   rt_uint8_t  flag)
186
{
187 188
    /* timer check */
    RT_ASSERT(timer != RT_NULL);
189

190 191
    /* timer object initialization */
    rt_object_init((rt_object_t)timer, RT_Object_Class_Timer, name);
192

193
    _rt_timer_init(timer, timeout, parameter, time, flag);
194
}
195
RTM_EXPORT(rt_timer_init);
196

197
/**
198 199 200
 * This function will detach a timer from timer management.
 *
 * @param timer the static timer object
201
 *
202 203 204 205
 * @return the operation status, RT_EOK on OK; RT_ERROR on error
 */
rt_err_t rt_timer_detach(rt_timer_t timer)
{
206
    register rt_base_t level;
207

208 209
    /* timer check */
    RT_ASSERT(timer != RT_NULL);
210

211 212
    /* disable interrupt */
    level = rt_hw_interrupt_disable();
213

214
    _rt_timer_remove(timer);
215

216 217
    /* enable interrupt */
    rt_hw_interrupt_enable(level);
218

219
    rt_object_detach((rt_object_t)timer);
220

221
    return -RT_EOK;
222
}
223
RTM_EXPORT(rt_timer_detach);
224 225 226 227 228 229 230 231 232 233 234 235 236

#ifdef RT_USING_HEAP
/**
 * This function will create a timer
 *
 * @param name the name of timer
 * @param timeout the timeout function
 * @param parameter the parameter of timeout function
 * @param time the tick of timer
 * @param flag the flag of timer
 *
 * @return the created timer object
 */
D
dzzxzz@gmail.com 已提交
237 238 239 240 241
rt_timer_t rt_timer_create(const char *name,
                           void (*timeout)(void *parameter),
                           void       *parameter,
                           rt_tick_t   time,
                           rt_uint8_t  flag)
242
{
243
    struct rt_timer *timer;
244

245 246 247 248 249 250
    /* allocate a object */
    timer = (struct rt_timer *)rt_object_allocate(RT_Object_Class_Timer, name);
    if (timer == RT_NULL)
    {
        return RT_NULL;
    }
251

252
    _rt_timer_init(timer, timeout, parameter, time, flag);
253

254
    return timer;
255
}
256
RTM_EXPORT(rt_timer_create);
257 258 259 260 261 262 263 264 265 266

/**
 * This function will delete a timer and release timer memory
 *
 * @param timer the timer to be deleted
 *
 * @return the operation status, RT_EOK on OK; RT_ERROR on error
 */
rt_err_t rt_timer_delete(rt_timer_t timer)
{
267
    register rt_base_t level;
268

269 270
    /* timer check */
    RT_ASSERT(timer != RT_NULL);
271

272 273
    /* disable interrupt */
    level = rt_hw_interrupt_disable();
274

275
    _rt_timer_remove(timer);
276

277 278
    /* enable interrupt */
    rt_hw_interrupt_enable(level);
279

280
    rt_object_delete((rt_object_t)timer);
281

282
    return -RT_EOK;
283
}
284
RTM_EXPORT(rt_timer_delete);
285 286 287 288 289 290 291
#endif

/**
 * This function will start the timer
 *
 * @param timer the timer to be started
 *
B
bernard.xiong@gmail.com 已提交
292
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
293 294 295
 */
rt_err_t rt_timer_start(rt_timer_t timer)
{
296
    unsigned int row_lvl;
297
    rt_list_t *timer_list;
298
    register rt_base_t level;
299 300 301
    rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL];
    unsigned int tst_nr;
    static unsigned int random_nr;
302

303 304
    /* timer check */
    RT_ASSERT(timer != RT_NULL);
305 306 307 308 309 310 311 312

	/* stop timer firstly */
	level = rt_hw_interrupt_disable();
	/* remove timer from list */
    _rt_timer_remove(timer);
    /* change status of timer */
    timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
    rt_hw_interrupt_enable(level);
313

314
    RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent)));
315

D
dzzxzz@gmail.com 已提交
316 317 318 319 320
    /*
     * get timeout tick,
     * the max timeout tick shall not great than RT_TICK_MAX/2
     */
    RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2);
321
    timer->timeout_tick = rt_tick_get() + timer->init_tick;
322

323 324
    /* disable interrupt */
    level = rt_hw_interrupt_disable();
325

326
#ifdef RT_USING_TIMER_SOFT
327 328 329
    if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
    {
        /* insert timer to soft timer list */
330
        timer_list = rt_soft_timer_list;
331 332
    }
    else
333
#endif
334 335
    {
        /* insert timer to system timer list */
336
        timer_list = rt_timer_list;
337 338
    }

339 340
    row_head[0]  = &timer_list[0];
    for (row_lvl = 0; row_lvl < RT_TIMER_SKIP_LIST_LEVEL; row_lvl++)
341
    {
342 343
        for (;row_head[row_lvl] != timer_list[row_lvl].prev;
             row_head[row_lvl]  = row_head[row_lvl]->next)
344
        {
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
            struct rt_timer *t;
            rt_list_t *p = row_head[row_lvl]->next;

            /* fix up the entry pointer */
            t = rt_list_entry(p, struct rt_timer, row[row_lvl]);

            /* If we have two timers that timeout at the same time, it's
             * preferred that the timer inserted early get called early.
             * So insert the new timer to the end the the some-timeout timer
             * list.
             */
            if ((t->timeout_tick - timer->timeout_tick) == 0)
            {
                continue;
            }
            else if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX / 2)
            {
                break;
            }
364
        }
365 366
        if (row_lvl != RT_TIMER_SKIP_LIST_LEVEL - 1)
            row_head[row_lvl+1] = row_head[row_lvl]+1;
367
    }
368 369 370 371 372 373 374 375 376 377 378

    /* Interestingly, this super simple timer insert counter works very very
     * well on distributing the list height uniformly. By means of "very very
     * well", I mean it beats the randomness of timer->timeout_tick very easily
     * (actually, the timeout_tick is not random and easy to be attacked). */
    random_nr++;
    tst_nr = random_nr;

    rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL-1],
                         &(timer->row[RT_TIMER_SKIP_LIST_LEVEL-1]));
    for (row_lvl = 2; row_lvl <= RT_TIMER_SKIP_LIST_LEVEL; row_lvl++)
379
    {
380 381 382 383 384 385 386 387
        if (!(tst_nr & RT_TIMER_SKIP_LIST_MASK))
            rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL - row_lvl],
                                 &(timer->row[RT_TIMER_SKIP_LIST_LEVEL - row_lvl]));
        else
            break;
        /* Shift over the bits we have tested. Works well with 1 bit and 2
         * bits. */
        tst_nr >>= (RT_TIMER_SKIP_LIST_MASK+1)>>1;
388 389 390 391 392 393
    }

    timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;

    /* enable interrupt */
    rt_hw_interrupt_enable(level);
394

395
#ifdef RT_USING_TIMER_SOFT
396 397 398 399 400 401 402 403 404 405
    if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
    {
        /* check whether timer thread is ready */
        if (timer_thread.stat != RT_THREAD_READY)
        {
            /* resume timer thread to check soft timer */
            rt_thread_resume(&timer_thread);
            rt_schedule();
        }
    }
406 407
#endif

408
    return -RT_EOK;
409
}
410
RTM_EXPORT(rt_timer_start);
411 412 413 414 415 416

/**
 * This function will stop the timer
 *
 * @param timer the timer to be stopped
 *
B
bernard.xiong@gmail.com 已提交
417
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
418 419 420
 */
rt_err_t rt_timer_stop(rt_timer_t timer)
{
421
    register rt_base_t level;
422

423 424 425 426
    /* timer check */
    RT_ASSERT(timer != RT_NULL);
    if (!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED))
        return -RT_ERROR;
427

428
    RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(timer->parent)));
429

430 431
    /* disable interrupt */
    level = rt_hw_interrupt_disable();
432

433
    _rt_timer_remove(timer);
434

435 436
    /* enable interrupt */
    rt_hw_interrupt_enable(level);
437

438 439
    /* change stat */
    timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
440

441
    return RT_EOK;
442
}
443
RTM_EXPORT(rt_timer_stop);
444 445 446 447 448 449 450 451

/**
 * This function will get or set some options of the timer
 *
 * @param timer the timer to be get or set
 * @param cmd the control command
 * @param arg the argument
 *
B
bernard.xiong@gmail.com 已提交
452
 * @return RT_EOK
453
 */
D
dzzxzz 已提交
454
rt_err_t rt_timer_control(rt_timer_t timer, rt_uint8_t cmd, void *arg)
455
{
456 457
    /* timer check */
    RT_ASSERT(timer != RT_NULL);
458

459 460 461 462 463
    switch (cmd)
    {
    case RT_TIMER_CTRL_GET_TIME:
        *(rt_tick_t *)arg = timer->init_tick;
        break;
464

465 466 467
    case RT_TIMER_CTRL_SET_TIME:
        timer->init_tick = *(rt_tick_t *)arg;
        break;
468

469 470 471
    case RT_TIMER_CTRL_SET_ONESHOT:
        timer->parent.flag &= ~RT_TIMER_FLAG_PERIODIC;
        break;
472

473 474 475 476
    case RT_TIMER_CTRL_SET_PERIODIC:
        timer->parent.flag |= RT_TIMER_FLAG_PERIODIC;
        break;
    }
477

478
    return RT_EOK;
479
}
480
RTM_EXPORT(rt_timer_control);
481 482

/**
483
 * This function will check timer list, if a timeout event happens, the
484 485
 * corresponding timeout function will be invoked.
 *
B
bernard.xiong@gmail.com 已提交
486
 * @note this function shall be invoked in operating system timer interrupt.
487
 */
488
void rt_timer_check(void)
489
{
490 491 492 493 494 495 496 497 498 499 500
    struct rt_timer *t;
    rt_tick_t current_tick;
    register rt_base_t level;

    RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));

    current_tick = rt_tick_get();

    /* disable interrupt */
    level = rt_hw_interrupt_disable();

501
    while (!rt_list_isempty(&rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL-1]))
502
    {
503 504
        t = rt_list_entry(rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
                          struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
505 506 507 508 509 510 511 512 513 514

        /*
         * It supposes that the new tick shall less than the half duration of
         * tick max.
         */
        if ((current_tick - t->timeout_tick) < RT_TICK_MAX/2)
        {
            RT_OBJECT_HOOK_CALL(rt_timer_timeout_hook, (t));

            /* remove timer from timer list firstly */
515
            _rt_timer_remove(t);
516 517 518 519 520 521 522 523 524 525

            /* call timeout function */
            t->timeout_func(t->parameter);

            /* re-get tick */
            current_tick = rt_tick_get();

            RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));

            if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
D
dzzxzz@gmail.com 已提交
526
                (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
            {
                /* start it */
                t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
                rt_timer_start(t);
            }
            else
            {
                /* stop timer */
                t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
            }
        }
        else
            break;
    }

    /* enable interrupt */
    rt_hw_interrupt_enable(level);

    RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n"));
546 547
}

548 549 550 551 552 553
/**
 * This function will return the next timeout tick in the system.
 *
 * @return the next timeout tick in the system
 */
rt_tick_t rt_timer_next_timeout_tick(void)
554
{
555
    return rt_timer_list_next_timeout(rt_timer_list);
556 557
}

558
#ifdef RT_USING_TIMER_SOFT
559 560 561 562
/**
 * This function will check timer list, if a timeout event happens, the
 * corresponding timeout function will be invoked.
 */
D
dzzxzz 已提交
563
void rt_soft_timer_check(void)
564
{
565 566 567 568 569 570 571 572
    rt_tick_t current_tick;
    rt_list_t *n;
    struct rt_timer *t;

    RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n"));

    current_tick = rt_tick_get();

573 574 575
	/* lock scheduler */
	rt_enter_critical();

576 577
    for (n = rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL-1].next;
         n != &(rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL-1]);)
578
    {
579
        t = rt_list_entry(n, struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL-1]);
580 581 582 583 584

        /*
         * It supposes that the new tick shall less than the half duration of
         * tick max.
         */
D
dzzxzz@gmail.com 已提交
585
        if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
586 587 588 589 590 591 592
        {
            RT_OBJECT_HOOK_CALL(rt_timer_timeout_hook, (t));

            /* move node to the next */
            n = n->next;

            /* remove timer from timer list firstly */
593
            _rt_timer_remove(t);
594

595 596
			/* not lock scheduler when performing timeout function */
			rt_exit_critical();
597 598 599 600 601 602 603 604
            /* call timeout function */
            t->timeout_func(t->parameter);

            /* re-get tick */
            current_tick = rt_tick_get();

            RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));

605 606 607
			/* lock scheduler */
			rt_enter_critical();

608
            if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
D
dzzxzz@gmail.com 已提交
609
                (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
610 611 612 613 614 615 616 617 618 619 620 621 622 623
            {
                /* start it */
                t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
                rt_timer_start(t);
            }
            else
            {
                /* stop timer */
                t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
            }
        }
        else break; /* not check anymore */
    }

624 625 626
	/* unlock scheduler */
	rt_exit_critical();

627
    RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
628 629
}

630
/* system timer thread entry */
D
dzzxzz 已提交
631
static void rt_thread_timer_entry(void *parameter)
632
{
633
    rt_tick_t next_timeout;
B
Bernard Xiong 已提交
634

635 636 637
    while (1)
    {
        /* get the next timeout tick */
638
        next_timeout = rt_timer_list_next_timeout(rt_soft_timer_list);
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
        if (next_timeout == RT_TICK_MAX)
        {
            /* no software timer exist, suspend self. */
            rt_thread_suspend(rt_thread_self());
            rt_schedule();
        }
        else
        {
            rt_tick_t current_tick;

            /* get current tick */
            current_tick = rt_tick_get();

            if ((next_timeout - current_tick) < RT_TICK_MAX/2)
            {
                /* get the delta timeout tick */
                next_timeout = next_timeout - current_tick;
                rt_thread_delay(next_timeout);
            }
        }

        /* check software timer */
        rt_soft_timer_check();
    }
663
}
664
#endif
665

666 667 668
/**
 * @ingroup SystemInit
 *
669
 * This function will initialize system timer
670
 */
D
dzzxzz 已提交
671
void rt_system_timer_init(void)
672
{
673 674 675 676 677 678
    int i;

    for (i = 0; i < sizeof(rt_timer_list)/sizeof(rt_timer_list[0]); i++)
    {
        rt_list_init(rt_timer_list+i);
    }
B
bernard.xiong 已提交
679
}
680

B
bernard.xiong 已提交
681 682 683
/**
 * @ingroup SystemInit
 *
684
 * This function will initialize system timer thread
B
bernard.xiong 已提交
685
 */
D
dzzxzz 已提交
686
void rt_system_timer_thread_init(void)
B
bernard.xiong 已提交
687 688
{
#ifdef RT_USING_TIMER_SOFT
689 690 691 692 693 694 695 696
    int i;

    for (i = 0;
         i < sizeof(rt_soft_timer_list)/sizeof(rt_soft_timer_list[0]);
         i++)
    {
        rt_list_init(rt_soft_timer_list+i);
    }
697

698 699 700
    /* start software timer thread */
    rt_thread_init(&timer_thread,
                   "timer",
D
dzzxzz@gmail.com 已提交
701 702 703 704 705 706
                   rt_thread_timer_entry,
                   RT_NULL,
                   &timer_thread_stack[0],
                   sizeof(timer_thread_stack),
                   RT_TIMER_THREAD_PRIO,
                   10);
707

708 709
    /* startup */
    rt_thread_startup(&timer_thread);
710
#endif
711
}
712

D
dogandog 已提交
713
/**@}*/