diff options
Diffstat (limited to 'os')
-rw-r--r-- | os/hal/ports/STM32/LLD/eicu_lld.c | 232 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/eicu_lld.h | 68 |
2 files changed, 64 insertions, 236 deletions
diff --git a/os/hal/ports/STM32/LLD/eicu_lld.c b/os/hal/ports/STM32/LLD/eicu_lld.c index 0b6f2e2..9b901f9 100644 --- a/os/hal/ports/STM32/LLD/eicu_lld.c +++ b/os/hal/ports/STM32/LLD/eicu_lld.c @@ -43,6 +43,16 @@ #define eicu_lld_invert_polarity(eicup, channel) \ (eicup)->tim->CCER ^= ((uint16_t)(STM32_TIM_CCER_CC1P << ((channel) * 4))) +/** + * @brief Returns the compare value of the latest cycle. + * + * @param[in] chp Pointer to channel structure that fired the interrupt. + * @return The number of ticks. + * + * @notapi + */ +#define eicu_lld_get_compare(chp) (*((chp)->ccrp) + 1) + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -127,11 +137,11 @@ EICUDriver EICUD12; * * @notapi */ -static eicuresult_t eicu_lld_get_both(EICUDriver *eicup, - eicuchannel_t channel, - eicucnt_t compare) { +static eicuresult_t get_time_both(EICUDriver *eicup, + eicuchannel_t channel, + eicucnt_t compare) { - const EICUChannelDriver *chp = &eicup->channel[channel]; + const EICUChannel *chp = &eicup->channel[channel]; eicuresult_t ret; /* Note! there is no overflow check because it handles under the hood of @@ -164,11 +174,11 @@ static eicuresult_t eicu_lld_get_both(EICUDriver *eicup, /** * */ -static eicucnt_t eicu_lld_get_width(EICUDriver *eicup, - eicuchannel_t channel, - eicucnt_t compare) { +static eicucnt_t get_time_width(EICUDriver *eicup, + eicuchannel_t channel, + eicucnt_t compare) { - const EICUChannelDriver *chp = &eicup->channel[channel]; + const EICUChannel *chp = &eicup->channel[channel]; /* Note! there is no overflow check because it handles under the hood of unsigned subtraction math.*/ @@ -194,11 +204,11 @@ static eicucnt_t eicu_lld_get_width(EICUDriver *eicup, /** * */ -static eicucnt_t eicu_lld_get_period(EICUDriver *eicup, - eicuchannel_t channel, - eicucnt_t compare) { +static eicucnt_t get_time_period(EICUDriver *eicup, + eicuchannel_t channel, + eicucnt_t compare) { - const EICUChannelDriver *chp = &eicup->channel[channel]; + const EICUChannel *chp = &eicup->channel[channel]; /* Note! there is no overflow check because it handles under the hood of unsigned subtraction math.*/ @@ -234,14 +244,14 @@ static eicucnt_t eicu_lld_get_period(EICUDriver *eicup, * @notapi */ static void isr_invoke_pulse_cb(EICUDriver *eicup, eicuchannel_t channel) { - EICUChannelDriver *chp = &eicup->channel[channel]; + EICUChannel *chp = &eicup->channel[channel]; eicucnt_t compare = eicu_lld_get_compare(chp); if (EICU_CH_ACTIVE == chp->state) { chp->state = EICU_CH_IDLE; eicu_lld_invert_polarity(eicup, channel); if (EICU_INPUT_PULSE == chp->config->mode) { - uint32_t width = eicu_lld_get_width(eicup, channel, compare); + uint32_t width = get_time_width(eicup, channel, compare); chp->config->capture_cb(eicup, channel, width, 0); } chp->last_idle = compare; @@ -250,7 +260,7 @@ static void isr_invoke_pulse_cb(EICUDriver *eicup, eicuchannel_t channel) { chp->state = EICU_CH_ACTIVE; eicu_lld_invert_polarity(eicup, channel); if (EICU_INPUT_BOTH == chp->config->mode) { - eicuresult_t both = eicu_lld_get_both(eicup, channel, compare); + eicuresult_t both = get_time_both(eicup, channel, compare); chp->config->capture_cb(eicup, channel, both.width, both.period); } chp->last_active = compare; @@ -266,9 +276,9 @@ static void isr_invoke_pulse_cb(EICUDriver *eicup, eicuchannel_t channel) { * @notapi */ static void isr_invoke_edge_cb(EICUDriver *eicup, eicuchannel_t channel) { - EICUChannelDriver *chp = &eicup->channel[channel]; + EICUChannel *chp = &eicup->channel[channel]; eicucnt_t compare = eicu_lld_get_compare(chp); - uint32_t period = eicu_lld_get_period(eicup, channel, compare); + uint32_t period = get_time_period(eicup, channel, compare); chp->config->capture_cb(eicup, channel, 0, period); chp->last_idle = compare; @@ -291,40 +301,6 @@ static void eicu_isr_invoke_cb(EICUDriver *eicup, eicuchannel_t channel) { } /** - * - */ -static void slow_mode_isr_handler(EICUDriver *eicup, uint16_t sr) { - - if ((sr & STM32_TIM_SR_CC1IF) != 0) - eicu_isr_invoke_cb(eicup, EICU_CHANNEL_1); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - eicu_isr_invoke_cb(eicup, EICU_CHANNEL_2); - if ((sr & STM32_TIM_SR_CC3IF) != 0) - eicu_isr_invoke_cb(eicup, EICU_CHANNEL_3); - if ((sr & STM32_TIM_SR_CC4IF) != 0) - eicu_isr_invoke_cb(eicup, EICU_CHANNEL_4); -} - -/** - * - */ -static void fast_mode_handler(EICUDriver *eicup, uint16_t sr) { - - if (eicup->config->iccfgp[0] != NULL) { - if ((sr & STM32_TIM_SR_CC1IF) != 0) - _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 { - 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); - } -} - -/** * @brief Shared IRQ handler. * * @param[in] eicup Pointer to the @p EICUDriver object @@ -340,79 +316,20 @@ static void eicu_lld_serve_interrupt(EICUDriver *eicup) { /* Clear interrupts */ eicup->tim->SR = ~sr; - if (EICU_FAST == eicup->config->mode) - fast_mode_handler(eicup, sr); - else - slow_mode_isr_handler(eicup, sr); - - if ((sr & STM32_TIM_SR_UIF) != 0) - _eicu_isr_invoke_overflow_cb(eicup); -} - -static void eicu_lld_fast_start(EICUDriver *eicup) { - (void)eicup; - osalSysHalt("unrealized yet"); -#if 0 - 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]->alvl == 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]->alvl == 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]; - } -#endif + if ((sr & STM32_TIM_SR_CC1IF) != 0) + eicu_isr_invoke_cb(eicup, EICU_CHANNEL_1); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + eicu_isr_invoke_cb(eicup, EICU_CHANNEL_2); + if ((sr & STM32_TIM_SR_CC3IF) != 0) + eicu_isr_invoke_cb(eicup, EICU_CHANNEL_3); + if ((sr & STM32_TIM_SR_CC4IF) != 0) + eicu_isr_invoke_cb(eicup, EICU_CHANNEL_4); } -static void eicu_lld_slow_start(EICUDriver *eicup) { +/** + * + */ +static void eicu_channels_start(EICUDriver *eicup) { /* Set each input channel that is used as: a normal input capture channel, link the corresponding CCR register and set polarity. */ @@ -423,7 +340,7 @@ static void eicu_lld_slow_start(EICUDriver *eicup) { eicup->tim->CCMR1 |= STM32_TIM_CCMR1_CC1S(1); /* Link CCR register */ - eicup->channel[0].wccrp = &eicup->tim->CCR[0]; + eicup->channel[0].ccrp = &eicup->tim->CCR[0]; /* Set input polarity */ if (eicup->config->iccfgp[0]->alvl == EICU_INPUT_ACTIVE_HIGH) @@ -438,7 +355,7 @@ static void eicu_lld_slow_start(EICUDriver *eicup) { eicup->tim->CCMR1 |= STM32_TIM_CCMR1_CC2S(1); /* Link CCR register */ - eicup->channel[1].wccrp = &eicup->tim->CCR[1]; + eicup->channel[1].ccrp = &eicup->tim->CCR[1]; /* Set input polarity */ if (eicup->config->iccfgp[1]->alvl == EICU_INPUT_ACTIVE_HIGH) @@ -453,7 +370,7 @@ static void eicu_lld_slow_start(EICUDriver *eicup) { eicup->tim->CCMR2 |= STM32_TIM_CCMR2_CC3S(1); /* Link CCR register */ - eicup->channel[2].wccrp = &eicup->tim->CCR[2]; + eicup->channel[2].ccrp = &eicup->tim->CCR[2]; /* Set input polarity */ if (eicup->config->iccfgp[2]->alvl == EICU_INPUT_ACTIVE_HIGH) @@ -468,7 +385,7 @@ static void eicu_lld_slow_start(EICUDriver *eicup) { eicup->tim->CCMR2 |= STM32_TIM_CCMR2_CC4S(1); /* Link CCR register */ - eicup->channel[3].wccrp = &eicup->tim->CCR[3]; + eicup->channel[3].ccrp = &eicup->tim->CCR[3]; /* Set input polarity */ if (eicup->config->iccfgp[3]->alvl == EICU_INPUT_ACTIVE_HIGH) @@ -478,42 +395,6 @@ static void eicu_lld_slow_start(EICUDriver *eicup) { } } -static void eicu_lld_enable_fast(EICUDriver *eicup) { - (void)eicup; - osalSysHalt("urealized"); -#if 0 - if (eicup->config->iccfgp[0] != NULL) { - 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]->capture_cb != NULL)) - eicup->tim->DIER |= STM32_TIM_DIER_CC2IE; - } - else { - if ((eicup->config->iccfgp[EICU_CHANNEL_2] != 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; - } -#endif -} - -static void eicu_lld_enable_slow(EICUDriver *eicup) { - if ((eicup->config->iccfgp[EICU_CHANNEL_1] != 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]->capture_cb != NULL)) - eicup->tim->DIER |= STM32_TIM_DIER_CC2IE; - if ((eicup->config->iccfgp[EICU_CHANNEL_3] != 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]->capture_cb != NULL)) - eicup->tim->DIER |= STM32_TIM_DIER_CC4IE; -} - /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ @@ -946,10 +827,7 @@ void eicu_lld_start(EICUDriver *eicup) { } #endif - if (eicup->config->mode == EICU_FAST) - eicu_lld_fast_start(eicup); - else - eicu_lld_slow_start(eicup); + eicu_channels_start(eicup); } /** @@ -960,7 +838,9 @@ void eicu_lld_start(EICUDriver *eicup) { * @notapi */ void eicu_lld_stop(EICUDriver *eicup) { + if (eicup->state == EICU_READY) { + /* Clock deactivation.*/ eicup->tim->CR1 = 0; /* Timer disabled. */ eicup->tim->DIER = 0; /* All IRQs disabled. */ @@ -1027,16 +907,22 @@ void eicu_lld_stop(EICUDriver *eicup) { * @notapi */ void eicu_lld_enable(EICUDriver *eicup) { + eicup->tim->EGR = STM32_TIM_EGR_UG; eicup->tim->SR = 0; /* Clear pending IRQs (if any). */ - if (eicup->config->mode == EICU_FAST) - eicu_lld_enable_fast(eicup); - else - eicu_lld_enable_slow(eicup); - - if (eicup->config->overflow_cb != NULL) - eicup->tim->DIER |= STM32_TIM_DIER_UIE; + if ((eicup->config->iccfgp[EICU_CHANNEL_1] != 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]->capture_cb != NULL)) + eicup->tim->DIER |= STM32_TIM_DIER_CC2IE; + if ((eicup->config->iccfgp[EICU_CHANNEL_3] != 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]->capture_cb != NULL)) + eicup->tim->DIER |= STM32_TIM_DIER_CC4IE; eicup->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; } diff --git a/os/hal/ports/STM32/LLD/eicu_lld.h b/os/hal/ports/STM32/LLD/eicu_lld.h index e96d52f..5c6c3fa 100644 --- a/os/hal/ports/STM32/LLD/eicu_lld.h +++ b/os/hal/ports/STM32/LLD/eicu_lld.h @@ -253,24 +253,6 @@ /* Driver data structures and types. */ /*===========================================================================*/ /** - * @brief EICU driver mode. - */ -typedef enum { - /** - * @brief Captures high speed signals. - * @note Only one input per timer possible. - * @note Needs at least 2 capture/compare channels in timer. - */ - EICU_FAST, - /** - * @brief Captures low speed signals. - * @details Suggested for example for PWM or PPM signals from RC receiver. - * @note Only one input per capture/compare channel needed. - */ - EICU_SLOW -} eicumode_t; - -/** * @brief Active level selector. */ typedef enum { @@ -331,7 +313,7 @@ typedef struct { } EICUChannelConfig; /** - * @brief EICU Capture Channel Config structure definition. + * @brief EICU Capture Channel structure definition. */ typedef struct { /** @@ -351,20 +333,16 @@ typedef struct { */ const EICUChannelConfig *config; /** - * @brief CCR registers for width capture. + * @brief CCR register pointer for faster access. */ - volatile uint32_t *wccrp; -} EICUChannelDriver; + volatile uint32_t *ccrp; +} EICUChannel; /** * @brief EICU Config structure definition. */ typedef struct { /** - * @brief Specifies the EICU capture mode. - */ - eicumode_t mode; - /** * @brief Specifies the Timer clock in Hz. */ eicufreq_t frequency; @@ -375,11 +353,6 @@ typedef struct { */ const EICUChannelConfig *iccfgp[EICU_CHANNEL_ENUM_END]; /** - * @brief Timer overflow event callback. - * @note Meaningful only when in @p EICU_FAST mode - */ - eicucallback_t overflow_cb; - /** * @brief TIM DIER register initialization data. */ uint32_t dier; @@ -400,7 +373,7 @@ struct EICUDriver { /** * @brief Channels' data structures. */ - EICUChannelDriver channel[EICU_CHANNEL_ENUM_END]; + EICUChannel channel[EICU_CHANNEL_ENUM_END]; /** * @brief Timer base clock. */ @@ -409,43 +382,12 @@ struct EICUDriver { * @brief Pointer to configuration for the driver. */ const EICUConfig *config; -// /** -// * @brief CCR registers for width capture. -// */ -// volatile uint32_t *wccrp[4]; - /** - * @brief CCR register for period capture. - * @note Only one is needed since only one PWM input per timer is allowed. - */ - volatile uint32_t *pccrp; }; /*===========================================================================*/ /* Driver macros. */ /*===========================================================================*/ -/** - * @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. - * - * @param[in] eicup Pointer to the EICUDriver object. - * @return The number of ticks. - * - * @notapi - */ -#define eicu_lld_get_period_fast(eicup) (*((eicup)->pccrp) + 1) - -/** - * @brief Returns the compare value of the latest cycle. - * - * @param[in] chp Pointer to channel structure that fired the interrupt. - * @return The number of ticks. - * - * @notapi - */ -#define eicu_lld_get_compare(chp) (*((chp)->wccrp) + 1) - /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ |