This is the mail archive of the ecos-patches@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

STM32 ADC driver


Here is a cleaned up version of the STM32 ADC driver.
diff --git a/packages/devs/adc/cortexm/stm32/current/ChangeLog b/packages/devs/adc/cortexm/stm32/current/ChangeLog
new file mode 100755
index 0000000..b0949fe
--- /dev/null
+++ b/packages/devs/adc/cortexm/stm32/current/ChangeLog
@@ -0,0 +1,29 @@
+2009-02-24  Simon Kallweit  <simon.kallweit@intefo.ch>
+
+	* STM32 ADC driver package created
+	* cdl/adc_stm32.cdl
+	* src/adc_stm32.c
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####                                                
+// -------------------------------------------                              
+// This file is part of eCos, the Embedded Configurable Operating System.   
+// Copyright (C) 2009 Free Software Foundation, Inc.                        
+//
+// This program is free software; you can redistribute it and/or modify     
+// it under the terms of the GNU General Public License as published by     
+// the Free Software Foundation; either version 2 or (at your option) any   
+// later version.                                                           
+//
+// This program is distributed in the hope that it will be useful, but      
+// WITHOUT ANY WARRANTY; without even the implied warranty of               
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        
+// General Public License for more details.                                 
+//
+// You should have received a copy of the GNU General Public License        
+// along with this program; if not, write to the                            
+// Free Software Foundation, Inc., 51 Franklin Street,                      
+// Fifth Floor, Boston, MA  02110-1301, USA.                                
+// -------------------------------------------                              
+// ####GPLCOPYRIGHTEND####                                                  
+//===========================================================================
diff --git a/packages/devs/adc/cortexm/stm32/current/cdl/adc_stm32.cdl b/packages/devs/adc/cortexm/stm32/current/cdl/adc_stm32.cdl
new file mode 100755
index 0000000..b61f347
--- /dev/null
+++ b/packages/devs/adc/cortexm/stm32/current/cdl/adc_stm32.cdl
@@ -0,0 +1,235 @@
+# ====================================================================
+#
+#      adc_stm32.cdl
+#
+#      eCos STM32 ADC configuration data
+#
+# ====================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####                                            
+## -------------------------------------------                              
+## This file is part of eCos, the Embedded Configurable Operating System.   
+## Copyright (C) 2009 Free Software Foundation, Inc.                        
+##
+## eCos is free software; you can redistribute it and/or modify it under    
+## the terms of the GNU General Public License as published by the Free     
+## Software Foundation; either version 2 or (at your option) any later      
+## version.                                                                 
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT      
+## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
+## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
+## for more details.                                                        
+##
+## You should have received a copy of the GNU General Public License        
+## along with eCos; if not, write to the Free Software Foundation, Inc.,    
+## 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
+##
+## As a special exception, if other files instantiate templates or use      
+## macros or inline functions from this file, or you compile this file      
+## and link it with other works to produce a work based on this file,       
+## this file does not by itself cause the resulting work to be covered by   
+## the GNU General Public License. However the source code for this file    
+## must still be made available in accordance with section (3) of the GNU   
+## General Public License v2.                                               
+##
+## This exception does not invalidate any other reasons why a work based    
+## on this file might be covered by the GNU General Public License.         
+## -------------------------------------------                              
+## ####ECOSGPLCOPYRIGHTEND####                                              
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Simon Kallweit <simon.kallweit@intefo.ch>
+# Contributors:   
+# Date:           2009-02-24
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+
+cdl_package CYGPKG_DEVS_ADC_CORTEXM_STM32 {
+    display     "ST STM32 ADC device driver"
+    
+    parent      CYGPKG_IO_ADC_DEVICES
+    active_if   CYGPKG_IO_ADC_DEVICES
+    active_if   CYGPKG_HAL_CORTEXM_STM32
+    requires    {CYGNUM_IO_ADC_SAMPLE_SIZE >= 12}
+    description "
+        This option enables the ADC device drivers for the ST STM32. The STM32
+        has up to 3 ADC devices. The driver supports both ADC1 and ADC3. ADC2
+        is not supported as it does cover the same inputs as ADC2 and does not
+        support DMA directly."
+           
+    include_dir cyg/io
+    compile     -library=libextras.a adc_stm32.c
+    
+    cdl_option CYGNUM_DEVS_ADC_CORTEXM_STM32_CLOCK_DIV {
+         display        "ADC clock divider"
+         flavor         data
+         legal_values   { 2 4 6 8 }
+         default_value  8
+         description    "
+             This option specifies the level of debug data output by
+             the STM32 ADC device driver. A value of 0 signifies
+             no debug data output; 1 signifies normal debug data
+             output. If an overrun occurred then this can only be
+             detected by debug output messages."         
+    }
+    
+    cdl_component CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1 {
+        display         "ADC1"
+        description     "
+            ADC1 supports 16 analog input channels as well as additional
+            channels for CPU temperature and internal VREF. This is a total of
+            18 channels. Note that only 16 channels may be active at once!
+            ADC1 uses TIM3 to generate scan events and DMA1 channel 1 for data
+            transmission."
+        
+        cdl_interface CYGINT_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNELS {
+            display         "Number of ADC channels"
+        }
+            
+        cdl_option CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC1_SAMPLE_TIME {
+            display         "Sample time"
+            flavor          data
+            legal_values    1 to 1000
+            default_value   20
+            description     "
+                Sampling time in us. When sampling the internal temperatur,
+                this needs to be at least 17.1 us."
+        }
+        
+        cdl_option CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC1_DEFAULT_RATE {
+            display         "Default sample rate"
+            flavor          data
+            legal_values    1 to 10000
+            default_value   100
+            description     "
+                The driver will be initialized with the default sample rate.
+                If you raise the default sample rate you might need to increase
+                the buffer size for each channel."
+        }
+        
+        cdl_option CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC1_DMA_INT_PRI {
+            display         "DMA interrupt priority"
+            flavor          data
+            default_value   0x80
+            description     "
+                Priority of the DMA request interrupt."
+        }
+        
+        # ADC1 supports 16 analog inputs + 2 additional channels (temperature/vref)
+        for { set ::channel 0 } { $::channel < 18 } { incr ::channel } {  
+    
+            cdl_component CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL[set ::channel] {
+                display         "ADC channel [set ::channel]"
+                flavor          bool
+                default_value   [set ::channel] == 0
+                implements      CYGINT_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNELS
+                description     "
+                    If the application needs to access the on-chip ADC
+                    channel [set ::channel] via an eCos ADC driver then
+                    this option should be enabled."
+     
+                cdl_option CYGDAT_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL[set ::channel]_NAME {
+                    display         "Device name"
+                    flavor          data
+                    default_value   [format {"\"/dev/adc0%d\""} $::channel]
+                    description     "
+                        This option controls the name that an eCos application
+                        should use to access this device via cyg_io_lookup(),
+                        open(), or similar calls."
+                }
+        
+                cdl_option CYGDAT_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL[set ::channel]_BUFSIZE {
+                    display         "Size of data buffer"
+                    flavor          data
+                    legal_values    1 to 65536
+                    default_value   128
+                    description     "
+                        This option controls the number of samples the
+                        buffer can store. The required RAM is = size of
+                        data buffer * 2."
+                } 
+            }
+        }
+    }
+
+    cdl_component CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3 {
+        display         "ADC3"
+        description     "
+            ADC3 supports 16 analog input channels. All channels may be active
+            at once. ADC3 uses TIM8 to generate scan events and DMA2 channel 5
+            for data transmission."
+        
+        cdl_interface CYGINT_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNELS {
+            display         "Number of ADC channels"
+        }
+            
+        cdl_option CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC3_SAMPLE_TIME {
+            display         "Sample time"
+            flavor          data
+            legal_values    1 to 1000
+            default_value   20
+            description     "
+                Sampling time in us. When sampling the internal temperatur,
+                this needs to be at least 17.1 us."
+        }
+        
+        cdl_option CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC3_DEFAULT_RATE {
+            display         "Default sample rate"
+            flavor          data
+            legal_values    1 to 10000
+            default_value   100
+            description     "
+                The driver will be initialized with the default sample rate.
+                If you raise the default sample rate you might need to increase
+                the buffer size for each channel."
+        }
+        
+        cdl_option CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC3_DMA_INT_PRI {
+            display         "DMA interrupt priority"
+            flavor          data
+            default_value   0x80
+            description     "
+                Priority of the DMA request interrupt."
+        }
+        
+        # ADC3 supports 16 analog inputs
+        for { set ::channel 0 } { $::channel < 16 } { incr ::channel } {  
+    
+            cdl_component CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL[set ::channel] {
+                display         "ADC channel [set ::channel]"
+                flavor          bool
+                default_value   [set ::channel] == 0
+                implements      CYGINT_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNELS
+                description     "
+                    If the application needs to access the on-chip ADC
+                    channel [set ::channel] via an eCos ADC driver then
+                    this option should be enabled."
+     
+                cdl_option CYGDAT_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL[set ::channel]_NAME {
+                    display         "Device name"
+                    flavor          data
+                    default_value   [format {"\"/dev/adc1%d\""} $::channel]
+                    description     "
+                        This option controls the name that an eCos application
+                        should use to access this device via cyg_io_lookup(),
+                        open(), or similar calls."
+                }
+        
+                cdl_option CYGDAT_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL[set ::channel]_BUFSIZE {
+                    display         "Size of data buffer"
+                    flavor          data
+                    legal_values    1 to 65536
+                    default_value   128
+                    description     "
+                        This option controls the number of samples the
+                        buffer can store. The required RAM is = size of
+                        data buffer * 2."
+                } 
+            }
+        }
+    }
+}
diff --git a/packages/devs/adc/cortexm/stm32/current/src/adc1.inl b/packages/devs/adc/cortexm/stm32/current/src/adc1.inl
new file mode 100644
index 0000000..5219c57
--- /dev/null
+++ b/packages/devs/adc/cortexm/stm32/current/src/adc1.inl
@@ -0,0 +1,108 @@
+
+// ADC input pins
+static const cyg_uint32 stm32_adc_pins1[] = {
+    CYGHWR_HAL_STM32_ADC1_IN0,
+    CYGHWR_HAL_STM32_ADC1_IN1,
+    CYGHWR_HAL_STM32_ADC1_IN2,
+    CYGHWR_HAL_STM32_ADC1_IN3,
+    CYGHWR_HAL_STM32_ADC1_IN4,
+    CYGHWR_HAL_STM32_ADC1_IN5,
+    CYGHWR_HAL_STM32_ADC1_IN6,
+    CYGHWR_HAL_STM32_ADC1_IN7,
+    CYGHWR_HAL_STM32_ADC1_IN8,
+    CYGHWR_HAL_STM32_ADC1_IN9,
+    CYGHWR_HAL_STM32_ADC1_IN10,
+    CYGHWR_HAL_STM32_ADC1_IN11,
+    CYGHWR_HAL_STM32_ADC1_IN12,
+    CYGHWR_HAL_STM32_ADC1_IN13,
+    CYGHWR_HAL_STM32_ADC1_IN14,
+    CYGHWR_HAL_STM32_ADC1_IN15,
+    CYGHWR_HAL_STM32_GPIO_NONE,
+    CYGHWR_HAL_STM32_GPIO_NONE,
+};
+
+// ADC setup
+static const stm32_adc_setup stm32_adc_setup1 = {
+    .adc_base       = CYGHWR_HAL_STM32_ADC1,
+    .dma_base       = CYGHWR_HAL_STM32_DMA1,
+    .dma_int_vector = CYGNUM_HAL_INTERRUPT_DMA1_CH1,
+    .dma_int_pri    = CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC1_DMA_INT_PRI,
+    .dma_channel    = 1,
+    .tim_base       = CYGHWR_HAL_STM32_TIM3,
+    .pins           = stm32_adc_pins1,
+    .extsel         = 4,
+    .sample_time    = CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC1_SAMPLE_TIME,
+};
+
+// ADC DMA buffer
+static cyg_uint16
+    stm32_adc_dma_buf1[CYGINT_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNELS]
+    __attribute__((aligned(2), section(".sram")));
+
+// ADC device info
+static stm32_adc_info stm32_adc_info1 = {
+    .setup          = &stm32_adc_setup1,
+    .dma_buf        = stm32_adc_dma_buf1,
+};
+
+// ADC device instance
+CYG_ADC_DEVICE(stm32_adc_device1,
+               &stm32_adc_funs,
+               &stm32_adc_info1,
+               CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC1_DEFAULT_RATE);
+
+// ADC channels
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL0
+STM32_ADC_CHANNEL(1, 0)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL1
+STM32_ADC_CHANNEL(1, 1)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL2
+STM32_ADC_CHANNEL(1, 2)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL3
+STM32_ADC_CHANNEL(1, 3)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL4
+STM32_ADC_CHANNEL(1, 4)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL5
+STM32_ADC_CHANNEL(1, 5)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL6
+STM32_ADC_CHANNEL(1, 6)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL7
+STM32_ADC_CHANNEL(1, 7)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL8
+STM32_ADC_CHANNEL(1, 8)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL9
+STM32_ADC_CHANNEL(1, 9)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL10
+STM32_ADC_CHANNEL(1, 10)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL11
+STM32_ADC_CHANNEL(1, 11)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL12
+STM32_ADC_CHANNEL(1, 12)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL13
+STM32_ADC_CHANNEL(1, 13)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL14
+STM32_ADC_CHANNEL(1, 14)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL15
+STM32_ADC_CHANNEL(1, 15)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL16
+STM32_ADC_CHANNEL(1, 16)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1_CHANNEL17
+STM32_ADC_CHANNEL(1, 17)
+#endif
diff --git a/packages/devs/adc/cortexm/stm32/current/src/adc3.inl b/packages/devs/adc/cortexm/stm32/current/src/adc3.inl
new file mode 100644
index 0000000..afcc151
--- /dev/null
+++ b/packages/devs/adc/cortexm/stm32/current/src/adc3.inl
@@ -0,0 +1,100 @@
+
+// ADC input pins
+static const cyg_uint32 stm32_adc_pins3[] = {
+    CYGHWR_HAL_STM32_ADC3_IN0,
+    CYGHWR_HAL_STM32_ADC3_IN1,
+    CYGHWR_HAL_STM32_ADC3_IN2,
+    CYGHWR_HAL_STM32_ADC3_IN3,
+    CYGHWR_HAL_STM32_ADC3_IN4,
+    CYGHWR_HAL_STM32_ADC3_IN5,
+    CYGHWR_HAL_STM32_ADC3_IN6,
+    CYGHWR_HAL_STM32_ADC3_IN7,
+    CYGHWR_HAL_STM32_ADC3_IN8,
+    CYGHWR_HAL_STM32_ADC3_IN9,
+    CYGHWR_HAL_STM32_ADC3_IN10,
+    CYGHWR_HAL_STM32_ADC3_IN11,
+    CYGHWR_HAL_STM32_ADC3_IN12,
+    CYGHWR_HAL_STM32_ADC3_IN13,
+    CYGHWR_HAL_STM32_ADC3_IN14,
+    CYGHWR_HAL_STM32_ADC3_IN15,
+};
+
+// ADC setup
+static const stm32_adc_setup stm32_adc_setup3 = {
+    .adc_base       = CYGHWR_HAL_STM32_ADC3,
+    .dma_base       = CYGHWR_HAL_STM32_DMA2,
+    .dma_int_vector = CYGNUM_HAL_INTERRUPT_DMA2_CH4_5,
+    .dma_int_pri    = 0x80,
+    .dma_channel    = 5,
+    .tim_base       = CYGHWR_HAL_STM32_TIM8,
+    .pins           = stm32_adc_pins3,
+    .extsel         = 4,
+    .sample_time    = CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC3_SAMPLE_TIME,
+};
+
+// ADC DMA buffer
+static cyg_uint16
+    stm32_adc_dma_buf3[CYGINT_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNELS]
+    __attribute__((aligned(2), section(".sram")));
+
+// ADC device info
+static stm32_adc_info stm32_adc_info3 = {
+    .setup          = &stm32_adc_setup3,
+    .dma_buf        = stm32_adc_dma_buf3,
+};
+
+// ADC device instance
+CYG_ADC_DEVICE(stm32_adc_device3,
+               &stm32_adc_funs,
+               &stm32_adc_info3,
+               CYGNUM_DEVS_ADC_CORTEXM_STM32_ADC3_DEFAULT_RATE);
+
+// ADC channels
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL0
+STM32_ADC_CHANNEL(3, 0)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL1
+STM32_ADC_CHANNEL(3, 1)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL2
+STM32_ADC_CHANNEL(3, 2)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL3
+STM32_ADC_CHANNEL(3, 3)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL4
+STM32_ADC_CHANNEL(3, 4)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL5
+STM32_ADC_CHANNEL(3, 5)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL6
+STM32_ADC_CHANNEL(3, 6)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL7
+STM32_ADC_CHANNEL(3, 7)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL8
+STM32_ADC_CHANNEL(3, 8)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL9
+STM32_ADC_CHANNEL(3, 9)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL10
+STM32_ADC_CHANNEL(3, 10)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL11
+STM32_ADC_CHANNEL(3, 11)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL12
+STM32_ADC_CHANNEL(3, 12)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL13
+STM32_ADC_CHANNEL(3, 13)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL14
+STM32_ADC_CHANNEL(3, 14)
+#endif
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3_CHANNEL15
+STM32_ADC_CHANNEL(3, 15)
+#endif
diff --git a/packages/devs/adc/cortexm/stm32/current/src/adc_stm32.c b/packages/devs/adc/cortexm/stm32/current/src/adc_stm32.c
new file mode 100755
index 0000000..e4848e7
--- /dev/null
+++ b/packages/devs/adc/cortexm/stm32/current/src/adc_stm32.c
@@ -0,0 +1,611 @@
+//==========================================================================
+//
+//      adc_stm32.c
+//
+//      ADC driver for STM32 on chip ADC
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####                                            
+// -------------------------------------------                              
+// This file is part of eCos, the Embedded Configurable Operating System.   
+// Copyright (C) 2009 Free Software Foundation, Inc.                        
+//
+// eCos is free software; you can redistribute it and/or modify it under    
+// the terms of the GNU General Public License as published by the Free     
+// Software Foundation; either version 2 or (at your option) any later      
+// version.                                                                 
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT      
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
+// for more details.                                                        
+//
+// You should have received a copy of the GNU General Public License        
+// along with eCos; if not, write to the Free Software Foundation, Inc.,    
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
+//
+// As a special exception, if other files instantiate templates or use      
+// macros or inline functions from this file, or you compile this file      
+// and link it with other works to produce a work based on this file,       
+// this file does not by itself cause the resulting work to be covered by   
+// the GNU General Public License. However the source code for this file    
+// must still be made available in accordance with section (3) of the GNU   
+// General Public License v2.                                               
+//
+// This exception does not invalidate any other reasons why a work based    
+// on this file might be covered by the GNU General Public License.         
+// -------------------------------------------                              
+// ####ECOSGPLCOPYRIGHTEND####                                              
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Simon Kallweit <simon.kallweit@intefo.ch>
+// Contributors:
+// Date:         2009-02-24
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/system.h>
+#include <pkgconf/devs_adc_cortexm_stm32.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/io/adc.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/drv_api.h>
+
+//-----------------------------------------------------------------------------
+// Diagnostic support
+// Switch the #if to 1 to generate some diagnostic messages.
+
+#if 0
+#include <cyg/infra/diag.h>
+#define adc_diag( __fmt, ... ) diag_printf("ADC: %30s[%4d]: " __fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__ );
+#else
+#define adc_diag( __fmt, ... ) 
+#endif
+
+
+//-----------------------------------------------------------------------------
+// STM32 ADC device setup
+
+typedef struct stm32_adc_setup {
+    CYG_ADDRESS         adc_base;       // ADC registers base address
+    CYG_ADDRESS         dma_base;       // DMA registers base address
+    cyg_vector_t        dma_int_vector; // DMA interrupt vector
+    cyg_priority_t      dma_int_pri;    // DMA interrupt priority
+    cyg_uint8           dma_channel;    // DMA channel to use
+    CYG_ADDRESS         tim_base;       // Timer registers base address
+    const cyg_uint32    *pins;          // ADC associated GPIO pins
+    cyg_uint8           extsel;         // ADC EXTSEL value (timer event)
+    cyg_uint32          sample_time;    // ADC sampling time in us
+} stm32_adc_setup;
+
+//-----------------------------------------------------------------------------
+// STM32 ADC device
+
+typedef struct stm32_adc_info {
+    const stm32_adc_setup   *setup;         // ADC setup
+    cyg_handle_t            dma_int_handle; // DMA interrupt handle
+    cyg_interrupt           dma_int_data;   // DMA interrupt data
+    cyg_uint16              *dma_buf;       // DMA buffer
+    cyg_adc_channel         *chan[18];      // Channel references by channel no
+    cyg_uint32              chan_mask;      // Channel mask
+} stm32_adc_info;
+
+//-----------------------------------------------------------------------------
+// API function call forward references
+
+static bool stm32_adc_init(struct cyg_devtab_entry *tab);
+static Cyg_ErrNo stm32_adc_lookup(struct cyg_devtab_entry **tab,
+                                  struct cyg_devtab_entry *sub_tab,
+                                  const char *name);
+
+static void stm32_adc_enable(cyg_adc_channel *chan);
+static void stm32_adc_disable(cyg_adc_channel *chan);
+static void stm32_adc_set_rate(cyg_adc_channel *chan, cyg_uint32 rate);
+
+static cyg_uint32 stm32_dma_isr(cyg_vector_t vector, cyg_addrword_t data);
+static void stm32_dma_dsr(cyg_vector_t vector, cyg_ucount32 count,
+                          cyg_addrword_t data);
+
+static void stm32_adc_init_clock(void);
+static void stm32_adc_init_device(cyg_adc_device *device);
+static void stm32_adc_update_sequence(cyg_adc_device *device);
+
+CYG_ADC_FUNCTIONS(stm32_adc_funs,
+                  stm32_adc_enable,
+                  stm32_adc_disable,
+                  stm32_adc_set_rate);
+
+//-----------------------------------------------------------------------------
+// STM32 ADC channel instance macro
+
+#define STM32_ADC_CHANNEL(_device_, _chan_)                                 \
+CYG_ADC_CHANNEL(                                                            \
+    stm32_adc##_device_##_channel##_chan_,                                  \
+    _chan_,                                                                 \
+    CYGDAT_DEVS_ADC_CORTEXM_STM32_ADC##_device_##_CHANNEL##_chan_##_BUFSIZE,\
+    &stm32_adc_device##_device_                                             \
+);                                                                          \
+DEVTAB_ENTRY(                                                               \
+    stm32_adc##_device_##_channel##_chan_##_device,                         \
+    CYGDAT_DEVS_ADC_CORTEXM_STM32_ADC##_device_##_CHANNEL##_chan_##_NAME,   \
+    0,                                                                      \
+    &cyg_io_adc_devio,                                                      \
+    stm32_adc_init,                                                         \
+    stm32_adc_lookup,                                                       \
+    &stm32_adc##_device_##_channel##_chan_                                  \
+);
+
+//-----------------------------------------------------------------------------
+// STM32 ADC device instances
+
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1
+#include "adc1.inl"
+#endif
+
+#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3
+#include "adc3.inl"
+#endif
+
+static cyg_bool initialized;
+static cyg_uint32 adc_clock;
+
+__externC cyg_uint32 hal_stm32_pclk1;
+__externC cyg_uint32 hal_stm32_pclk2;
+
+//-----------------------------------------------------------------------------
+// This function is called from the device IO infrastructure to initialize the
+// device. It should perform any work needed to start up the device, short of
+// actually starting the generation of samples. This function will be called
+// for each channel, so if there is initialization that only needs to be done
+// once, such as creating and interrupt object, then care should be taken to do
+// this. This function should also call cyg_adc_device_init() to initialize the
+// generic parts of the driver.
+
+static bool
+stm32_adc_init(struct cyg_devtab_entry *tab)
+{
+    cyg_adc_channel *chan = (cyg_adc_channel *) tab->priv;
+    cyg_adc_device *device = chan->device;
+    stm32_adc_info *info = device->dev_priv;
+    
+    adc_diag("Initializing device\n");
+    
+    // Initialize ADC clock
+    if (!initialized) {
+        stm32_adc_init_clock();
+        initialized = true;
+    }
+    
+    // Keep reference to channel
+    info->chan[chan->channel] = chan;
+
+    if (!info->dma_int_handle) {
+        // Initialize ADC device
+        stm32_adc_init_device(device);
+        
+        // Set default rate
+        stm32_adc_set_rate(chan, chan->device->config.rate);
+        
+        // Initialize DMA interrupt
+        cyg_drv_interrupt_create(info->setup->dma_int_vector,
+                                 info->setup->dma_int_pri,
+                                (cyg_addrword_t) device,
+                                &stm32_dma_isr,
+                                &stm32_dma_dsr,
+                                &info->dma_int_handle,
+                                &info->dma_int_data);
+        cyg_drv_interrupt_attach(info->dma_int_handle);
+        cyg_drv_interrupt_unmask(info->setup->dma_int_vector);
+    }
+    
+    // Initialize generic parts of ADC device
+    cyg_adc_device_init(device);
+    
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+// This function is called when a client looks up or opens a channel. It should
+// call cyg_adc_channel_init() to initialize the generic part of the channel.
+// It should also perform any operations needed to start the channel generating
+// samples.
+
+static Cyg_ErrNo
+stm32_adc_lookup(struct cyg_devtab_entry **tab,
+                 struct cyg_devtab_entry *sub_tab,
+                 const char *name)
+{
+    cyg_adc_channel *chan = (cyg_adc_channel *) (*tab)->priv;
+    stm32_adc_info *info = chan->device->dev_priv;
+    cyg_uint32 cr;
+
+    adc_diag("Opening device\n");
+    
+    // Configure the input pin, if available
+    if (info->setup->pins[chan->channel] != CYGHWR_HAL_STM32_GPIO_NONE)
+        CYGHWR_HAL_STM32_GPIO_SET(info->setup->pins[chan->channel]);
+    
+    // Activate temperature and VREF if necessary
+    if (chan->channel >= 16) {
+        HAL_READ_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+        cr |= CYGHWR_HAL_STM32_ADC_CR2_TSVREFE;
+        HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+    }
+
+    // Initialize generic parts of the channel
+    cyg_adc_channel_init(chan);
+
+    // The generic ADC manual says: When a channel is first looked up or 
+    // opened, then it is automatically enabled and samples start to
+    // accumulate - so we start the channel now
+    chan->enabled = true;
+    stm32_adc_enable(chan);
+
+    return ENOERR;
+}
+
+//-----------------------------------------------------------------------------
+// This function is called from the generic ADC package to enable the channel
+// in response to a CYG_IO_SET_CONFIG_ADC_ENABLE config operation. It should
+// take any steps needed to start the channel generating samples
+
+static void
+stm32_adc_enable(cyg_adc_channel *chan)
+{
+    stm32_adc_info *info = chan->device->dev_priv;
+    cyg_uint32 cr;
+    cyg_bool start;
+    
+    adc_diag("Enabling channel\n");
+
+    start = !info->chan_mask;
+
+    // Update the scanning sequence
+    info->chan_mask |= (1 << chan->channel);
+    stm32_adc_update_sequence(chan->device);
+    
+    // Start scanning when first channel was activated
+    if (start) {
+        // Enable timer
+        adc_diag("Starting scanning\n");
+        HAL_READ_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR1, cr);
+        cr |= CYGHWR_HAL_STM32_TIM_CR1_CEN;
+        HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR1, cr);
+    }
+}
+
+//-----------------------------------------------------------------------------
+// This function is called from the generic ADC package to enable the channel
+// in response to a CYG_IO_SET_CONFIG_ADC_DISABLE config operation. It should
+// take any steps needed to stop the channel generating samples.
+
+static void
+stm32_adc_disable(cyg_adc_channel *chan)
+{
+    stm32_adc_info *info = chan->device->dev_priv;
+    cyg_uint32 cr;
+    
+    adc_diag("Disabling channel\n");
+    
+    // Update scanning sequence
+    info->chan_mask &= ~(1 << chan->channel);
+    stm32_adc_update_sequence(chan->device);
+    
+    // Stop scanning when no channel is active
+    if (!info->chan_mask) {
+        // Disable timer
+        adc_diag("Stopping scanning\n");
+        HAL_READ_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR1, cr);
+        cr &= ~CYGHWR_HAL_STM32_TIM_CR1_CEN;
+        HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR1, cr);
+    }
+}
+
+//-----------------------------------------------------------------------------
+// This function is called from the generic ADC package to enable the channel
+// in response to a CYG_IO_SET_CONFIG_ADC_RATE config operation. It should take
+// any steps needed to change the sample rate of the channel, or of the entire
+// device. We use a timer channel to generate the interrupts for sampling the
+// analog channels
+
+static void
+stm32_adc_set_rate( cyg_adc_channel *chan, cyg_uint32 rate)
+{
+    cyg_adc_device *device = chan->device;
+    stm32_adc_info *info = device->dev_priv;
+    cyg_uint32 clock;
+    cyg_uint32 period, prescaler;
+    cyg_uint32 cr;
+    
+    adc_diag("Setting rate to %d\n", rate);
+
+    device->config.rate = rate;
+    
+    clock = hal_stm32_timer_clock(info->setup->tim_base);
+    
+    period = clock / rate;
+    prescaler = (period / 0x10000) + 1;
+    period = period / prescaler;
+    
+    HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_PSC,
+                     prescaler - 1);
+    HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_ARR,
+                     period - 1);
+    
+    // Set direction = down, clock divider = 1
+    cr = CYGHWR_HAL_STM32_TIM_CR1_DIR | CYGHWR_HAL_STM32_TIM_CR1_CKD_1;
+    HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR1, cr);
+    
+    // Reinitialize timer
+    cr = CYGHWR_HAL_STM32_TIM_EGR_UG;
+    HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_EGR, cr);
+    
+    // Enable generation of TRGO event
+    cr = CYGHWR_HAL_STM32_TIM_CR2_MMS_UPDATE;
+    HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR2, cr);
+}
+
+//-----------------------------------------------------------------------------
+// This function is the ISR attached to the ADC device's DMA channel interrupt
+// vector. It is responsible for reading samples from the DMA buffer and
+// passing them on to the generic layer.
+
+static cyg_uint32
+stm32_dma_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+    cyg_adc_device *device = (cyg_adc_device *) data;
+    stm32_adc_info *info = (stm32_adc_info *) device->dev_priv;
+    cyg_uint32 chan_active = info->chan_mask;
+    cyg_uint16 *sample = info->dma_buf;
+    cyg_adc_channel **chan = info->chan;
+    cyg_uint32 res = 0;
+    
+    while (chan_active) {
+        if (chan_active & 0x1)
+            res |= (CYG_ISR_HANDLED |
+                    cyg_adc_receive_sample(*chan, *sample++ & 0xfff));
+        chan_active >>= 1;
+        chan++;
+    }
+
+    HAL_WRITE_UINT32(info->setup->dma_base + CYGHWR_HAL_STM32_DMA_IFCR,
+                     CYGHWR_HAL_STM32_DMA_IFCR_MASK(info->setup->dma_channel));
+    
+    cyg_drv_interrupt_acknowledge(vector);
+    
+    return res;
+}
+
+//-----------------------------------------------------------------------------
+// This function is the DSR attached to the ADC device's DMA channel interrupt
+// vector. It is called by the kernel if the ISR return value contains the
+// CYG_ISR_CALL_DSR bit. It needs to call cyg_adc_wakeup() for each channel
+// that has its wakeup field set.
+
+static void
+stm32_dma_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    cyg_adc_device *device = (cyg_adc_device *) data;
+    stm32_adc_info *info = (stm32_adc_info *) device->dev_priv;
+    cyg_uint32 chan_active = info->chan_mask;
+    cyg_adc_channel **chan = info->chan;
+    
+    while (chan_active) {
+        if (chan_active & 0x1)
+            if ((*chan)->wakeup)
+                cyg_adc_wakeup(*chan);
+        chan_active >>= 1;
+        chan++;
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Initializes the ADC system clock.
+
+static void
+stm32_adc_init_clock(void)
+{
+    CYG_ADDRESS rcc = CYGHWR_HAL_STM32_RCC;
+    cyg_uint32 cfgr;
+    
+    adc_diag("Initializing ADC system clock\n");
+    
+    HAL_READ_UINT32(rcc + CYGHWR_HAL_STM32_RCC_CFGR, cfgr);
+    cfgr &= ~CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_XXX;
+
+#if CYGNUM_DEVS_ADC_CORTEXM_STM32_CLOCK_DIV == 2
+    cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_2;
+    adc_clock = hal_stm32_pclk2 / 2;
+#elif CYGNUM_DEVS_ADC_CORTEXM_STM32_CLOCK_DIV == 4
+    cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_4;
+    adc_clock = hal_stm32_pclk2 / 4;
+#elif CYGNUM_DEVS_ADC_CORTEXM_STM32_CLOCK_DIV == 6
+    cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_6;
+    adc_clock = hal_stm32_pclk2 / 6;
+#elif CYGNUM_DEVS_ADC_CORTEXM_STM32_CLOCK_DIV == 8
+    cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_8;
+    adc_clock = hal_stm32_pclk2 / 8;
+#endif
+
+    HAL_READ_UINT32(rcc + CYGHWR_HAL_STM32_RCC_CFGR, cfgr);
+}
+
+//-----------------------------------------------------------------------------
+// Initializes an ADC device.
+
+static void
+stm32_adc_init_device(cyg_adc_device *device)
+{
+    stm32_adc_info *info = device->dev_priv;
+    cyg_uint32 cr;
+    cyg_uint64 tmp;
+    cyg_uint32 cycles;
+    cyg_uint32 smpr;
+    int i;
+    
+    static const cyg_uint32 cycles_table[] = 
+        { 15, 75, 135, 285, 415, 555, 715, 2395 };
+    
+    // Make sure ADC is powered on
+    cr = CYGHWR_HAL_STM32_ADC_CR2_ADON;
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+    
+    // Reset calibration
+    cr |= CYGHWR_HAL_STM32_ADC_CR2_RSTCAL;
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+    do {
+        HAL_READ_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+    } while (cr & CYGHWR_HAL_STM32_ADC_CR2_RSTCAL);
+    
+    // Do calibration
+    cr |= CYGHWR_HAL_STM32_ADC_CR2_CAL;
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+    do {
+        HAL_READ_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+    } while (cr & CYGHWR_HAL_STM32_ADC_CR2_CAL);
+    
+    // Power off ADC 
+    cr &= CYGHWR_HAL_STM32_ADC_CR2_ADON;
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+    
+    // Enable external triggering and DMA
+    cr |= CYGHWR_HAL_STM32_ADC_CR2_DMA |
+          CYGHWR_HAL_STM32_ADC_CR2_EXTTRIG |
+          CYGHWR_HAL_STM32_ADC_CR2_EXTSEL(info->setup->extsel);
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+    
+    // Enable scanning
+    cr = CYGHWR_HAL_STM32_ADC_CR1_SCAN;
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR1, cr);
+    
+    // Setup DMA channel
+    HAL_WRITE_UINT32(info->setup->dma_base + 
+                     CYGHWR_HAL_STM32_DMA_CPAR(info->setup->dma_channel),
+                     info->setup->adc_base + CYGHWR_HAL_STM32_ADC_DR);
+    HAL_WRITE_UINT32(info->setup->dma_base +
+                     CYGHWR_HAL_STM32_DMA_CMAR(info->setup->dma_channel),
+                     (CYG_ADDRESS) info->dma_buf);
+    HAL_WRITE_UINT32(info->setup->dma_base +
+                     CYGHWR_HAL_STM32_DMA_CNDTR(info->setup->dma_channel),
+                     0);
+    HAL_WRITE_UINT32(info->setup->dma_base +
+                     CYGHWR_HAL_STM32_DMA_CCR(info->setup->dma_channel),
+                     CYGHWR_HAL_STM32_DMA_CCR_TCIE |
+                     CYGHWR_HAL_STM32_DMA_CCR_TEIE |
+                     CYGHWR_HAL_STM32_DMA_CCR_CIRC |
+                     CYGHWR_HAL_STM32_DMA_CCR_MINC |
+                     CYGHWR_HAL_STM32_DMA_CCR_PSIZE16 |
+                     CYGHWR_HAL_STM32_DMA_CCR_MSIZE16);
+
+    // Compute duration of a single cycle in pico-seconds
+    tmp = 1000000000000LL / adc_clock;
+    // Compute tenths of cycles for target sample time
+    tmp = (info->setup->sample_time * 1000000 * 10) / tmp;
+    cycles = tmp;
+    
+    adc_diag("Setting ADC sample time to %d us (%d.%d cycles)\n",
+             info->setup->sample_time, cycles / 10, cycles % 10);
+    
+    // Find best matching SMPR value
+    if (cycles > cycles_table[7]) {
+        adc_diag("ADC sample time too long\n");
+        smpr = 7;
+    } else {
+        for (smpr = 7; smpr > 0; smpr--)
+            if (cycles > cycles_table[smpr])
+                break;
+    }
+    
+    // Expand SMPR value to all channels
+    for (i = 0; i < 10; i++)
+        smpr |= smpr << 3;
+    
+    // Set sampling time
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_SMPR1, smpr);
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_SMPR2, smpr);
+}
+
+//-----------------------------------------------------------------------------
+// Updates the sequence for the regular group. ADC and DMA are disabled during
+// the update. The sequence registers and DMA count registers are rewritten.
+// Note: As the regular group consists of 16 channels max, we cannot activate
+// the theoretical maximum of 18 channels (analog ins + temperature/VREF).
+
+static void
+stm32_adc_update_sequence(cyg_adc_device *device)
+{
+    stm32_adc_info *info = device->dev_priv;
+    int i;
+    int count = 0;
+    cyg_uint32 cr;
+    cyg_uint32 sqr1 = 0;
+    cyg_uint32 sqr2 = 0;
+    cyg_uint32 sqr3 = 0;
+    
+    adc_diag("Updateing regular group\n");
+    
+    // Disable ADC
+    HAL_READ_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+    cr &= ~CYGHWR_HAL_STM32_ADC_CR2_ADON;
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+
+    // Disable DMA
+    HAL_READ_UINT32(info->setup->dma_base +
+                    CYGHWR_HAL_STM32_DMA_CCR(info->setup->dma_channel), cr);
+    cr &= ~CYGHWR_HAL_STM32_DMA_CCR_EN;
+    HAL_WRITE_UINT32(info->setup->dma_base +
+                     CYGHWR_HAL_STM32_DMA_CCR(info->setup->dma_channel), cr);
+
+    // Initialize scanning sequence (regular group)
+    for (i = 0; i < 18; i++) {
+        if (!(info->chan_mask & (1 << i)))
+            continue;
+        
+        if (count < 6) {
+            sqr3 |= CYGHWR_HAL_STM32_ADC_SQRx_SQ(count, i);
+        } else if (count < 12) {
+            sqr2 |= CYGHWR_HAL_STM32_ADC_SQRx_SQ(count - 6, i);
+        } else if (count < 16) {
+            sqr1 |= CYGHWR_HAL_STM32_ADC_SQRx_SQ(count - 12, i);
+        } else {
+            CYG_FAIL("Too many active channels\n");
+        }
+        count++;
+    }
+    
+    sqr1 |= CYGHWR_HAL_STM32_ADC_SQR1_L(count - 1);
+    
+    adc_diag("sqr1: %p sqr2: %p sqr3: %p\n",
+             (void *) sqr1, (void *) sqr2, (void *) sqr3);
+    
+    // Write sequence registers
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_SQR1, sqr1);
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_SQR2, sqr2);
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_SQR3, sqr3);
+    
+    // Update DMA
+    HAL_WRITE_UINT32(info->setup->dma_base +
+                     CYGHWR_HAL_STM32_DMA_CNDTR(info->setup->dma_channel),
+                     count);
+    
+    // Enable DMA
+    HAL_READ_UINT32(info->setup->dma_base +
+                    CYGHWR_HAL_STM32_DMA_CCR(info->setup->dma_channel), cr);
+    cr |= CYGHWR_HAL_STM32_DMA_CCR_EN;
+    HAL_WRITE_UINT32(info->setup->dma_base +
+                     CYGHWR_HAL_STM32_DMA_CCR(info->setup->dma_channel), cr);
+    
+    // Enable ADC
+    HAL_READ_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+    cr |= CYGHWR_HAL_STM32_ADC_CR2_ADON;
+    HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr);
+}
diff --git a/packages/ecos.db b/packages/ecos.db
index b8b2613..9039f86 100644
--- a/packages/ecos.db
+++ b/packages/ecos.db
@@ -6848,6 +6857,16 @@ package CYGPKG_DEVS_WALLCLOCK_STM32 {
         STM32 controller and compatibles"
 }
 
+package CYGPKG_DEVS_ADC_CORTEXM_STM32 {
+    alias         { "STM32 ADC driver" adc_stm32 }
+    hardware
+    directory     devs/adc/cortexm/stm32
+    script        adc_stm32.cdl
+    description "
+    This package provides a driver for the ADC interfaces found on the
+    ST STM32 microcontroller family."
+}
+
 target stm3210e_eval {
         alias { "ST STM3210E EVAL board" stm3210e }
         packages { CYGPKG_HAL_CORTEXM

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]