312 lines
8.5 KiB
C
Raw Permalink Normal View History

2025-09-28 09:58:38 +08:00
/* ----------------------------------------------------------------------------
* Copyright (c) 2020-2030 OnMicro Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of OnMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* -------------------------------------------------------------------------- */
/**
* @file evt.c
* @brief event
* @date 01. April 2020
* @author OnMicro SW Team
*
* @version
* Version 1.0
* - Initial release
*
* @{
*/
/*******************************************************************************
* INCLUDES
*/
#include "om_utils.h"
#include "evt.h"
#include "trc_io.h"
/*******************************************************************************
* MACROS
*/
/*******************************************************************************
* TYPEDEFS
*/
/// environment structure
typedef struct
{
/// Event field
volatile uint32_t field;
/// Callback table
evt_callback_t callback[EVT_TYPE_NUM];
#ifdef CONFIG_EVT_RTOS_SUPPORT
/// callback for evt_set
evt_callback_t schedule_trigger_callback;
#endif
}evt_env_t;
/*******************************************************************************
* GLOBAL VARIABLES
*/
/// environment
static evt_env_t evt_env;
/*******************************************************************************
* LOCAL FUNCTION DEFINITIONS
*/
/**
****************************************************************************************
* @brief evt clz
*
* @param[in] val val
*
* @return clz
****************************************************************************************
**/
__RAM_CODES("PM")
static uint32_t evt_ctz(uint32_t x)
{
#ifdef __RBIT // armv7+
return __CLZ(__RBIT(x));
#else
int c = __CLZ(x & -x); //lint !e501 use x&-x to get the lowest bit 1, and clear other bits
return x ? 31 - c : c;
#endif
}
/*******************************************************************************
* EXPORTED FUNCTION DEFINITIONS
*/
/**
****************************************************************************************
* @brief evt init
****************************************************************************************
**/
void evt_init(void)
{
memset(&evt_env, 0, sizeof(evt_env));
}
/**
****************************************************************************************
* @brief evt callback set
*
* @param[in] evt_type event type
* @param[in] callback callback
*
* @return
****************************************************************************************
**/
void evt_callback_set(evt_type_t evt_type, evt_callback_t callback)
{
OM_ASSERT(evt_type < EVT_TYPE_NUM);
evt_env.callback[evt_type] = callback;
}
/**
****************************************************************************************
* @brief evt callback get
*
* @param[in] evt_type event type
****************************************************************************************
**/
evt_callback_t evt_callback_get(evt_type_t evt_type)
{
return (evt_env.callback[evt_type]);
}
#ifdef CONFIG_EVT_RTOS_SUPPORT
/**
****************************************************************************************
* @brief evt schedule trigger callback set
*
* @param[in] callback callback
****************************************************************************************
**/
void evt_schedule_trigger_callback_set(evt_callback_t callback)
{
/// callback for evt_set
evt_env.schedule_trigger_callback = callback;
}
#endif
/**
****************************************************************************************
* @brief evt set
*
* @param[in] evt_type event type
****************************************************************************************
**/
__RAM_CODES("PM")
void evt_set(evt_type_t evt_type)
{
OM_ASSERT(evt_type < EVT_TYPE_NUM);
OM_CRITICAL_BEGIN();
evt_env.field |= (1 << evt_type);
OM_CRITICAL_END();
#ifdef CONFIG_EVT_RTOS_SUPPORT
if (evt_env.schedule_trigger_callback)
evt_env.schedule_trigger_callback();
#endif
}
/**
****************************************************************************************
* @brief evt clear
*
* @param[in] evt_type event type
****************************************************************************************
**/
__RAM_CODES("PM")
void evt_clear(evt_type_t evt_type)
{
OM_ASSERT(evt_type < EVT_TYPE_NUM);
OM_CRITICAL_BEGIN();
evt_env.field &= ~(1u << evt_type);
OM_CRITICAL_END();
}
/**
****************************************************************************************
* @brief evt get
*
* @param[in] evt_type event type
*
* @return is on ?
****************************************************************************************
**/
uint8_t evt_get(evt_type_t evt_type)
{
uint8_t state;
OM_ASSERT(evt_type < EVT_TYPE_NUM);
OM_CRITICAL_BEGIN();
state = (evt_env.field >> evt_type) & 1;
OM_CRITICAL_END();
return state;
}
/**
****************************************************************************************
* @brief evt get all
*
* @return
****************************************************************************************
**/
__RAM_CODES("PM")
uint32_t evt_get_all(void)
{
return evt_env.field;
}
/**
****************************************************************************************
* @brief evt flush
****************************************************************************************
**/
void evt_flush(void)
{
evt_env.field = 0;
}
/**
****************************************************************************************
* @brief evt schedule
****************************************************************************************
**/
__RAM_CODES("PM")
void evt_schedule(void)
{
// Get the volatile value
uint32_t field = evt_env.field;
while (field) { // Compiler is assumed to optimize with loop inversion
// Find highest priority event set
uint32_t hdl = evt_ctz(field);
if(evt_env.callback[hdl] != NULL) {
// Execute corresponding handler
TRC_IO(TRC_IO_EVT_EXEC_CB, 1);
(evt_env.callback[hdl])();
TRC_IO(TRC_IO_EVT_EXEC_CB, 0);
} else {
OM_ASSERT(0);
}
// Update the volatile value
field = evt_env.field;
}
}
/**
****************************************************************************************
* @brief evt schedule once
*
* @return not schedule event
****************************************************************************************
**/
uint32_t evt_schedule_once(void)
{
// Get the volatile value
uint32_t field = evt_env.field;
if (field) { // Compiler is assumed to optimize with loop inversion
// Find highest priority event set
uint8_t hdl = evt_ctz(field);
if(evt_env.callback[hdl] != NULL) {
// Execute corresponding handler
TRC_IO(TRC_IO_EVT_EXEC_CB, 1);
(evt_env.callback[hdl])();
TRC_IO(TRC_IO_EVT_EXEC_CB, 0);
} else {
OM_ASSERT(0);
}
// Update the volatile value
field = evt_env.field;
}
return field;
}
/** @} */