diff --git a/boards/OLIMEX_LPC_P2148/buzzer.c b/boards/OLIMEX_LPC_P2148/buzzer.c index 39c501e07..8f1137446 100644 --- a/boards/OLIMEX_LPC_P2148/buzzer.c +++ b/boards/OLIMEX_LPC_P2148/buzzer.c @@ -69,7 +69,9 @@ void buzzInit(void) { static void stop(void *p) { StopCounter((TC *)p); + chSysLockFromIsr(); chEvtBroadcastI(&BuzzerSilentEventSource); + chSysUnlockFromIsr(); } /** diff --git a/demos/ARMCM3-STM32F103ZG-FATFS/main.c b/demos/ARMCM3-STM32F103ZG-FATFS/main.c index 4181c7004..8199275cd 100644 --- a/demos/ARMCM3-STM32F103ZG-FATFS/main.c +++ b/demos/ARMCM3-STM32F103ZG-FATFS/main.c @@ -89,6 +89,7 @@ bool_t sdc_lld_is_write_protected(SDCDriver *sdcp) { static void tmrfunc(void *p) { SDCDriver *sdcp = p; + chSysLockFromIsr(); if (cnt > 0) { if (sdcIsCardInserted(sdcp)) { if (--cnt == 0) { @@ -105,6 +106,7 @@ static void tmrfunc(void *p) { } } chVTSetI(&tmr, MS2ST(SDC_POLLING_DELAY), tmrfunc, sdcp); + chSysUnlockFromIsr(); } /** diff --git a/docs/reports/SPC563M64-80.txt b/docs/reports/SPC563M64-80.txt index d786aa30e..fc754adcc 100644 --- a/docs/reports/SPC563M64-80.txt +++ b/docs/reports/SPC563M64-80.txt @@ -5,8 +5,8 @@ Settings: SYSCLK=80 *** ChibiOS/RT test suite *** -*** Kernel: 2.4.0 -*** Compiled: Jan 17 2012 - 14:35:40 +*** Kernel: 2.5.0 +*** Compiled: Feb 8 2012 - 10:21:46 *** Compiler: GCC 4.4.1 *** Architecture: Power Architecture *** Core Variant: e200z3 @@ -100,35 +100,35 @@ Settings: SYSCLK=80 --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.1 (Benchmark, messages #1) ---- Score : 283160 msgs/S, 566320 ctxswc/S +--- Score : 278226 msgs/S, 556452 ctxswc/S --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.2 (Benchmark, messages #2) ---- Score : 226208 msgs/S, 452416 ctxswc/S +--- Score : 224935 msgs/S, 449870 ctxswc/S --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.3 (Benchmark, messages #3) ---- Score : 226208 msgs/S, 452416 ctxswc/S +--- Score : 224935 msgs/S, 449870 ctxswc/S --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.4 (Benchmark, context switch) ---- Score : 897232 ctxswc/S +--- Score : 890960 ctxswc/S --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.5 (Benchmark, threads, full cycle) ---- Score : 180251 threads/S +--- Score : 178638 threads/S --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.6 (Benchmark, threads, create only) ---- Score : 261812 threads/S +--- Score : 255935 threads/S --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.7 (Benchmark, mass reschedule, 5 threads) ---- Score : 73862 reschedules/S, 443172 ctxswc/S +--- Score : 73319 reschedules/S, 439914 ctxswc/S --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.8 (Benchmark, round robin context switching) ---- Score : 614140 ctxswc/S +--- Score : 609448 ctxswc/S --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.9 (Benchmark, I/O Queues throughput) @@ -136,7 +136,7 @@ Settings: SYSCLK=80 --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.10 (Benchmark, virtual timers set/reset) ---- Score : 1093664 timers/S +--- Score : 1094200 timers/S --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.11 (Benchmark, semaphores wait/signal) @@ -144,11 +144,11 @@ Settings: SYSCLK=80 --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.12 (Benchmark, mutexes lock/unlock) ---- Score : 841236 lock+unlock/S +--- Score : 841232 lock+unlock/S --- Result: SUCCESS ---------------------------------------------------------------------------- --- Test Case 11.13 (Benchmark, RAM footprint) ---- System: 768 bytes +--- System: 764 bytes --- Thread: 72 bytes --- Timer : 20 bytes --- Semaph: 12 bytes diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 996033da5..7458d9252 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -167,8 +167,10 @@ static void i2c_lld_safety_timeout(void *p) { if (i2cp->thread) { i2c_lld_abort_operation(i2cp); + chSysLockFromIsr(); i2cp->thread->p_u.rdymsg = RDY_TIMEOUT; chSchReadyI(i2cp->thread); + chSysUnlockFromIsr(); } } diff --git a/os/hal/src/mmc_spi.c b/os/hal/src/mmc_spi.c index 8f11355b8..f4bcb51fd 100644 --- a/os/hal/src/mmc_spi.c +++ b/os/hal/src/mmc_spi.c @@ -105,6 +105,7 @@ static uint8_t crc7(uint8_t crc, const uint8_t *buffer, size_t len) { static void tmrfunc(void *p) { MMCDriver *mmcp = p; + chSysLockFromIsr(); if (mmcp->cnt > 0) { if (mmcp->is_inserted()) { if (--mmcp->cnt == 0) { @@ -123,6 +124,7 @@ static void tmrfunc(void *p) { } } chVTSetI(&mmcp->vt, MS2ST(MMC_POLLING_DELAY), tmrfunc, mmcp); + chSysUnlockFromIsr(); } /** diff --git a/os/kernel/include/chvt.h b/os/kernel/include/chvt.h index 95fb16408..355f66064 100644 --- a/os/kernel/include/chvt.h +++ b/os/kernel/include/chvt.h @@ -55,7 +55,8 @@ * * @api */ -#define MS2ST(msec) ((systime_t)(((((msec) - 1L) * CH_FREQUENCY) / 1000L) + 1L)) +#define MS2ST(msec) ((systime_t)(((((msec) - 1L) * CH_FREQUENCY) / \ + 1000L) + 1L)) /** * @brief Microseconds to system ticks. @@ -67,7 +68,8 @@ * * @api */ -#define US2ST(usec) ((systime_t)(((((usec) - 1L) * CH_FREQUENCY) / 1000000L) + 1L)) +#define US2ST(usec) ((systime_t)(((((usec) - 1L) * CH_FREQUENCY) / \ + 1000000L) + 1L)) /** @} */ /** @@ -112,40 +114,84 @@ typedef struct { volatile systime_t vt_systime; /**< @brief System Time counter. */ } VTList; -extern VTList vtlist; - /** * @name Macro Functions * @{ */ /** * @brief Virtual timers ticker. + * @note The system lock is released before entering the callback and + * re-acquired immediately after. It is callback's responsibility + * to acquire the lock if needed. This is done in order to reduce + * interrupts jitter when many timers are in use. * * @iclass */ -#define chVTDoTickI() { \ - vtlist.vt_systime++; \ - if (&vtlist != (VTList *)vtlist.vt_next) { \ - VirtualTimer *vtp; \ - \ - --vtlist.vt_next->vt_time; \ - while (!(vtp = vtlist.vt_next)->vt_time) { \ - vtfunc_t fn = vtp->vt_func; \ - vtp->vt_func = (vtfunc_t)NULL; \ - vtp->vt_next->vt_prev = (void *)&vtlist; \ - (&vtlist)->vt_next = vtp->vt_next; \ - fn(vtp->vt_par); \ - } \ - } \ +#define chVTDoTickI() { \ + vtlist.vt_systime++; \ + if (&vtlist != (VTList *)vtlist.vt_next) { \ + VirtualTimer *vtp; \ + \ + --vtlist.vt_next->vt_time; \ + while (!(vtp = vtlist.vt_next)->vt_time) { \ + vtfunc_t fn = vtp->vt_func; \ + vtp->vt_func = (vtfunc_t)NULL; \ + vtp->vt_next->vt_prev = (void *)&vtlist; \ + (&vtlist)->vt_next = vtp->vt_next; \ + chSysUnlockFromIsr(); \ + fn(vtp->vt_par); \ + chSysLockFromIsr(); \ + } \ + } \ } /** - * @brief Returns TRUE if the speciified timer is armed. + * @brief Returns @p TRUE if the specified timer is armed. * * @iclass */ #define chVTIsArmedI(vtp) ((vtp)->vt_func != NULL) +/** + * @brief Enables a virtual timer. + * @note The associated function is invoked from interrupt context. + * + * @param[out] vtp the @p VirtualTimer structure pointer + * @param[in] time the number of ticks before the operation timeouts, the + * special values are handled as follow: + * - @a TIME_INFINITE is allowed but interpreted as a + * normal time specification. + * - @a TIME_IMMEDIATE this value is not allowed. + * . + * @param[in] vtfunc the timer callback function. After invoking the + * callback the timer is disabled and the structure can + * be disposed or reused. + * @param[in] par a parameter that will be passed to the callback + * function + * + * @api + */ +#define chVTSet(vtp, time, vtfunc, par) { \ + chSysLock(); \ + chVTSetI(vtp, time, vtfunc, par); \ + chSysUnlock(); \ +} + +/** + * @brief Disables a Virtual Timer. + * @note The timer is first checked and disabled only if armed. + * + * @param[in] vtp the @p VirtualTimer structure pointer + * + * @api + */ +#define chVTReset(vtp) { \ + chSysLock(); \ + if (chVTIsArmedI(vtp)) \ + chVTResetI(vtp); \ + chSysUnlock(); \ +} + /** * @brief Current system time. * @details Returns the number of system ticks since the @p chSysInit() @@ -153,13 +199,15 @@ extern VTList vtlist; * @note The counter can reach its maximum and then restart from zero. * @note This function is designed to work with the @p chThdSleepUntil(). * - * @return The system time in ticks.r + * @return The system time in ticks. * * @api */ #define chTimeNow() (vtlist.vt_systime) /** @} */ +extern VTList vtlist; + /* * Virtual Timers APIs. */ diff --git a/os/kernel/src/chschd.c b/os/kernel/src/chschd.c index 808e06300..9739a595b 100644 --- a/os/kernel/src/chschd.c +++ b/os/kernel/src/chschd.c @@ -127,10 +127,12 @@ void chSchGoSleepS(tstate_t newstate) { static void wakeup(void *p) { Thread *tp = (Thread *)p; + chSysLockFromIsr(); switch (tp->p_state) { case THD_STATE_READY: /* Handling the special case where the thread has been made ready by another thread with higher priority.*/ + chSysUnlockFromIsr(); return; #if CH_USE_SEMAPHORES || CH_USE_QUEUES || \ (CH_USE_CONDVARS && CH_USE_CONDVARS_TIMEOUT) @@ -151,6 +153,7 @@ static void wakeup(void *p) { } tp->p_u.rdymsg = RDY_TIMEOUT; chSchReadyI(tp); + chSysUnlockFromIsr(); } /** diff --git a/os/kernel/src/chvt.c b/os/kernel/src/chvt.c index 4869cebef..6389aaf6d 100644 --- a/os/kernel/src/chvt.c +++ b/os/kernel/src/chvt.c @@ -49,8 +49,7 @@ void _vt_init(void) { /** * @brief Enables a virtual timer. - * @note The associated function is invoked by an interrupt handler within - * the I-Locked state, see @ref system_states. + * @note The associated function is invoked from interrupt context. * * @param[out] vtp the @p VirtualTimer structure pointer * @param[in] time the number of ticks before the operation timeouts, the diff --git a/os/various/evtimer.c b/os/various/evtimer.c index 314e0cc12..fedc5d6e4 100644 --- a/os/various/evtimer.c +++ b/os/various/evtimer.c @@ -32,8 +32,10 @@ static void tmrcb(void *p) { EvTimer *etp = p; + chSysLockFromIsr(); chEvtBroadcastI(&etp->et_es); chVTSetI(&etp->et_vt, etp->et_interval, tmrcb, etp); + chSysUnlockFromIsr(); } /** @@ -60,12 +62,7 @@ void evtStart(EvTimer *etp) { */ void evtStop(EvTimer *etp) { - chSysLock(); - - if (chVTIsArmedI(&etp->et_vt)) - chVTResetI(&etp->et_vt); - - chSysUnlock(); + chVTReset(&etp->et_vt); } /** @} */ diff --git a/readme.txt b/readme.txt index c4ac352a4..d757e889c 100644 --- a/readme.txt +++ b/readme.txt @@ -93,6 +93,9 @@ - NEW: Revision of the round-robin scheduling, now threads do not lose their time slice when preempted. Each thread has its own time slices counter. TODO: Seek optimizations. +- NEW: Modified the Virtual Timers management, now the callback is invoked + not in lock mode. This change reduces the interrupt jitter caused by + multiple timers used at same time. *** 2.3.5 *** - FIX: Fixed RTC compile problem on STM32F103 (bug 3468445). diff --git a/test/test.c b/test/test.c index bce0b5788..55cfdf445 100644 --- a/test/test.c +++ b/test/test.c @@ -278,9 +278,7 @@ void test_start_timer(unsigned ms) { systime_t duration = MS2ST(ms); test_timer_done = FALSE; - chSysLock(); - chVTSetI(&vt, duration, tmr, NULL); - chSysUnlock(); + chVTSet(&vt, duration, tmr, NULL); } /* diff --git a/testhal/STM32F1xx/UART/main.c b/testhal/STM32F1xx/UART/main.c index bdc222e35..0d36e2b89 100644 --- a/testhal/STM32F1xx/UART/main.c +++ b/testhal/STM32F1xx/UART/main.c @@ -26,7 +26,10 @@ static VirtualTimer vt1, vt2; static void restart(void *p) { (void)p; + + chSysLockFromIsr(); uartStartSendI(&UARTD2, 14, "Hello World!\r\n"); + chSysUnlockFromIsr(); } static void ledoff(void *p) { diff --git a/testhal/STM32F4xx/UART/main.c b/testhal/STM32F4xx/UART/main.c index 377a75934..69aed3c19 100644 --- a/testhal/STM32F4xx/UART/main.c +++ b/testhal/STM32F4xx/UART/main.c @@ -26,7 +26,10 @@ static VirtualTimer vt1, vt2; static void restart(void *p) { (void)p; + + chSysLockFromIsr(); uartStartSendI(&UARTD2, 14, "Hello World!\r\n"); + chSysUnlockFromIsr(); } static void ledoff(void *p) { diff --git a/testhal/STM32L1xx/UART/main.c b/testhal/STM32L1xx/UART/main.c index 8bb5ea6d7..65f834672 100644 --- a/testhal/STM32L1xx/UART/main.c +++ b/testhal/STM32L1xx/UART/main.c @@ -26,7 +26,10 @@ static VirtualTimer vt1, vt2; static void restart(void *p) { (void)p; + + chSysLockFromIsr(); uartStartSendI(&UARTD1, 14, "Hello World!\r\n"); + chSysUnlockFromIsr(); } static void ledoff(void *p) { diff --git a/todo.txt b/todo.txt index 04ca10f0b..32c58b9b2 100644 --- a/todo.txt +++ b/todo.txt @@ -13,8 +13,8 @@ X SDC driver port to STM32F2 and STM32F4. Within 2.5.x: * Revision of scheduling strategy for threads at equal priority. -- Handling of Virtual Timer callbacks out of critical zone. -- Add normal API (not iclass) variants of the VT functions. +* Handling of Virtual Timer callbacks out of critical zone. +* Add normal API (not iclass) variants of the VT functions. - Add the RTC service inside the kernel and port, remove from HAL. - Add option to use the RTC counter instead of the systick counter into the trace buffer.