From a0baaface35fec7ecab6f78e66de35c6e1187857 Mon Sep 17 00:00:00 2001
From: gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>
Date: Thu, 31 Mar 2011 18:21:08 +0000
Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2855
 35acf78f-673a-0410-8e92-d51de3d6d3f4

---
 os/hal/include/icu.h             | 12 ++++++++++++
 os/hal/platforms/STM32/icu_lld.c | 27 ++++++++++++++++++++++-----
 os/hal/platforms/STM32/icu_lld.h | 25 ++++++++++---------------
 os/hal/templates/icu_lld.h       | 21 ++++++++++-----------
 4 files changed, 54 insertions(+), 31 deletions(-)

diff --git a/os/hal/include/icu.h b/os/hal/include/icu.h
index f13349760..26fc120ad 100644
--- a/os/hal/include/icu.h
+++ b/os/hal/include/icu.h
@@ -59,6 +59,18 @@ typedef enum {
   ICU_IDLE = 5,                     /**< Idle cycle phase.                  */
 } icustate_t;
 
+/**
+ * @brief   Type of a structure representing an ICU driver.
+ */
+typedef struct ICUDriver ICUDriver;
+
+/**
+ * @brief   ICU notification callback type.
+ *
+ * @param[in] icup      pointer to a @p ICUDriver object
+ */
+typedef void (*icucallback_t)(ICUDriver *icup);
+
 #include "icu_lld.h"
 
 /*===========================================================================*/
diff --git a/os/hal/platforms/STM32/icu_lld.c b/os/hal/platforms/STM32/icu_lld.c
index 04c2f6372..d59027e4f 100644
--- a/os/hal/platforms/STM32/icu_lld.c
+++ b/os/hal/platforms/STM32/icu_lld.c
@@ -248,6 +248,7 @@ void icu_lld_init(void) {
  * @notapi
  */
 void icu_lld_start(ICUDriver *icup) {
+  uint32_t clock, psc;
 
   if (icup->state == ICU_STOP) {
     /* Clock activation and timer reset.*/
@@ -258,6 +259,7 @@ void icu_lld_start(ICUDriver *icup) {
       RCC->APB2RSTR = 0;
       NVICEnableVector(TIM1_CC_IRQn,
                        CORTEX_PRIORITY_MASK(STM32_ICU_TIM1_IRQ_PRIORITY));
+      clock = STM32_TIMCLK2;
     }
 #endif
 #if STM32_ICU_USE_TIM2
@@ -267,6 +269,7 @@ void icu_lld_start(ICUDriver *icup) {
       RCC->APB1RSTR = 0;
       NVICEnableVector(TIM2_IRQn,
                        CORTEX_PRIORITY_MASK(STM32_ICU_TIM2_IRQ_PRIORITY));
+      clock = STM32_TIMCLK1;
     }
 #endif
 #if STM32_ICU_USE_TIM3
@@ -276,6 +279,7 @@ void icu_lld_start(ICUDriver *icup) {
       RCC->APB1RSTR = 0;
       NVICEnableVector(TIM3_IRQn,
                        CORTEX_PRIORITY_MASK(STM32_ICU_TIM3_IRQ_PRIORITY));
+      clock = STM32_TIMCLK1;
     }
 #endif
 #if STM32_ICU_USE_TIM4
@@ -285,6 +289,7 @@ void icu_lld_start(ICUDriver *icup) {
       RCC->APB1RSTR = 0;
       NVICEnableVector(TIM4_IRQn,
                        CORTEX_PRIORITY_MASK(STM32_ICU_TIM4_IRQ_PRIORITY));
+      clock = STM32_TIMCLK1;
     }
 #endif
 
@@ -295,16 +300,28 @@ void icu_lld_start(ICUDriver *icup) {
       RCC->APB1RSTR = 0;
       NVICEnableVector(TIM5_IRQn,
                        CORTEX_PRIORITY_MASK(STM32_ICU_TIM5_IRQ_PRIORITY));
+      clock = STM32_TIMCLK1;
     }
 #endif
   }
+  else {
+    /* Driver re-configuration scenario, it must be stopped first.*/
+    icup->tim->CR1  = 0;                    /* Timer disabled.              */
+    icup->tim->DIER = 0;                    /* All IRQs disabled.           */
+    icup->tim->SR   = 0;                    /* Clear eventual pending IRQs. */
+    icup->tim->CCR1 = 0;                    /* Comparator 1 disabled.       */
+    icup->tim->CCR2 = 0;                    /* Comparator 2 disabled.       */
+    icup->tim->CNT  = 0;                    /* Counter reset to zero.       */
+  }
 
-  /* Timer configuration, PWM input mode.*/
-  icup->tim->CR1   = 0;                     /* Initially stopped.           */
-  icup->tim->CR2   = 0;
+  /* Timer configuration.*/
+  psc = (clock / icup->config->frequency) - 1;
+  chDbgAssert((psc <= 0xFFFF) &&
+              ((psc + 1) * icup->config->frequency) == clock,
+              "icu_lld_start(), #1", "invalid frequency");
+  icup->tim->PSC  = (uint16_t)psc;
   icup->tim->ARR   = 0xFFFF;
-  icup->tim->PSC   = icup->config->psc;     /* Prescaler value.             */
-  icup->tim->DIER  = 0;
+
   /* CCMR1_CC1S = 01 = CH1 Input on TI1.
      CCMR1_CC2S = 10 = CH2 Input on TI2.*/
   icup->tim->CCMR1 = TIM_CCMR1_CC1S_0 |
diff --git a/os/hal/platforms/STM32/icu_lld.h b/os/hal/platforms/STM32/icu_lld.h
index 758b9c352..437390d52 100644
--- a/os/hal/platforms/STM32/icu_lld.h
+++ b/os/hal/platforms/STM32/icu_lld.h
@@ -162,21 +162,14 @@ typedef enum {
 } icumode_t;
 
 /**
- * @brief   ICU counter type.
- */
-typedef uint16_t icucnt_t;
-
-/**
- * @brief   Type of a structure representing an ICU driver.
+ * @brief   ICU frequency type.
  */
-typedef struct ICUDriver ICUDriver;
+typedef uint32_t icufreq_t;
 
 /**
- * @brief   ICU notification callback type.
- *
- * @param[in] icup      pointer to a @p ICUDriver object
+ * @brief   ICU counter type.
  */
-typedef void (*icucallback_t)(ICUDriver *icup);
+typedef uint16_t icucnt_t;
 
 /**
  * @brief   Driver configuration structure.
@@ -187,6 +180,12 @@ typedef struct {
    * @brief   Driver mode.
    */
   icumode_t                 mode;
+  /**
+   * @brief   Timer clock in Hz.
+   * @note    The low level can use assertions in order to catch invalid
+   *          frequency specifications.
+   */
+  icufreq_t                 frequency;
   /**
    * @brief   Callback for pulse width measurement.
    */
@@ -196,10 +195,6 @@ typedef struct {
    */
   icucallback_t             period_cb;
   /* End of the mandatory fields.*/
-  /**
-   * @brief TIM PSC (pre-scaler) register initialization data.
-   */
-  uint16_t                  psc;
 } ICUConfig;
 
 /**
diff --git a/os/hal/templates/icu_lld.h b/os/hal/templates/icu_lld.h
index 68ec93df6..34549b76e 100644
--- a/os/hal/templates/icu_lld.h
+++ b/os/hal/templates/icu_lld.h
@@ -56,21 +56,14 @@ typedef enum {
 } icumode_t;
 
 /**
- * @brief   ICU counter type.
- */
-typedef uint16_t icucnt_t;
-
-/**
- * @brief   Type of a structure representing an ICU driver.
+ * @brief   ICU frequency type.
  */
-typedef struct ICUDriver ICUDriver;
+typedef uint32_t icufreq_t;
 
 /**
- * @brief   ICU notification callback type.
- *
- * @param[in] icup      pointer to a @p ICUDriver object
+ * @brief   ICU counter type.
  */
-typedef void (*icucallback_t)(ICUDriver *icup);
+typedef uint16_t icucnt_t;
 
 /**
  * @brief   Driver configuration structure.
@@ -81,6 +74,12 @@ typedef struct {
    * @brief   Driver mode.
    */
   icumode_t                 mode;
+  /**
+   * @brief   Timer clock in Hz.
+   * @note    The low level can use assertions in order to catch invalid
+   *          frequency specifications.
+   */
+  icufreq_t                 frequency;
   /**
    * @brief   Callback for pulse width measurement.
    */
-- 
cgit v1.2.3