Advanced Distributed Systems module at HSLU
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

105 lines
3.2 KiB

/**
* \file
* \brief Event driver implementation.
* \author Erich Styger, erich.styger@hslu.ch
* \license SPDX-License-Identifier: BSD-3-Clause
* This module implements a generic event driver. We are using numbered events starting with zero.
* EVNT_HandleEvent() can be used to process the pending events. Note that the event with the number zero
* has the highest priority and will be handled first.
*/
#include "platform.h"
#if PL_CONFIG_USE_EVENTS
#include "Event.h" /* our own interface */
#include "McuCriticalSection.h"
typedef uint32_t EVNT_MemUnit; /*!< memory unit used to store events flags */
#define EVNT_MEM_UNIT_NOF_BITS (sizeof(EVNT_MemUnit)*8u)
/*!< number of bits in memory unit */
static EVNT_MemUnit EVNT_Events[((EVNT_NOF_EVENTS-1)/EVNT_MEM_UNIT_NOF_BITS)+1]; /*!< Bit set of events */
#define SET_EVENT(event) \
EVNT_Events[(event)/EVNT_MEM_UNIT_NOF_BITS] |= (1u<<(EVNT_MEM_UNIT_NOF_BITS-1))>>(((event)%EVNT_MEM_UNIT_NOF_BITS)) /*!< Set the event */
#define CLR_EVENT(event) \
EVNT_Events[(event)/EVNT_MEM_UNIT_NOF_BITS] &= ~((1u<<(EVNT_MEM_UNIT_NOF_BITS-1))>>(((event)%EVNT_MEM_UNIT_NOF_BITS))) /*!< Clear the event */
#define GET_EVENT(event) \
(EVNT_Events[(event)/EVNT_MEM_UNIT_NOF_BITS]&((1u<<(EVNT_MEM_UNIT_NOF_BITS-1))>>(((event)%EVNT_MEM_UNIT_NOF_BITS)))) /*!< Return TRUE if event is set */
void EVNT_SetEvent(EVNT_Handle event) {
McuCriticalSection_CriticalVariable()
McuCriticalSection_EnterCritical();
SET_EVENT(event);
McuCriticalSection_ExitCritical();
}
void EVNT_ClearEvent(EVNT_Handle event) {
McuCriticalSection_CriticalVariable()
McuCriticalSection_EnterCritical();
CLR_EVENT(event);
McuCriticalSection_ExitCritical();
}
bool EVNT_EventIsSet(EVNT_Handle event) {
bool res;
McuCriticalSection_CriticalVariable()
McuCriticalSection_EnterCritical();
res = (GET_EVENT(event)!=0);
McuCriticalSection_ExitCritical();
return res;
}
bool EVNT_EventIsSetAutoClear(EVNT_Handle event) {
bool res;
McuCriticalSection_CriticalVariable()
McuCriticalSection_EnterCritical();
res = GET_EVENT(event);
if (res) {
CLR_EVENT(event); /* automatically clear event */
}
McuCriticalSection_ExitCritical();
return res;
}
void EVNT_HandleEvent(void (*callback)(EVNT_Handle), bool clearEvent) {
/* Handle the one with the highest priority. Zero is the event with the highest priority. */
EVNT_Handle event;
McuCriticalSection_CriticalVariable()
McuCriticalSection_EnterCritical();
for (event=(EVNT_Handle)0; event<EVNT_NOF_EVENTS; event++) { /* does a test on every event */
if (GET_EVENT(event)) { /* event present? */
if (clearEvent) {
CLR_EVENT(event); /* clear event */
}
break; /* get out of loop */
}
}
McuCriticalSection_ExitCritical();
if (event != EVNT_NOF_EVENTS) {
callback(event);
/* Note: if the callback sets the event, we will get out of the loop.
* We will catch it by the next iteration.
*/
}
}
void EVNT_Init(void) {
uint8_t i;
i = 0;
do {
EVNT_Events[i] = 0; /* initialize data structure */
i++;
} while(i<sizeof(EVNT_Events)/sizeof(EVNT_Events[0]));
}
void EVNT_Deinit(void) {
/* nothing needed */
}
#endif /* PL_HAS_EVENTS */