mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			
						commit
						802c89707e
					
				| 
						 | 
				
			
			@ -660,6 +660,91 @@ void test_timer_time_measurement()
 | 
			
		|||
    TEST_ASSERT_DURATION_WITHIN(delta(wait_val), wait_val, p_timer->elapsed_time());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This test verifies if a timer can be successfully copied.
 | 
			
		||||
 *
 | 
			
		||||
 * For this test Timer which uses os ticker
 | 
			
		||||
 * must be used.
 | 
			
		||||
 *
 | 
			
		||||
 * Given timer is created
 | 
			
		||||
 * Delay occurs
 | 
			
		||||
 * Timer is copied
 | 
			
		||||
 * Timer is stopped
 | 
			
		||||
 * Timer is copied again
 | 
			
		||||
 * Delay occurs
 | 
			
		||||
 * Then original timer and second copy should have measured first delay.
 | 
			
		||||
 * First copy should have measured both delays.
 | 
			
		||||
 */
 | 
			
		||||
template<int wait_val_us>
 | 
			
		||||
void test_timer_copying()
 | 
			
		||||
{
 | 
			
		||||
    microseconds wait_val(wait_val_us);
 | 
			
		||||
    const Timer &original = *static_cast<Timer *>(p_timer);
 | 
			
		||||
 | 
			
		||||
    /* Start the timer. */
 | 
			
		||||
    p_timer->start();
 | 
			
		||||
 | 
			
		||||
    /* Wait <wait_val_us> us. */
 | 
			
		||||
    busy_wait(wait_val);
 | 
			
		||||
 | 
			
		||||
    /* Copy the timer */
 | 
			
		||||
    Timer running_copy{original};
 | 
			
		||||
 | 
			
		||||
    /* Stop the original timer. */
 | 
			
		||||
    p_timer->stop();
 | 
			
		||||
 | 
			
		||||
    /* Copy the timer */
 | 
			
		||||
    Timer stopped_copy{original};
 | 
			
		||||
 | 
			
		||||
    /* Wait <wait_val_us> us. */
 | 
			
		||||
    busy_wait(wait_val);
 | 
			
		||||
 | 
			
		||||
    /* Stop the running copy. */
 | 
			
		||||
    running_copy.stop();
 | 
			
		||||
 | 
			
		||||
    /* Check results. */
 | 
			
		||||
    TEST_ASSERT_DURATION_WITHIN(delta(wait_val), wait_val, p_timer->elapsed_time());
 | 
			
		||||
    TEST_ASSERT_EQUAL_DURATION(p_timer->elapsed_time(), stopped_copy.elapsed_time());
 | 
			
		||||
    TEST_ASSERT_DURATION_WITHIN(delta(wait_val * 2), wait_val * 2, running_copy.elapsed_time());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This test verifies if a timer can be successfully moved.
 | 
			
		||||
 *
 | 
			
		||||
 * For this test Timer which uses os ticker
 | 
			
		||||
 * must be used.
 | 
			
		||||
 *
 | 
			
		||||
 * Given timer is created
 | 
			
		||||
 * Delay occurs
 | 
			
		||||
 * Timer is moved
 | 
			
		||||
 * Delay occurs
 | 
			
		||||
 * Then moved timer should have measured both delays.
 | 
			
		||||
 */
 | 
			
		||||
template<int wait_val_us>
 | 
			
		||||
void test_timer_moving()
 | 
			
		||||
{
 | 
			
		||||
    microseconds wait_val(wait_val_us);
 | 
			
		||||
    Timer &original = *static_cast<Timer *>(p_timer);
 | 
			
		||||
 | 
			
		||||
    /* Start the timer. */
 | 
			
		||||
    p_timer->start();
 | 
			
		||||
 | 
			
		||||
    /* Wait <wait_val_us> us. */
 | 
			
		||||
    busy_wait(wait_val);
 | 
			
		||||
 | 
			
		||||
    /* Move the timer */
 | 
			
		||||
    Timer moved_timer{std::move(original)};
 | 
			
		||||
 | 
			
		||||
    /* No longer valid to do anything with the original, other than destroy it (happens in cleanup) */
 | 
			
		||||
 | 
			
		||||
    /* Wait <wait_val_us> us. */
 | 
			
		||||
    busy_wait(wait_val);
 | 
			
		||||
 | 
			
		||||
    /* Stop the moved timer . */
 | 
			
		||||
    moved_timer.stop();
 | 
			
		||||
 | 
			
		||||
    /* Check results. */
 | 
			
		||||
    TEST_ASSERT_DURATION_WITHIN(delta(wait_val * 2), wait_val * 2, moved_timer.elapsed_time());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t test_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
    GREENTEA_SETUP(15, "default_auto");
 | 
			
		||||
| 
						 | 
				
			
			@ -683,6 +768,9 @@ Case cases[] = {
 | 
			
		|||
    Case("Test: Timer - time measurement 10 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<10000>, timer_os_ticker_cleanup_handler),
 | 
			
		||||
    Case("Test: Timer - time measurement 100 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<100000>, timer_os_ticker_cleanup_handler),
 | 
			
		||||
    Case("Test: Timer - time measurement 1 s.", timer_os_ticker_setup_handler, test_timer_time_measurement<1000000>, timer_os_ticker_cleanup_handler),
 | 
			
		||||
 | 
			
		||||
    Case("Test: Timer - copying 5 ms.", timer_os_ticker_setup_handler, test_timer_copying<5000>, timer_os_ticker_cleanup_handler),
 | 
			
		||||
    Case("Test: Timer - moving 5 ms.", timer_os_ticker_setup_handler, test_timer_moving<5000>, timer_os_ticker_cleanup_handler),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Specification specification(test_setup, cases);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,9 @@
 | 
			
		|||
#include "platform/NonCopyable.h"
 | 
			
		||||
 | 
			
		||||
namespace mbed {
 | 
			
		||||
 | 
			
		||||
class CriticalSectionLock;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \defgroup drivers_Timer Timer class
 | 
			
		||||
 * \ingroup drivers-public-api-ticker
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +54,7 @@ namespace mbed {
 | 
			
		|||
 * }
 | 
			
		||||
 * @endcode
 | 
			
		||||
 */
 | 
			
		||||
class TimerBase : private NonCopyable<TimerBase> {
 | 
			
		||||
class TimerBase {
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    /** Start the timer
 | 
			
		||||
| 
						 | 
				
			
			@ -109,13 +112,24 @@ public:
 | 
			
		|||
protected:
 | 
			
		||||
    TimerBase(const ticker_data_t *data);
 | 
			
		||||
    TimerBase(const ticker_data_t *data, bool lock_deepsleep);
 | 
			
		||||
    TimerBase(const TimerBase &t);
 | 
			
		||||
    TimerBase(TimerBase &&t);
 | 
			
		||||
    ~TimerBase();
 | 
			
		||||
 | 
			
		||||
    const TimerBase &operator=(const TimerBase &) = delete;
 | 
			
		||||
 | 
			
		||||
    std::chrono::microseconds slicetime() const;
 | 
			
		||||
    TickerDataClock::time_point _start{};   // the start time of the latest slice
 | 
			
		||||
    std::chrono::microseconds _time{};    // any accumulated time from previous slices
 | 
			
		||||
    TickerDataClock _ticker_data;
 | 
			
		||||
    bool _lock_deepsleep;    // flag that indicates if deep sleep should be disabled
 | 
			
		||||
    bool _running = false;   // whether the timer is running
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // Copy storage while a lock is held
 | 
			
		||||
    TimerBase(const TimerBase &t, const CriticalSectionLock &) : TimerBase(t, false) {}
 | 
			
		||||
    // Copy storage only - used by delegating constructors
 | 
			
		||||
    TimerBase(const TimerBase &t, bool) : _start(t._start), _time(t._time), _ticker_data(t._ticker_data), _lock_deepsleep(t._lock_deepsleep), _running(t._running) {}
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,26 @@ TimerBase::TimerBase(const ticker_data_t *data, bool lock_deepsleep) : _ticker_d
 | 
			
		|||
    reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This creates a temporary CriticalSectionLock while we delegate to the
 | 
			
		||||
// constructor that does the copy, thus holding critical section during the copy,
 | 
			
		||||
// ensuring locking on the source. Then continue our own initialization
 | 
			
		||||
// outside the critical section
 | 
			
		||||
TimerBase::TimerBase(const TimerBase &t) : TimerBase(t, CriticalSectionLock{})
 | 
			
		||||
{
 | 
			
		||||
    // If running, new copy needs an extra lock
 | 
			
		||||
    if (_running && _lock_deepsleep) {
 | 
			
		||||
        sleep_manager_lock_deep_sleep();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unlike copy constructor, no need for lock on move - we must be only person
 | 
			
		||||
// accessing source.
 | 
			
		||||
TimerBase::TimerBase(TimerBase &&t) : TimerBase(t, false)
 | 
			
		||||
{
 | 
			
		||||
    // Original is marked as no longer running - we adopt any lock it had
 | 
			
		||||
    t._running = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TimerBase::~TimerBase()
 | 
			
		||||
{
 | 
			
		||||
    if (_running) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue