Improvements to message and callback timer frameworks.

Reduced disable/enable time dur function calls.
Added the option to use either atomic semaphores or interrupt enables to control access.
This commit is contained in:
John Wellbelove 2018-02-05 21:16:43 +00:00
parent 4b1eeee511
commit 879fb1f626
9 changed files with 645 additions and 616 deletions

View File

@ -1,5 +1,5 @@
name=Embedded Template Library
version=10.17.0
version=10.18.0
author= John Wellbelove <john.wellbelove@etlcpp.com>
maintainer=John Wellbelove <john.wellbelove@etlcpp.com>
sentence=A C++ template library tailored for embedded systems.

View File

@ -261,7 +261,6 @@ struct ecl_time_config
struct ecl_timer_config* ptimers;
uint_least8_t max_timers;
volatile ecl_timer_enable_t enabled;
ECL_TIMER_TIMER_SEMAPHORE process_semaphore;
volatile uint_least8_t registered_timers;
};
@ -274,7 +273,6 @@ void ecl_timer_init(struct ecl_timer_config* ptimers_, uint_least8_t max_timers_
ecl.ptimers = ptimers_;
ecl.max_timers = max_timers_;
ecl.enabled = 0;
ecl.process_semaphore = 0;
ecl.registered_timers = 0;
int i;
@ -298,7 +296,7 @@ ecl_timer_id_t ecl_timer_register(void (*pcallback_)(),
ecl_timer_id_t id = ECL_TIMER_NO_TIMER;
ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore);
ECL_TIMER_DISABLE_PROCESSING;
int is_space = (ecl.registered_timers < ecl.max_timers);
@ -321,7 +319,7 @@ ecl_timer_id_t ecl_timer_register(void (*pcallback_)(),
}
}
ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore);
ECL_TIMER_ENABLE_PROCESSING;
return id;
}
@ -337,7 +335,7 @@ ecl_timer_result_t ecl_timer_unregister(ecl_timer_id_t id_)
if (id_ != ECL_TIMER_NO_TIMER)
{
ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore);
ECL_TIMER_DISABLE_PROCESSING;
struct ecl_timer_config* ptimer = &ecl.ptimers[id_];
@ -355,7 +353,7 @@ ecl_timer_result_t ecl_timer_unregister(ecl_timer_id_t id_)
}
}
ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore);
ECL_TIMER_ENABLE_PROCESSING;
}
return result;
@ -385,7 +383,7 @@ ecl_timer_result_t ecl_timer_is_running()
//*******************************************
void ecl_timer_clear()
{
ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore);
ECL_TIMER_DISABLE_PROCESSING;
ecl_timer_list_clear();
@ -397,7 +395,7 @@ void ecl_timer_clear()
ecl.registered_timers = 0;
ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore);
ECL_TIMER_ENABLE_PROCESSING;
}
//*******************************************
@ -411,7 +409,7 @@ ecl_timer_result_t ecl_timer_tick(uint32_t count)
if (ecl.enabled)
{
if (ECL_TIMER_PROCESSING_ENABLED(ecl.process_semaphore))
if (ECL_TIMER_PROCESSING_ENABLED)
{
// We have something to do?
int has_active = !ecl_timer_list_empty();
@ -463,8 +461,6 @@ ecl_timer_result_t ecl_timer_start(ecl_timer_id_t id_, ecl_timer_start_t immedia
{
assert(ecl.ptimers != 0);
ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore);
ecl_timer_result_t result = ECL_TIMER_FAIL;
// Valid timer id?
@ -478,6 +474,7 @@ ecl_timer_result_t ecl_timer_start(ecl_timer_id_t id_, ecl_timer_start_t immedia
// Has a valid period.
if (ptimer->period != ECL_TIMER_INACTIVE)
{
ECL_TIMER_DISABLE_PROCESSING;
if (ecl_timer_is_active(ptimer))
{
ecl_timer_list_remove(ptimer->id, 0);
@ -485,14 +482,13 @@ ecl_timer_result_t ecl_timer_start(ecl_timer_id_t id_, ecl_timer_start_t immedia
ptimer->delta = immediate_ ? 0 : ptimer->period;
ecl_timer_list_insert(ptimer->id);
ECL_TIMER_ENABLE_PROCESSING;
result = ECL_TIMER_PASS;
}
}
}
ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore);
return result;
}
@ -503,8 +499,6 @@ ecl_timer_result_t ecl_timer_stop(ecl_timer_id_t id_)
{
assert(ecl.ptimers != 0);
ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore);
ecl_timer_result_t result = ECL_TIMER_FAIL;
// Valid timer id?
@ -517,14 +511,14 @@ ecl_timer_result_t ecl_timer_stop(ecl_timer_id_t id_)
{
if (ecl_timer_is_active(ptimer))
{
ECL_TIMER_DISABLE_PROCESSING;
ecl_timer_list_remove(ptimer->id, 0);
ECL_TIMER_ENABLE_PROCESSING;
result = ECL_TIMER_PASS;
}
}
}
ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore);
return result;
}

View File

@ -42,6 +42,30 @@ SOFTWARE.
#undef ETL_FILE
#define ETL_FILE "42"
#if !defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK) && !defined(ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK)
#error ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK or ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK not defined
#endif
#if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK) && defined(ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK)
#error Only define one of ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK or ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK
#endif
#if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK)
#define ETL_DISABLE_TIMER_UPDATES (++process_semaphore)
#define ETL_ENABLE_TIMER_UPDATES (--process_semaphore)
#define ETL_TIMER_UPDATES_ENABLED (process_semaphore.load() == 0)
#endif
#if defined(ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK)
#if !defined(ETL_CALLBACK_TIMER_DISABLE_INTERRUPTS) || !defined(ETL_CALLBACK_TIMER_ENABLE_INTERRUPTS)
#error ETL_CALLBACK_TIMER_DISABLE_INTERRUPTS and/or ETL_CALLBACK_TIMER_ENABLE_INTERRUPTS not defined
#endif
#define ETL_DISABLE_TIMER_UPDATES (ETL_CALLBACK_TIMER_DISABLE_INTERRUPTS)
#define ETL_ENABLE_TIMER_UPDATES (ETL_CALLBACK_TIMER_ENABLE_INTERRUPTS)
#define ETL_TIMER_UPDATES_ENABLED true
#endif
namespace etl
{
//*************************************************************************
@ -326,7 +350,7 @@ namespace etl
{
etl::timer::id::type id = etl::timer::id::NO_TIMER;
disable_timer_updates();
ETL_DISABLE_TIMER_UPDATES;
bool is_space = (registered_timers < MAX_TIMERS);
@ -348,7 +372,7 @@ namespace etl
}
}
enable_timer_updates();
ETL_ENABLE_TIMER_UPDATES;
return id;
}
@ -362,7 +386,7 @@ namespace etl
{
etl::timer::id::type id = etl::timer::id::NO_TIMER;
disable_timer_updates();
ETL_DISABLE_TIMER_UPDATES;
bool is_space = (registered_timers < MAX_TIMERS);
@ -384,7 +408,7 @@ namespace etl
}
}
enable_timer_updates();
ETL_ENABLE_TIMER_UPDATES;
return id;
}
@ -398,7 +422,7 @@ namespace etl
if (id_ != etl::timer::id::NO_TIMER)
{
disable_timer_updates();
ETL_DISABLE_TIMER_UPDATES;
etl::callback_timer_data& timer = timer_array[id_];
@ -416,7 +440,7 @@ namespace etl
}
}
enable_timer_updates();
ETL_ENABLE_TIMER_UPDATES;
}
return result;
@ -443,7 +467,7 @@ namespace etl
//*******************************************
void clear()
{
disable_timer_updates();
ETL_DISABLE_TIMER_UPDATES;
active_list.clear();
@ -454,7 +478,7 @@ namespace etl
registered_timers = 0;
enable_timer_updates();
ETL_ENABLE_TIMER_UPDATES;
}
//*******************************************
@ -467,7 +491,7 @@ namespace etl
{
if (enabled)
{
if (process_semaphore.load() == 0)
if (ETL_TIMER_UPDATES_ENABLED)
{
// We have something to do?
bool has_active = !active_list.empty();
@ -525,8 +549,6 @@ namespace etl
//*******************************************
bool start(etl::timer::id::type id_, bool immediate_ = false)
{
disable_timer_updates();
bool result = false;
// Valid timer id?
@ -540,6 +562,7 @@ namespace etl
// Has a valid period.
if (timer.period != etl::timer::state::INACTIVE)
{
ETL_DISABLE_TIMER_UPDATES;
if (timer.is_active())
{
active_list.remove(timer.id, false);
@ -547,14 +570,13 @@ namespace etl
timer.delta = immediate_ ? 0 : timer.period;
active_list.insert(timer.id);
ETL_ENABLE_TIMER_UPDATES;
result = true;
}
}
}
enable_timer_updates();
return result;
}
@ -563,8 +585,6 @@ namespace etl
//*******************************************
bool stop(etl::timer::id::type id_)
{
disable_timer_updates();
bool result = false;
// Valid timer id?
@ -577,14 +597,14 @@ namespace etl
{
if (timer.is_active())
{
ETL_DISABLE_TIMER_UPDATES;
active_list.remove(timer.id, false);
ETL_ENABLE_TIMER_UPDATES;
result = true;
}
}
}
enable_timer_updates();
return result;
}
@ -625,7 +645,9 @@ namespace etl
: timer_array(timer_array_),
active_list(timer_array_),
enabled(false),
#if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK)
process_semaphore(0),
#endif
registered_timers(0),
MAX_TIMERS(MAX_TIMERS_)
{
@ -633,22 +655,6 @@ namespace etl
private:
//*******************************************
/// Enable timer callback events.
//*******************************************
void enable_timer_updates()
{
--process_semaphore;
}
//*******************************************
/// Disable timer callback events.
//*******************************************
void disable_timer_updates()
{
++process_semaphore;
}
// The array of timer data structures.
callback_timer_data* const timer_array;
@ -656,7 +662,9 @@ namespace etl
__private_callback_timer__::list active_list;
volatile bool enabled;
#if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK)
volatile etl::timer_semaphore_t process_semaphore;
#endif
volatile uint_least8_t registered_timers;
public:
@ -688,6 +696,10 @@ namespace etl
};
}
#undef ETL_DISABLE_TIMER_UPDATES
#undef ETL_ENABLE_TIMER_UPDATES
#undef ETL_TIMER_UPDATES_ENABLED
#undef ETL_FILE
#endif

View File

@ -45,6 +45,30 @@ SOFTWARE.
#undef ETL_FILE
#define ETL_FILE "41"
#if !defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) && !defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
#error ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK or ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK not defined
#endif
#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) && defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
#error Only define one of ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK or ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK
#endif
#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
#define ETL_DISABLE_TIMER_UPDATES (++process_semaphore)
#define ETL_ENABLE_TIMER_UPDATES (--process_semaphore)
#define ETL_TIMER_UPDATES_ENABLED (process_semaphore.load() == 0)
#endif
#if defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
#if !defined(ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS) || !defined(ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS)
#error ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS and/or ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS not defined
#endif
#define ETL_DISABLE_TIMER_UPDATES (ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS)
#define ETL_ENABLE_TIMER_UPDATES (ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS)
#define ETL_TIMER_UPDATES_ENABLED true
#endif
namespace etl
{
//*************************************************************************
@ -323,7 +347,7 @@ namespace etl
{
etl::timer::id::type id = etl::timer::id::NO_TIMER;
disable_timer_updates();
ETL_DISABLE_TIMER_UPDATES;
bool is_space = (registered_timers < MAX_TIMERS);
@ -349,7 +373,7 @@ namespace etl
}
}
enable_timer_updates();
ETL_ENABLE_TIMER_UPDATES;
return id;
}
@ -363,7 +387,7 @@ namespace etl
if (id_ != etl::timer::id::NO_TIMER)
{
disable_timer_updates();
ETL_DISABLE_TIMER_UPDATES;
etl::message_timer_data& timer = timer_array[id_];
@ -381,7 +405,7 @@ namespace etl
}
}
enable_timer_updates();
ETL_ENABLE_TIMER_UPDATES;
}
return result;
@ -408,7 +432,7 @@ namespace etl
//*******************************************
void clear()
{
disable_timer_updates();
ETL_DISABLE_TIMER_UPDATES;
active_list.clear();
@ -419,7 +443,7 @@ namespace etl
registered_timers = 0;
enable_timer_updates();
ETL_ENABLE_TIMER_UPDATES;
}
//*******************************************
@ -432,7 +456,7 @@ namespace etl
{
if (enabled)
{
if (process_semaphore.load() == 0)
if ETL_IF_CONSTEXPR(ETL_TIMER_UPDATES_ENABLED)
{
// We have something to do?
bool has_active = !active_list.empty();
@ -492,8 +516,6 @@ namespace etl
{
bool result = false;
disable_timer_updates();
// Valid timer id?
if (id_ != etl::timer::id::NO_TIMER)
{
@ -505,6 +527,7 @@ namespace etl
// Has a valid period.
if (timer.period != etl::timer::state::INACTIVE)
{
ETL_DISABLE_TIMER_UPDATES;
if (timer.is_active())
{
active_list.remove(timer.id, false);
@ -512,14 +535,13 @@ namespace etl
timer.delta = immediate_ ? 0 : timer.period;
active_list.insert(timer.id);
ETL_ENABLE_TIMER_UPDATES;
result = true;
}
}
}
enable_timer_updates();
return result;
}
@ -530,8 +552,6 @@ namespace etl
{
bool result = false;
disable_timer_updates();
// Valid timer id?
if (id_ != etl::timer::id::NO_TIMER)
{
@ -542,14 +562,14 @@ namespace etl
{
if (timer.is_active())
{
ETL_DISABLE_TIMER_UPDATES;
active_list.remove(timer.id, false);
ETL_ENABLE_TIMER_UPDATES;
result = true;
}
}
}
enable_timer_updates();
return result;
}
@ -590,7 +610,9 @@ namespace etl
: timer_array(timer_array_),
active_list(timer_array_),
enabled(false),
#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
process_semaphore(0),
#endif
registered_timers(0),
MAX_TIMERS(MAX_TIMERS_)
{
@ -605,22 +627,6 @@ namespace etl
private:
//*******************************************
/// Enable timer callback events.
//*******************************************
void enable_timer_updates()
{
--process_semaphore;
}
//*******************************************
/// Disable timer callback events.
//*******************************************
void disable_timer_updates()
{
++process_semaphore;
}
// The array of timer data structures.
message_timer_data* const timer_array;
@ -628,7 +634,10 @@ namespace etl
__private_message_timer__::list active_list;
volatile bool enabled;
#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
volatile etl::timer_semaphore_t process_semaphore;
#endif
volatile uint_least8_t registered_timers;
public:
@ -660,6 +669,10 @@ namespace etl
};
}
#undef ETL_DISABLE_TIMER_UPDATES
#undef ETL_ENABLE_TIMER_UPDATES
#undef ETL_TIMER_UPDATES_ENABLED
#undef ETL_FILE
#endif

View File

@ -1,3 +1,9 @@
===============================================================================
10.18.0
Improvements to message and callback timer frameworks.
Reduced disable/enable time dur function calls.
Added the option to use either atomic semaphores or interrupt enables to control access.
===============================================================================
10.17.0
Added emplace functions to etl::variant.

File diff suppressed because it is too large Load Diff

View File

@ -31,18 +31,18 @@ SOFTWARE.
#include <stdint.h>
extern uint32_t timer_semaphore;
#if defined(_MSC_VER)
#include <Windows.h>
#define ECL_TIMER_TIMER_SEMAPHORE uint32_t
#define ECL_TIMER_DISABLE_PROCESSING(x) InterlockedIncrement((volatile long*)&x)
#define ECL_TIMER_ENABLE_PROCESSING(x) InterlockedDecrement((volatile long*)&x)
#define ECL_TIMER_PROCESSING_ENABLED(x) (InterlockedAdd((volatile long*)&x, 0) == 0)
#define ECL_TIMER_DISABLE_PROCESSING InterlockedIncrement((volatile long*)&timer_semaphore)
#define ECL_TIMER_ENABLE_PROCESSING InterlockedDecrement((volatile long*)&timer_semaphore)
#define ECL_TIMER_PROCESSING_ENABLED (InterlockedAdd((volatile long*)&timer_semaphore, 0) == 0)
#else
#define ECL_TIMER_TIMER_SEMAPHORE uint32_t
#define ECL_TIMER_DISABLE_PROCESSING(x) __sync_fetch_and_add(&x, 1)
#define ECL_TIMER_ENABLE_PROCESSING(x) __sync_fetch_and_sub(&x, 1)
#define ECL_TIMER_PROCESSING_ENABLED(x) (__sync_fetch_and_add(&x, 0) == 0)
#define ECL_TIMER_DISABLE_PROCESSING __sync_fetch_and_add(&timer_semaphore, 1)
#define ECL_TIMER_ENABLE_PROCESSING __sync_fetch_and_sub(&timer_semaphore, 1)
#define ECL_TIMER_PROCESSING_ENABLED (__sync_fetch_and_add(&timer_semaphore, 0) == 0)
#endif
#endif

View File

@ -39,6 +39,9 @@ SOFTWARE.
#define ETL_IDEQUE_REPAIR_ENABLE
#define ETL_IN_UNIT_TEST
#define ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK
#define ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK
#define ETL_POLYMORPHIC_BITSET
#define ETL_POLYMORPHIC_DEQUE
#define ETL_POLYMORPHIC_FLAT_MAP

View File

@ -33,6 +33,8 @@ SOFTWARE.
extern "C"
{
uint32_t timer_semaphore;
#include "ecl_timer.h"
}