mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #6534 from c1728p9/rtos_suspend
Update idle loop to reduce calls to suspendpull/6715/merge
						commit
						675528b6c0
					
				| 
						 | 
					@ -25,6 +25,7 @@
 | 
				
			||||||
#include "greentea-client/test_env.h"
 | 
					#include "greentea-client/test_env.h"
 | 
				
			||||||
#include "unity.h"
 | 
					#include "unity.h"
 | 
				
			||||||
#include "utest.h"
 | 
					#include "utest.h"
 | 
				
			||||||
 | 
					#include "ticker_api.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#include "rtx_lib.h"
 | 
					#include "rtx_lib.h"
 | 
				
			||||||
| 
						 | 
					@ -44,7 +45,9 @@ private:
 | 
				
			||||||
    Semaphore _sem;
 | 
					    Semaphore _sem;
 | 
				
			||||||
    virtual void handler()
 | 
					    virtual void handler()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        increment_tick();
 | 
					        core_util_critical_section_enter();
 | 
				
			||||||
 | 
					        _increment_tick();
 | 
				
			||||||
 | 
					        core_util_critical_section_exit();
 | 
				
			||||||
        _sem.release();
 | 
					        _sem.release();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,6 +57,11 @@ public:
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SysTimerTest(const ticker_data_t *data) :
 | 
				
			||||||
 | 
					            SysTimer(data), _sem(0, 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual ~SysTimerTest()
 | 
					    virtual ~SysTimerTest()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -64,6 +72,65 @@ public:
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					timestamp_t mock_ticker_timestamp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mock_ticker_init()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t mock_ticker_read()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return mock_ticker_timestamp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mock_ticker_disable_interrupt()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mock_ticker_clear_interrupt()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mock_ticker_set_interrupt(timestamp_t timestamp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mock_ticker_fire_interrupt()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ticker_info_t *mock_ticker_get_info()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static const ticker_info_t mock_ticker_info = {
 | 
				
			||||||
 | 
					        .frequency = 1000000,
 | 
				
			||||||
 | 
					        .bits = 32
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    return &mock_ticker_info;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ticker_interface_t mock_ticker_interface = {
 | 
				
			||||||
 | 
					    .init = mock_ticker_init,
 | 
				
			||||||
 | 
					    .read = mock_ticker_read,
 | 
				
			||||||
 | 
					    .disable_interrupt = mock_ticker_disable_interrupt,
 | 
				
			||||||
 | 
					    .clear_interrupt = mock_ticker_clear_interrupt,
 | 
				
			||||||
 | 
					    .set_interrupt = mock_ticker_set_interrupt,
 | 
				
			||||||
 | 
					    .fire_interrupt = mock_ticker_fire_interrupt,
 | 
				
			||||||
 | 
					    .get_info = mock_ticker_get_info,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ticker_event_queue_t mock_ticker_event_queue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ticker_data_t mock_ticker_data = {
 | 
				
			||||||
 | 
					    .interface = &mock_ticker_interface,
 | 
				
			||||||
 | 
					    .queue = &mock_ticker_event_queue
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mock_ticker_reset()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    mock_ticker_timestamp = 0;
 | 
				
			||||||
 | 
					    memset(&mock_ticker_event_queue, 0, sizeof mock_ticker_event_queue);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Test tick count is zero upon creation
 | 
					/** Test tick count is zero upon creation
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Given a SysTimer
 | 
					 * Given a SysTimer
 | 
				
			||||||
| 
						 | 
					@ -79,26 +146,29 @@ void test_created_with_zero_tick_count(void)
 | 
				
			||||||
/** Test tick count is updated correctly
 | 
					/** Test tick count is updated correctly
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Given a SysTimer
 | 
					 * Given a SysTimer
 | 
				
			||||||
 * When @a update_tick method is called immediately after creation
 | 
					 * When the @a suspend and @a resume methods are called immediately after creation
 | 
				
			||||||
 * Then the tick count is not updated
 | 
					 * Then the tick count is not updated
 | 
				
			||||||
 * When @a update_tick is called again after a delay
 | 
					 * When @a suspend and @a resume methods are called again after a delay
 | 
				
			||||||
 * Then the tick count is updated
 | 
					 * Then the tick count is updated
 | 
				
			||||||
 *     and the number of ticks incremented is equal TEST_TICKS - 1
 | 
					 *     and the number of ticks incremented is equal TEST_TICKS - 1
 | 
				
			||||||
 * When @a update_tick is called again without a delay
 | 
					 * When @a suspend and @a resume methods are called again without a delay
 | 
				
			||||||
 * Then the tick count is not updated
 | 
					 * Then the tick count is not updated
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void test_update_tick(void)
 | 
					void test_update_tick(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SysTimerTest st;
 | 
					    mock_ticker_reset();
 | 
				
			||||||
    TEST_ASSERT_EQUAL_UINT32(0, st.update_tick());
 | 
					    SysTimerTest st(&mock_ticker_data);
 | 
				
			||||||
 | 
					    st.suspend(TEST_TICKS * 2);
 | 
				
			||||||
 | 
					    TEST_ASSERT_EQUAL_UINT32(0, st.resume());
 | 
				
			||||||
    TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
 | 
					    TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
 | 
				
			||||||
    us_timestamp_t test_ticks_elapsed_ts = st.get_time() + DELAY_US;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (st.get_time() <= test_ticks_elapsed_ts) {}
 | 
					    st.suspend(TEST_TICKS * 2);
 | 
				
			||||||
    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.update_tick());
 | 
					    mock_ticker_timestamp = DELAY_US;
 | 
				
			||||||
 | 
					    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.resume());
 | 
				
			||||||
    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
 | 
					    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TEST_ASSERT_EQUAL_UINT32(0, st.update_tick());
 | 
					    st.suspend(TEST_TICKS * 2);
 | 
				
			||||||
 | 
					    TEST_ASSERT_EQUAL_UINT32(0, st.resume());
 | 
				
			||||||
    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
 | 
					    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,12 +180,13 @@ void test_update_tick(void)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void test_get_time(void)
 | 
					void test_get_time(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SysTimerTest st;
 | 
					    mock_ticker_reset();
 | 
				
			||||||
 | 
					    SysTimerTest st(&mock_ticker_data);
 | 
				
			||||||
    us_timestamp_t t1 = st.get_time();
 | 
					    us_timestamp_t t1 = st.get_time();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    wait_us(DELAY_US);
 | 
					    mock_ticker_timestamp = DELAY_US;
 | 
				
			||||||
    us_timestamp_t t2 = st.get_time();
 | 
					    us_timestamp_t t2 = st.get_time();
 | 
				
			||||||
    TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1);
 | 
					    TEST_ASSERT_EQUAL_UINT64(DELAY_US, t2 - t1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Test cancel_tick
 | 
					/** Test cancel_tick
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@
 | 
				
			||||||
#if DEVICE_LOWPOWERTIMER
 | 
					#if DEVICE_LOWPOWERTIMER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "hal/lp_ticker_api.h"
 | 
					#include "hal/lp_ticker_api.h"
 | 
				
			||||||
 | 
					#include "mbed_critical.h"
 | 
				
			||||||
#include "rtx_core_cm.h"
 | 
					#include "rtx_core_cm.h"
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#include "rtx_lib.h"
 | 
					#include "rtx_lib.h"
 | 
				
			||||||
| 
						 | 
					@ -43,6 +44,14 @@ namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SysTimer::SysTimer() :
 | 
					SysTimer::SysTimer() :
 | 
				
			||||||
        TimerEvent(get_lp_ticker_data()), _start_time(0), _tick(0)
 | 
					        TimerEvent(get_lp_ticker_data()), _start_time(0), _tick(0)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _start_time = ticker_read_us(_ticker_data);
 | 
				
			||||||
 | 
					    _suspend_time_passed = true;
 | 
				
			||||||
 | 
					    _suspended = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SysTimer::SysTimer(const ticker_data_t *data) :
 | 
				
			||||||
 | 
					        TimerEvent(data), _start_time(0), _tick(0)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    _start_time = ticker_read_us(_ticker_data);
 | 
					    _start_time = ticker_read_us(_ticker_data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -61,23 +70,30 @@ void SysTimer::setup_irq()
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SysTimer::schedule_tick(uint32_t delta)
 | 
					void SysTimer::suspend(uint32_t ticks)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    insert_absolute(_start_time + (_tick + delta) * 1000000ULL / OS_TICK_FREQ);
 | 
					    core_util_critical_section_enter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    schedule_tick(ticks);
 | 
				
			||||||
 | 
					    _suspend_time_passed = false;
 | 
				
			||||||
 | 
					    _suspended = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    core_util_critical_section_exit();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SysTimer::cancel_tick()
 | 
					bool SysTimer::suspend_time_passed()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    return _suspend_time_passed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t SysTimer::resume()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    core_util_critical_section_enter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _suspended = false;
 | 
				
			||||||
 | 
					    _suspend_time_passed = true;
 | 
				
			||||||
    remove();
 | 
					    remove();
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t SysTimer::get_tick()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return _tick & 0xFFFFFFFF;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint32_t SysTimer::update_tick()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    uint64_t new_tick = (ticker_read_us(_ticker_data) - _start_time) * OS_TICK_FREQ / 1000000;
 | 
					    uint64_t new_tick = (ticker_read_us(_ticker_data) - _start_time) * OS_TICK_FREQ / 1000000;
 | 
				
			||||||
    if (new_tick > _tick) {
 | 
					    if (new_tick > _tick) {
 | 
				
			||||||
        // Don't update to the current tick. Instead, update to the
 | 
					        // Don't update to the current tick. Instead, update to the
 | 
				
			||||||
| 
						 | 
					@ -88,9 +104,34 @@ uint32_t SysTimer::update_tick()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    uint32_t elapsed_ticks = new_tick - _tick;
 | 
					    uint32_t elapsed_ticks = new_tick - _tick;
 | 
				
			||||||
    _tick = new_tick;
 | 
					    _tick = new_tick;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    core_util_critical_section_exit();
 | 
				
			||||||
    return elapsed_ticks;
 | 
					    return elapsed_ticks;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void SysTimer::schedule_tick(uint32_t delta)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    core_util_critical_section_enter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    insert_absolute(_start_time + (_tick + delta) * 1000000ULL / OS_TICK_FREQ);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    core_util_critical_section_exit();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void SysTimer::cancel_tick()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    core_util_critical_section_enter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    remove();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    core_util_critical_section_exit();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t SysTimer::get_tick()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return _tick & 0xFFFFFFFF;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
us_timestamp_t SysTimer::get_time()
 | 
					us_timestamp_t SysTimer::get_time()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return ticker_read_us(_ticker_data);
 | 
					    return ticker_read_us(_ticker_data);
 | 
				
			||||||
| 
						 | 
					@ -100,8 +141,10 @@ SysTimer::~SysTimer()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SysTimer::set_irq_pending()
 | 
					void SysTimer::_set_irq_pending()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    // Protected function synchronized externally
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if (defined(NO_SYSTICK))
 | 
					#if (defined(NO_SYSTICK))
 | 
				
			||||||
    NVIC_SetPendingIRQ(mbed_get_m0_tick_irqn());
 | 
					    NVIC_SetPendingIRQ(mbed_get_m0_tick_irqn());
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
| 
						 | 
					@ -109,15 +152,25 @@ void SysTimer::set_irq_pending()
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SysTimer::increment_tick()
 | 
					void SysTimer::_increment_tick()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    // Protected function synchronized externally
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _tick++;
 | 
					    _tick++;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SysTimer::handler()
 | 
					void SysTimer::handler()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    set_irq_pending();
 | 
					    core_util_critical_section_enter();
 | 
				
			||||||
    increment_tick();
 | 
					
 | 
				
			||||||
 | 
					    if (_suspended) {
 | 
				
			||||||
 | 
					        _suspend_time_passed = true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        _set_irq_pending();
 | 
				
			||||||
 | 
					        _increment_tick();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    core_util_critical_section_exit();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,7 @@ class SysTimer: private mbed::TimerEvent, private mbed::NonCopyable<SysTimer> {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SysTimer();
 | 
					    SysTimer();
 | 
				
			||||||
 | 
					    SysTimer(const ticker_data_t *data);
 | 
				
			||||||
    virtual ~SysTimer();
 | 
					    virtual ~SysTimer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -56,6 +57,34 @@ public:
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static void setup_irq();
 | 
					    static void setup_irq();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Set wakeup time and schedule a wakeup event after delta ticks
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * After suspend has been called the function suspend_time_passed
 | 
				
			||||||
 | 
					     * can be used to determine if the suspend time has passed.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param delta Ticks to remain suspended
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void suspend(uint32_t delta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Check if the suspend time has passed
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return true if the specified number of ticks has passed otherwise false
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    bool suspend_time_passed();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Exit suspend mode and return elapsed ticks
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Due to a scheduling issue, the number of ticks returned is decremented
 | 
				
			||||||
 | 
					     * by 1 so that a handler can be called and update to the current value.
 | 
				
			||||||
 | 
					     * This allows scheduling restart successfully after the OS is resumed.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return the number of elapsed ticks minus 1
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    uint32_t resume();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Schedule an os tick to fire
 | 
					     * Schedule an os tick to fire
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					@ -77,17 +106,6 @@ public:
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    uint32_t get_tick();
 | 
					    uint32_t get_tick();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Update the internal tick count
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return The number of ticks incremented
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @note Due to a scheduling issue, the number of ticks returned is decremented
 | 
					 | 
				
			||||||
     * by 1 so that a handler can be called and update to the current value.
 | 
					 | 
				
			||||||
     * This allows scheduling restart successfully after the OS is resumed.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    uint32_t update_tick();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get the time
 | 
					     * Get the time
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					@ -97,10 +115,12 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
    virtual void handler();
 | 
					    virtual void handler();
 | 
				
			||||||
    void increment_tick();
 | 
					    void _increment_tick();
 | 
				
			||||||
    static void set_irq_pending();
 | 
					    static void _set_irq_pending();
 | 
				
			||||||
    us_timestamp_t _start_time;
 | 
					    us_timestamp_t _start_time;
 | 
				
			||||||
    uint64_t _tick;
 | 
					    uint64_t _tick;
 | 
				
			||||||
 | 
					    bool _suspend_time_passed;
 | 
				
			||||||
 | 
					    bool _suspended;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,21 +95,24 @@ uint32_t OS_Tick_GetInterval (void) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void default_idle_hook(void)
 | 
					static void default_idle_hook(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t elapsed_ticks = 0;
 | 
					    uint32_t ticks_to_sleep = osKernelSuspend();
 | 
				
			||||||
 | 
					    os_timer->suspend(ticks_to_sleep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    core_util_critical_section_enter();
 | 
					    bool event_pending = false;
 | 
				
			||||||
    uint32_t ticks_to_sleep = svcRtxKernelSuspend();
 | 
					    while (!os_timer->suspend_time_passed() && !event_pending) {
 | 
				
			||||||
    if (ticks_to_sleep) {
 | 
					 | 
				
			||||||
        os_timer->schedule_tick(ticks_to_sleep);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sleep();
 | 
					        core_util_critical_section_enter();
 | 
				
			||||||
 | 
					        if (osRtxInfo.kernel.pendSV) {
 | 
				
			||||||
 | 
					            event_pending = true;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            sleep();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        core_util_critical_section_exit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        os_timer->cancel_tick();
 | 
					        // Ensure interrupts get a chance to fire
 | 
				
			||||||
        // calculate how long we slept
 | 
					        __ISB();
 | 
				
			||||||
        elapsed_ticks = os_timer->update_tick();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    svcRtxKernelResume(elapsed_ticks);
 | 
					    osKernelResume(os_timer->resume());
 | 
				
			||||||
    core_util_critical_section_exit();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#elif defined(FEATURE_UVISOR)
 | 
					#elif defined(FEATURE_UVISOR)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue