| Index: emcore/trunk/init.c | 
| — | — | @@ -273,5 +273,6 @@ | 
| 274 | 274 | ib->bootalloc = bootalloc; | 
| 275 | 275 | thread_create(&(ib->initthread), initthreadname, initthread, ib->initstack, | 
| 276 | 276 | sizeof(ib->initstack), OS_THREAD, 127, true); | 
|  | 277 | +    timer_init(); | 
| 277 | 278 | interrupt_init(); | 
| 278 | 279 | } | 
| Index: emcore/trunk/target/ipodnano2g/timer.c | 
| — | — | @@ -27,22 +27,42 @@ | 
| 28 | 28 | #include "s5l8701.h" | 
| 29 | 29 |  | 
| 30 | 30 |  | 
| 31 |  | -void setup_tick()
 | 
|  | 31 | +void timer_init() | 
| 32 | 32 | { | 
| 33 |  | -    int cycles = SYSTEM_TICK / 100;
 | 
| 34 |  | -    
 | 
| 35 |  | -    /* configure timer for 10 kHz */
 | 
| 36 |  | -    TBCMD = (1 << 1);   /* TB_CLR */
 | 
| 37 |  | -    TBPRE = 300 - 1;    /* prescaler */
 | 
| 38 |  | -    TBCON = (0 << 13) | /* TB_INT1_EN */
 | 
| 39 |  | -            (1 << 12) | /* TB_INT0_EN */
 | 
|  | 33 | +} | 
|  | 34 | + | 
|  | 35 | +void timer_schedule_wakeup(uint32_t usecs) | 
|  | 36 | +{ | 
|  | 37 | +    if (usecs > 11184640) | 
|  | 38 | +    { | 
|  | 39 | +        TBPRE = 511; | 
|  | 40 | +        TBDATA1 = 65535; | 
|  | 41 | +    } | 
|  | 42 | +    else if (usecs > 21845) | 
|  | 43 | +    { | 
|  | 44 | +        TBPRE = 511; | 
|  | 45 | +        TBDATA1 = (usecs * 192) >> 15; | 
|  | 46 | +    } | 
|  | 47 | +    else | 
|  | 48 | +    { | 
|  | 49 | +        TBPRE = 0; | 
|  | 50 | +        TBDATA1 = (usecs * 192) >> 6; | 
|  | 51 | +    } | 
|  | 52 | +    TBCON = (1 << 13) | /* TB_INT1_EN */ | 
|  | 53 | +            (0 << 12) | /* TB_INT0_EN */ | 
| 40 | 54 | (0 << 11) | /* TB_START */ | 
| 41 | 55 | (2 << 8) |  /* TB_CS = PCLK / 16 */ | 
| 42 |  | -            (0 << 4);   /* TB_MODE_SEL = interval mode */
 | 
| 43 |  | -    TBDATA0 = cycles;   /* set interval period */
 | 
|  | 56 | +            (2 << 4);   /* TB_MODE_SEL = one-shot mode */ | 
|  | 57 | +    TBCMD = (1 << 1);   /* TB_CLR */ | 
| 44 | 58 | TBCMD = (1 << 0);   /* TB_EN */ | 
| 45 | 59 | } | 
| 46 | 60 |  | 
|  | 61 | +void timer_kill_wakeup() | 
|  | 62 | +{ | 
|  | 63 | +    TBCMD = (1 << 1);   /* TB_CLR */ | 
|  | 64 | +    TBCON = TBCON; | 
|  | 65 | +} | 
|  | 66 | + | 
| 47 | 67 | void INT_TIMERB(void) | 
| 48 | 68 | { | 
| 49 | 69 | TBCON = TBCON; | 
| Index: emcore/trunk/target/ipodnano3g/timer.c | 
| — | — | @@ -27,10 +27,8 @@ | 
| 28 | 28 | #include "s5l8702.h" | 
| 29 | 29 |  | 
| 30 | 30 |  | 
| 31 |  | -void setup_tick()
 | 
|  | 31 | +void timer_init() | 
| 32 | 32 | { | 
| 33 |  | -    int cycles = SYSTEM_TICK / 100;
 | 
| 34 |  | -    
 | 
| 35 | 33 | TACMD = (1 << 1);   /* TA_CLR */ | 
| 36 | 34 | TBCMD = (1 << 1);   /* TB_CLR */ | 
| 37 | 35 | TCCMD = (1 << 1);   /* TC_CLR */ | 
| — | — | @@ -37,18 +35,40 @@ | 
| 38 | 36 | TDCMD = (1 << 1);   /* TD_CLR */ | 
| 39 | 37 | TGCMD = (1 << 1);   /* TG_CLR */ | 
| 40 | 38 | THCMD = (1 << 1);   /* TH_CLR */ | 
|  | 39 | +} | 
| 41 | 40 |  | 
| 42 |  | -    /* configure timer for 10 kHz */
 | 
| 43 |  | -    TBPRE = 337 - 1;    /* prescaler */
 | 
| 44 |  | -    TBCON = (0 << 13) | /* TB_INT1_EN */
 | 
| 45 |  | -            (1 << 12) | /* TB_INT0_EN */
 | 
|  | 41 | +void timer_schedule_wakeup(uint32_t usecs) | 
|  | 42 | +{ | 
|  | 43 | +    if (usecs > 9942053) | 
|  | 44 | +    { | 
|  | 45 | +        TBPRE = 511; | 
|  | 46 | +        TBDATA1 = 65535; | 
|  | 47 | +    } | 
|  | 48 | +    else if (usecs > 19417) | 
|  | 49 | +    { | 
|  | 50 | +        TBPRE = 511; | 
|  | 51 | +        TBDATA1 = (usecs * 216) >> 15; | 
|  | 52 | +    } | 
|  | 53 | +    else | 
|  | 54 | +    { | 
|  | 55 | +        TBPRE = 0; | 
|  | 56 | +        TBDATA1 = (usecs * 216) >> 6; | 
|  | 57 | +    } | 
|  | 58 | +    TBCON = (1 << 13) | /* TB_INT1_EN */ | 
|  | 59 | +            (0 << 12) | /* TB_INT0_EN */ | 
| 46 | 60 | (0 << 11) | /* TB_START */ | 
| 47 | 61 | (3 << 8) |  /* TB_CS = PCLK / 64 */ | 
| 48 |  | -            (0 << 4);   /* TB_MODE_SEL = interval mode */
 | 
| 49 |  | -    TBDATA0 = cycles;   /* set interval period */
 | 
|  | 62 | +            (2 << 4);   /* TB_MODE_SEL = one-shot mode */ | 
|  | 63 | +    TBCMD = (1 << 1);   /* TB_CLR */ | 
| 50 | 64 | TBCMD = (1 << 0);   /* TB_EN */ | 
| 51 | 65 | } | 
| 52 | 66 |  | 
|  | 67 | +void timer_kill_wakeup() | 
|  | 68 | +{ | 
|  | 69 | +    TBCMD = (1 << 1);   /* TB_CLR */ | 
|  | 70 | +    TBCON = TBCON; | 
|  | 71 | +} | 
|  | 72 | + | 
| 53 | 73 | void INT_TIMERB(void) | 
| 54 | 74 | { | 
| 55 | 75 | TBCON = TBCON; | 
| Index: emcore/trunk/target/ipodnano4g/timer.c | 
| — | — | @@ -27,10 +27,8 @@ | 
| 28 | 28 | #include "s5l8720.h" | 
| 29 | 29 |  | 
| 30 | 30 |  | 
| 31 |  | -void setup_tick()
 | 
|  | 31 | +void timer_init() | 
| 32 | 32 | { | 
| 33 |  | -    int cycles = SYSTEM_TICK / 100;
 | 
| 34 |  | -    
 | 
| 35 | 33 | TACMD = (1 << 1);   /* TA_CLR */ | 
| 36 | 34 | TBCMD = (1 << 1);   /* TB_CLR */ | 
| 37 | 35 | TCCMD = (1 << 1);   /* TC_CLR */ | 
| — | — | @@ -38,18 +36,40 @@ | 
| 39 | 37 | TFCMD = (1 << 1);   /* TF_CLR */ | 
| 40 | 38 | TGCMD = (1 << 1);   /* TG_CLR */ | 
| 41 | 39 | THCMD = (1 << 1);   /* TH_CLR */ | 
|  | 40 | +} | 
| 42 | 41 |  | 
| 43 |  | -    /* configure timer for 10 kHz */
 | 
| 44 |  | -    TBPRE = 208 - 1;    /* prescaler */
 | 
| 45 |  | -    TBCON = (0 << 13) | /* TB_INT1_EN */
 | 
| 46 |  | -            (1 << 12) | /* TB_INT0_EN */
 | 
|  | 42 | +void timer_schedule_wakeup(uint32_t usecs) | 
|  | 43 | +{ | 
|  | 44 | +    if (usecs > 16146247) | 
|  | 45 | +    { | 
|  | 46 | +        TBPRE = 511; | 
|  | 47 | +        TBDATA1 = 65535; | 
|  | 48 | +    } | 
|  | 49 | +    else if (usecs > 31535) | 
|  | 50 | +    { | 
|  | 51 | +        TBPRE = 511; | 
|  | 52 | +        TBDATA1 = (usecs * 133) >> 15; | 
|  | 53 | +    } | 
|  | 54 | +    else | 
|  | 55 | +    { | 
|  | 56 | +        TBPRE = 0; | 
|  | 57 | +        TBDATA1 = (usecs * 133) >> 6; | 
|  | 58 | +    } | 
|  | 59 | +    TBCON = (1 << 13) | /* TB_INT1_EN */ | 
|  | 60 | +            (0 << 12) | /* TB_INT0_EN */ | 
| 47 | 61 | (0 << 11) | /* TB_START */ | 
| 48 | 62 | (3 << 8) |  /* TB_CS = PCLK / 64 */ | 
| 49 |  | -            (0 << 4);   /* TB_MODE_SEL = interval mode */
 | 
| 50 |  | -    TBDATA0 = cycles;   /* set interval period */
 | 
|  | 63 | +            (2 << 4);   /* TB_MODE_SEL = one-shot mode */ | 
|  | 64 | +    TBCMD = (1 << 1);   /* TB_CLR */ | 
| 51 | 65 | TBCMD = (1 << 0);   /* TB_EN */ | 
| 52 | 66 | } | 
| 53 | 67 |  | 
|  | 68 | +void timer_kill_wakeup() | 
|  | 69 | +{ | 
|  | 70 | +    TBCMD = (1 << 1);   /* TB_CLR */ | 
|  | 71 | +    TBCON = TBCON; | 
|  | 72 | +} | 
|  | 73 | + | 
| 54 | 74 | void INT_TIMERB(void) | 
| 55 | 75 | { | 
| 56 | 76 | TBCON = TBCON; | 
| Index: emcore/trunk/thread.c | 
| — | — | @@ -238,7 +238,6 @@ | 
| 239 | 239 | idle_thread.type = CORE_THREAD; | 
| 240 | 240 | idle_thread.name = "idle thread"; | 
| 241 | 241 | idle_thread.stack = (uint32_t*)-1; | 
| 242 |  | -    setup_tick();
 | 
| 243 | 242 | } | 
| 244 | 243 |  | 
| 245 | 244 | bool scheduler_freeze(bool value) | 
| — | — | @@ -275,6 +274,9 @@ | 
| 276 | 275 | current_thread->block_type = THREAD_DEFUNCT_STKOV; | 
| 277 | 276 | wakeup_signal(&dbgwakeup); | 
| 278 | 277 | } | 
|  | 278 | + | 
|  | 279 | +    timer_kill_wakeup(); | 
|  | 280 | + | 
| 279 | 281 | if (usec - last_tick > SCHEDULER_TICK) | 
| 280 | 282 | { | 
| 281 | 283 | uint32_t diff = usec - last_tick; | 
| — | — | @@ -286,10 +288,12 @@ | 
| 287 | 289 | } | 
| 288 | 290 | } | 
| 289 | 291 |  | 
|  | 292 | +    uint32_t next_unblock = 0xffffffff; | 
| 290 | 293 | if (scheduler_frozen) thread = &idle_thread; | 
| 291 | 294 | else | 
| 292 | 295 | { | 
| 293 | 296 | for (t = head_thread; t; t = t->thread_next) | 
|  | 297 | +        { | 
| 294 | 298 | if (t->state == THREAD_BLOCKED && t->timeout != -1 | 
| 295 | 299 | && TIME_AFTER(usec, t->blocked_since + t->timeout)) | 
| 296 | 300 | { | 
| — | — | @@ -300,6 +304,12 @@ | 
| 301 | 305 | t->blocked_by = NULL; | 
| 302 | 306 | t->timeout = 0; | 
| 303 | 307 | } | 
|  | 308 | +            else if (t->state == THREAD_BLOCKED && t->timeout != -1) | 
|  | 309 | +            { | 
|  | 310 | +                uint32_t left = t->blocked_since + t->timeout - usec; | 
|  | 311 | +                if (left < next_unblock) next_unblock = left; | 
|  | 312 | +            } | 
|  | 313 | +        } | 
| 304 | 314 |  | 
| 305 | 315 | if (!thread || thread->state != THREAD_READY) | 
| 306 | 316 | { | 
| — | — | @@ -317,6 +327,9 @@ | 
| 318 | 328 | } | 
| 319 | 329 | } | 
| 320 | 330 | } | 
|  | 331 | + | 
|  | 332 | +        if (thread == &idle_thread) timer_schedule_wakeup(next_unblock); | 
|  | 333 | +        else timer_schedule_wakeup(SYSTEM_TICK); | 
| 321 | 334 | } | 
| 322 | 335 |  | 
| 323 | 336 | current_thread = thread; | 
| Index: emcore/trunk/timer.h | 
| — | — | @@ -45,7 +45,9 @@ | 
| 46 | 46 | } | 
| 47 | 47 |  | 
| 48 | 48 |  | 
| 49 |  | -void setup_tick() INITCODE_ATTR;
 | 
|  | 49 | +void timer_init() INITCODE_ATTR; | 
|  | 50 | +void timer_schedule_wakeup(uint32_t usecs) ICODE_ATTR; | 
|  | 51 | +void timer_kill_wakeup() ICODE_ATTR; | 
| 50 | 52 | void INT_TIMERB() ICODE_ATTR; | 
| 51 | 53 |  | 
| 52 | 54 |  |