Improvements to the STM32 ICU driver.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3955 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
995e1f732e
commit
39fa1818ff
|
@ -103,25 +103,29 @@ typedef void (*icucallback_t)(ICUDriver *icup);
|
||||||
* @brief Returns the width of the latest pulse.
|
* @brief Returns the width of the latest pulse.
|
||||||
* @details The pulse width is defined as number of ticks between the start
|
* @details The pulse width is defined as number of ticks between the start
|
||||||
* edge and the stop edge.
|
* edge and the stop edge.
|
||||||
|
* @note This function is meant to be invoked from the width capture
|
||||||
|
* callback only.
|
||||||
*
|
*
|
||||||
* @param[in] icup pointer to the @p ICUDriver object
|
* @param[in] icup pointer to the @p ICUDriver object
|
||||||
* @return The number of ticks.
|
* @return The number of ticks.
|
||||||
*
|
*
|
||||||
* @iclass
|
* @special
|
||||||
*/
|
*/
|
||||||
#define icuGetWidthI(icup) icu_lld_get_width(icup)
|
#define icuGetWidth(icup) icu_lld_get_width(icup)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the width of the latest cycle.
|
* @brief Returns the width of the latest cycle.
|
||||||
* @details The cycle width is defined as number of ticks between a start
|
* @details The cycle width is defined as number of ticks between a start
|
||||||
* edge and the next start edge.
|
* edge and the next start edge.
|
||||||
|
* @note This function is meant to be invoked from the width capture
|
||||||
|
* callback only.
|
||||||
*
|
*
|
||||||
* @param[in] icup pointer to the @p ICUDriver object
|
* @param[in] icup pointer to the @p ICUDriver object
|
||||||
* @return The number of ticks.
|
* @return The number of ticks.
|
||||||
*
|
*
|
||||||
* @iclass
|
* @special
|
||||||
*/
|
*/
|
||||||
#define icuGetPeriodI(icup) icu_lld_get_period(icup)
|
#define icuGetPeriod(icup) icu_lld_get_period(icup)
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -101,10 +101,17 @@ static void icu_lld_serve_interrupt(ICUDriver *icup) {
|
||||||
|
|
||||||
sr = icup->tim->SR & icup->tim->DIER;
|
sr = icup->tim->SR & icup->tim->DIER;
|
||||||
icup->tim->SR = 0;
|
icup->tim->SR = 0;
|
||||||
|
if (icup->config->channel == ICU_CHANNEL_1) {
|
||||||
if ((sr & TIM_SR_CC1IF) != 0)
|
if ((sr & TIM_SR_CC1IF) != 0)
|
||||||
_icu_isr_invoke_period_cb(icup);
|
_icu_isr_invoke_period_cb(icup);
|
||||||
if ((sr & TIM_SR_CC2IF) != 0)
|
if ((sr & TIM_SR_CC2IF) != 0)
|
||||||
_icu_isr_invoke_width_cb(icup);
|
_icu_isr_invoke_width_cb(icup);
|
||||||
|
} else {
|
||||||
|
if ((sr & TIM_SR_CC1IF) != 0)
|
||||||
|
_icu_isr_invoke_width_cb(icup);
|
||||||
|
if ((sr & TIM_SR_CC2IF) != 0)
|
||||||
|
_icu_isr_invoke_period_cb(icup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -283,6 +290,10 @@ void icu_lld_init(void) {
|
||||||
void icu_lld_start(ICUDriver *icup) {
|
void icu_lld_start(ICUDriver *icup) {
|
||||||
uint32_t psc;
|
uint32_t psc;
|
||||||
|
|
||||||
|
chDbgAssert((icup->config->channel == ICU_CHANNEL_1) ||
|
||||||
|
(icup->config->channel == ICU_CHANNEL_2),
|
||||||
|
"icu_lld_start(), #1", "invalid input");
|
||||||
|
|
||||||
if (icup->state == ICU_STOP) {
|
if (icup->state == ICU_STOP) {
|
||||||
/* Clock activation and timer reset.*/
|
/* Clock activation and timer reset.*/
|
||||||
#if STM32_ICU_USE_TIM1
|
#if STM32_ICU_USE_TIM1
|
||||||
|
@ -359,7 +370,12 @@ void icu_lld_start(ICUDriver *icup) {
|
||||||
icup->tim->PSC = (uint16_t)psc;
|
icup->tim->PSC = (uint16_t)psc;
|
||||||
icup->tim->ARR = 0xFFFF;
|
icup->tim->ARR = 0xFFFF;
|
||||||
|
|
||||||
/* CCMR1_CC1S = 01 = CH1 Input on TI1.
|
chDbgAssert((icup->config->channel != ICU_CHANNEL_1) &&
|
||||||
|
(icup->config->channel != ICU_CHANNEL_2),
|
||||||
|
"icu_lld_start(), #2", "invalid channel");
|
||||||
|
if (icup->config->channel == ICU_CHANNEL_1) {
|
||||||
|
/* Selected input 1.
|
||||||
|
CCMR1_CC1S = 01 = CH1 Input on TI1.
|
||||||
CCMR1_CC2S = 10 = CH2 Input on TI1.*/
|
CCMR1_CC2S = 10 = CH2 Input on TI1.*/
|
||||||
icup->tim->CCMR1 = TIM_CCMR1_CC1S_0 |
|
icup->tim->CCMR1 = TIM_CCMR1_CC1S_0 |
|
||||||
TIM_CCMR1_CC2S_1;
|
TIM_CCMR1_CC2S_1;
|
||||||
|
@ -376,6 +392,34 @@ void icu_lld_start(ICUDriver *icup) {
|
||||||
else
|
else
|
||||||
icup->tim->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P |
|
icup->tim->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P |
|
||||||
TIM_CCER_CC2E;
|
TIM_CCER_CC2E;
|
||||||
|
/* Direct pointers to the capture registers in order to make reading
|
||||||
|
data faster from within callbacks.*/
|
||||||
|
icup->wccrp = &icup->tim->CCR[1];
|
||||||
|
icup->pccrp = &icup->tim->CCR[0];
|
||||||
|
} else {
|
||||||
|
/* Selected input 2.
|
||||||
|
CCMR1_CC1S = 10 = CH1 Input on TI2.
|
||||||
|
CCMR1_CC2S = 01 = CH2 Input on TI2.*/
|
||||||
|
icup->tim->CCMR1 = TIM_CCMR1_CC1S_1 |
|
||||||
|
TIM_CCMR1_CC2S_0;
|
||||||
|
/* SMCR_TS = 110, input is TI2FP2.
|
||||||
|
SMCR_SMS = 100, reset on rising edge.*/
|
||||||
|
icup->tim->SMCR = TIM_SMCR_TS_2 | TIM_SMCR_TS_1 |
|
||||||
|
TIM_SMCR_SMS_2;
|
||||||
|
/* The CCER settings depend on the selected trigger mode.
|
||||||
|
ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge.
|
||||||
|
ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/
|
||||||
|
if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH)
|
||||||
|
icup->tim->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P |
|
||||||
|
TIM_CCER_CC2E;
|
||||||
|
else
|
||||||
|
icup->tim->CCER = TIM_CCER_CC1E |
|
||||||
|
TIM_CCER_CC2E | TIM_CCER_CC2P;
|
||||||
|
/* Direct pointers to the capture registers in order to make reading
|
||||||
|
data faster from within callbacks.*/
|
||||||
|
icup->wccrp = &icup->tim->CCR[0];
|
||||||
|
icup->pccrp = &icup->tim->CCR[1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -442,10 +486,17 @@ void icu_lld_stop(ICUDriver *icup) {
|
||||||
void icu_lld_enable(ICUDriver *icup) {
|
void icu_lld_enable(ICUDriver *icup) {
|
||||||
|
|
||||||
icup->tim->SR = 0; /* Clear pending IRQs (if any). */
|
icup->tim->SR = 0; /* Clear pending IRQs (if any). */
|
||||||
|
if (icup->config->channel == ICU_CHANNEL_1) {
|
||||||
if (icup->config->period_cb != NULL)
|
if (icup->config->period_cb != NULL)
|
||||||
icup->tim->DIER |= TIM_DIER_CC1IE;
|
icup->tim->DIER |= TIM_DIER_CC1IE;
|
||||||
if (icup->config->width_cb != NULL)
|
if (icup->config->width_cb != NULL)
|
||||||
icup->tim->DIER |= TIM_DIER_CC2IE;
|
icup->tim->DIER |= TIM_DIER_CC2IE;
|
||||||
|
} else {
|
||||||
|
if (icup->config->width_cb != NULL)
|
||||||
|
icup->tim->DIER |= TIM_DIER_CC1IE;
|
||||||
|
if (icup->config->period_cb != NULL)
|
||||||
|
icup->tim->DIER |= TIM_DIER_CC2IE;
|
||||||
|
}
|
||||||
icup->tim->CR1 = TIM_CR1_URS | TIM_CR1_CEN;
|
icup->tim->CR1 = TIM_CR1_URS | TIM_CR1_CEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,14 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
typedef uint32_t icufreq_t;
|
typedef uint32_t icufreq_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ICU channel.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ICU_CHANNEL_1 = 0, /**< Use TIMxCH1. */
|
||||||
|
ICU_CHANNEL_2 = 1, /**< Use TIMxCH2. */
|
||||||
|
} icuchannel_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ICU counter type.
|
* @brief ICU counter type.
|
||||||
*/
|
*/
|
||||||
|
@ -220,6 +228,11 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
icucallback_t period_cb;
|
icucallback_t period_cb;
|
||||||
/* End of the mandatory fields.*/
|
/* End of the mandatory fields.*/
|
||||||
|
/**
|
||||||
|
* @brief Timer input channel to be used.
|
||||||
|
* @note Only inputs TIMx 1 and 2 are supported.
|
||||||
|
*/
|
||||||
|
icuchannel_t channel;
|
||||||
} ICUConfig;
|
} ICUConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,6 +259,14 @@ struct ICUDriver {
|
||||||
* @brief Pointer to the TIMx registers block.
|
* @brief Pointer to the TIMx registers block.
|
||||||
*/
|
*/
|
||||||
stm32_tim_t *tim;
|
stm32_tim_t *tim;
|
||||||
|
/**
|
||||||
|
* @bried CCR register used for width capture.
|
||||||
|
*/
|
||||||
|
volatile uint32_t *wccrp;
|
||||||
|
/**
|
||||||
|
* @bried CCR register used for period capture.
|
||||||
|
*/
|
||||||
|
volatile uint32_t *pccrp;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -262,7 +283,7 @@ struct ICUDriver {
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
#define icu_lld_get_width(icup) ((icup)->tim->CCR[1] + 1)
|
#define icu_lld_get_width(icup) (*((icup)->wccrp) + 1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the width of the latest cycle.
|
* @brief Returns the width of the latest cycle.
|
||||||
|
@ -274,7 +295,7 @@ struct ICUDriver {
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
#define icu_lld_get_period(icup) ((icup)->tim->CCR[0] + 1)
|
#define icu_lld_get_period(icup) (*((icup)->pccrp) + 1)
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* External declarations. */
|
/* External declarations. */
|
||||||
|
|
|
@ -103,6 +103,8 @@
|
||||||
multiple timers used at same time.
|
multiple timers used at same time.
|
||||||
- NEW: Added board files and demo for Olimex LPC-P1343 (contributed by
|
- NEW: Added board files and demo for Olimex LPC-P1343 (contributed by
|
||||||
Johnny Halfmoon).
|
Johnny Halfmoon).
|
||||||
|
- NEW: Added handling of input 2 to the STM32 ICU driver (contributed by
|
||||||
|
Fabio).
|
||||||
|
|
||||||
*** 2.3.5 ***
|
*** 2.3.5 ***
|
||||||
- FIX: Fixed RTC compile problem on STM32F103 (bug 3468445).
|
- FIX: Fixed RTC compile problem on STM32F103 (bug 3468445).
|
||||||
|
|
|
@ -53,19 +53,20 @@ icucnt_t last_width, last_period;
|
||||||
|
|
||||||
static void icuwidthcb(ICUDriver *icup) {
|
static void icuwidthcb(ICUDriver *icup) {
|
||||||
|
|
||||||
last_width = icuGetWidthI(icup);
|
last_width = icuGetWidth(icup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void icuperiodcb(ICUDriver *icup) {
|
static void icuperiodcb(ICUDriver *icup) {
|
||||||
|
|
||||||
last_period = icuGetPeriodI(icup);
|
last_period = icuGetPeriod(icup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ICUConfig icucfg = {
|
static ICUConfig icucfg = {
|
||||||
ICU_INPUT_ACTIVE_HIGH,
|
ICU_INPUT_ACTIVE_HIGH,
|
||||||
10000, /* 10KHz ICU clock frequency. */
|
10000, /* 10KHz ICU clock frequency. */
|
||||||
icuwidthcb,
|
icuwidthcb,
|
||||||
icuperiodcb
|
icuperiodcb,
|
||||||
|
ICU_CHANNEL_1
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
10
todo.txt
10
todo.txt
|
@ -16,8 +16,10 @@ Within 2.5.x:
|
||||||
* Handling of Virtual Timer callbacks out of critical zone.
|
* Handling of Virtual Timer callbacks out of critical zone.
|
||||||
* Add normal API (not iclass) variants of the VT functions.
|
* Add normal API (not iclass) variants of the VT functions.
|
||||||
* MMC_SPI driver speedup.
|
* MMC_SPI driver speedup.
|
||||||
- Add the RTC service inside the kernel and port, remove from HAL.
|
- MAC driver for STM32F107, STM32F2xx, STM32F4xx.
|
||||||
- Add option to use the RTC counter instead of the systick counter into the
|
- USB driver model revision.
|
||||||
|
- STM32 OTG USB cell support for CL, F2, F4 devices.
|
||||||
|
- Add option to use another counter instead of the systick counter into the
|
||||||
trace buffer.
|
trace buffer.
|
||||||
- Add a chSysIntegrityCheck() API to the kernel.
|
- Add a chSysIntegrityCheck() API to the kernel.
|
||||||
- Add guard pages as extra stack checking mechanism. Guard pages should be
|
- Add guard pages as extra stack checking mechanism. Guard pages should be
|
||||||
|
@ -28,15 +30,13 @@ Within 2.5.x:
|
||||||
- Runtime errors manager in HAL.
|
- Runtime errors manager in HAL.
|
||||||
- Critical errors manager in HAL (to replace or complement assertions).
|
- Critical errors manager in HAL (to replace or complement assertions).
|
||||||
- Streaming DAC/I2S driver model and STM32 implementation.
|
- Streaming DAC/I2S driver model and STM32 implementation.
|
||||||
- USB driver model revision.
|
|
||||||
- MAC driver for STM32F107, STM32F2xx, STM32F4xx.
|
|
||||||
- STM32 OTG USB cell support for CL, F2, F4 devices.
|
|
||||||
- Add ADC3 support to the STM32 ADC driver.
|
- Add ADC3 support to the STM32 ADC driver.
|
||||||
- Update C++ wrapper.
|
- Update C++ wrapper.
|
||||||
- FatFs 0.9x integration.
|
- FatFs 0.9x integration.
|
||||||
- Nios II support.
|
- Nios II support.
|
||||||
- LPC17xx support.
|
- LPC17xx support.
|
||||||
- NUC120 support.
|
- NUC120 support.
|
||||||
|
? Add the RTC service inside the kernel and port, remove from HAL.
|
||||||
|
|
||||||
Within 2.x.x
|
Within 2.x.x
|
||||||
- Software I2C implementation using a GPT instance for timings.
|
- Software I2C implementation using a GPT instance for timings.
|
||||||
|
|
Loading…
Reference in New Issue