ST driver enhancements related to multi core support.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14117 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2021-04-01 12:01:41 +00:00
parent 29b49974c4
commit 0a7b3b9e88
4 changed files with 217 additions and 74 deletions

View File

@ -61,30 +61,40 @@ typedef void (*st_callback_t)(unsigned alarm);
/*===========================================================================*/
#if (ST_LLD_NUM_ALARMS > 1) && !defined(__DOXYGEN__)
extern st_callback_t st_callbacks[ST_LLD_NUM_ALARMS - 1];
extern st_callback_t st_callbacks[ST_LLD_NUM_ALARMS];
#endif
#ifdef __cplusplus
extern "C" {
#endif
void stInit(void);
#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
systime_t stGetCounter(void);
#if defined(ST_LLD_MULTICORE_SUPPORT)
void stBindAlarm(void);
#endif
void stStartAlarm(systime_t abstime);
void stStopAlarm(void);
void stSetAlarm(systime_t abstime);
systime_t stGetAlarm(void);
systime_t stGetCounter(void);
bool stIsAlarmActive(void);
#if ST_LLD_NUM_ALARMS > 1
bool stIsAlarmActiveN(unsigned alarm);
void stStartAlarmN(unsigned alarm, systime_t abstime, st_callback_t cb);
void stSetCallback(unsigned alarm, st_callback_t cb);
#if defined(ST_LLD_MULTICORE_SUPPORT)
void stBindAlarmN(unsigned alarm);
#endif
void stStartAlarmN(unsigned alarm, systime_t abstime);
void stStopAlarmN(unsigned alarm);
void stSetAlarmN(unsigned alarm, systime_t abstime);
systime_t stGetAlarmN(unsigned alarm);
#endif
bool stIsAlarmActiveN(unsigned alarm);
#endif /* ST_LLD_NUM_ALARMS > 1 */
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
#ifdef __cplusplus
}
#endif
#endif /* HAL_ST_H */
/** @} */

View File

@ -46,10 +46,22 @@
/* Driver local types. */
/*===========================================================================*/
typedef struct {
uint32_t n;
uint32_t prio;
} alarm_irq_t;
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
static const alarm_irq_t alarm_irqs[ST_LLD_NUM_ALARMS] = {
{RP_TIMER_IRQ0_NUMBER, RP_IRQ_TIMER_ALARM0_PRIORITY},
{RP_TIMER_IRQ1_NUMBER, RP_IRQ_TIMER_ALARM1_PRIORITY},
{RP_TIMER_IRQ2_NUMBER, RP_IRQ_TIMER_ALARM2_PRIORITY},
{RP_TIMER_IRQ3_NUMBER, RP_IRQ_TIMER_ALARM3_PRIORITY}
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
@ -89,7 +101,17 @@ OSAL_IRQ_HANDLER(RP_TIMER_IRQ0_HANDLER) {
OSAL_IRQ_PROLOGUE();
st_lld_serve_interrupt();
osalDbgAssert((TIMER->INTS & TIMER_INTS_ALARM0) != 0U, "not pending");
TIMER->INTR = TIMER_INTR_ALARM0;
#if defined(ST_LLD_ALARM0_STATIC_CB)
ST_LLD_ALARM0_STATIC_CB();
#else
if (st_callbacks[0] != NULL) {
st_callbacks[0](0U);
}
#endif
OSAL_IRQ_EPILOGUE();
}
@ -105,7 +127,17 @@ OSAL_IRQ_HANDLER(RP_TIMER_IRQ1_HANDLER) {
OSAL_IRQ_PROLOGUE();
st_lld_serve_interrupt();
osalDbgAssert((TIMER->INTS & TIMER_INTS_ALARM1) != 0U, "not pending");
TIMER->INTR = TIMER_INTR_ALARM1;
#if defined(ST_LLD_ALARM1_STATIC_CB)
ST_LLD_ALARM1_STATIC_CB();
#else
if (st_callbacks[1] != NULL) {
st_callbacks[1](1U);
}
#endif
OSAL_IRQ_EPILOGUE();
}
@ -121,7 +153,17 @@ OSAL_IRQ_HANDLER(RP_TIMER_IRQ2_HANDLER) {
OSAL_IRQ_PROLOGUE();
st_lld_serve_interrupt();
osalDbgAssert((TIMER->INTS & TIMER_INTS_ALARM2) != 0U, "not pending");
TIMER->INTR = TIMER_INTR_ALARM2;
#if defined(ST_LLD_ALARM2_STATIC_CB)
ST_LLD_ALARM2_STATIC_CB();
#else
if (st_callbacks[2] != NULL) {
st_callbacks[2](2U);
}
#endif
OSAL_IRQ_EPILOGUE();
}
@ -137,7 +179,17 @@ OSAL_IRQ_HANDLER(RP_TIMER_IRQ3_HANDLER) {
OSAL_IRQ_PROLOGUE();
st_lld_serve_interrupt();
osalDbgAssert((TIMER->INTS & TIMER_INTS_ALARM3) != 0U, "not pending");
TIMER->INTR = TIMER_INTR_ALARM3;
#if defined(ST_LLD_ALARM3_STATIC_CB)
ST_LLD_ALARM3_STATIC_CB();
#else
if (st_callbacks[3] != NULL) {
st_callbacks[3](3U);
}
#endif
OSAL_IRQ_EPILOGUE();
}
@ -171,6 +223,7 @@ void st_lld_init(void) {
TIMER->INTR = TIMER_INTR_ALARM3 | TIMER_INTR_ALARM2 |
TIMER_INTR_ALARM1 | TIMER_INTR_ALARM0;
#if 0
/* IRQs enabled.*/
#if !defined(ST_TIMER_ALARM0_SUPPRESS_ISR)
nvicEnableVector(RP_TIMER_IRQ0_NUMBER, RP_IRQ_TIMER_ALARM0_PRIORITY);
@ -184,6 +237,7 @@ void st_lld_init(void) {
#if !defined(ST_TIMER_ALARM3_SUPPRESS_ISR)
nvicEnableVector(RP_TIMER_IRQ3_NUMBER, RP_IRQ_TIMER_ALARM3_PRIORITY);
#endif
#endif
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
@ -208,35 +262,38 @@ void st_lld_init(void) {
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
}
#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__)
#if defined(ST_LLD_MULTICORE_SUPPORT) || defined(__DOXYGEN__)
/**
* @brief IRQ handling code.
* @brief Enables an alarm interrupt on the invoking core.
* @note Must be called before any other alarm-related function.
*
* @param[in] alarm alarm channel number (0..ST_LLD_NUM_ALARMS-1)
*
* @notapi
*/
void st_lld_serve_interrupt(void) {
uint32_t ints;
void st_lld_bind_alarm(void) {
ints = TIMER->INTS;
TIMER->INTR = ints;
/* Alarms 0 and 1 are used for system ticks for core 0 and core 1.*/
if ((ints & (TIMER_INTS_ALARM1 | TIMER_INTS_ALARM0)) != 0U) {
osalSysLockFromISR();
osalOsTimerHandlerI();
osalSysUnlockFromISR();
}
if ((ints & TIMER_INTS_ALARM2) != 0U) {
if (st_callbacks[0] != NULL) {
st_callbacks[0](2U);
}
}
if ((ints & TIMER_INTS_ALARM3) != 0U) {
if (st_callbacks[1] != NULL) {
st_callbacks[1](3U);
}
}
nvicEnableVector(alarm_irqs[0].n, alarm_irqs[0].prio);
}
#if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__)
/**
* @brief Enables an alarm interrupt on the invoking core.
* @note Must be called before any other alarm-related function.
*
* @param[in] alarm alarm channel number (0..ST_LLD_NUM_ALARMS-1)
*
* @notapi
*/
void st_lld_bind_alarm_n(unsigned alarm) {
nvicEnableVector(alarm_irqs[alarm].n, alarm_irqs[alarm].prio);
}
#endif /* ST_LLD_NUM_ALARMS > 1 */
#endif /* defined(ST_LLD_MULTICORE_SUPPORT) */
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
/** @} */

View File

@ -37,9 +37,29 @@
#define ST_LLD_NUM_ALARMS 4U
/**
* @brief Number of supported callbacks.
* @brief Static callback for alarm 0.
*/
#define ST_LLD_NUM_CALLBACKS (ST_LLD_NUM_ALARMS - 2U)
#define ST_LLD_ALARM0_STATIC_CB() \
do { \
osalSysLockFromISR(); \
osalOsTimerHandlerI(); \
osalSysUnlockFromISR(); \
} while (false)
/**
* @brief Static callback for alarm 1.
*/
#define ST_LLD_ALARM1_STATIC_CB() \
do { \
osalSysLockFromISR(); \
osalOsTimerHandlerI(); \
osalSysUnlockFromISR(); \
} while (false)
/**
* @brief Defined for inclusion of the IRQ-binding API.
*/
#define ST_LLD_MULTICORE_SUPPORT
/*===========================================================================*/
/* Driver pre-compile time settings. */
@ -129,7 +149,10 @@ extern "C" {
#endif
void st_lld_init(void);
#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
void st_lld_serve_interrupt(void);
#if defined(ST_LLD_MULTICORE_SUPPORT)
void st_lld_bind_alarm(void);
void st_lld_bind_alarm_n(unsigned alarm);
#endif
#endif
#ifdef __cplusplus
}
@ -140,7 +163,6 @@ extern "C" {
/*===========================================================================*/
#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__)
/**
* @brief Returns the time counter value.
*
@ -297,7 +319,6 @@ static inline bool st_lld_is_alarm_active_n(unsigned alarm) {
return (bool)((TIMER->INTE & (1U << alarm)) != 0U);
}
#endif /* ST_LLD_NUM_ALARMS > 1 */
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
#endif /* HAL_ST_LLD_H */

View File

@ -42,8 +42,13 @@
/* Driver local variables. */
/*===========================================================================*/
/**
* @brief Callback pointers for each alarm.
* @note If some alarms have static callbacks defined in the LLD then
* some of the pointers might be unused (never called through).
*/
#if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__)
st_callback_t st_callbacks[ST_LLD_NUM_ALARMS - 1];
st_callback_t st_callbacks[ST_LLD_NUM_ALARMS];
#endif
/*===========================================================================*/
@ -65,7 +70,7 @@ void stInit(void) {
#if ST_LLD_NUM_ALARMS > 1
unsigned i;
for (i = 0U; i < (unsigned)ST_LLD_NUM_ALARMS - 1U; i++) {
for (i = 0U; i < (unsigned)ST_LLD_NUM_ALARMS; i++) {
st_callbacks[i] = NULL;
}
#endif
@ -73,6 +78,35 @@ void stInit(void) {
}
#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__)
/**
* @brief Returns the time counter value.
* @note This functionality is only available in free running mode, the
* behaviour in periodic mode is undefined.
*
* @return The counter value.
*
* @api
*/
systime_t stGetCounter(void) {
return st_lld_get_counter();
}
#if defined(ST_LLD_MULTICORE_SUPPORT) || defined(__DOXYGEN__)
/**
* @brief Enables an alarm interrupt on the invoking core.
* @note Must be called before any other alarm-related function.
*
* @api
*/
void stBindAlarm(void) {
osalDbgAssert(stIsAlarmActive() == false, "already active");
st_lld_bind_alarm();
}
#endif /* defined(ST_LLD_MULTICORE_SUPPORT) */
/**
* @brief Starts the alarm zero.
* @note Makes sure that no spurious alarms are triggered after
@ -135,20 +169,6 @@ systime_t stGetAlarm(void) {
return st_lld_get_alarm();
}
/**
* @brief Returns the time counter value.
* @note This functionality is only available in free running mode, the
* behaviour in periodic mode is undefined.
*
* @return The counter value.
*
* @api
*/
systime_t stGetCounter(void) {
return st_lld_get_counter();
}
/**
* @brief Determines if the alarm zero is active.
*
@ -165,20 +185,42 @@ bool stIsAlarmActive(void) {
#if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__)
/**
* @brief Determines if the specified alarm is active.
* @brief Associates a callback to an alarm.
* @note Makes sure that no spurious alarms are triggered after
* this call.
* @note This functionality is only available in free running mode, the
* behavior in periodic mode is undefined.
*
* @param[in] alarm alarm channel number (1..ST_LLD_NUM_ALARMS)
* @return The alarm status.
* @retval false if the alarm is not active.
* @retval true is the alarm is active
* @param[in] alarm alarm channel number (0..ST_LLD_NUM_ALARMS-1)
* @param[in] cb alarm callback or @p NULL
*
* @api
*/
bool stIsAlarmActiveN(unsigned alarm) {
void stSetCallback(unsigned alarm, st_callback_t cb) {
return st_lld_is_alarm_active_n(alarm);
osalDbgCheck(alarm < (unsigned)ST_LLD_NUM_ALARMS);
st_callbacks[alarm] = cb;
}
#if defined(ST_LLD_MULTICORE_SUPPORT) || defined(__DOXYGEN__)
/**
* @brief Enables an alarm interrupt on the invoking core.
* @note Must be called before any other alarm-related function.
*
* @param[in] alarm alarm channel number (0..ST_LLD_NUM_ALARMS-1)
*
* @api
*/
void stBindAlarmN(unsigned alarm) {
osalDbgCheck(alarm < (unsigned)ST_LLD_NUM_ALARMS);
osalDbgAssert(stIsAlarmActive() == false, "already active");
st_lld_bind_alarm_n(alarm);
}
#endif /* defined(ST_LLD_MULTICORE_SUPPORT) */
/**
* @brief Starts an additional alarm.
* @note Makes sure that no spurious alarms are triggered after
@ -186,18 +228,16 @@ bool stIsAlarmActiveN(unsigned alarm) {
* @note This functionality is only available in free running mode, the
* behavior in periodic mode is undefined.
*
* @param[in] alarm alarm channel number (0..ST_LLD_NUM_ALARMS-1)
* @param[in] abstime the time to be set for the first alarm
* @param[in] alarm alarm channel number (1..ST_LLD_NUM_ALARMS)
* @param[in] cb alarm callback
*
* @api
*/
void stStartAlarmN(unsigned alarm, systime_t abstime, st_callback_t cb) {
void stStartAlarmN(unsigned alarm, systime_t abstime) {
osalDbgCheck((alarm > 0U) && (alarm < (unsigned)ST_LLD_NUM_ALARMS));
osalDbgCheck(alarm < (unsigned)ST_LLD_NUM_ALARMS);
osalDbgAssert(stIsAlarmActiveN(alarm) == false, "already active");
st_callbacks[alarm - 1U] = cb;
st_lld_start_alarm_n(alarm, abstime);
}
@ -206,15 +246,14 @@ void stStartAlarmN(unsigned alarm, systime_t abstime, st_callback_t cb) {
* @note This functionality is only available in free running mode, the
* behavior in periodic mode is undefined.
*
* @param[in] alarm alarm channel number (1..ST_LLD_NUM_ALARMS)
* @param[in] alarm alarm channel number (0..ST_LLD_NUM_ALARMS-1)
*
* @api
*/
void stStopAlarmN(unsigned alarm) {
osalDbgCheck((alarm > 0U) && (alarm < (unsigned)ST_LLD_NUM_ALARMS));
osalDbgCheck(alarm < (unsigned)ST_LLD_NUM_ALARMS);
st_callbacks[alarm - 1U] = NULL;
st_lld_stop_alarm_n(alarm);
}
@ -223,14 +262,14 @@ void stStopAlarmN(unsigned alarm) {
* @note This functionality is only available in free running mode, the
* behavior in periodic mode is undefined.
*
* @param[in] alarm alarm channel number (1..ST_LLD_NUM_ALARMS)
* @param[in] alarm alarm channel number (0..ST_LLD_NUM_ALARMS-1)
* @param[in] abstime the time to be set for the next alarm
*
* @api
*/
void stSetAlarmN(unsigned alarm, systime_t abstime) {
osalDbgCheck((alarm > 0U) && (alarm < (unsigned)ST_LLD_NUM_ALARMS));
osalDbgCheck(alarm < (unsigned)ST_LLD_NUM_ALARMS);
osalDbgAssert(stIsAlarmActiveN(alarm) != false, "not active");
st_lld_set_alarm_n(alarm, abstime);
@ -241,20 +280,36 @@ void stSetAlarmN(unsigned alarm, systime_t abstime) {
* @note This functionality is only available in free running mode, the
* behavior in periodic mode is undefined.
*
* @param[in] alarm alarm channel number (1..ST_LLD_NUM_ALARMS)
* @param[in] alarm alarm channel number (0..ST_LLD_NUM_ALARMS-1)
* @return The currently set alarm time.
*
* @api
*/
systime_t stGetAlarmN(unsigned alarm) {
osalDbgCheck((alarm > 0U) && (alarm < (unsigned)ST_LLD_NUM_ALARMS));
osalDbgCheck(alarm < (unsigned)ST_LLD_NUM_ALARMS);
osalDbgAssert(stIsAlarmActiveN(alarm) != false, "not active");
return st_lld_get_alarm_n(alarm);
}
#endif /* ST_LLD_NUM_ALARMS > 1 */
/**
* @brief Determines if the specified alarm is active.
*
* @param[in] alarm alarm channel number (0..ST_LLD_NUM_ALARMS-1)
* @return The alarm status.
* @retval false if the alarm is not active.
* @retval true is the alarm is active
*
* @api
*/
bool stIsAlarmActiveN(unsigned alarm) {
osalDbgCheck(alarm < (unsigned)ST_LLD_NUM_ALARMS);
return st_lld_is_alarm_active_n(alarm);
}
#endif /* ST_LLD_NUM_ALARMS > 1 */
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */