Конфигурацията на линкера:
SECTIONS
{
.events :
{
__events_start = .
KEEP(*(SORT(.events*)))
__events_end = .
}
.event_handlers :
{
__event_handlers_start = .
KEEP(*(SORT(.event_handlers*)))
__event_handlers_end = .
}
}
# Keep INSERT AFTER to append this linker script to the default one.
# See https://www.sourceware.org/binutils/docs/ld/Miscellaneous-Commands.
INSERT AFTER .text
Хедър файла на евънта:
\
typedef _type _value_t
\
extern _value_t _value
extern _value_t _default
\
extern event_t _event
\
static inline void _set(_type value) \
{ \
_type old = _value
_value = value
event_notify(&_event, &old, &value)
} \
\
static inline _type _get(void) \
{ \
return _value
}
__EVENT_DECLARE( \
_type, \
CONCAT_N(__, _name, _event), \
CONCAT_N(__, _name, _value_t), \
CONCAT_N(__, _name, _value), \
CONCAT_N(__, _name, _default), \
CONCAT_N(_name, _set), \
CONCAT_N(_name, _get))
\
_value_t _value = _default_value
_value_t _default = _default_value
\
event_t _event __attribute__((section(EVENTS_SECTION))) = { \
.name =
.value = &_value, \
.default_value = &_default, \
.size = sizeof(_value), \
.is_persistent = _persistent \
};
__EVENT_IMPLEMENT( \
_name, \
_type, \
_default_value, \
_persistent, \
CONCAT_N(__, _name, _event), \
CONCAT_N(__, _name, _value_t), \
CONCAT_N(__, _name, _value), \
CONCAT_N(__, _name, _default))
static void _wrapper(const void* const old_value, const void* const new_value) \
{ \
_handler((const _value_t* const)old_value, (const _value_t* const)new_value)
} \
\
event_handler_t _list __attribute__((__used__, section(EVENTS_HANDLER_SECTION))) = { \
.event = &_event, \
.handler = _wrapper \
}
__EVENT_SUBSCRIBE( \
CONCAT_N(__, _name, _event), \
_handler, \
CONCAT_N(__, _name, _wrapper_, __LINE__), \
CONCAT_N(__, _name, _list_, __LINE__), \
CONCAT_N(__, _name, _value_t))
Имплементация за всички евънти:
void event_notify(const event_t* const event, const void* const old_value, const void* const new_value)
{
if (!notifications_enabled)
return;
if (event->is_persistent)
{
void (*persistent_handler_copy)(const event_t* const event, const void* const value) = persistent_handler;
if (persistent_handler_copy != NULL)
persistent_handler_copy(event, new_value);
}
BP_LOG_DEBUG("Looking for handlers for %s", event->name);
for (const event_handler_t* event_handler = __event_handlers_start; event_handler < __event_handlers_end; event_handler++)
{
BP_LOG_DEBUG("Calling handler %s", event->name);
if (event_handler->event == event)
event_handler->handler(old_value, new_value);
}
}
И употреба:
Дефинираш си евънт някъде в хедър файл.
EVENT_DECLARE(system_tick_second, uint32_t);
В Ц файл правиш имплементация.
EVENT_IMPLEMENT(system_tick_second, uint32_t, 0);
Закачване на хендлър:
void pid_second_tick_callback(const uint32_t* const old, const uint32_t* const new)
{
...
}
EVENT_SUBSCRIBE(system_tick_second, pid_second_tick_callback);
Нотификация при нов евънт:
system_tick_second_set(sys_ticks++);