EICU. Fixed handlign of 32-bit timers. General code cleanup. PWM mode still untested.

This commit is contained in:
barthess 2015-03-01 21:09:12 +03:00
parent 8bb246b572
commit 4764c3ba15
4 changed files with 181 additions and 154 deletions

View File

@ -43,12 +43,12 @@
* @brief Driver state machine possible states.
*/
typedef enum {
EICU_UNINIT = 0, /* Not initialized. */
EICU_STOP = 1, /* Stopped. */
EICU_READY = 2, /* Ready. */
EICU_WAITING = 3, /* Waiting for first edge. */
EICU_ACTIVE = 4, /* Active cycle phase. */
EICU_IDLE = 5 /* Idle cycle phase. */
EICU_UNINIT = 0, /* Not initialized. */
EICU_STOP = 1, /* Stopped. */
EICU_READY = 2, /* Ready. */
EICU_WAITING = 3, /* Waiting for first edge. */
EICU_ACTIVE = 4, /* Active cycle phase. */
EICU_IDLE = 5 /* Idle cycle phase. */
} eicustate_t;
/**
@ -103,10 +103,10 @@ typedef void (*eicucallback_t)(EICUDriver *eicup, eicuchannel_t channel);
#define eicuDisableI(eicup) eicu_lld_disable(eicup)
/**
* @brief Returns the width of the latest pulse.
* @details The pulse width is defined as number of ticks between the start
* edge and the stop edge.
* @note This function is meant to be invoked from the width capture
* @brief Returns the time of the latest measurement.
* @details The pulse width is defined as number of ticks between the 2
* capture events depending on EICU mode (pulse width or period).
* @note This function is meant to be invoked from the capture
* callback only.
*
* @param[in] eicup Pointer to the @p EICUDriver object
@ -115,13 +115,13 @@ typedef void (*eicucallback_t)(EICUDriver *eicup, eicuchannel_t channel);
*
* @special
*/
#define eicuGetWidth(eicup, channel) eicu_lld_get_width((eicup), (channel))
#define eicuGetTime(eicup, channel) eicu_lld_get_time((eicup), (channel))
/**
* @brief Returns the width of the latest cycle.
* @details The cycle width is defined as number of ticks between a start
* edge and the next start edge.
* @note This function is meant to be invoked from the width capture
* @note This function is meant to be invoked from the capture
* callback only.
*
* @param[in] eicup Pointer to the @p EICUDriver object
@ -144,11 +144,12 @@ typedef void (*eicucallback_t)(EICUDriver *eicup, eicuchannel_t channel);
*
* @notapi
*/
#define _eicu_isr_invoke_pwm_width_cb(eicup, channel) { \
if ((eicup)->state != EICU_WAITING) { \
(eicup)->state = EICU_IDLE; \
(eicup)->config->iccfgp[channel]->width_cb((eicup), (channel)); \
} \
static inline void _eicu_isr_invoke_pwm_width_cb(EICUDriver *eicup,
eicuchannel_t channel) {
if (eicup->state != EICU_WAITING) {
eicup->state = EICU_IDLE;
eicup->config->iccfgp[channel]->capture_cb(eicup, channel);
}
}
/**
@ -159,11 +160,12 @@ typedef void (*eicucallback_t)(EICUDriver *eicup, eicuchannel_t channel);
*
* @notapi
*/
#define _eicu_isr_invoke_pwm_period_cb(eicup, channel) { \
eicustate_t previous_state = (eicup)->state; \
(eicup)->state = EICU_ACTIVE; \
if (previous_state != EICU_WAITING) \
(eicup)->config->period_cb((eicup), (channel)); \
static inline void _eicu_isr_invoke_pwm_period_cb(EICUDriver *eicup,
eicuchannel_t channel) {
eicustate_t previous_state = eicup->state;
eicup->state = EICU_ACTIVE;
if (previous_state != EICU_WAITING)
eicup->config->period_cb(eicup, channel);
}
/**
@ -178,16 +180,18 @@ typedef void (*eicucallback_t)(EICUDriver *eicup, eicuchannel_t channel);
*
* @notapi
*/
#define _eicu_isr_invoke_pulse_width_cb(eicup, channel) { \
if ((eicup)->state == EICU_ACTIVE) { \
(eicup)->state = EICU_READY; \
eicu_lld_invert_polarity((eicup), (channel)); \
(eicup)->config->iccfgp[(channel)]->width_cb((eicup), (channel)); \
} else { \
(eicup)->state = EICU_ACTIVE; \
(eicup)->last_count[(channel)] = eicu_lld_get_compare((eicup), (channel)); \
eicu_lld_invert_polarity((eicup), (channel)); \
} \
static inline void _eicu_isr_invoke_pulse_width_cb(EICUDriver *eicup,
eicuchannel_t channel) {
if (eicup->state == EICU_ACTIVE) {
eicup->state = EICU_READY;
eicu_lld_invert_polarity(eicup, channel);
eicup->config->iccfgp[channel]->capture_cb(eicup, channel);
}
else {
eicup->state = EICU_ACTIVE;
eicup->last_count[channel] = eicu_lld_get_compare(eicup, channel);
eicu_lld_invert_polarity(eicup, channel);
}
}
/**
@ -198,9 +202,11 @@ typedef void (*eicucallback_t)(EICUDriver *eicup, eicuchannel_t channel);
*
* @notapi
*/
#define _eicu_isr_invoke_edge_detect_cb(eicup, channel) { \
(eicup)->state = EICU_READY; \
(eicup)->config->iccfgp[(channel)]->width_cb((eicup), (channel)); \
static inline void _eicu_isr_invoke_edge_detect_cb(EICUDriver *eicup,
eicuchannel_t channel) {
eicup->state = EICU_READY;
eicup->config->iccfgp[channel]->capture_cb(eicup, channel);
eicup->last_count[channel] = eicu_lld_get_compare(eicup, channel);
}
/**

View File

@ -25,7 +25,6 @@
/*
* Hardware Abstraction Layer for Extended Input Capture Unit
*/
#include "hal.h"
#if HAL_USE_EICU || defined(__DOXYGEN__)
@ -113,8 +112,7 @@ EICUDriver EICUD12;
*
* @param[in] eicup Pointer to the @p EICUDriver object
*/
static void eicu_lld_serve_interrupt(EICUDriver *eicup)
{
static void eicu_lld_serve_interrupt(EICUDriver *eicup) {
uint16_t sr;
sr = eicup->tim->SR;
@ -125,19 +123,23 @@ static void eicu_lld_serve_interrupt(EICUDriver *eicup)
/* Clear interrupts */
eicup->tim->SR = ~sr;
if (eicup->config->input_type == EICU_INPUT_PWM) {
switch (eicup->config->input_type) {
case EICU_INPUT_PWM:
if (eicup->config->iccfgp[0] != NULL) {
if ((sr & STM32_TIM_SR_CC1IF) != 0)
_eicu_isr_invoke_pwm_period_cb(eicup, EICU_CHANNEL_1);
_eicu_isr_invoke_pwm_period_cb(eicup,EICU_CHANNEL_1);
if ((sr & STM32_TIM_SR_CC2IF) != 0)
_eicu_isr_invoke_pwm_width_cb(eicup, EICU_CHANNEL_1);
} else {
}
else {
if ((sr & STM32_TIM_SR_CC1IF) != 0)
_eicu_isr_invoke_pwm_width_cb(eicup, EICU_CHANNEL_2);
if ((sr & STM32_TIM_SR_CC2IF) != 0)
_eicu_isr_invoke_pwm_period_cb(eicup, EICU_CHANNEL_2);
_eicu_isr_invoke_pwm_period_cb(eicup,EICU_CHANNEL_2);
}
} else if (eicup->config->input_type == EICU_INPUT_PULSE) {
break;
case EICU_INPUT_PULSE:
if ((sr & STM32_TIM_SR_CC1IF) != 0)
_eicu_isr_invoke_pulse_width_cb(eicup, EICU_CHANNEL_1);
if ((sr & STM32_TIM_SR_CC2IF) != 0)
@ -146,7 +148,9 @@ static void eicu_lld_serve_interrupt(EICUDriver *eicup)
_eicu_isr_invoke_pulse_width_cb(eicup, EICU_CHANNEL_3);
if ((sr & STM32_TIM_SR_CC4IF) != 0)
_eicu_isr_invoke_pulse_width_cb(eicup, EICU_CHANNEL_4);
} else { /* EICU_INPUT_EDGE */
break;
case EICU_INPUT_EDGE:
if ((sr & STM32_TIM_SR_CC1IF) != 0)
_eicu_isr_invoke_edge_detect_cb(eicup, EICU_CHANNEL_1);
if ((sr & STM32_TIM_SR_CC2IF) != 0)
@ -155,6 +159,11 @@ static void eicu_lld_serve_interrupt(EICUDriver *eicup)
_eicu_isr_invoke_edge_detect_cb(eicup, EICU_CHANNEL_3);
if ((sr & STM32_TIM_SR_CC4IF) != 0)
_eicu_isr_invoke_edge_detect_cb(eicup, EICU_CHANNEL_4);
break;
default:
osalSysHalt("Unhandled case");
break;
}
if ((sr & STM32_TIM_SR_UIF) != 0)
@ -551,7 +560,7 @@ void eicu_lld_start(EICUDriver *eicup) {
((psc + 1) * eicup->config->frequency) == eicup->clock,
"invalid frequency");
eicup->tim->PSC = (uint16_t)psc;
eicup->tim->ARR = 0xFFFF;
eicup->tim->ARR = (eicucnt_t)-1;
/* Reset registers */
eicup->tim->SMCR = 0;
@ -574,60 +583,79 @@ void eicu_lld_start(EICUDriver *eicup) {
eicup->tim->CCMR2 = 0;
#endif
if (eicup->config->input_type == EICU_INPUT_PWM)
{
/* TIM9 and TIM12 have only 2 channels.*/
#if STM32_EICU_USE_TIM9
if (eicup == &EICUD9) {
osalDbgCheck((eicup->config->iccfgp[2] == NULL) &&
(eicup->config->iccfgp[3] == NULL));
}
#endif
#if STM32_EICU_USE_TIM12
if (eicup == &EICUD12) {
osalDbgCheck((eicup->config->iccfgp[2] == NULL) &&
(eicup->config->iccfgp[3] == NULL));
}
#endif
if (eicup->config->input_type == EICU_INPUT_PWM) {
if (eicup->config->iccfgp[0] != NULL) {
/* Selected input 1.
CCMR1_CC1S = 01 = CH1 Input on TI1.
CCMR1_CC2S = 10 = CH2 Input on TI1.*/
eicup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(1) | STM32_TIM_CCMR1_CC2S(2);
/* SMCR_TS = 101, input is TI1FP1.
SMCR_SMS = 100, reset on rising edge.*/
eicup->tim->SMCR = STM32_TIM_SMCR_TS(5) | STM32_TIM_SMCR_SMS(4);
/* The CCER settings depend on the selected trigger mode.
EICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge.
EICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.
*/
if (eicup->config->iccfgp[0]->mode == EICU_INPUT_ACTIVE_HIGH)
eicup->tim->CCER = STM32_TIM_CCER_CC1E |
STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P;
else
eicup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P |
STM32_TIM_CCER_CC2E;
/* Direct pointers to the capture registers in order to make reading
data faster from within callbacks.*/
eicup->wccrp[0] = &eicup->tim->CCR[1];
eicup->pccrp = &eicup->tim->CCR[0];
} else {
/* Selected input 2.
CCMR1_CC1S = 10 = CH1 Input on TI2.
CCMR1_CC2S = 01 = CH2 Input on TI2.*/
eicup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(2) | STM32_TIM_CCMR1_CC2S(1);
/* SMCR_TS = 110, input is TI2FP2.
SMCR_SMS = 100, reset on rising edge.*/
eicup->tim->SMCR = STM32_TIM_SMCR_TS(6) | STM32_TIM_SMCR_SMS(4);
/* The CCER settings depend on the selected trigger mode.
EICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge.
EICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.
*/
if (eicup->config->iccfgp[1]->mode == EICU_INPUT_ACTIVE_HIGH)
eicup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P |
STM32_TIM_CCER_CC2E;
else
eicup->tim->CCER = STM32_TIM_CCER_CC1E |
STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P;
/* Selected input 1.
CCMR1_CC1S = 01 = CH1 Input on TI1.
CCMR1_CC2S = 10 = CH2 Input on TI1.*/
eicup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(1) | STM32_TIM_CCMR1_CC2S(2);
/* SMCR_TS = 101, input is TI1FP1.
SMCR_SMS = 100, reset on rising edge.*/
eicup->tim->SMCR = STM32_TIM_SMCR_TS(5) | STM32_TIM_SMCR_SMS(4);
/* The CCER settings depend on the selected trigger mode.
EICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge.
EICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.
*/
if (eicup->config->iccfgp[0]->mode == EICU_INPUT_ACTIVE_HIGH) {
eicup->tim->CCER = STM32_TIM_CCER_CC1E |
STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P;
}
else {
eicup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P |
STM32_TIM_CCER_CC2E;
}
/* Direct pointers to the capture registers in order to make reading
data faster from within callbacks.*/
eicup->wccrp[0] = &eicup->tim->CCR[1];
eicup->pccrp = &eicup->tim->CCR[0];
}
else {
/* Selected input 2.
CCMR1_CC1S = 10 = CH1 Input on TI2.
CCMR1_CC2S = 01 = CH2 Input on TI2.*/
eicup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(2) | STM32_TIM_CCMR1_CC2S(1);
/* SMCR_TS = 110, input is TI2FP2.
SMCR_SMS = 100, reset on rising edge.*/
eicup->tim->SMCR = STM32_TIM_SMCR_TS(6) | STM32_TIM_SMCR_SMS(4);
/* The CCER settings depend on the selected trigger mode.
EICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge.
EICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.
*/
if (eicup->config->iccfgp[1]->mode == EICU_INPUT_ACTIVE_HIGH) {
eicup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P |
STM32_TIM_CCER_CC2E;
}
else {
eicup->tim->CCER = STM32_TIM_CCER_CC1E |
STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P;
}
/* Direct pointers to the capture registers in order to make reading
data faster from within callbacks.*/
eicup->wccrp[1] = &eicup->tim->CCR[0];
eicup->pccrp = &eicup->tim->CCR[1];
}
} else { /* EICU_INPUT_EDGE & EICU_INPUT_PULSE */
}
else { /* EICU_INPUT_EDGE & EICU_INPUT_PULSE */
/* Set each input channel that is used as: a normal input capture channel,
link the corresponding CCR register and set polarity. */
@ -777,29 +805,32 @@ void eicu_lld_enable(EICUDriver *eicup) {
if (eicup->config->period_cb != NULL)
eicup->tim->DIER |= STM32_TIM_DIER_CC1IE;
if ((eicup->config->iccfgp[EICU_CHANNEL_1] != NULL) &&
(eicup->config->iccfgp[EICU_CHANNEL_1]->width_cb != NULL))
(eicup->config->iccfgp[EICU_CHANNEL_1]->capture_cb != NULL))
eicup->tim->DIER |= STM32_TIM_DIER_CC2IE;
} else {
}
else {
if ((eicup->config->iccfgp[EICU_CHANNEL_2] != NULL) &&
(eicup->config->iccfgp[EICU_CHANNEL_2]->width_cb != NULL))
(eicup->config->iccfgp[EICU_CHANNEL_2]->capture_cb != NULL))
eicup->tim->DIER |= STM32_TIM_DIER_CC1IE;
if (eicup->config->period_cb != NULL)
eicup->tim->DIER |= STM32_TIM_DIER_CC2IE;
}
} else { /* EICU_INPUT_PULSE & EICU_INPUT_EDGE */
}
else { /* EICU_INPUT_PULSE || EICU_INPUT_EDGE */
if ((eicup->config->iccfgp[EICU_CHANNEL_1] != NULL) &&
(eicup->config->iccfgp[EICU_CHANNEL_1]->width_cb != NULL))
(eicup->config->iccfgp[EICU_CHANNEL_1]->capture_cb != NULL))
eicup->tim->DIER |= STM32_TIM_DIER_CC1IE;
if ((eicup->config->iccfgp[EICU_CHANNEL_2] != NULL) &&
eicup->config->iccfgp[EICU_CHANNEL_2]->width_cb != NULL)
(eicup->config->iccfgp[EICU_CHANNEL_2]->capture_cb != NULL))
eicup->tim->DIER |= STM32_TIM_DIER_CC2IE;
if ((eicup->config->iccfgp[EICU_CHANNEL_3] != NULL) &&
eicup->config->iccfgp[EICU_CHANNEL_3]->width_cb != NULL)
(eicup->config->iccfgp[EICU_CHANNEL_3]->capture_cb != NULL))
eicup->tim->DIER |= STM32_TIM_DIER_CC3IE;
if ((eicup->config->iccfgp[EICU_CHANNEL_4] != NULL) &&
eicup->config->iccfgp[EICU_CHANNEL_4]->width_cb != NULL)
(eicup->config->iccfgp[EICU_CHANNEL_4]->capture_cb != NULL))
eicup->tim->DIER |= STM32_TIM_DIER_CC4IE;
}
if (eicup->config->overflow_cb != NULL)
eicup->tim->DIER |= STM32_TIM_DIER_UIE;
@ -822,9 +853,8 @@ void eicu_lld_disable(EICUDriver *eicup) {
}
/**
* @brief Returns the width of the latest pulse.
* @details The pulse width is defined as number of ticks between the start
* edge and the stop edge.
* @brief Returns the time between latest 2 capture events.
* @details The time is defined as number of ticks.
*
* @param[in] eicup Pointer to the EICUDriver object.
* @param[in] channel The timer channel that fired the interrupt.
@ -832,21 +862,29 @@ void eicu_lld_disable(EICUDriver *eicup) {
*
* @notapi
*/
uint16_t eicu_lld_get_width(EICUDriver *eicup, uint16_t channel) {
uint16_t capture, last_count;
capture = eicu_lld_get_compare(eicup, channel);
eicucnt_t eicu_lld_get_time(EICUDriver *eicup, eicuchannel_t channel) {
/* Add code to compensate for overflows when in pulse */
if (eicup->config->input_type == EICU_INPUT_PULSE) {
last_count = eicup->last_count[channel];
/* Note! there is no overflow check because it handles under the hood of
unsigned subtraction math.*/
if (capture > last_count) /* No overflow */
capture = capture - last_count;
else if (capture < last_count) /* Timer overflow */
capture = ((0xFFFF - last_count) + capture);
/* 16-bit timer */
if (0xFFFF == eicup->tim->ARR) {
uint16_t capture = eicu_lld_get_compare(eicup, channel);
uint16_t last_count = eicup->last_count[channel];
uint16_t ret = capture - last_count;
return ret;
}
/* 32-bit timer */
else if (0xFFFFFFFF == eicup->tim->ARR) {
eicucnt_t capture = eicu_lld_get_compare(eicup, channel);
eicucnt_t last_count = eicup->last_count[channel];
return capture - last_count;
}
/* error trap */
else {
osalSysHalt("ARR register must be loaded with maximum possible value");
return 0;
}
return capture;
}
#endif /* HAL_USE_EICU */

View File

@ -257,32 +257,17 @@
* @brief EICU driver mode.
*/
typedef enum {
/**
* @brief Trigger on rising edge.
*/
EICU_INPUT_ACTIVE_HIGH = 0,
/**
* @brief Trigger on falling edge.
*/
EICU_INPUT_ACTIVE_LOW = 1,
EICU_INPUT_ACTIVE_HIGH = 0, /**< Trigger on rising edge. */
EICU_INPUT_ACTIVE_LOW = 1, /**< Trigger on falling edge. */
} eicumode_t;
/**
* @brief Input type selector.
*/
typedef enum {
/**
* @brief Triggers on the edge of the input.
*/
EICU_INPUT_EDGE = 0,
/**
* @brief Triggers on detected pulse.
*/
EICU_INPUT_PULSE = 1,
/**
* @brief Triggers on detected PWM period and width.
*/
EICU_INPUT_PWM = 2
EICU_INPUT_EDGE = 0, /**< Triggers on the edge of the input.*/
EICU_INPUT_PULSE = 1, /**< Triggers on detected pulse.*/
EICU_INPUT_PWM = 2 /**< Triggers on detected PWM period and width. */
} eicuinput_t;
/**
@ -293,10 +278,10 @@ typedef uint32_t eicufreq_t;
/**
* @brief EICU counter type.
*/
typedef uint16_t eicucnt_t;
typedef uint32_t eicucnt_t;
/**
* @brief EICU Input Capture Settings structure definition.
* @brief EICU Capture Channel Config structure definition.
*/
typedef struct {
/**
@ -305,16 +290,15 @@ typedef struct {
eicumode_t mode;
/**
* @brief Capture event callback. Used for PWM width, pulse width and
* normal capture event.
* pulse period capture event.
*/
eicucallback_t width_cb;
} EICU_IC_Settings;
eicucallback_t capture_cb;
} EICUChannelConfig;
/**
* @brief EICU Input Capture Config structure definition.
* @brief EICU Config structure definition.
*/
typedef struct
{
typedef struct {
/**
* @brief Select which input type the driver will be configured for.
*/
@ -328,10 +312,10 @@ typedef struct
* @note A NULL parameter indicates the channel as unused.
* @note In PWM mode, only Channel 1 OR Channel 2 may be used.
*/
const EICU_IC_Settings *iccfgp[4];
const EICUChannelConfig *iccfgp[4];
/**
* @brief Period capture event callback.
* @note Only used when in PWM measuremtent mode
* @note Only used when in PWM measurement mode
*/
eicucallback_t period_cb;
/**
@ -345,10 +329,9 @@ typedef struct
} EICUConfig;
/**
* @brief EICU Input Capture Driver structure definition
* @brief EICU Driver structure definition
*/
struct EICUDriver
{
struct EICUDriver {
/**
* @brief STM32 timer peripheral for Input Capture.
*/
@ -358,7 +341,7 @@ struct EICUDriver
*/
eicustate_t state;
/**
* @brief Temporary width holder during pulse measurement.
* @brief Temporary width holder during measurement.
*/
eicucnt_t last_count[4];
/**
@ -416,7 +399,7 @@ struct EICUDriver
* @notapi
*/
#define eicu_lld_invert_polarity(eicup, channel) \
(eicup)->tim->CCER ^= ((uint16_t)(STM32_TIM_CCER_CC1P << ((channel) * 4)))
(eicup)->tim->CCER ^= ((uint16_t)(STM32_TIM_CCER_CC1P << ((channel) * 4)))
/*===========================================================================*/
/* External declarations. */
@ -461,7 +444,7 @@ extern "C" {
void eicu_lld_stop(EICUDriver *eicup);
void eicu_lld_enable(EICUDriver *eicup);
void eicu_lld_disable(EICUDriver *eicup);
uint16_t eicu_lld_get_width(EICUDriver *eicup, uint16_t channel);
eicucnt_t eicu_lld_get_time(EICUDriver *eicup, eicuchannel_t channel);
#ifdef __cplusplus
}
#endif

View File

@ -138,8 +138,8 @@ void eicuDisable(EICUDriver *eicup) {
osalDbgCheck(eicup != NULL);
osalSysLock();
osalDbgAssert((eicup->state == EICU_READY) || (eicup->state == EICU_WAITING) ||
(eicup->state == EICU_ACTIVE) || (eicup->state == EICU_IDLE),
osalDbgAssert((eicup->state == EICU_READY) || (eicup->state == EICU_IDLE) ||
(eicup->state == EICU_ACTIVE) || (eicup->state == EICU_WAITING),
"invalid state");
eicu_lld_disable(eicup);
eicup->state = EICU_READY;