summaryrefslogtreecommitdiff
path: root/ecos/packages/devs/adc
diff options
context:
space:
mode:
Diffstat (limited to 'ecos/packages/devs/adc')
-rw-r--r--ecos/packages/devs/adc/arm/at91/current/ChangeLog31
-rw-r--r--ecos/packages/devs/adc/arm/at91/current/cdl/adc_at91.cdl355
-rw-r--r--ecos/packages/devs/adc/arm/at91/current/include/adc_at91.inl200
-rw-r--r--ecos/packages/devs/adc/arm/at91/current/src/adc_at91.c457
-rw-r--r--ecos/packages/devs/adc/arm/at91/current/tests/at91_adc_test.c290
-rwxr-xr-xecos/packages/devs/adc/arm/lpc24xx/current/ChangeLog30
-rwxr-xr-xecos/packages/devs/adc/arm/lpc24xx/current/cdl/adc_lpc24xx.cdl160
-rwxr-xr-xecos/packages/devs/adc/arm/lpc24xx/current/src/adc_lpc24xx.c509
-rwxr-xr-xecos/packages/devs/adc/arm/lpc24xx/current/tests/lpc24xx_adc_test.c300
-rw-r--r--ecos/packages/devs/adc/cortexm/lm3s/current/ChangeLog31
-rw-r--r--ecos/packages/devs/adc/cortexm/lm3s/current/cdl/adc_lm3s.cdl217
-rw-r--r--ecos/packages/devs/adc/cortexm/lm3s/current/include/adc_lm3s.inl140
-rw-r--r--ecos/packages/devs/adc/cortexm/lm3s/current/src/adc_lm3s.c489
-rw-r--r--ecos/packages/devs/adc/cortexm/lm3s/current/tests/lm3s_adc_test.c256
-rw-r--r--ecos/packages/devs/adc/cortexm/stm32/current/ChangeLog53
-rw-r--r--ecos/packages/devs/adc/cortexm/stm32/current/cdl/adc_stm32.cdl242
-rw-r--r--ecos/packages/devs/adc/cortexm/stm32/current/src/adc1.inl163
-rw-r--r--ecos/packages/devs/adc/cortexm/stm32/current/src/adc3.inl155
-rw-r--r--ecos/packages/devs/adc/cortexm/stm32/current/src/adc_stm32.c631
-rw-r--r--ecos/packages/devs/adc/synth/current/ChangeLog35
-rw-r--r--ecos/packages/devs/adc/synth/current/cdl/adc_synth.cdl158
-rw-r--r--ecos/packages/devs/adc/synth/current/src/adc_synth.c482
22 files changed, 5384 insertions, 0 deletions
diff --git a/ecos/packages/devs/adc/arm/at91/current/ChangeLog b/ecos/packages/devs/adc/arm/at91/current/ChangeLog
new file mode 100644
index 0000000..2c3576e
--- /dev/null
+++ b/ecos/packages/devs/adc/arm/at91/current/ChangeLog
@@ -0,0 +1,31 @@
+2010-05-18 ccoutand <ccoutand@stmi.com>
+
+ * AT91 ADC driver package created
+ * cdl/adc_at91.cdl
+ * src/adc_at91.c
+ * include/adc_at91.inl
+ * tests/at91_adc_test.c
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2010 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/ecos/packages/devs/adc/arm/at91/current/cdl/adc_at91.cdl b/ecos/packages/devs/adc/arm/at91/current/cdl/adc_at91.cdl
new file mode 100644
index 0000000..14062fb
--- /dev/null
+++ b/ecos/packages/devs/adc/arm/at91/current/cdl/adc_at91.cdl
@@ -0,0 +1,355 @@
+# ====================================================================
+#
+# adc_at91.cdl
+#
+# eCos AT91 ADC configuration data
+#
+# ====================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2008 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): ccoutand@stmi.com
+# Contributors:
+# Date: 2010-02-12
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+
+cdl_package CYGPKG_DEVS_ADC_ARM_AT91 {
+ display "ADC hardware device driver for AT91 family of ARM controllers"
+
+ parent CYGPKG_IO_ADC_DEVICES
+ active_if CYGPKG_IO_ADC_DEVICES
+ active_if CYGPKG_HAL_ARM_AT91
+ description "
+ This package provides a generic ADC device driver for the on-chip
+ ADC peripherals in AT91 processors."
+
+ include_dir cyg/io
+ compile -library=libextras.a adc_at91.c
+
+ define_proc {
+ puts $::cdl_system_header "#define CYGDAT_DEVS_ADC_ARM_AT91_INL <cyg/io/adc_at91.inl>"
+ }
+
+ #
+ # Primary ADC ( ADC0 )
+ #
+ cdl_component CYGPKG_DEVS_ADC_ARM_AT91_ADC0 {
+ display "Atmel AT91 ADC port 0 driver"
+ flavor bool
+ default_value 1
+ description "
+ This option includes the device driver for the on-chip ADC 0 of the
+ AT91 processors"
+
+
+ cdl_interface CYGINT_DEVS_ADC_ARM_AT91_ADC0_CHANNELS {
+ display "Number of ADC0 channels"
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC0_SELECT_TIMER {
+ display "Interrupt priority"
+ flavor data
+ legal_values {0 1 2}
+ default_value 1
+ description "
+ This option selects the timer channel to be used for
+ generating the sampling interval. Timer channel 0 can
+ be assigned as Real Time Kernel clock so timer channel
+ 1 is set to be the default value."
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC0_PRESCAL {
+ display "ADC clock setting"
+ flavor data
+ legal_values 0 to 255
+ default_value 128
+ description "
+ This option sets the AT91 ADC PRESCAL value.
+ ADCClock = MCK / ((PRESCAL + 1) * 2)"
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC0_STARTUP_TIME {
+ display "ADC start-up time"
+ flavor data
+ legal_values 0 to 255
+ default_value 128
+ description "
+ This option sets the AT91 ADC start-up time value.
+ ADC start-up time = (STARTUP+1) * 8 / ADCClock"
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC0_SHTIM {
+ display "ADC start up time"
+ flavor data
+ legal_values 0 to 15
+ default_value 7
+ description "
+ This option sets the AT91 ADC Sample and Hold Time.
+ Sample and Hold Time = SHTIM / ADCClock"
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC0_INTPRIO {
+ display "Interrupt priority"
+ flavor data
+ legal_values 0 to 15
+ default_value 15
+ description "
+ This option selects the interrupt priority for the ADC
+ interrupts. Timer x is used for generating the sample
+ clock. So this option configures the interrupt priority
+ for timer x. There are 16 priority levels corresponding to
+ the values 0 through 15 decimal, of which 15 is the lowest
+ priority. The reset value of these registers defaults all
+ interrupts to the lowest priority, allowing a single write
+ to elevate the priority of an individual interrupt."
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC0_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."
+ }
+
+ # Support up to 8 ADC channels
+ for { set ::channel 0 } { $::channel < 8 } { incr ::channel } {
+
+ cdl_component CYGPKG_DEVS_ADC_ARM_AT91_ADC0_CHANNEL[set ::channel] {
+ display "Access ADC channel [set ::channel]"
+ flavor bool
+ default_value [set ::channel] == 0
+ implements CYGINT_DEVS_ADC_ARM_AT91_ADC0_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_ARM_AT91_ADC0_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_ARM_AT91_ADC0_CHANNEL[set ::channel]_BUFSIZE {
+ display "Size of data buffer"
+ flavor data
+ legal_values 0x01 to 0x2000000
+ default_value 512
+ description "
+ This option controls the number of samples the
+ buffer can store. The required RAM depends on the
+ sample size and on the number of samples. If the
+ sample size is <= 8 bit the the required RAM =
+ size of data buffer. If the sample size is 9 or 10
+ bit then required RAM = size of data buffer * 2."
+ }
+ }
+ }
+ }
+
+ #
+ # ADC1
+ #
+ cdl_component CYGPKG_DEVS_ADC_ARM_AT91_ADC1 {
+ display "Atmel AT91 ADC port 1 driver"
+ flavor bool
+ default_value 0
+
+ requires { CYGHWR_HAL_ARM_AT91 == "M55800A" }
+
+ description "
+ This option includes the device driver for the on-chip ADC 1 of the
+ AT91 processors"
+
+
+ cdl_interface CYGINT_DEVS_ADC_ARM_AT91_ADC1_CHANNELS {
+ display "Number of ADC1 channels"
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC1_SELECT_TIMER {
+ display "Interrupt priority"
+ flavor data
+ legal_values {0 1 2}
+ default_value 2
+ description "
+ This option selects the timer channel to be used for
+ generating the sampling interval. Timer channel 0 can
+ be assigned as Real Time Kernel clock so timer channel
+ 1 is set to be the default value."
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC1_PRESCAL {
+ display "ADC clock setting"
+ flavor data
+ legal_values 0 to 255
+ default_value 128
+ description "
+ This option sets the AT91 ADC PRESCAL value.
+ ADCClock = MCK / ((PRESCAL + 1) * 2)"
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC1_STARTUP_TIME {
+ display "ADC start-up time"
+ flavor data
+ legal_values 0 to 255
+ default_value 128
+ description "
+ This option sets the AT91 ADC start-up time value.
+ ADC start-up time = (STARTUP+1) * 8 / ADCClock"
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC1_SHTIM {
+ display "ADC start up time"
+ flavor data
+ legal_values 0 to 15
+ default_value 7
+ description "
+ This option sets the AT91 ADC Sample and Hold Time.
+ Sample and Hold Time = SHTIM / ADCClock"
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_ADC1_INTPRIO {
+ display "Interrupt priority"
+ flavor data
+ legal_values 0 to 15
+ default_value 15
+ description "
+ This option selects the interrupt priority for the ADC
+ interrupts. Timer x is used for generating the sample
+ clock. So this option configures the interrupt priority
+ for timer x. There are 16 priority levels corresponding to
+ the values 0 through 15 decimal, of which 15 is the lowest
+ priority. The reset value of these registers defaults all
+ interrupts to the lowest priority, allowing a single write
+ to elevate the priority of an individual interrupt."
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_AT91_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."
+ }
+
+ # Support up to 8 ADC channels
+ for { set ::channel 0 } { $::channel < 8 } { incr ::channel } {
+
+ cdl_component CYGPKG_DEVS_ADC_ARM_AT91_ADC1_CHANNEL[set ::channel] {
+ display "Access ADC channel [set ::channel]"
+ flavor bool
+ default_value [set ::channel] == 0
+ implements CYGINT_DEVS_ADC_ARM_AT91_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_ARM_AT91_ADC1_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_ARM_AT91_ADC1_CHANNEL[set ::channel]_BUFSIZE {
+ display "Size of data buffer"
+ flavor data
+ legal_values 0x01 to 0x2000000
+ default_value 512
+ description "
+ This option controls the number of samples the
+ buffer can store. The required RAM depends on the
+ sample size and on the number of samples. If the
+ sample size is <= 8 bit the the required RAM =
+ size of data buffer. If the sample size is 9 or 10
+ bit then required RAM = size of data buffer * 2."
+ }
+ }
+ }
+ }
+
+ cdl_option CYGPKG_DEVS_ADC_ARM_AT91_DEBUG_LEVEL {
+ display "Driver debug output level"
+ flavor data
+ legal_values {0 1}
+ default_value 0
+ description "
+ This option specifies the level of debug data output by
+ the AT91 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 CYGSEM_DEVS_ADC_ARM_AT91_SAMPLE_SIZE_LIMIT {
+ display "Sample size limit"
+ flavor bool
+ calculated 1
+ requires { ( CYGNUM_IO_ADC_SAMPLE_SIZE == 8 )
+ || ( CYGNUM_IO_ADC_SAMPLE_SIZE == 10 ) }
+ description "
+ This component forces a limit (or rounds) the sample
+ size for AT91 ADC channels which in the most are 10-bit."
+ }
+
+ cdl_option CYGPKG_DEVS_ADC_ARM_AT91_TESTS {
+ display "Tests for AT91 ADC driver"
+ flavor data
+ no_define
+ calculated { "tests/at91_adc_test" }
+ description "
+ This option specifies the set of tests for the AT91
+ ADC device driver."
+ }
+
+}
diff --git a/ecos/packages/devs/adc/arm/at91/current/include/adc_at91.inl b/ecos/packages/devs/adc/arm/at91/current/include/adc_at91.inl
new file mode 100644
index 0000000..523cbf6
--- /dev/null
+++ b/ecos/packages/devs/adc/arm/at91/current/include/adc_at91.inl
@@ -0,0 +1,200 @@
+//==========================================================================
+//
+// adc_at91.inl
+//
+// ADC driver for AT91 on chip ADC
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 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): Atmel AT91 on-chip ADC device driver, ccoutand
+//
+// Contributors:
+// Date: 2010-05-27
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#ifndef CYGONCE_DEVS_ADC_ARM_AT91_INL
+#define CYGONCE_DEVS_ADC_ARM_AT91_INL
+
+// Some AT91 HAL are defining the timer 0 vector as TC0 and other as TIMER0
+#ifndef CYGNUM_HAL_INTERRUPT_TC0
+#define CYGNUM_HAL_INTERRUPT_TC0 CYGNUM_HAL_INTERRUPT_TIMER0
+#endif
+
+// Declare ADC0
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC0
+
+static at91_adc_info at91_adc0_info =
+{
+ .adc_base = AT91_ADC,
+ .timer_base = AT91_TC,
+ .tc_base = AT91_TC + (AT91_TC_TC_SIZE * CYGNUM_DEVS_ADC_ARM_AT91_ADC0_SELECT_TIMER),
+ .timer_vector = CYGNUM_HAL_INTERRUPT_TC0 + CYGNUM_DEVS_ADC_ARM_AT91_ADC0_SELECT_TIMER,
+ .timer_intprio = CYGNUM_DEVS_ADC_ARM_AT91_ADC0_INTPRIO,
+ .timer_id = CYGNUM_DEVS_ADC_ARM_AT91_ADC0_SELECT_TIMER,
+ .int_handle = 0,
+ .adc_prescal = CYGNUM_DEVS_ADC_ARM_AT91_ADC0_PRESCAL,
+ .adc_startup_time = CYGNUM_DEVS_ADC_ARM_AT91_ADC0_STARTUP_TIME,
+ .adc_shtim = CYGNUM_DEVS_ADC_ARM_AT91_ADC0_SHTIM,
+#if CYGNUM_IO_ADC_SAMPLE_SIZE > 8
+ .resolution = AT91_ADC_MR_LOWREC_10BITS,
+#else
+ .resolution = AT91_ADC_MR_LOWRES_8BITS,
+#endif
+ .chan_mask = 0
+};
+
+CYG_ADC_DEVICE( at91_adc0_device,
+ &at91_adc_funs,
+ &at91_adc0_info,
+ CYGNUM_DEVS_ADC_ARM_AT91_ADC0_DEFAULT_RATE);
+
+#define AT91_ADC0_CHANNEL( __chan ) \
+CYG_ADC_CHANNEL( at91_adc0_channel##__chan, \
+ __chan, \
+ CYGDAT_DEVS_ADC_ARM_AT91_ADC0_CHANNEL##__chan##_BUFSIZE, \
+ &at91_adc0_device ); \
+ \
+DEVTAB_ENTRY( at91_adc0_channel##__chan##_device, \
+ CYGDAT_DEVS_ADC_ARM_AT91_ADC0_CHANNEL##__chan##_NAME, \
+ 0, \
+ &cyg_io_adc_devio, \
+ at91_adc_init, \
+ at91_adc_lookup, \
+ &at91_adc0_channel##__chan );
+
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC0_CHANNEL0
+AT91_ADC0_CHANNEL(0);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC0_CHANNEL1
+AT91_ADC0_CHANNEL(1);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC0_CHANNEL2
+AT91_ADC0_CHANNEL(2);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC0_CHANNEL3
+AT91_ADC0_CHANNEL(3);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC0_CHANNEL4
+AT91_ADC0_CHANNEL(4);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC0_CHANNEL5
+AT91_ADC0_CHANNEL(5);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC0_CHANNEL6
+AT91_ADC0_CHANNEL(6);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC0_CHANNEL7
+AT91_ADC0_CHANNEL(7);
+#endif
+
+#endif // CYGPKG_DEVS_ADC_ARM_AT91_ADC0
+
+
+
+// Declare ADC1
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC1
+
+static at91_adc_info at91_adc1_info =
+{
+ .adc_base = AT91_ADC1,
+ .timer_base = AT91_TC,
+ .tc_base = AT91_TC + (AT91_TC_TC_SIZE * CYGNUM_DEVS_ADC_ARM_AT91_ADC1_SELECT_TIMER),
+ .timer_vector = CYGNUM_HAL_INTERRUPT_TC0 + CYGNUM_DEVS_ADC_ARM_AT91_ADC1_SELECT_TIMER,
+ .timer_intprio = CYGNUM_DEVS_ADC_ARM_AT91_ADC1_INTPRIO,
+ .timer_id = CYGNUM_DEVS_ADC_ARM_AT91_ADC1_SELECT_TIMER,
+ .int_handle = 0,
+ .adc_prescal = CYGNUM_DEVS_ADC_ARM_AT91_ADC1_PRESCAL,
+ .adc_startup_time = CYGNUM_DEVS_ADC_ARM_AT91_ADC1_STARTUP_TIME,
+ .adc_shtim = CYGNUM_DEVS_ADC_ARM_AT91_ADC1_SHTIM,
+#if CYGNUM_IO_ADC_SAMPLE_SIZE > 8
+ .resolution = AT91_ADC_MR_LOWREC_10BITS,
+#else
+ .resolution = AT91_ADC_MR_LOWRES_8BITS,
+#endif
+ .chan_mask = 0
+};
+CYG_ADC_DEVICE( at91_adc1_device,
+ &at91_adc_funs,
+ &at91_adc1_info,
+ CYGNUM_DEVS_ADC_ARM_AT91_ADC1_DEFAULT_RATE);
+
+#define AT91_ADC1_CHANNEL( __chan ) \
+CYG_ADC_CHANNEL( at91_adc1_channel##__chan, \
+ __chan, \
+ CYGDAT_DEVS_ADC_ARM_AT91_ADC1_CHANNEL##__chan##_BUFSIZE, \
+ &at91_adc1_device ); \
+ \
+DEVTAB_ENTRY( at91_adc1_channel##__chan##_device, \
+ CYGDAT_DEVS_ADC_ARM_AT91_ADC1_CHANNEL##__chan##_NAME, \
+ 0, \
+ &cyg_io_adc_devio, \
+ at91_adc_init, \
+ at91_adc_lookup, \
+ &at91_adc1_channel##__chan );
+
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC1_CHANNEL0
+AT91_ADC1_CHANNEL(0);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC1_CHANNEL1
+AT91_ADC1_CHANNEL(1);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC1_CHANNEL2
+AT91_ADC1_CHANNEL(2);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC1_CHANNEL3
+AT91_ADC1_CHANNEL(3);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC1_CHANNEL4
+AT91_ADC1_CHANNEL(4);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC1_CHANNEL5
+AT91_ADC1_CHANNEL(5);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC1_CHANNEL6
+AT91_ADC1_CHANNEL(6);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_AT91_ADC1_CHANNEL7
+AT91_ADC1_CHANNEL(7);
+#endif
+
+#endif // CYGPKG_DEVS_ADC_ARM_AT91_ADC1
+
+#endif // CYGONCE_DEVS_ADC_ARM_AT91_INL
diff --git a/ecos/packages/devs/adc/arm/at91/current/src/adc_at91.c b/ecos/packages/devs/adc/arm/at91/current/src/adc_at91.c
new file mode 100644
index 0000000..6364bf1
--- /dev/null
+++ b/ecos/packages/devs/adc/arm/at91/current/src/adc_at91.c
@@ -0,0 +1,457 @@
+//==========================================================================
+//
+// adc_at91.c
+//
+// ADC driver for AT91 on chip ADC
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 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): Uwe Kindler <uwe_kindler@web.de>
+// Updated for Atmel AT91 device, ccoutand <ccoutand@stmi.com>
+// Contributors:
+// Date: 2010-02-15
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+//==========================================================================
+// INCLUDES
+//==========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/devs_adc_arm_at91.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/diag.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>
+
+#if CYGPKG_DEVS_ADC_ARM_AT91_DEBUG_LEVEL > 0
+ #define at91_adc_printf(args...) diag_printf(args)
+#else
+ #define at91_adc_printf(args...)
+#endif
+
+#define AT91_ADC_CHER_CHx(_ch_) (0x1 << _ch_)
+#define AT91_ADC_CHER_CDRx(_ch_) (_ch_ << 2)
+
+//==========================================================================
+// DATA TYPES
+//==========================================================================
+typedef struct at91_adc_info
+{
+ cyg_uint32 adc_base; // base address of ADC peripheral
+ cyg_uint8 adc_prescal; // ADC prescal value
+ cyg_uint8 adc_startup_time; // ADC Startup Time value
+ cyg_uint8 adc_shtim; // ADC SHTIM value
+ cyg_uint8 timer_id; // select timer
+ cyg_uint32 timer_base; // base address of Timer peripheral
+ cyg_uint32 tc_base; // base address of Timer channel
+ cyg_vector_t timer_vector; // interrupt vector number
+ int timer_intprio; // interrupt priority of ADC interrupt
+ cyg_uint32 timer_cnt; // Timer value
+ cyg_uint8 timer_clk; // Timer clock setting
+ cyg_uint32 resolution;
+ cyg_handle_t int_handle; // For initializing the interrupt
+ cyg_interrupt int_data;
+ struct cyg_adc_channel *channel[AT91_MAX_ADC_CHAN]; // stores references to channel objects
+ cyg_uint8 chan_mask; // mask that indicates channels used
+ // by ADC driver
+} at91_adc_info;
+
+
+//==========================================================================
+// DECLARATIONS
+//==========================================================================
+static bool at91_adc_init(struct cyg_devtab_entry *tab);
+static Cyg_ErrNo at91_adc_lookup(struct cyg_devtab_entry **tab,
+ struct cyg_devtab_entry *sub_tab,
+ const char *name);
+static void at91_adc_enable( cyg_adc_channel *chan );
+static void at91_adc_disable( cyg_adc_channel *chan );
+static void at91_adc_set_rate( cyg_adc_channel *chan, cyg_uint32 rate );
+static cyg_uint32 at91_adc_isr(cyg_vector_t vector, cyg_addrword_t data);
+static void at91_adc_dsr(cyg_vector_t vector,
+ cyg_ucount32 count,
+ cyg_addrword_t data);
+
+// -------------------------------------------------------------------------
+// Driver functions:
+CYG_ADC_FUNCTIONS( at91_adc_funs,
+ at91_adc_enable,
+ at91_adc_disable,
+ at91_adc_set_rate );
+
+
+#include CYGDAT_DEVS_ADC_ARM_AT91_INL // Instantiate ADCs
+
+//==========================================================================
+// 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 at91_adc_init(struct cyg_devtab_entry *tab)
+{
+ cyg_adc_channel *chan = (cyg_adc_channel *)tab->priv;
+ cyg_adc_device *device = chan->device;
+ at91_adc_info *info = device->dev_priv;
+ cyg_uint32 regval;
+
+ if (!info->int_handle)
+ {
+ cyg_drv_interrupt_create(info->timer_vector,
+ info->timer_intprio,
+ (cyg_addrword_t)device,
+ &at91_adc_isr,
+ &at91_adc_dsr,
+ &(info->int_handle),
+ &(info->int_data));
+ cyg_drv_interrupt_attach(info->int_handle);
+ cyg_drv_interrupt_mask(info->timer_vector);
+
+ // Reset ADC
+ HAL_WRITE_UINT32((info->adc_base + AT91_ADC_CR), AT91_ADC_CR_SWRST);
+
+ // Disable counter interrupts
+ HAL_WRITE_UINT32(info->tc_base+AT91_TC_CCR, AT91_TC_CCR_CLKDIS);
+ HAL_WRITE_UINT32(info->tc_base+AT91_TC_IDR, 0xffffffff);
+
+ // Clear status bit
+ HAL_READ_UINT32(info->tc_base + AT91_TC_SR, regval);
+
+ // Enable peripheral clocks for TC
+ HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, \
+ ((AT91_PMC_PCER_TC0) << info->timer_id));
+
+ //
+ // Disable all interrupts, all channels
+ //
+ HAL_WRITE_UINT32((info->adc_base + AT91_ADC_CHDR), \
+ AT91_ADC_CHER_CH0 |\
+ AT91_ADC_CHER_CH1 |\
+ AT91_ADC_CHER_CH2 |\
+ AT91_ADC_CHER_CH3 |\
+ AT91_ADC_CHER_CH4 |\
+ AT91_ADC_CHER_CH5 |\
+ AT91_ADC_CHER_CH6 |\
+ AT91_ADC_CHER_CH7);
+ HAL_WRITE_UINT32((info->adc_base + AT91_ADC_IDR), \
+ AT91_ADC_CHER_CH0 |\
+ AT91_ADC_CHER_CH1 |\
+ AT91_ADC_CHER_CH2 |\
+ AT91_ADC_CHER_CH3 |\
+ AT91_ADC_CHER_CH4 |\
+ AT91_ADC_CHER_CH5 |\
+ AT91_ADC_CHER_CH6 |\
+ AT91_ADC_CHER_CH7);
+
+ //
+ // setup the default sample rate
+ //
+ at91_adc_set_rate(chan, chan->device->config.rate);
+
+ // setup ADC mode
+ HAL_WRITE_UINT32((info->adc_base + AT91_ADC_MR), \
+ ( ( info->adc_prescal << AT91_ADC_MR_PRESCAL_SHIFT ) & \
+ AT91_ADC_MR_PRESCAL_MASK ) | \
+ ( ( info->adc_startup_time << AT91_ADC_MR_STARTUP_SHIFT ) & \
+ AT91_ADC_MR_STARTUP_MASK ) | \
+ ( ( info->adc_shtim << AT91_ADC_MR_SHTIM_SHIFT ) & \
+ AT91_ADC_MR_SHTIM_MASK ) | \
+ AT91_ADC_MR_TRGSEL_TIOA0 | \
+ info->resolution);
+
+
+ } // if (!info->int_handle)
+
+ cyg_adc_device_init(device); // initialize generic parts of driver
+
+ 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 at91_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;
+ at91_adc_info *info = chan->device->dev_priv;
+
+ info->channel[chan->channel] = chan;
+ cyg_adc_channel_init(chan); // initialize generic parts of channel
+
+ //
+ // 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;
+ at91_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 at91_adc_enable(cyg_adc_channel *chan)
+{
+ at91_adc_info *info = chan->device->dev_priv;
+
+ // Enable the channel
+ HAL_WRITE_UINT32((info->adc_base + AT91_ADC_CHER), \
+ AT91_ADC_CHER_CHx(chan->channel));
+
+ //
+ // Unmask interrupt as soon as 1 channel is enable
+ //
+ if (!info->chan_mask)
+ {
+ cyg_drv_interrupt_unmask(info->timer_vector);
+
+ // Enable timer interrupt
+ HAL_WRITE_UINT32(info->tc_base+AT91_TC_IER, AT91_TC_IER_CPC);
+
+ // Enable the clock
+ HAL_WRITE_UINT32(info->tc_base+AT91_TC_CCR, AT91_TC_CCR_TRIG | AT91_TC_CCR_CLKEN);
+
+ // Start timer
+ HAL_WRITE_UINT32(info->tc_base+AT91_TC_CCR, AT91_TC_CCR_TRIG);
+
+ // Start ADC sampling
+ HAL_WRITE_UINT32((info->adc_base + AT91_ADC_CR), AT91_ADC_CR_START);
+
+ }
+
+ info->chan_mask |= AT91_ADC_CHER_CHx(chan->channel);
+
+}
+
+
+//==========================================================================
+// 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 at91_adc_disable(cyg_adc_channel *chan)
+{
+ at91_adc_info *info = chan->device->dev_priv;
+ cyg_uint32 sr;
+
+ info->chan_mask &= ~ AT91_ADC_CHER_CHx(chan->channel);
+
+ // Disable the channel
+ HAL_WRITE_UINT32((info->adc_base + AT91_ADC_CHDR), \
+ AT91_ADC_CHER_CHx(chan->channel));
+
+ //
+ // If no channel is enabled the we disable interrupts now
+ //
+ if (!info->chan_mask)
+ {
+ cyg_drv_interrupt_mask(info->timer_vector);
+
+ // Clear interrupt
+ HAL_READ_UINT32(info->tc_base+AT91_TC_SR, sr);
+
+ // Disable timer interrupt
+ HAL_WRITE_UINT32(info->tc_base+AT91_TC_IDR, AT91_TC_IER_CPC);
+
+ // Disable the clock
+ HAL_WRITE_UINT32(info->tc_base+AT91_TC_CCR, AT91_TC_CCR_CLKDIS);
+
+ }
+}
+
+
+//==========================================================================
+// 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 at91_adc_set_rate( cyg_adc_channel *chan, cyg_uint32 rate)
+{
+ cyg_adc_device *device = chan->device;
+ at91_adc_info *info = (at91_adc_info *)device->dev_priv;
+ cyg_uint8 timer_clk = AT91_TC_CMR_CLKS_MCK2;
+ cyg_uint32 tmr_period = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / ( rate << 1);
+
+ if( tmr_period > 0xffff )
+ {
+ tmr_period = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / ( rate << 5);
+ timer_clk = AT91_TC_CMR_CLKS_MCK32;
+ }
+
+ if( tmr_period > 0xffff )
+ {
+ tmr_period = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / ( rate << 7);
+ timer_clk = AT91_TC_CMR_CLKS_MCK128;
+ }
+
+ if( tmr_period > 0xffff )
+ {
+ tmr_period = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / ( rate << 10);
+ timer_clk = AT91_TC_CMR_CLKS_MCK1024;
+ }
+
+ if( tmr_period > 0xffff )
+ {
+ tmr_period = 0xffff;
+ timer_clk = AT91_TC_CMR_CLKS_MCK1024;
+ at91_adc_printf("AT91 ADC timer, rate too high!");
+ }
+
+ device->config.rate = rate;
+ info->timer_clk = timer_clk;
+ info->timer_cnt = tmr_period;
+
+ // Set timer values
+ HAL_WRITE_UINT32(info->tc_base+AT91_TC_CMR, AT91_TC_CMR_CPCTRG | info->timer_clk);
+ HAL_WRITE_UINT32(info->tc_base+AT91_TC_RC, info->timer_cnt);
+
+ at91_adc_printf("AT91 ADC Timer settings %d, %d", info->timer_clk, info->timer_cnt);
+
+ return;
+}
+
+
+//==========================================================================
+// This function is the ISR attached to the ADC device's interrupt vector.
+// It is responsible for reading samples from the channels and passing them
+// on to the generic layer. It needs to check each channel for data, and call
+// cyg_adc_receive_sample() for each new sample available, and then ready the
+// device for the next interrupt.
+//==========================================================================
+static cyg_uint32 at91_adc_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+ cyg_adc_device *device = (cyg_adc_device *) data;
+ at91_adc_info *info = (at91_adc_info *)device->dev_priv;
+ cyg_uint32 regval, adc_status;
+ cyg_uint32 res = 0;
+ cyg_adc_sample_t adcdata;
+ cyg_uint32 sr;
+
+ cyg_uint8 active_channels = info->chan_mask;
+ cyg_uint8 channel_no = 0;
+
+ // Clear timer interrupt
+ HAL_READ_UINT32(info->tc_base+AT91_TC_SR, sr);
+
+ // Check on channel conversion done
+ HAL_READ_UINT32(info->adc_base + AT91_ADC_SR, adc_status);
+
+ while (active_channels)
+ {
+ if (active_channels & 0x01)
+ {
+ // If ADC conversion done, save sample
+ if(adc_status & AT91_ADC_CHER_CHx(channel_no))
+ {
+ HAL_READ_UINT32((info->adc_base + AT91_ADC_CDR0 + AT91_ADC_CHER_CDRx(channel_no)), regval);
+ adcdata = regval & 0x3FF;
+ res |= CYG_ISR_HANDLED
+ | cyg_adc_receive_sample(info->channel[channel_no],
+ adcdata);
+ }
+ } // if (active_channels & 0x01)
+ active_channels >>= 1;
+ channel_no++;
+ } // while (active_channels)
+
+ // Restart sampling
+ HAL_WRITE_UINT32((info->adc_base + AT91_ADC_CR), AT91_ADC_CR_START);
+
+ cyg_drv_interrupt_acknowledge(info->timer_vector);
+
+ return res;
+}
+
+
+//==========================================================================
+// This function is the DSR attached to the ADC device's interrupt vector.
+// It is called by the kernel if the ISR return value contains the
+// CYG_ISR_HANDLED bit. It needs to call cyg_adc_wakeup() for each channel
+// that has its wakeup field set.
+//==========================================================================
+static void at91_adc_dsr(cyg_vector_t vector,
+ cyg_ucount32 count,
+ cyg_addrword_t data)
+{
+ cyg_adc_device *device = (cyg_adc_device *) data;
+ at91_adc_info *info = device->dev_priv;
+ cyg_uint8 active_channels = info->chan_mask;
+ cyg_uint8 chan_no = 0;
+
+ while (active_channels)
+ {
+ if (active_channels & 0x01)
+ {
+ if(info->channel[chan_no]->wakeup)
+ {
+ cyg_adc_wakeup(info->channel[chan_no]);
+ }
+ }
+ chan_no++;
+ active_channels >>= 1;
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// eof adc_at91.c
diff --git a/ecos/packages/devs/adc/arm/at91/current/tests/at91_adc_test.c b/ecos/packages/devs/adc/arm/at91/current/tests/at91_adc_test.c
new file mode 100644
index 0000000..9199b04
--- /dev/null
+++ b/ecos/packages/devs/adc/arm/at91/current/tests/at91_adc_test.c
@@ -0,0 +1,290 @@
+//==========================================================================
+//
+// at91_adc_test.c
+//
+// ADC driver for AT91 on chip ADC
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 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): Uwe Kindler <uwe_kindler@web.de>
+// Updated for Atmel AT91 device, ccoutand <ccoutand@stmi.com>
+// Contributors:
+// Date: 2010-02-15
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h> // test macros
+#include <cyg/infra/cyg_ass.h> // assertion macros
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_diag.h>
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+
+// Package requirements
+#if defined(CYGPKG_IO_ADC) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/adc.h>
+#include <pkgconf/devs_adc_arm_at91.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/kernel/kapi.h>
+
+#if CYGINT_DEVS_ADC_ARM_AT91_ADC0_CHANNELS > 0
+
+#define MAX_ADC_CHANNEL_TO_TEST 4
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+ cyg_thread obj;
+ long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+ cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+// LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t adc_thread;
+thread_data_t adc_thread_data;
+
+
+//===========================================================================
+// ADC THREAD
+//===========================================================================
+void adc_thread(cyg_addrword_t data)
+{
+ int res;
+ cyg_io_handle_t handle[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ cyg_uint32 sample_cnt[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ cyg_uint32 cfg_data;
+ cyg_uint32 len;
+ cyg_uint32 start_time;
+ cyg_uint32 end_time;
+ int i;
+ cyg_uint8 seconds = 0;
+ float final_seconds;
+ cyg_uint32 samples_expected;
+
+
+ diag_printf("This test reads samples from all enabled ADC channels.\n"
+ "Each second the number of already acquired samples\n"
+ "will be printed. After 10 seconds all ADC channels\n"
+ "will be stopped and each ADC buffer will be read until\n"
+ "it is empty. If the number of acquired samples is much\n"
+ "smaller than the number of expected samples, then you\n"
+ "should lower the sample rate.\n\n");
+
+ // Get a handle for ADC device 0 channel 0 - 3 (lookup also trigger a channel enable)
+ res = cyg_io_lookup( "/dev/adc00", &handle[0]);
+ res = cyg_io_lookup( "/dev/adc01", &handle[1]);
+ res = cyg_io_lookup( "/dev/adc02", &handle[2]);
+ res = cyg_io_lookup( "/dev/adc03", &handle[3]);
+
+ //
+ // switch all channels to non blocking
+ //
+ for (i = 0; i < MAX_ADC_CHANNEL_TO_TEST; ++i)
+ {
+ if (handle[i])
+ {
+ cfg_data = 0;
+ len = sizeof(cfg_data);
+ res = cyg_io_set_config(handle[i],
+ CYG_IO_SET_CONFIG_READ_BLOCKING,
+ &cfg_data,
+ &len);
+ if (ENOERR != res)
+ {
+ CYG_TEST_FAIL_FINISH("Error switching ADC channel to non blocking");
+ }
+ sample_cnt[i] = 0;
+ }
+ }
+
+ start_time = cyg_current_time();
+ do
+ {
+ for (i = 0; i < MAX_ADC_CHANNEL_TO_TEST; ++i)
+ {
+ if (handle[i])
+ {
+ cyg_adc_sample_t sample;
+
+ // read a sample from the channel
+ do
+ {
+ cyg_uint32 len = sizeof(sample);
+ res = cyg_io_read( handle[i], &sample, &len );
+ }
+ while (-EAGAIN == res);
+ if (ENOERR == res)
+ {
+ sample_cnt[i]++;
+ }
+ } // if (handle[i])
+ }
+ //
+ // print number of acquired samples - if one second is expired.
+ // we expect that the number of acquired samples is nearly the
+ // sample rate
+ //
+ end_time = cyg_current_time();
+ if ((end_time - start_time) >= 100)
+ {
+ start_time = end_time;
+ diag_printf("%d\t %d\t %d\t %d\n",
+ sample_cnt[0],
+ sample_cnt[1],
+ sample_cnt[2],
+ sample_cnt[3]);
+ seconds++;
+ } // if ((end_time - start_time) >= 100)
+ } while (seconds < 10);
+
+ //
+ // Now stop all channels
+ //
+ for (i = 0; i < MAX_ADC_CHANNEL_TO_TEST; ++i)
+ {
+ if (handle[i])
+ {
+ res = cyg_io_set_config(handle[i],
+ CYG_IO_SET_CONFIG_ADC_DISABLE,
+ 0,
+ 0);
+ if (ENOERR != res)
+ {
+ CYG_TEST_FAIL_FINISH("Error disabling ADC channel");
+ }
+ } // if (handle[i])
+ }
+ end_time = cyg_current_time();
+ end_time = seconds * 1000 + (end_time - start_time) * 10;
+ final_seconds = end_time / 1000.0;
+
+ //
+ // Now read all remaining samples from buffer
+ //
+ for (i = 0; i < MAX_ADC_CHANNEL_TO_TEST; ++i)
+ {
+ if (handle[i])
+ {
+ do
+ {
+ cyg_adc_sample_t sample;
+ cyg_uint32 len = sizeof(sample);
+ res = cyg_io_read( handle[i], &sample, &len );
+ if (ENOERR == res)
+ {
+ sample_cnt[i]++;
+ }
+ } while (ENOERR == res);
+ } // if (handle[i])
+ }
+
+ diag_printf("\n\n----------------------------------------\n");
+ samples_expected = final_seconds * CYGNUM_DEVS_ADC_ARM_AT91_ADC0_DEFAULT_RATE;
+ diag_printf("Samples expected after %d milliseconds: %d\n",
+ end_time, samples_expected);
+ diag_printf("Samples read (per channel):\n");
+ diag_printf("%d\t %d\t %d\t %d\n",
+ sample_cnt[0],
+ sample_cnt[1],
+ sample_cnt[2],
+ sample_cnt[3]);
+
+ CYG_TEST_PASS_FINISH("ADC test OK");
+}
+
+
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+
+ //
+ // create the main ADC test thread
+ //
+ cyg_thread_create(4, adc_thread,
+ (cyg_addrword_t) 0,
+ "at91_adc_thread",
+ (void *) adc_thread_data.stack,
+ 1024 * sizeof(long),
+ &adc_thread_data.hdl,
+ &adc_thread_data.obj);
+
+ cyg_thread_resume(adc_thread_data.hdl);
+
+ cyg_scheduler_start();
+}
+#else // CYGINT_DEVS_ADC_ARM_AT91_CHANNELS > 0
+#define N_A_MSG "Needs at least one enabled ADC channel"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_ADC && CYGPKG_KERNEL
+#define N_A_MSG "Needs Kernel and ADC support"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA(N_A_MSG);
+}
+#endif // N_A_MSG
+
+
+// EOF can_tx.c
+
+//---------------------------------------------------------------------------
+// eof at91_adc_test.c
diff --git a/ecos/packages/devs/adc/arm/lpc24xx/current/ChangeLog b/ecos/packages/devs/adc/arm/lpc24xx/current/ChangeLog
new file mode 100755
index 0000000..b2b727f
--- /dev/null
+++ b/ecos/packages/devs/adc/arm/lpc24xx/current/ChangeLog
@@ -0,0 +1,30 @@
+2008-11-01 Uwe Kindler <uwe_kindler@web.de>
+
+ * LPC24xx ADC driver package created
+ * cdl/adc_lpc24xx.cdl
+ * src/adc_lpc24xx.c
+ * tests/lpc24xx_adc_test.c
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 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/ecos/packages/devs/adc/arm/lpc24xx/current/cdl/adc_lpc24xx.cdl b/ecos/packages/devs/adc/arm/lpc24xx/current/cdl/adc_lpc24xx.cdl
new file mode 100755
index 0000000..75c737d
--- /dev/null
+++ b/ecos/packages/devs/adc/arm/lpc24xx/current/cdl/adc_lpc24xx.cdl
@@ -0,0 +1,160 @@
+# ====================================================================
+#
+# adc_lpc24xx.cdl
+#
+# eCos LPC24xx ADC configuration data
+#
+# ====================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2008 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): Uwe Kindler <uwe_kindler@web.de>
+# Contributors:
+# Date: 2008-09-24
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+
+cdl_package CYGPKG_DEVS_ADC_ARM_LPC24XX {
+ display "ADC hardware device driver for LPC24xx family of ARM controllers"
+
+ parent CYGPKG_IO_ADC_DEVICES
+ active_if CYGPKG_IO_ADC_DEVICES
+ active_if CYGPKG_HAL_ARM_LPC24XX
+ requires {CYGNUM_IO_ADC_SAMPLE_SIZE <= 10}
+ requires {CYGNUM_IO_ADC_SAMPLE_SIZE >= 3}
+ description "
+ This package provides a generic ADC device driver for the on-chip
+ ADC peripherals in LPX24xx processors."
+
+ include_dir cyg/io
+ compile -library=libextras.a adc_lpc24xx.c
+
+ cdl_interface CYGINT_DEVS_ADC_ARM_LPC24XX_CHANNELS {
+ display "Number of ADC channels"
+ }
+
+ cdl_option CYGPKG_DEVS_ADC_ARM_LPC24XX_DEBUG_LEVEL {
+ display "Driver debug output level"
+ flavor data
+ legal_values {0 1 2}
+ default_value 0
+ description "
+ This option specifies the level of debug data output by
+ the LPC24XX 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_option CYGNUM_DEVS_ADC_ARM_LPC24XX_INTPRIO {
+ display "Interrupt priority"
+ flavor data
+ legal_values 0 to 15
+ default_value 15
+ description "
+ This option selects the interrupt priority for the ADC
+ interrupts. Timer 1 is used for generating the sample
+ clock. So this option configures the interrupt priority
+ for timer 1. There are 16 priority levels corresponding to
+ the values 0 through 15 decimal, of which 15 is the lowest
+ priority. The reset value of these registers defaults all
+ interrupts to the lowest priority, allowing a single write
+ to elevate the priority of an individual interrupt."
+ }
+
+
+ cdl_option CYGNUM_DEVS_ADC_ARM_LPC24XX_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."
+ }
+
+ # Support up to 8 ADC channels
+ for { set ::channel 0 } { $::channel < 8 } { incr ::channel } {
+
+ cdl_component CYGPKG_DEVS_ADC_ARM_LPC24XX_CHANNEL[set ::channel] {
+ display "Access ADC channel [set ::channel]"
+ flavor bool
+ default_value [set ::channel] == 0
+ implements CYGINT_DEVS_ADC_ARM_LPC24XX_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_ARM_LPC24XX_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_ARM_LPC24XX_CHANNEL[set ::channel]_BUFSIZE {
+ display "Size of data buffer"
+ flavor data
+ legal_values 0x01 to 0x2000000
+ default_value 512
+ description "
+ This option controls the number of samples the
+ buffer can store. The required RAM depends on the
+ sample size and on the number of samples. If the
+ sample size is <= 8 bit the the required RAM =
+ size of data buffer. If the sample size is 9 or 10
+ bit then required RAM = size of data buffer * 2."
+ }
+ }
+ }
+
+ cdl_option CYGPKG_DEVS_ADC_ARM_LPC24XX_TESTS {
+ display "Tests for LPC24xx ADC driver"
+ flavor data
+ no_define
+ calculated { "tests/lpc24xx_adc_test" }
+ description "
+ This option specifies the set of tests for the LPC24xx
+ ADC device driver."
+ }
+
+}
diff --git a/ecos/packages/devs/adc/arm/lpc24xx/current/src/adc_lpc24xx.c b/ecos/packages/devs/adc/arm/lpc24xx/current/src/adc_lpc24xx.c
new file mode 100755
index 0000000..5f8863f
--- /dev/null
+++ b/ecos/packages/devs/adc/arm/lpc24xx/current/src/adc_lpc24xx.c
@@ -0,0 +1,509 @@
+//==========================================================================
+//
+// adc_lpc24xx.c
+//
+// ADC driver for LPC24xx on chip ADC
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 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): Uwe Kindler <uwe_kindler@web.de>
+// Contributors:
+// Date: 2008-09-21
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+//==========================================================================
+// INCLUDES
+//==========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/devs_adc_arm_lpc24xx.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/diag.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>
+
+
+
+//==========================================================================
+// DEFINES
+//==========================================================================
+
+//--------------------------------------------------------------------------
+// Register definition
+//
+#define ADC_BASE CYGARC_HAL_LPC24XX_REG_AD_BASE
+#define ADC_CR (ADC_BASE + 0x0000)
+#define ADC_GDR (ADC_BASE + 0x0004)
+#define ADC_INTEN (ADC_BASE + 0x000C)
+#define ADC_DR(_chan_) (ADC_BASE + 0x0010 + ((_chan_) << 2))
+#define ADC_STAT (ADC_BASE + 0x0030)
+
+#define DR_OVR (0x01 << 30)
+#define DR_DONE (0x01 << 31)
+#define CR_BURST (0x01 << 16)
+#define CR_PDN (0x01 << 21)
+
+
+#if CYGPKG_DEVS_ADC_ARM_LPC24XX_DEBUG_LEVEL > 0
+ #define debug1_printf(args...) diag_printf(args)
+#else
+ #define debug1_printf(args...)
+#endif
+
+#define LPC2XXX_CHAN_CNT 8 // maximum number of channels for LPC2xxx device
+
+
+//==========================================================================
+// DATA TYPES
+//==========================================================================
+typedef struct lpc2xxx_adc_info
+{
+ cyg_uint32 base; // base address of ADC peripheral
+ cyg_vector_t vector; // interrupt vector number
+ int intprio; // interrupt priority of ADC interrupt
+ cyg_handle_t int_handle; // For initializing the interrupt
+ cyg_interrupt int_data;
+ struct cyg_adc_channel* channel[LPC2XXX_CHAN_CNT]; // stores references to
+ // channel objects
+#if CYGPKG_DEVS_ADC_ARM_LPC24XX_DEBUG_LEVEL > 1
+ cyg_uint32 isr_cnt; // number of ISR = number of samples
+ cyg_uint32 zero_time;
+#endif // CYGPKG_DEVS_ADC_ARM_LPC24XX_DEBUG_LEVEL > 1
+ cyg_uint8 chan_mask; // mask that indicates channels used
+ // by ADC driver
+} lpc2xxx_adc_info;
+
+
+//==========================================================================
+// DECLARATIONS
+//==========================================================================
+static bool lpc2xxx_adc_init(struct cyg_devtab_entry *tab);
+static Cyg_ErrNo lpc2xxx_adc_lookup(struct cyg_devtab_entry **tab,
+ struct cyg_devtab_entry *sub_tab,
+ const char *name);
+static void lpc2xxx_adc_enable( cyg_adc_channel *chan );
+static void lpc2xxx_adc_disable( cyg_adc_channel *chan );
+static void lpc2xxx_adc_set_rate( cyg_adc_channel *chan, cyg_uint32 rate );
+static cyg_uint32 lpc2xxx_adc_isr(cyg_vector_t vector, cyg_addrword_t data);
+static void lpc2xxx_adc_dsr(cyg_vector_t vector,
+ cyg_ucount32 count,
+ cyg_addrword_t data);
+
+
+//==========================================================================
+// Instantiate data structures
+
+// -------------------------------------------------------------------------
+// Driver functions:
+CYG_ADC_FUNCTIONS( lpc2xxx_adc_funs,
+ lpc2xxx_adc_enable,
+ lpc2xxx_adc_disable,
+ lpc2xxx_adc_set_rate );
+
+// -------------------------------------------------------------------------
+// Device instance:
+static lpc2xxx_adc_info lpc2xxx_adc_info0 =
+{
+ .base = CYGARC_HAL_LPC2XXX_REG_AD_BASE,
+ .vector = CYGNUM_HAL_INTERRUPT_TIMER1,
+ .intprio = CYGNUM_DEVS_ADC_ARM_LPC24XX_INTPRIO,
+ .int_handle = 0,
+#if CYGPKG_DEVS_ADC_ARM_LPC24XX_DEBUG_LEVEL > 0
+ .isr_cnt = 0,
+#endif
+ .chan_mask = 0
+};
+
+CYG_ADC_DEVICE( lpc2xxx_adc_device,
+ &lpc2xxx_adc_funs,
+ &lpc2xxx_adc_info0,
+ CYGNUM_DEVS_ADC_ARM_LPC24XX_DEFAULT_RATE);
+
+// -------------------------------------------------------------------------
+// Channel instances:
+
+#define LPC2XXX_ADC_CHANNEL( __chan ) \
+CYG_ADC_CHANNEL( lpc2xxx_adc_channel##__chan, \
+ __chan, \
+ CYGDAT_DEVS_ADC_ARM_LPC24XX_CHANNEL##__chan##_BUFSIZE, \
+ &lpc2xxx_adc_device ); \
+ \
+DEVTAB_ENTRY( lpc2xxx_adc_channel##__chan##_device, \
+ CYGDAT_DEVS_ADC_ARM_LPC24XX_CHANNEL##__chan##_NAME, \
+ 0, \
+ &cyg_io_adc_devio, \
+ lpc2xxx_adc_init, \
+ lpc2xxx_adc_lookup, \
+ &lpc2xxx_adc_channel##__chan );
+
+#ifdef CYGPKG_DEVS_ADC_ARM_LPC24XX_CHANNEL0
+LPC2XXX_ADC_CHANNEL(0);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_LPC24XX_CHANNEL1
+LPC2XXX_ADC_CHANNEL(1);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_LPC24XX_CHANNEL2
+LPC2XXX_ADC_CHANNEL(2);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_LPC24XX_CHANNEL3
+LPC2XXX_ADC_CHANNEL(3);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_LPC24XX_CHANNEL4
+LPC2XXX_ADC_CHANNEL(4);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_LPC24XX_CHANNEL5
+LPC2XXX_ADC_CHANNEL(5);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_LPC24XX_CHANNEL6
+LPC2XXX_ADC_CHANNEL(6);
+#endif
+#ifdef CYGPKG_DEVS_ADC_ARM_LPC24XX_CHANNEL7
+LPC2XXX_ADC_CHANNEL(7);
+#endif
+
+//==========================================================================
+// 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 lpc2xxx_adc_init(struct cyg_devtab_entry *tab)
+{
+ cyg_adc_channel *chan = (cyg_adc_channel *)tab->priv;
+ cyg_adc_device *device = chan->device;
+ lpc2xxx_adc_info *info = device->dev_priv;
+
+ if (!info->int_handle)
+ {
+ cyg_drv_interrupt_create(info->vector,
+ info->intprio,
+ (cyg_addrword_t)device,
+ &lpc2xxx_adc_isr,
+ &lpc2xxx_adc_dsr,
+ &(info->int_handle),
+ &(info->int_data));
+ cyg_drv_interrupt_attach(info->int_handle);
+ cyg_drv_interrupt_unmask(info->vector);
+
+ //
+ // The APB clock (PCLK) is divided by (this value plus one) to produce
+ // the clock for the A/D converter, which should be less than or equal
+ // to 4.5 MHz. Typically, software should program the smallest value in
+ // this field that yields a clock of 4.5 MHz or slightly less, but in
+ // certain cases (such as a high-impedance analog source) a slower
+ // clock may be desirable.
+ // Set clock division factor so ADC clock is <= 4.5 MHz
+ //
+ cyg_uint8 clkdiv = CYGNUM_HAL_ARM_LPC24XX_ADC_CLK / 4500001;
+
+ //
+ // Enable A/D converter and setup the configured sample size
+ // The eCos ADC I/O manual says: Channels are initialized in a disabled
+ // state and generate no samples - let's do this now
+ // We initialize the device to operate in burst mode and we enable
+ // conversion for all channels here
+ //
+ HAL_WRITE_UINT32(ADC_INTEN, 0); // disables all interrupts
+ HAL_WRITE_UINT32(ADC_CR, CR_BURST // burst mode
+ | CR_PDN // A/D converter is operational
+ | 0xFF // enable all channels
+ | ((10 - CYGNUM_IO_ADC_SAMPLE_SIZE) << 17)
+ | (clkdiv << 8));// set clock divider
+
+ //
+ // setup the default sample rate
+ //
+ lpc2xxx_adc_set_rate(chan, chan->device->config.rate);
+ } // if (!info->int_handle)
+
+ cyg_adc_device_init(device); // initialize generic parts of driver
+ 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 lpc2xxx_adc_lookup(struct cyg_devtab_entry **tab,
+ struct cyg_devtab_entry *sub_tab,
+ const char *name)
+{
+ typedef struct adc_pin_cfg_st
+ {
+ cyg_uint8 port;
+ cyg_uint8 pin;
+ cyg_uint8 func;
+ } adc_pin_cfg_t;
+ static const adc_pin_cfg_t acd_pin_cfg_tbl[] =
+ {
+ {0, 23, 1},
+ {0, 24, 1},
+ {0, 25, 1},
+ {0, 26, 1},
+ {1, 30, 3},
+ {1, 31, 3},
+ {0, 12, 3},
+ {0, 13, 3},
+ };
+ cyg_adc_channel *chan = (cyg_adc_channel *)(*tab)->priv;
+ lpc2xxx_adc_info *info = chan->device->dev_priv;
+ adc_pin_cfg_t *pin_cfg = (adc_pin_cfg_t *)&acd_pin_cfg_tbl[chan->channel];
+
+ //
+ // This ADC driver is quite LP24xx specific. The pin function of each pin
+ // is well defined in the LP24xx specification. Therefore we can setup
+ // the pin function here. If someone decides that this driver can be used
+ // by other LPC2xxx or LPC3xxx variants too and that the driver should
+ // become more generic, then we might need to move the pin configuration
+ // out of this driver an into the variant / platform HAL
+ //
+ CYG_HAL_ARM_LPC24XX_PIN_CFG(pin_cfg->port, pin_cfg->pin, pin_cfg->func);
+ info->channel[chan->channel] = chan;
+ cyg_adc_channel_init(chan); // initialize generic parts of channel
+
+ //
+ // 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;
+ lpc2xxx_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 lpc2xxx_adc_enable(cyg_adc_channel *chan)
+{
+ cyg_uint32 regval;
+ lpc2xxx_adc_info *info = chan->device->dev_priv;
+
+ //
+ // Enable interrupts for timer to start generation of samples in timer
+ // ISR if this is the first channel that is enabled. If there are
+ // already some channels enabled, then the interrupt is already enabled
+ //
+ if (!info->chan_mask)
+ {
+ HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxMCR, regval);
+#if CYGPKG_DEVS_ADC_ARM_LPC24XX_DEBUG_LEVEL > 0
+ info->zero_time = cyg_current_time() * 10;
+#endif
+ regval |= CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_INT;
+ HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxMCR, regval);
+ }
+
+ info->chan_mask |= (0x01 << chan->channel);
+}
+
+
+//==========================================================================
+// 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 lpc2xxx_adc_disable(cyg_adc_channel *chan)
+{
+ cyg_uint32 regval;
+ lpc2xxx_adc_info *info = chan->device->dev_priv;
+
+ info->chan_mask &= ~(0x01 << chan->channel);
+
+ //
+ // If no channel is enabled the we disable interrupts now
+ //
+ if (!info->chan_mask)
+ {
+ HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxMCR, regval);
+ regval &= ~CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_INT;
+ HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxMCR, regval);
+ }
+}
+
+
+//==========================================================================
+// 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 lpc2xxx_adc_set_rate( cyg_adc_channel *chan, cyg_uint32 rate)
+{
+ cyg_adc_device *device = chan->device;
+ cyg_uint32 regval;
+
+ cyg_uint32 tmr_period = hal_lpc_get_pclk(CYNUM_HAL_LPC24XX_PCLK_TIMER1) /
+ rate;
+ device->config.rate = rate;
+
+ //
+ // Disable and reset counter, set prescale register to 0 and
+ // Set up match register
+ //
+ HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxTCR,
+ CYGARC_HAL_LPC24XX_REG_TxTCR_CTR_RESET);
+ HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxPR, 0);
+ HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxMR0, tmr_period);
+ //
+ // Reset on match and Enable counter
+ //
+ HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxMCR, regval);
+ regval |= CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_RESET; // reset on match
+ regval &= ~CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_STOP; // do not stop on match
+ HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxMCR, regval);
+ HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxTCR,
+ CYGARC_HAL_LPC24XX_REG_TxTCR_CTR_ENABLE);
+}
+
+
+//==========================================================================
+// This function is the ISR attached to the ADC device's interrupt vector.
+// It is responsible for reading samples from the channels and passing them
+// on to the generic layer. It needs to check each channel for data, and call
+// cyg_adc_receive_sample() for each new sample available, and then ready the
+// device for the next interrupt.
+//==========================================================================
+static cyg_uint32 lpc2xxx_adc_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+ cyg_adc_device *device = (cyg_adc_device *) data;
+ lpc2xxx_adc_info *info = (lpc2xxx_adc_info *)device->dev_priv;
+ cyg_uint32 regval;
+ cyg_uint32 res = 0;
+ cyg_adc_sample_t adcdata;
+
+#if CYGPKG_DEVS_ADC_ARM_LPC24XX_DEBUG_LEVEL > 1
+ //
+ // Print debug information for channel 1 - this is the channel that
+ // triggers the interrupt and that is used for measuring lost samples
+ //
+ if (!(++info->isr_cnt % device->config.rate))
+ {
+ cyg_uint32 current_time_ms = cyg_current_time() * 10;
+ debug1_printf("ms %d smpl. %d\n",
+ current_time_ms - info->zero_time, info->isr_cnt);
+ info->zero_time = current_time_ms;
+ } // if (!(info->isr_count % device->config.rate))
+#endif // CYGPKG_DEVS_ADC_ARM_LPC24XX_DEBUG_LEVEL > 1
+
+ cyg_uint8 active_channels = info->chan_mask;
+ cyg_uint8 channel_no = 0;
+ while (active_channels)
+ {
+ if (active_channels & 0x01)
+ {
+ HAL_READ_UINT32(ADC_DR(channel_no), regval);
+ adcdata = (regval >> 6) & 0x3FF;
+ res |= CYG_ISR_HANDLED
+ | cyg_adc_receive_sample(info->channel[channel_no],
+ adcdata);
+ } // if (active_channels & 0x01)
+ active_channels >>= 1;
+ channel_no++;
+ } // while (active_channels)
+
+ HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER1_BASE +
+ CYGARC_HAL_LPC24XX_REG_TxIR,
+ CYGARC_HAL_LPC24XX_REG_TxIR_MR0); // Clear interrupt
+ cyg_drv_interrupt_acknowledge(info->vector);
+ return res;
+}
+
+
+//==========================================================================
+// This function is the DSR attached to the ADC device's interrupt vector.
+// It is called by the kernel if the ISR return value contains the
+// CYG_ISR_HANDLED bit. It needs to call cyg_adc_wakeup() for each channel
+// that has its wakeup field set.
+//==========================================================================
+static void lpc2xxx_adc_dsr(cyg_vector_t vector,
+ cyg_ucount32 count,
+ cyg_addrword_t data)
+{
+ cyg_adc_device *device = (cyg_adc_device *) data;
+ lpc2xxx_adc_info *info = device->dev_priv;
+ cyg_uint8 active_channels = info->chan_mask;
+ cyg_uint8 chan_no = 0;
+
+ while (active_channels)
+ {
+ if (active_channels & 0x01)
+ {
+ if(info->channel[chan_no]->wakeup)
+ {
+ cyg_adc_wakeup(info->channel[chan_no]);
+ }
+ }
+ chan_no++;
+ active_channels >>= 1;
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// eof adc_lpc24xx.c
diff --git a/ecos/packages/devs/adc/arm/lpc24xx/current/tests/lpc24xx_adc_test.c b/ecos/packages/devs/adc/arm/lpc24xx/current/tests/lpc24xx_adc_test.c
new file mode 100755
index 0000000..dae9531
--- /dev/null
+++ b/ecos/packages/devs/adc/arm/lpc24xx/current/tests/lpc24xx_adc_test.c
@@ -0,0 +1,300 @@
+//==========================================================================
+//
+// lpc24xx_adc_test.c
+//
+// ADC performance test for LPC24xxx
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 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): Uwe Kindler
+// Contributors:
+// Date: 2008-11-01
+// Description: ADC performance test for LPC24xxx
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+// INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h> // test macros
+#include <cyg/infra/cyg_ass.h> // assertion macros
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_diag.h>
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+
+// Package requirements
+#if defined(CYGPKG_IO_ADC) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/adc.h>
+#include <pkgconf/devs_adc_arm_lpc24xx.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/kernel/kapi.h>
+
+#if CYGINT_DEVS_ADC_ARM_LPC24XX_CHANNELS > 0
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+ cyg_thread obj;
+ long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+ cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+// LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t adc_thread;
+thread_data_t adc_thread_data;
+
+
+//===========================================================================
+// ADC THREAD
+//===========================================================================
+void adc_thread(cyg_addrword_t data)
+{
+ int res;
+ cyg_io_handle_t handle[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ cyg_uint32 sample_cnt[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ cyg_uint32 cfg_data;
+ cyg_uint32 len;
+ cyg_uint32 start_time;
+ cyg_uint32 end_time;
+ int i;
+ cyg_uint8 seconds = 0;
+ float final_seconds;
+ cyg_uint32 samples_expected;
+
+
+ diag_printf("This test reads samples from all enabled ADC channels.\n"
+ "Each second the number of already acquired samples\n"
+ "will be printed. After 10 seconds all ADC channels\n"
+ "will be stopped and each ADC buffer will be read until\n"
+ "it is empty. If the number of acquired samples is much\n"
+ "smaller than the number of expected samples, then you\n"
+ "should lower the sample rate.\n\n");
+
+ // Get a handle for ADC device 0 channel 1 - 8
+ res = cyg_io_lookup( "/dev/adc00", &handle[0]);
+ res = cyg_io_lookup( "/dev/adc01", &handle[1]);
+ res = cyg_io_lookup( "/dev/adc02", &handle[2]);
+ res = cyg_io_lookup( "/dev/adc03", &handle[3]);
+ res = cyg_io_lookup( "/dev/adc04", &handle[4]);
+ res = cyg_io_lookup( "/dev/adc05", &handle[5]);
+ res = cyg_io_lookup( "/dev/adc06", &handle[6]);
+ res = cyg_io_lookup( "/dev/adc07", &handle[7]);
+
+ //
+ // switch all channels to non blocking
+ //
+ for (i = 0; i < 8; ++i)
+ {
+ if (handle[i])
+ {
+ cfg_data = 0;
+ len = sizeof(cfg_data);
+ res = cyg_io_set_config(handle[i],
+ CYG_IO_SET_CONFIG_READ_BLOCKING,
+ &cfg_data,
+ &len);
+ if (ENOERR != res)
+ {
+ CYG_TEST_FAIL_FINISH("Error switching ADC channel to non blocking");
+ }
+ sample_cnt[i] = 0;
+ } // if (handle[i])
+ } // for (i = 0; i < 8; ++i)
+
+ start_time = cyg_current_time();
+ do
+ {
+ for (i = 0; i < 8; ++i)
+ {
+ if (handle[i])
+ {
+ cyg_adc_sample_t sample;
+
+ // read a sample from the channel
+ do
+ {
+ cyg_uint32 len = sizeof(sample);
+ res = cyg_io_read( handle[i], &sample, &len );
+ }
+ while (-EAGAIN == res);
+ if (ENOERR == res)
+ {
+ sample_cnt[i]++;
+ }
+ } // if (handle[i])
+ }
+ //
+ // print number of acquired samples - if one second is expired.
+ // we expect that the number of acquired samples is nearly the
+ // sample rate
+ //
+ end_time = cyg_current_time();
+ if ((end_time - start_time) >= 100)
+ {
+ start_time = end_time;
+ diag_printf("%d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\n",
+ sample_cnt[0],
+ sample_cnt[1],
+ sample_cnt[2],
+ sample_cnt[3],
+ sample_cnt[4],
+ sample_cnt[5],
+ sample_cnt[6],
+ sample_cnt[7]);
+ seconds++;
+ } // if ((end_time - start_time) >= 100)
+ } while (seconds < 10);
+
+ //
+ // Now stop all channels
+ //
+ for (i = 0; i < 8; ++i)
+ {
+ if (handle[i])
+ {
+ res = cyg_io_set_config(handle[i],
+ CYG_IO_SET_CONFIG_ADC_DISABLE,
+ 0,
+ 0);
+ if (ENOERR != res)
+ {
+ CYG_TEST_FAIL_FINISH("Error disabling ADC channel");
+ }
+ } // if (handle[i])
+ }
+ end_time = cyg_current_time();
+ end_time = seconds * 1000 + (end_time - start_time) * 10;
+ final_seconds = end_time / 1000.0;
+
+ //
+ // Now read all remaining samples from buffer
+ //
+ for (i = 0; i < 8; ++i)
+ {
+ if (handle[i])
+ {
+ do
+ {
+ cyg_adc_sample_t sample;
+ cyg_uint32 len = sizeof(sample);
+ res = cyg_io_read( handle[i], &sample, &len );
+ if (ENOERR == res)
+ {
+ sample_cnt[i]++;
+ }
+ } while (ENOERR == res);
+ } // if (handle[i])
+ }
+
+ diag_printf("\n\n----------------------------------------\n");
+ samples_expected = final_seconds * CYGNUM_DEVS_ADC_ARM_LPC24XX_DEFAULT_RATE;
+ diag_printf("Samples expected after %d milliseconds: %d\n",
+ end_time, samples_expected);
+ diag_printf("Samples read (per channel):\n");
+ diag_printf("%d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\n",
+ sample_cnt[0],
+ sample_cnt[1],
+ sample_cnt[2],
+ sample_cnt[3],
+ sample_cnt[4],
+ sample_cnt[5],
+ sample_cnt[6],
+ sample_cnt[7]);
+
+ CYG_TEST_PASS_FINISH("ADC test OK");
+}
+
+
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+
+ //
+ // create the main ADC test thread
+ //
+ cyg_thread_create(4, adc_thread,
+ (cyg_addrword_t) 0,
+ "lpc24xx_adc_thread",
+ (void *) adc_thread_data.stack,
+ 1024 * sizeof(long),
+ &adc_thread_data.hdl,
+ &adc_thread_data.obj);
+
+ cyg_thread_resume(adc_thread_data.hdl);
+
+ cyg_scheduler_start();
+}
+#else // CYGINT_DEVS_ADC_ARM_LPC24XX_CHANNELS > 0
+#define N_A_MSG "Needs at least one enabled ADC channel"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_ADC && CYGPKG_KERNEL
+#define N_A_MSG "Needs Kernel and ADC support"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA(N_A_MSG);
+}
+#endif // N_A_MSG
+
+
+// EOF can_tx.c
+
+//---------------------------------------------------------------------------
+// eof i2c_test.c
+
diff --git a/ecos/packages/devs/adc/cortexm/lm3s/current/ChangeLog b/ecos/packages/devs/adc/cortexm/lm3s/current/ChangeLog
new file mode 100644
index 0000000..baabea6
--- /dev/null
+++ b/ecos/packages/devs/adc/cortexm/lm3s/current/ChangeLog
@@ -0,0 +1,31 @@
+2011-01-18 Christophe Coutand <ccoutand@stmi.com>
+
+ * cdl/adc_lm3s.cdl:
+ * src/adc_lm3s.c:
+ * include/adc_lm3s.inl:
+ * tests/lm3s_adc_test.c:
+ New package -- Stellaris Cortex M3 ADC driver package.
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2011 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/ecos/packages/devs/adc/cortexm/lm3s/current/cdl/adc_lm3s.cdl b/ecos/packages/devs/adc/cortexm/lm3s/current/cdl/adc_lm3s.cdl
new file mode 100644
index 0000000..ab2b765
--- /dev/null
+++ b/ecos/packages/devs/adc/cortexm/lm3s/current/cdl/adc_lm3s.cdl
@@ -0,0 +1,217 @@
+# ====================================================================
+#
+# adc_lm3s.cdl
+#
+# eCos Stellaris Cortex M3 ADC configuration data
+#
+# ====================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2011 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): ccoutand
+# Contributors:
+# Date: 2011-01-12
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_ADC_CORTEXM_LM3S {
+ display "ADC driver for Stellaris Cortex M3 microcontroller family"
+
+ parent CYGPKG_IO_ADC_DEVICES
+ active_if CYGPKG_IO_ADC_DEVICES
+ active_if CYGPKG_HAL_CORTEXM_LM3S
+ include_dir cyg/io
+ description "
+ This package provides a generic ADC device driver for the on-chip
+ ADC peripherals in Stellaris microcontroller."
+
+ compile -library=libextras.a adc_lm3s.c
+
+ define_proc {
+ puts $::cdl_system_header "#define CYGDAT_DEVS_ADC_CORTEXM_LM3S_INL <cyg/io/adc_lm3s.inl>"
+ }
+
+ # ---------------------------------------------------------------------
+ # Primary ADC ( ADC0 ) port
+
+ cdl_component CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0 {
+ display "ADC port 0"
+ flavor bool
+ default_value 1
+ description "
+ This option includes the device driver for the on-chip ADC0
+ of the Stellaris device."
+
+ cdl_interface CYGINT_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNELS {
+ display "Number of ADC0 channels"
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_SELECT_TIMER {
+ display "ADC sampling timer"
+ flavor data
+ legal_values { 0 1 2 }
+ default_value 0
+ description "
+ This option selects the timer channel generating the
+ ADC sampling interval."
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_INTPRIO {
+ display "ADC Interrupt priority"
+ flavor data
+ default_value 0x60
+ description "
+ This option selects the interrupt priority for the ADC
+ interrupts."
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_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_LM3S_ADC0_AVERAGING {
+ display "Sample averaging"
+ flavor data
+ legal_values { 0 2 4 8 16 32 64 }
+ default_value 0
+ description "
+ Select the ADC sample averaging."
+ }
+
+ cdl_component CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_TEMP_SENSOR {
+ display "Internal Temperature Sensor"
+ flavor bool
+ default_value 0
+ description "
+ Enable one ADC channel for internal temperature sensor
+ reading."
+
+ cdl_option CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_TEMP_SENSOR_CHANNEL {
+ display "Select sensor channel"
+ flavor data
+ legal_values { 0 to (CYGINT_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNELS-1) }
+ default_value 1
+ description "
+ This option select ADC channel reserved for
+ temperature sensor reading."
+ }
+ }
+
+ # -----------------------------------------------------------------
+ # Support up to 8 ADC channels
+
+ for { set ::channel 0 } { $::channel < 8 } { incr ::channel } {
+ cdl_component CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL[set ::channel] {
+ display "Access ADC channel [set ::channel]"
+ flavor bool
+ default_value [set ::channel] == 0
+ implements CYGINT_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNELS
+ description "
+ If the application needs to access the on-chip ADC0
+ channel [set ::channel] via an eCos ADC driver then
+ this option should be enabled."
+
+ cdl_option CYGDAT_DEVS_ADC_CORTEXM_LM3S_ADC0_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_LM3S_ADC0_CHANNEL[set ::channel]_BUFSIZE {
+ display "Size of data buffer"
+ flavor data
+ legal_values 0x01 to 0x16
+ default_value 0x4
+ description "
+ This option controls the number of samples the
+ buffer can store. The required RAM depends on the
+ sample size and on the number of samples. If the
+ sample size is <= 8 bit the the required RAM =
+ size of data buffer. If the sample size is 9 or 10
+ bit then required RAM = size of data buffer * 2."
+ }
+ }
+ }
+ }
+
+ cdl_option CYGPKG_DEVS_ADC_CORTEXM_LM3S_DEBUG_LEVEL {
+ display "Driver debug output level"
+ flavor data
+ legal_values { 0 1 }
+ default_value 0
+ description "
+ This option specifies the level of debug data output by
+ the Stellaris 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 CYGSEM_DEVS_ADC_CORTEXM_LM3S_SAMPLE_SIZE_LIMIT {
+ display "Sample size limit"
+ flavor bool
+ calculated 1
+ requires { ( CYGNUM_IO_ADC_SAMPLE_SIZE == 10 ) }
+ description "
+ This component forces a limit (or rounds) the sample size
+ for Stellaris ADC channels which in the most are 10-bit."
+ }
+
+ cdl_option CYGPKG_DEVS_ADC_CORTEXM_LM3S_TESTS {
+ display "Tests for Stellaris 800 Series ADC driver"
+ flavor data
+ no_define
+ active_if CYGPKG_KERNEL
+ active_if CYGPKG_IO_ADC
+ calculated { "tests/lm3s_adc_test" }
+ description "
+ This option specifies the set of tests for the Stellaris
+ ADC device driver."
+ }
+}
+
+# EOF adc_lm3s.cdl
diff --git a/ecos/packages/devs/adc/cortexm/lm3s/current/include/adc_lm3s.inl b/ecos/packages/devs/adc/cortexm/lm3s/current/include/adc_lm3s.inl
new file mode 100644
index 0000000..655da59
--- /dev/null
+++ b/ecos/packages/devs/adc/cortexm/lm3s/current/include/adc_lm3s.inl
@@ -0,0 +1,140 @@
+//==========================================================================
+//
+// adc_lm3s.inl
+//
+// ADC driver for Stellaris Cortex M3 microcontroller
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2011 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): ccoutand
+//
+// Contributors:
+// Date: 2011-01-08
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#ifndef CYGONCE_DEVS_ADC_CORTEXM_LM3S_INL
+#define CYGONCE_DEVS_ADC_CORTEXM_LM3S_INL
+
+// Declare ADC0
+#ifdef CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0
+
+static lm3s_adc_info lm3s_adc0_info =
+{
+ .timer_base = CYGHWR_HAL_LM3S_GPTIM0 + ( 0x1000 * CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_SELECT_TIMER ),
+ .adc_intprio = CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_INTPRIO,
+ .adc_vector = CYGNUM_HAL_INTERRUPT_ADC0_S0,
+ .adc_base = CYGHWR_HAL_LM3S_ADC0,
+ .adc_periph = CYGHWR_HAL_LM3S_P_ADC0,
+ .timer_periph = (CYGHWR_HAL_LM3S_SC_RCGC1_TIMER0 << CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_SELECT_TIMER),
+#if CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_AVERAGING == 0
+ .adc_avg = 0,
+#elif CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_AVERAGING == 2
+ .adc_avg = 1,
+#elif CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_AVERAGING == 4
+ .adc_avg = 2,
+#elif CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_AVERAGING == 8
+ .adc_avg = 3,
+#elif CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_AVERAGING == 16
+ .adc_avg = 4,
+#elif CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_AVERAGING == 32
+ .adc_avg = 5,
+#elif CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_AVERAGING == 64
+ .adc_avg = 6,
+#endif
+#if defined(CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_TEMP_SENSOR)
+ .sensor_channel = CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_TEMP_SENSOR_CHANNEL,
+#else
+ .sensor_channel = 0xff,
+#endif
+ .max_channel = CYGINT_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNELS,
+ .int_handle = 0,
+ .chan_mask = 0
+};
+
+CYG_ADC_DEVICE( \
+ lm3s_adc0_device, \
+ &lm3s_adc_funs, \
+ &lm3s_adc0_info, \
+ CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_DEFAULT_RATE);
+
+#define LM3S_ADC0_CHANNEL( __chan ) \
+CYG_ADC_CHANNEL( \
+ lm3s_adc0_channel##__chan, \
+ __chan, \
+ CYGDAT_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL##__chan##_BUFSIZE, \
+ &lm3s_adc0_device ); \
+DEVTAB_ENTRY( \
+ lm3s_adc0_channel##__chan##_device, \
+ CYGDAT_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL##__chan##_NAME, \
+ 0, \
+ &cyg_io_adc_devio, \
+ lm3s_adc_init, \
+ lm3s_adc_lookup, \
+ &lm3s_adc0_channel##__chan );
+
+#ifdef CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL0
+LM3S_ADC0_CHANNEL(0);
+#endif
+#ifdef CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL1
+LM3S_ADC0_CHANNEL(1);
+#endif
+#ifdef CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL2
+LM3S_ADC0_CHANNEL(2);
+#endif
+#ifdef CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL3
+LM3S_ADC0_CHANNEL(3);
+#endif
+#ifdef CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL4
+LM3S_ADC0_CHANNEL(4);
+#endif
+#ifdef CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL5
+LM3S_ADC0_CHANNEL(5);
+#endif
+#ifdef CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL6
+LM3S_ADC0_CHANNEL(6);
+#endif
+#ifdef CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNEL7
+LM3S_ADC0_CHANNEL(7);
+#endif
+
+#endif // CYGPKG_DEVS_ADC_CORTEXM_LM3S_ADC0
+
+#endif // CYGONCE_DEVS_ADC_CORTEXM_LM3S_INL
diff --git a/ecos/packages/devs/adc/cortexm/lm3s/current/src/adc_lm3s.c b/ecos/packages/devs/adc/cortexm/lm3s/current/src/adc_lm3s.c
new file mode 100644
index 0000000..027e9c1
--- /dev/null
+++ b/ecos/packages/devs/adc/cortexm/lm3s/current/src/adc_lm3s.c
@@ -0,0 +1,489 @@
+//==========================================================================
+//
+// adc_lm3s.c
+//
+// ADC driver for Stellaris Cortex M3 microcontroller
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2011 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): Uwe Kindler <uwe_kindler@web.de>
+// Updated for Stellaris device, ccoutand
+// Contributors:
+// Date: 2011-01-08
+// Purpose:
+// Description:
+//
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+//==========================================================================
+// INCLUDES
+//==========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/devs_adc_cortexm_lm3s.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/diag.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>
+
+#if CYGPKG_DEVS_ADC_CORTEXM_LM3S_DEBUG_LEVEL > 0
+# define lm3s_adc_diag(args...) diag_printf(args)
+#else
+# define lm3s_adc_diag(args...)
+#endif
+
+#define CYGHWR_HAL_LM3S_ADC_MAX_CHAN 8
+
+//==========================================================================
+// DATA TYPES
+//==========================================================================
+typedef struct lm3s_adc_info {
+ cyg_uint32 adc_base; // ADC base address
+ cyg_uint32 adc_periph; // ADC peripheral mask
+ cyg_vector_t adc_vector; // Interrupt vector number
+ cyg_priority_t adc_intprio; // Interrupt priority of ADC interrupt
+ cyg_uint32 timer_base; // Base address of Timer peripheral
+ cyg_uint32 timer_interval; // Timer value
+ cyg_uint32 timer_periph; // Timer peripheral mask
+ cyg_uint8 sensor_channel; // Temperature sensor channel if any
+ cyg_uint8 max_channel; // Number of ADC channel
+ cyg_handle_t int_handle; // For initializing the interrupt
+ cyg_interrupt int_data;
+ cyg_uint8 adc_avg; // Sample averaging
+ // Stores references to channel objects
+ struct cyg_adc_channel *channel[CYGHWR_HAL_LM3S_ADC_MAX_CHAN];
+ cyg_uint8 chan_mask; // Mask that indicates channels used
+ // by ADC driver
+} lm3s_adc_info;
+
+
+//==========================================================================
+// DECLARATIONS
+//==========================================================================
+static bool lm3s_adc_init(struct cyg_devtab_entry *tab);
+static Cyg_ErrNo lm3s_adc_lookup(struct cyg_devtab_entry **tab,
+ struct cyg_devtab_entry *sub_tab,
+ const char *name);
+static void lm3s_adc_enable(cyg_adc_channel * chan);
+static void lm3s_adc_disable(cyg_adc_channel * chan);
+static void lm3s_adc_set_rate(cyg_adc_channel * chan, cyg_uint32 rate);
+static cyg_uint32 lm3s_adc_isr(cyg_vector_t vector, cyg_addrword_t data);
+static void lm3s_adc_dsr(cyg_vector_t vector,
+ cyg_ucount32 count, cyg_addrword_t data);
+
+static void lm3s_adc_disable_sequencer0(cyg_uint32);
+static void lm3s_adc_enable_sequencer0(cyg_uint32);
+static void lm3s_adc_flush(cyg_uint32);
+static void lm3s_adc_update_sequencer0(cyg_adc_channel *);
+
+// -------------------------------------------------------------------------
+// Driver functions:
+CYG_ADC_FUNCTIONS( lm3s_adc_funs,
+ lm3s_adc_enable,
+ lm3s_adc_disable,
+ lm3s_adc_set_rate );
+
+
+#include CYGDAT_DEVS_ADC_CORTEXM_LM3S_INL // Instantiate ADCs
+
+
+//==========================================================================
+//
+// The eCos Sellaris ADC drivers uses a single sequencer ( sequencer 0 ).
+// The same sequencer is used to sample all channels.
+// Sampling of the different channel is triggered from a timer interrupt.
+// The ADC driver flexibility does not allow to trigger sampling from
+// external GPIO or analog comparator event. It should be noted that enabling
+// / disabling an ADC channel disturbs the sampling of other channels since it
+// requires to stop sampling to re-organize the sequencer. Also the FIFO
+// is flushed to ensure correct sample order out of the sequencer FIFO.
+//
+//==========================================================================
+static bool
+lm3s_adc_init(struct cyg_devtab_entry *tab)
+{
+ cyg_adc_channel *chan = (cyg_adc_channel *) tab->priv;
+ cyg_adc_device *device = chan->device;
+ lm3s_adc_info *info = device->dev_priv;
+
+ lm3s_adc_diag("ADC: Init\n");
+
+ if (!info->int_handle) {
+ lm3s_adc_diag("ADC: IRQ vect %d, pri %d\n",
+ info->adc_vector, info->adc_intprio);
+
+ cyg_drv_interrupt_create(info->adc_vector,
+ info->adc_intprio,
+ (cyg_addrword_t)device,
+ &lm3s_adc_isr,
+ &lm3s_adc_dsr,
+ &(info->int_handle), &(info->int_data));
+ cyg_drv_interrupt_attach(info->int_handle);
+ cyg_drv_interrupt_mask(info->adc_vector);
+
+ // Enable ADC and sampling timer peripheral
+ CYGHWR_HAL_LM3S_PERIPH_SET(info->adc_periph, 1);
+ CYGHWR_HAL_LM3S_PERIPH_SET((CYGHWR_HAL_LM3S_PERIPH_GC1 | info->
+ timer_periph), 1);
+
+ // Disable timer
+ HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CTL, 0);
+
+ // Disable / reset sequencer
+ HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_ACTSS, 0);
+ HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_MUX0, 0);
+ HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_CTL0, 0);
+
+ // Trigger sampling from timer
+ HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_EMUX,
+ CYGHWR_HAL_LM3S_ADC_EMUX_EM_TIMER(0));
+
+ // Set Averaging
+ HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SAC,
+ info->adc_avg);
+
+ // Setup timer
+ HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CFG,
+ CYGHWR_HAL_LM3S_GPTIM_CFG_32BIT);
+ HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_TAMR,
+ CYGHWR_HAL_LM3S_GPTIM_TAMR_PERIODIC);
+
+ // Setup the default sample rate
+ lm3s_adc_set_rate(chan, chan->device->config.rate);
+
+ }
+
+ // Initialize generic parts of driver
+ 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
+lm3s_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;
+ lm3s_adc_info *info = chan->device->dev_priv;
+
+ lm3s_adc_diag("ADC: Opening channel %d\n", chan->channel);
+
+ if (chan->channel > info->max_channel)
+ return ENOENT;
+
+ info->channel[chan->channel] = chan;
+
+ // Initialize generic parts of 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;
+ lm3s_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
+lm3s_adc_enable(cyg_adc_channel * chan)
+{
+ lm3s_adc_info *info = chan->device->dev_priv;
+ cyg_uint32 ctl =
+ CYGHWR_HAL_LM3S_GPTIM_CTL_TAEN | CYGHWR_HAL_LM3S_GPTIM_CTL_TAOTE;
+ cyg_uint32 start = !info->chan_mask;
+
+ // Disable ADC sequencer 0 and timer
+ HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CTL, 0);
+ lm3s_adc_disable_sequencer0(info->adc_base);
+
+ // Update sequencer
+ info->chan_mask |= (1 << chan->channel);
+ lm3s_adc_update_sequencer0(chan);
+
+ // Unmask interrupt as soon as 1 channel is enable
+ if (start) {
+ cyg_drv_interrupt_unmask(info->adc_vector);
+ }
+ // Enable sequencer and timer
+ lm3s_adc_enable_sequencer0(info->adc_base);
+ HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CTL, ctl);
+}
+
+
+//==========================================================================
+// 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
+lm3s_adc_disable(cyg_adc_channel * chan)
+{
+ lm3s_adc_info *info = chan->device->dev_priv;
+ cyg_uint32 ctl =
+ CYGHWR_HAL_LM3S_GPTIM_CTL_TAEN | CYGHWR_HAL_LM3S_GPTIM_CTL_TAOTE;
+
+ // Disable ADC sequencer 0 and timer
+ HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CTL, 0);
+ lm3s_adc_disable_sequencer0(info->adc_base);
+
+ // Update sequencer
+ info->chan_mask &= ~(1 << chan->channel);
+ lm3s_adc_update_sequencer0(chan);
+
+ // Stop scanning when no channel is active
+ if (!info->chan_mask) {
+ cyg_drv_interrupt_mask(info->adc_vector);
+ return;
+ }
+ // Enable sequencer and timer
+ lm3s_adc_enable_sequencer0(info->adc_base);
+ HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CTL, ctl);
+}
+
+
+//==========================================================================
+// 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
+lm3s_adc_set_rate(cyg_adc_channel * chan, cyg_uint32 rate)
+{
+ cyg_adc_device *device = chan->device;
+ lm3s_adc_info *info = (lm3s_adc_info *) device->dev_priv;
+
+ info->timer_interval = hal_lm3s_timer_clock() / rate;
+
+ lm3s_adc_diag("ADC: Timer interval %d\n", info->timer_interval);
+
+ HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_TAILR,
+ info->timer_interval);
+}
+
+
+//==========================================================================
+// This function is the ISR attached to the ADC device's interrupt vector.
+// It is responsible for reading samples from the channels and passing them
+// on to the generic layer. It needs to check each channel for data, and call
+// cyg_adc_receive_sample() for each new sample available, and then ready the
+// device for the next interrupt.
+//==========================================================================
+static cyg_uint32
+lm3s_adc_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+ cyg_adc_device *device = (cyg_adc_device *) data;
+ lm3s_adc_info *info = (lm3s_adc_info *) device->dev_priv;
+ cyg_uint32 regval;
+ cyg_uint32 res = 0;
+ cyg_adc_sample_t adcdata;
+ cyg_uint32 sr;
+
+ cyg_uint8 active_channels = info->chan_mask;
+ cyg_uint8 channel_no = 0;
+
+ while (active_channels) {
+ HAL_READ_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_FIFO0_SR, sr);
+ // Check FIFO Full
+ if ((sr & CYGHWR_HAL_LM3S_ADC_SS_FIFO_SR_FULL)) {
+ lm3s_adc_diag("ADC: FIFO Full\n");
+ }
+ // Check FIFO Empty
+ if ((sr & CYGHWR_HAL_LM3S_ADC_SS_FIFO_SR_EMPTY)) {
+ lm3s_adc_diag("ADC: FIFO Empty\n");
+ }
+ if (active_channels & 0x01) {
+ // If ADC conversion done, save sample
+ if (!(sr & CYGHWR_HAL_LM3S_ADC_SS_FIFO_SR_EMPTY)) {
+ HAL_READ_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_FIFO0,
+ regval);
+ adcdata = regval & 0x3FF;
+ res |= CYG_ISR_HANDLED
+ | cyg_adc_receive_sample(info->channel[channel_no],
+ adcdata);
+ }
+ }
+ active_channels >>= 1;
+ channel_no++;
+ }
+
+ HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_ISCR,
+ CYGHWR_HAL_LM3S_ADC_ISCR_IN(0));
+
+ cyg_drv_interrupt_acknowledge(info->adc_vector);
+
+ return res;
+}
+
+
+//==========================================================================
+// This function is the DSR attached to the ADC device's interrupt vector.
+// It is called by the kernel if the ISR return value contains the
+// CYG_ISR_HANDLED bit. It needs to call cyg_adc_wakeup() for each channel
+// that has its wakeup field set.
+//==========================================================================
+static void
+lm3s_adc_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+ cyg_adc_device *device = (cyg_adc_device *) data;
+ lm3s_adc_info *info = device->dev_priv;
+ cyg_uint8 active_channels = info->chan_mask;
+ cyg_uint8 chan_no = 0;
+
+ while (active_channels) {
+ if (active_channels & 0x01) {
+ if (info->channel[chan_no]->wakeup) {
+ cyg_adc_wakeup(info->channel[chan_no]);
+ }
+ }
+ chan_no++;
+ active_channels >>= 1;
+ }
+}
+
+
+static void
+lm3s_adc_disable_sequencer0(cyg_uint32 base)
+{
+ cyg_uint32 reg;
+
+ HAL_WRITE_UINT32(base + CYGHWR_HAL_LM3S_ADC_IMR, 0);
+ HAL_WRITE_UINT32(base + CYGHWR_HAL_LM3S_ADC_ISCR,
+ CYGHWR_HAL_LM3S_ADC_ISCR_IN(0));
+ HAL_READ_UINT32(base + CYGHWR_HAL_LM3S_ADC_ACTSS, reg);
+ reg &= ~(CYGHWR_HAL_LM3S_ADC_ACTSS_ASEN(0));
+ HAL_WRITE_UINT32(base + CYGHWR_HAL_LM3S_ADC_ACTSS, reg);
+}
+
+
+static void
+lm3s_adc_enable_sequencer0(cyg_uint32 base)
+{
+ cyg_uint32 reg;
+
+ HAL_READ_UINT32(base + CYGHWR_HAL_LM3S_ADC_ACTSS, reg);
+ reg |= (CYGHWR_HAL_LM3S_ADC_ACTSS_ASEN(0));
+ HAL_WRITE_UINT32(base + CYGHWR_HAL_LM3S_ADC_ACTSS, reg);
+ HAL_WRITE_UINT32(base + CYGHWR_HAL_LM3S_ADC_IMR,
+ CYGHWR_HAL_LM3S_ADC_IMR_MASK(0));
+}
+
+
+static void
+lm3s_adc_flush(cyg_uint32 base)
+{
+ volatile cyg_uint32 d;
+ volatile cyg_uint32 i;
+
+ HAL_READ_UINT32(base + CYGHWR_HAL_LM3S_ADC_SS_FIFO0_SR, i);
+ while (!(i & CYGHWR_HAL_LM3S_ADC_SS_FIFO_SR_EMPTY)) {
+ HAL_READ_UINT32(base + CYGHWR_HAL_LM3S_ADC_SS_FIFO0, d);
+ HAL_READ_UINT32(base + CYGHWR_HAL_LM3S_ADC_SS_FIFO0_SR, i);
+ }
+}
+
+
+static void
+lm3s_adc_update_sequencer0(cyg_adc_channel * chan)
+{
+ lm3s_adc_info *info = chan->device->dev_priv;
+ cyg_uint8 i;
+ cyg_uint8 cnt = 0;
+ cyg_uint32 mux = 0;
+ cyg_uint32 ctl = 0;
+
+ lm3s_adc_diag("ADC: Update sequencer for channel %d\n", chan->channel);
+
+ // Update sequencer
+ for (i = 0; i < info->max_channel; i++) {
+ if (!(info->chan_mask & (1 << i)))
+ continue;
+
+ // Clear and update MUX register
+ mux &= ~(CYGHWR_HAL_LM3S_ADC_SS_MUX0_M(cnt));
+ mux |= CYGHWR_HAL_LM3S_ADC_SS_MUX0_V(i, cnt);
+
+ // Temperature sensor channel
+ if (i == info->sensor_channel) {
+ ctl |= CYGHWR_HAL_LM3S_ADC_SS_CTL0_TS(cnt);
+ lm3s_adc_diag("ADC: Channel %d mapped to temperature sensor\n",
+ i);
+ }
+
+ cnt++;
+ }
+
+ lm3s_adc_diag("ADC: MUX0 Register: 0x%x\n", mux);
+ HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_MUX0, mux);
+
+ if (info->chan_mask) {
+ ctl |= CYGHWR_HAL_LM3S_ADC_SS_CTL0_END((cnt - 1));
+ ctl |= CYGHWR_HAL_LM3S_ADC_SS_CTL0_IE((cnt - 1));
+ }
+
+ lm3s_adc_diag("ADC: CTL0 Register: 0x%x\n", ctl);
+ HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_CTL0, ctl);
+
+ lm3s_adc_flush(info->adc_base);
+}
+
+
+//---------------------------------------------------------------------------
+// EOF adc_lm3s.c
diff --git a/ecos/packages/devs/adc/cortexm/lm3s/current/tests/lm3s_adc_test.c b/ecos/packages/devs/adc/cortexm/lm3s/current/tests/lm3s_adc_test.c
new file mode 100644
index 0000000..ff0f161
--- /dev/null
+++ b/ecos/packages/devs/adc/cortexm/lm3s/current/tests/lm3s_adc_test.c
@@ -0,0 +1,256 @@
+//==========================================================================
+//
+// lm3s_adc_test.c
+//
+// ADC driver for Stellaris Cortex M3 microcontroller
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2011 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): Uwe Kindler <uwe_kindler@web.de>
+// Updated for Stellaris Cortex microcontroller, ccoutand
+// Contributors:
+// Date: 2011-01-11
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h> // test macros
+#include <cyg/infra/cyg_ass.h> // assertion macros
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_diag.h>
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/adc.h>
+#include <pkgconf/devs_adc_cortexm_lm3s.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+# include <cyg/kernel/kapi.h>
+
+# if CYGINT_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNELS > 0
+
+# define MAX_ADC_CHANNEL_TO_TEST 4
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+typedef struct st_thread_data {
+ cyg_thread obj;
+ int stack[(CYGNUM_HAL_STACK_SIZE_MINIMUM / sizeof(int))];
+ cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+// LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t adc_thread;
+thread_data_t adc_thread_data;
+
+
+//===========================================================================
+// ADC THREAD
+//===========================================================================
+void
+adc_thread(cyg_addrword_t data)
+{
+ int res;
+ cyg_io_handle_t handle[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ cyg_uint32 sample_cnt[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ cyg_uint32 cfg_data;
+ cyg_uint32 len;
+ cyg_uint32 start_time;
+ cyg_uint32 end_time;
+ int i;
+ cyg_uint8 seconds = 0;
+ float final_seconds;
+ cyg_uint32 samples_expected;
+
+
+ diag_printf("This test reads samples from all enabled ADC channels.\n"
+ "Each second the number of already acquired samples\n"
+ "will be printed. After 10 seconds all ADC channels\n"
+ "will be stopped and each ADC buffer will be read until\n"
+ "it is empty. If the number of acquired samples is much\n"
+ "smaller than the number of expected samples, then you\n"
+ "should lower the sample rate.\n\n");
+
+ // Get a handle for ADC device 0 channel 0 - 3 (lookup also trigger a
+ // channel enable)
+ res = cyg_io_lookup("/dev/adc00", &handle[0]);
+ res = cyg_io_lookup("/dev/adc01", &handle[1]);
+ res = cyg_io_lookup("/dev/adc02", &handle[2]);
+ res = cyg_io_lookup("/dev/adc03", &handle[3]);
+
+ // Switch all channels to non blocking
+ for (i = 0; i < MAX_ADC_CHANNEL_TO_TEST; ++i) {
+ if (handle[i]) {
+ cfg_data = 0;
+ len = sizeof(cfg_data);
+ res = cyg_io_set_config(handle[i],
+ CYG_IO_SET_CONFIG_READ_BLOCKING,
+ &cfg_data, &len);
+ if (ENOERR != res) {
+ CYG_TEST_FAIL_FINISH
+ ("Error switching ADC channel to non blocking");
+ }
+ sample_cnt[i] = 0;
+ }
+ }
+
+ start_time = cyg_current_time();
+
+ do {
+ for (i = 0; i < MAX_ADC_CHANNEL_TO_TEST; ++i) {
+ if (handle[i]) {
+ cyg_adc_sample_t sample;
+
+ // read a sample from the channel
+ do {
+ cyg_uint32 len = sizeof(sample);
+ res = cyg_io_read(handle[i], &sample, &len);
+ }
+ while (-EAGAIN == res);
+ if (ENOERR == res) {
+ sample_cnt[i]++;
+ }
+ }
+ }
+
+ end_time = cyg_current_time();
+
+ // Print number of acquired samples - if one second is expired.
+ // we expect that the number of acquired samples is nearly the
+ // sample rate.
+ if ((end_time - start_time) >= 100) {
+ start_time = end_time;
+ diag_printf("%d\t %d\t %d\t %d\n",
+ sample_cnt[0],
+ sample_cnt[1], sample_cnt[2], sample_cnt[3]);
+ seconds++;
+ }
+ } while (seconds < 10);
+
+ // Now stop all channels
+ for (i = 0; i < MAX_ADC_CHANNEL_TO_TEST; ++i) {
+ if (handle[i]) {
+ res = cyg_io_set_config(handle[i],
+ CYG_IO_SET_CONFIG_ADC_DISABLE, 0, 0);
+ if (ENOERR != res) {
+ CYG_TEST_FAIL_FINISH("Error disabling ADC channel");
+ }
+ }
+ }
+
+ end_time = cyg_current_time();
+ end_time = seconds * 1000 + (end_time - start_time) * 10;
+ final_seconds = end_time / 1000.0;
+
+ // Now read all remaining samples from buffer
+ for (i = 0; i < MAX_ADC_CHANNEL_TO_TEST; ++i) {
+ if (handle[i]) {
+ do {
+ cyg_adc_sample_t sample;
+ cyg_uint32 len = sizeof(sample);
+ res = cyg_io_read(handle[i], &sample, &len);
+ if (ENOERR == res) {
+ sample_cnt[i]++;
+ }
+ } while (ENOERR == res);
+ }
+ }
+
+ diag_printf("\n\n----------------------------------------\n");
+ samples_expected =
+ final_seconds * CYGNUM_DEVS_ADC_CORTEXM_LM3S_ADC0_DEFAULT_RATE;
+ diag_printf("Samples expected after %d milliseconds: %d\n", end_time,
+ samples_expected);
+ diag_printf("Samples read (per channel):\n");
+ diag_printf("%d\t %d\t %d\t %d\n",
+ sample_cnt[0], sample_cnt[1], sample_cnt[2], sample_cnt[3]);
+
+ CYG_TEST_PASS_FINISH("ADC test OK");
+}
+
+
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+
+ // Create the main ADC test thread
+ cyg_thread_create(4,
+ adc_thread,
+ (cyg_addrword_t)0,
+ "lm3s_adc_thread",
+ (void *)adc_thread_data.stack,
+ CYGNUM_HAL_STACK_SIZE_MINIMUM,
+ &adc_thread_data.hdl,
+ &adc_thread_data.obj
+ );
+
+ cyg_thread_resume(adc_thread_data.hdl);
+
+ cyg_scheduler_start();
+}
+# else// CYGINT_DEVS_ADC_CORTEXM_LM3S_ADC0_CHANNELS > 0
+# define N_A_MSG "Needs at least one enabled ADC channel"
+# endif
+
+#else // CYGFUN_KERNEL_API_C
+# define N_A_MSG "Needs kernel C API"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA(N_A_MSG);
+}
+#endif // N_A_MSG
+
+
+//---------------------------------------------------------------------------
+// EOF lm3s_adc_test.c
diff --git a/ecos/packages/devs/adc/cortexm/stm32/current/ChangeLog b/ecos/packages/devs/adc/cortexm/stm32/current/ChangeLog
new file mode 100644
index 0000000..30f9008
--- /dev/null
+++ b/ecos/packages/devs/adc/cortexm/stm32/current/ChangeLog
@@ -0,0 +1,53 @@
+2012-04-13 Christophe Coutand <ecos@hotmail.co.uk>
+
+ * src/adc_stm32.c:
+ * src/adc1.inl:
+ * src/adc3.inl:
+ Peripheral clocks are enable / disable using new
+ CYGHWR_HAL_STM32_CLOCK_DISABLE / CYGHWR_HAL_STM32_CLOCK_ENABLE
+ macro supplied from the variant HAL. In addition, make sure timer
+ clock is enable.
+
+2011-05-02 Christophe Coutand <ecos@hotmail.co.uk>
+
+ * cdl/adc_stm32.cdl:
+ * src/adc_stm32.c:
+ Make sure DMA clock is enabled. Fix ADC clock divider not set in
+ stm32_adc_init_clock.
+
+2009-03-05 Simon Kallweit <simon.kallweit@intefo.ch>
+
+ * src/adc_stm32.c:
+ Fixed a bug in setup and usage of the timer.
+
+2009-02-24 Simon Kallweit <simon.kallweit@intefo.ch>
+
+ * cdl/adc_stm32.cdl:
+ * src/adc_stm32.c:
+ * src/adc1.inl:
+ * src/adc3.inl:
+ STM32 ADC driver package created.
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2009, 2011 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/ecos/packages/devs/adc/cortexm/stm32/current/cdl/adc_stm32.cdl b/ecos/packages/devs/adc/cortexm/stm32/current/cdl/adc_stm32.cdl
new file mode 100644
index 0000000..4187a50
--- /dev/null
+++ b/ecos/packages/devs/adc/cortexm/stm32/current/cdl/adc_stm32.cdl
@@ -0,0 +1,242 @@
+# ====================================================================
+#
+# adc_stm32.cdl
+#
+# eCos STM32 ADC configuration data
+#
+# ====================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2009, 2011 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 CYGPKG_DEVS_ADC_CORTEXM_STM32_TRACE {
+ display "ADC driver tracing"
+ flavor bool
+ default_value 0
+ description "
+ Enable tracing of the ADC driver. Select to debug the driver."
+ }
+
+ 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 ADC clock divider value. The
+ ADC clock frequency is defined as PCLK2 / ADC divider. "
+ }
+
+ cdl_component CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1 {
+ display "ADC1"
+ default_value 0
+ 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"
+ default_value 0
+ 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/ecos/packages/devs/adc/cortexm/stm32/current/src/adc1.inl b/ecos/packages/devs/adc/cortexm/stm32/current/src/adc1.inl
new file mode 100644
index 0000000..0394c1f
--- /dev/null
+++ b/ecos/packages/devs/adc/cortexm/stm32/current/src/adc1.inl
@@ -0,0 +1,163 @@
+//==========================================================================
+//
+// adc1.inl
+//
+// Parameters for ADC device 1
+//
+//==========================================================================
+// ####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####
+//
+//==========================================================================
+
+// 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_clkena = CYGHWR_HAL_STM32_ADC1_CLOCK,
+ .tim_clkena = CYGHWR_HAL_STM32_TIM3_CLOCK,
+};
+
+// 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
+
+//-----------------------------------------------------------------------------
+// End of adc1.inl
diff --git a/ecos/packages/devs/adc/cortexm/stm32/current/src/adc3.inl b/ecos/packages/devs/adc/cortexm/stm32/current/src/adc3.inl
new file mode 100644
index 0000000..790c1ac
--- /dev/null
+++ b/ecos/packages/devs/adc/cortexm/stm32/current/src/adc3.inl
@@ -0,0 +1,155 @@
+//==========================================================================
+//
+// adc3.inl
+//
+// Parameters for ADC device 3
+//
+//==========================================================================
+// ####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####
+//
+//==========================================================================
+
+// 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_clkena = CYGHWR_HAL_STM32_ADC3_CLOCK,
+ .tim_clkena = CYGHWR_HAL_STM32_TIM8_CLOCK,
+};
+
+// 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
+
+//-----------------------------------------------------------------------------
+// End of adc3.inl
diff --git a/ecos/packages/devs/adc/cortexm/stm32/current/src/adc_stm32.c b/ecos/packages/devs/adc/cortexm/stm32/current/src/adc_stm32.c
new file mode 100644
index 0000000..5a7a0e6
--- /dev/null
+++ b/ecos/packages/devs/adc/cortexm/stm32/current/src/adc_stm32.c
@@ -0,0 +1,631 @@
+//==========================================================================
+//
+// 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, 2011 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.
+
+#ifdef CYGPKG_DEVS_ADC_CORTEXM_STM32_TRACE
+# 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
+ cyg_uint32 adc_clkena; // ADC clock enable
+ cyg_uint32 tim_clkena; // Timer clock enable
+} 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);
+
+ // Reinitialize timer
+ cr = CYGHWR_HAL_STM32_TIM_EGR_UG;
+ HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_EGR, 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 isr;
+ cyg_uint32 res = CYG_ISR_HANDLED;
+
+ HAL_READ_UINT32(info->setup->dma_base + CYGHWR_HAL_STM32_DMA_ISR, isr);
+ if (!(isr & CYGHWR_HAL_STM32_DMA_ISR_MASK(info->setup->dma_channel)))
+ return 0;
+
+ while (chan_active) {
+ if (chan_active & 0x1)
+ res |= 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_WRITE_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 };
+
+ CYGHWR_HAL_STM32_CLOCK_ENABLE( info->setup->adc_clkena );
+ CYGHWR_HAL_STM32_CLOCK_ENABLE( info->setup->tim_clkena );
+
+ // 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);
+
+
+ // Set timer 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);
+
+ // 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);
+
+
+ // Setup DMA channel
+ // Ensure that the DMA clocks are enabled.
+ if (info->setup->dma_base == CYGHWR_HAL_STM32_DMA1)
+ CYGHWR_HAL_STM32_CLOCK_ENABLE( CYGHWR_HAL_STM32_DMA1_CLOCK );
+ else
+ CYGHWR_HAL_STM32_CLOCK_ENABLE( CYGHWR_HAL_STM32_DMA2_CLOCK );
+
+ 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("Updating 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);
+}
+
+//-----------------------------------------------------------------------------
+// End of adc_stm32.c
diff --git a/ecos/packages/devs/adc/synth/current/ChangeLog b/ecos/packages/devs/adc/synth/current/ChangeLog
new file mode 100644
index 0000000..c0f8049
--- /dev/null
+++ b/ecos/packages/devs/adc/synth/current/ChangeLog
@@ -0,0 +1,35 @@
+2009-03-05 Simon Kallweit <simon.kallweit@intefo.ch>
+
+ * cdl/adc_synth.cdl:
+ * cdl/adc_synth.c:
+ Fixed some typos.
+
+2009-02-27 Simon Kallweit <simon.kallweit@intefo.ch>
+
+ * cdl/adc_synth.cdl
+ * src/adc_synth.c
+ Synthetic ADC driver package created.
+
+//===========================================================================
+// ####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/ecos/packages/devs/adc/synth/current/cdl/adc_synth.cdl b/ecos/packages/devs/adc/synth/current/cdl/adc_synth.cdl
new file mode 100644
index 0000000..ac471f7
--- /dev/null
+++ b/ecos/packages/devs/adc/synth/current/cdl/adc_synth.cdl
@@ -0,0 +1,158 @@
+# ====================================================================
+#
+# adc_synth.cdl
+#
+# eCos Synthetic 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-27
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+
+cdl_package CYGPKG_DEVS_ADC_SYNTH {
+ display "Synthetic ADC device driver"
+
+ parent CYGPKG_IO_ADC_DEVICES
+ active_if CYGPKG_IO_ADC_DEVICES
+ active_if CYGPKG_HAL_SYNTH
+ requires {CYGNUM_IO_ADC_SAMPLE_SIZE >= CYGNUM_DEVS_ADC_SYNTH_SAMPLE_SIZE}
+ description "
+ This option enables the ADC device drivers for Synthetic target."
+
+ include_dir cyg/io
+ compile -library=libextras.a adc_synth.c
+
+ cdl_interface CYGINT_DEVS_ADC_SYNTH_CHANNELS {
+ display "Number of ADC channels"
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_SYNTH_SAMPLE_SIZE {
+ display "Sample size"
+ flavor data
+ legal_values 1 to 32
+ default_value 16
+ description "
+ Sample size provided by the ADC channels."
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_SYNTH_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."
+ }
+
+ # Support 16 channels
+ for { set ::channel 0 } { $::channel < 16 } { incr ::channel } {
+
+ cdl_component CYGHWR_DEVS_ADC_SYNTH_CHANNEL[set ::channel] {
+ display "ADC channel [set ::channel]"
+ flavor none
+ implements CYGINT_DEVS_ADC_SYNTH_CHANNELS
+ description "
+ If the application needs to access the ADC
+ channel [set ::channel] via an eCos ADC driver then
+ this option should be enabled."
+
+ cdl_option CYGDAT_DEVS_ADC_SYNTH_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 CYGNUM_DEVS_ADC_SYNTH_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 * size of sample."
+ }
+
+ cdl_option CYGDAT_DEVS_ADC_SYNTH_CHANNEL[set ::channel]_SOURCE {
+ display "Channel source"
+ flavor data
+ legal_values { "CONST" "RANDOM" "FILE" }
+ default_value { "CONST" }
+ description "
+ This option controls the sample source of the virtual ADC
+ channel. CONST mode always returns a constant sample value.
+ RANDOM mode returns random samples. FILE returns samples as
+ read by a file on the host."
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_SYNTH_CHANNEL[set ::channel]_CONST_VALUE {
+ display "Constant sample value"
+ flavor data
+ default_value 0
+ description "
+ Constant sample value returned when CONST mode is selected."
+ }
+
+ cdl_option CYGDAT_DEVS_ADC_SYNTH_CHANNEL[set ::channel]_FILENAME {
+ display "Sample data filename"
+ flavor data
+ default_value [format {"\"adc0%d\""} $::channel]
+ description "
+ Filename of sample data file used in FILE mode."
+ }
+
+ cdl_option CYGNUM_DEVS_ADC_SYNTH_CHANNEL[set ::channel]_MODE {
+ display "Channel mode"
+ flavor data
+ calculated CYGDAT_DEVS_ADC_SYNTH_CHANNEL[set ::channel]_SOURCE == { "CONST" } ? 0 : \
+ CYGDAT_DEVS_ADC_SYNTH_CHANNEL[set ::channel]_SOURCE == { "RANDOM" } ? 1 : \
+ CYGDAT_DEVS_ADC_SYNTH_CHANNEL[set ::channel]_SOURCE == { "FILE" } ? 2 : -1
+ }
+ }
+ }
+}
diff --git a/ecos/packages/devs/adc/synth/current/src/adc_synth.c b/ecos/packages/devs/adc/synth/current/src/adc_synth.c
new file mode 100644
index 0000000..42ddab2
--- /dev/null
+++ b/ecos/packages/devs/adc/synth/current/src/adc_synth.c
@@ -0,0 +1,482 @@
+//==========================================================================
+//
+// adc_synth.c
+//
+// ADC driver for Synthetic 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-27
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/kernel.h>
+#include <pkgconf/devs_adc_synth.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
+
+#define NUM_CHANNELS 16
+
+#define MODE_CONST 0
+#define MODE_RANDOM 1
+#define MODE_FILE 2
+
+#define SAMPLE_BITS ((1 << CYGNUM_DEVS_ADC_SYNTH_SAMPLE_SIZE) - 1)
+
+//-----------------------------------------------------------------------------
+// Synthetic ADC channel
+
+typedef struct synth_adc_channel_info {
+ cyg_uint32 mode; // Channel mode
+ cyg_uint32 const_value; // Const sample value
+ char *filename; // Sampling data filename
+
+ int fd; // File descriptor of sample file
+ cyg_uint32 num_samples; // Number of samples in the file
+ cyg_adc_sample_t *base; // Base address of mapped sample file
+ cyg_adc_sample_t *sample; // Current sample
+
+ cyg_adc_sample_t (*get_sample)(cyg_adc_channel *chan);
+} synth_adc_channel_info;
+
+//-----------------------------------------------------------------------------
+// Synthetic ADC device
+
+typedef struct synth_adc_info {
+ synth_adc_channel_info *chan_info; // Channel infos
+ cyg_adc_channel *chan[NUM_CHANNELS]; // Channel references
+ cyg_uint32 chan_mask; // Active channels
+ cyg_handle_t alarm_handle; // Alarm handle
+ cyg_alarm alarm_data; // Alarm data
+ cyg_tick_count_t alarm_interval; // Alarm interval in ticks
+ cyg_uint32 alarm_samples; // Number of samples per tick
+} synth_adc_info;
+
+//-----------------------------------------------------------------------------
+// API function call forward references
+
+static bool synth_adc_init(struct cyg_devtab_entry *tab);
+static Cyg_ErrNo synth_adc_lookup(struct cyg_devtab_entry **tab,
+ struct cyg_devtab_entry *sub_tab,
+ const char *name);
+
+static void synth_adc_enable(cyg_adc_channel *chan);
+static void synth_adc_disable(cyg_adc_channel *chan);
+static void synth_adc_set_rate(cyg_adc_channel *chan, cyg_uint32 rate);
+
+static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data);
+
+static cyg_adc_sample_t synth_adc_get_sample_const(cyg_adc_channel *chan);
+static cyg_adc_sample_t synth_adc_get_sample_random(cyg_adc_channel *chan);
+static cyg_adc_sample_t synth_adc_get_sample_file(cyg_adc_channel *chan);
+
+static cyg_uint32 rand(void);
+
+CYG_ADC_FUNCTIONS(synth_adc_funs,
+ synth_adc_enable,
+ synth_adc_disable,
+ synth_adc_set_rate);
+
+//-----------------------------------------------------------------------------
+// Synthetic ADC channel info macro
+
+#define SYNTH_ADC_CHANNEL_INFO(_chan_) \
+{ \
+ .mode = CYGNUM_DEVS_ADC_SYNTH_CHANNEL##_chan_##_MODE, \
+ .const_value = CYGNUM_DEVS_ADC_SYNTH_CHANNEL##_chan_##_CONST_VALUE, \
+ .filename = CYGDAT_DEVS_ADC_SYNTH_CHANNEL##_chan_##_FILENAME, \
+}
+
+//-----------------------------------------------------------------------------
+// Synthetic ADC channel instance macro
+
+#define SYNTH_ADC_CHANNEL(_chan_) \
+CYG_ADC_CHANNEL( \
+ synth_adc_channel##_chan_, \
+ _chan_, \
+ CYGNUM_DEVS_ADC_SYNTH_CHANNEL##_chan_##_BUFSIZE, \
+ &synth_adc_device \
+); \
+DEVTAB_ENTRY( \
+ synth_adc_channel##_chan_##_device, \
+ CYGDAT_DEVS_ADC_SYNTH_CHANNEL##_chan_##_NAME, \
+ 0, \
+ &cyg_io_adc_devio, \
+ synth_adc_init, \
+ synth_adc_lookup, \
+ &synth_adc_channel##_chan_ \
+);
+
+//-----------------------------------------------------------------------------
+// Synthetic ADC device instance
+
+static synth_adc_channel_info synth_adc_channel_infos[NUM_CHANNELS] = {
+ SYNTH_ADC_CHANNEL_INFO(0),
+ SYNTH_ADC_CHANNEL_INFO(1),
+ SYNTH_ADC_CHANNEL_INFO(2),
+ SYNTH_ADC_CHANNEL_INFO(3),
+ SYNTH_ADC_CHANNEL_INFO(4),
+ SYNTH_ADC_CHANNEL_INFO(5),
+ SYNTH_ADC_CHANNEL_INFO(6),
+ SYNTH_ADC_CHANNEL_INFO(7),
+ SYNTH_ADC_CHANNEL_INFO(8),
+ SYNTH_ADC_CHANNEL_INFO(9),
+ SYNTH_ADC_CHANNEL_INFO(10),
+ SYNTH_ADC_CHANNEL_INFO(11),
+ SYNTH_ADC_CHANNEL_INFO(12),
+ SYNTH_ADC_CHANNEL_INFO(13),
+ SYNTH_ADC_CHANNEL_INFO(14),
+ SYNTH_ADC_CHANNEL_INFO(15),
+};
+
+static synth_adc_info synth_adc_info0 = {
+ .chan_info = synth_adc_channel_infos,
+};
+
+CYG_ADC_DEVICE(synth_adc_device,
+ &synth_adc_funs,
+ &synth_adc_info0,
+ CYGNUM_DEVS_ADC_SYNTH_DEFAULT_RATE);
+
+SYNTH_ADC_CHANNEL(0)
+SYNTH_ADC_CHANNEL(1)
+SYNTH_ADC_CHANNEL(2)
+SYNTH_ADC_CHANNEL(3)
+SYNTH_ADC_CHANNEL(4)
+SYNTH_ADC_CHANNEL(5)
+SYNTH_ADC_CHANNEL(6)
+SYNTH_ADC_CHANNEL(7)
+SYNTH_ADC_CHANNEL(8)
+SYNTH_ADC_CHANNEL(9)
+SYNTH_ADC_CHANNEL(10)
+SYNTH_ADC_CHANNEL(11)
+SYNTH_ADC_CHANNEL(12)
+SYNTH_ADC_CHANNEL(13)
+SYNTH_ADC_CHANNEL(14)
+SYNTH_ADC_CHANNEL(15)
+
+
+//-----------------------------------------------------------------------------
+// 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
+synth_adc_init(struct cyg_devtab_entry *tab)
+{
+ static cyg_bool initialized = false;
+ cyg_adc_channel *chan = (cyg_adc_channel *) tab->priv;
+ cyg_adc_device *device = chan->device;
+ synth_adc_info *info = device->dev_priv;
+ synth_adc_channel_info *chan_info = &info->chan_info[chan->channel];
+ cyg_handle_t counter;
+
+ adc_diag("Initializing device\n");
+
+ // Initialize channel
+ info->chan[chan->channel] = chan;
+ switch (chan_info->mode) {
+ case MODE_CONST:
+ chan_info->get_sample = synth_adc_get_sample_const;
+ break;
+ case MODE_RANDOM:
+ chan_info->get_sample = synth_adc_get_sample_random;
+ break;
+ case MODE_FILE:
+ chan_info->get_sample = synth_adc_get_sample_file;
+ break;
+ }
+
+ // Set default rate
+ if (!initialized) {
+ // Initialize alarm
+ cyg_clock_to_counter(cyg_real_time_clock(), &counter);
+ cyg_alarm_create(counter, alarm_handler, (cyg_addrword_t) device,
+ &info->alarm_handle, &info->alarm_data);
+
+ synth_adc_set_rate(chan, chan->device->config.rate);
+ initialized = true;
+ }
+
+ // 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
+synth_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;
+ synth_adc_info *info = chan->device->dev_priv;
+ synth_adc_channel_info *chan_info = &info->chan_info[chan->channel];
+
+ adc_diag("Opening device\n");
+
+ // When this channel is in file mode, initialize file access
+ if (chan_info->mode == MODE_FILE) {
+ struct cyg_hal_sys_new_stat stat;
+
+ // Open the file
+ chan_info->fd = cyg_hal_sys_open(chan_info->filename,
+ CYG_HAL_SYS_O_RDONLY, 0);
+ if (chan_info->fd == -ENOENT) {
+ adc_diag("Cannot open sampling file '%s' for channel '%s'\n",
+ chan_info->filename, (*tab)->name);
+ CYG_FAIL("Cannot open sampling file\n");
+ }
+
+ // Get file size
+ if (cyg_hal_sys_newfstat(chan_info->fd, &stat) != 0) {
+ CYG_FAIL("Cannot stat sampling file\n");
+ }
+ chan_info->num_samples = stat.st_size / sizeof(cyg_adc_sample_t);
+ if (chan_info->num_samples <= 0)
+ CYG_FAIL("Sampling file too small\n");
+
+ // Memory map
+ chan_info->base = (cyg_adc_sample_t *) cyg_hal_sys_mmap(
+ NULL,
+ chan_info->num_samples * sizeof(cyg_adc_sample_t),
+ CYG_HAL_SYS_PROT_READ,
+ CYG_HAL_SYS_MAP_SHARED,
+ chan_info->fd,
+ 0);
+ if (chan_info->base == (void *) -1)
+ CYG_FAIL("Cannot memory map sampling file\n");
+ chan_info->sample = chan_info->base;
+
+ adc_diag("Mapped to %p\n", chan_info->base);
+ }
+
+ // 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;
+ synth_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
+synth_adc_enable(cyg_adc_channel *chan)
+{
+ synth_adc_info *info = chan->device->dev_priv;
+ cyg_bool start;
+
+ adc_diag("Enabling channel\n");
+
+ start = !info->chan_mask;
+ info->chan_mask |= (1 << chan->channel);
+
+ // Start scanning when first channel was activated
+ if (start) {
+ // Enable timer
+ adc_diag("Starting scanning\n");
+ cyg_alarm_initialize(info->alarm_handle,
+ cyg_current_time() + info->alarm_interval,
+ info->alarm_interval);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// 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
+synth_adc_disable(cyg_adc_channel *chan)
+{
+ synth_adc_info *info = chan->device->dev_priv;
+
+ adc_diag("Disabling channel\n");
+
+ info->chan_mask &= ~(1 << chan->channel);
+
+ // Stop scanning when no channel is active
+ if (!info->chan_mask) {
+ // Disable timer
+ adc_diag("Stopping scanning\n");
+ cyg_alarm_disable(info->alarm_handle);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// 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
+synth_adc_set_rate(cyg_adc_channel *chan, cyg_uint32 rate)
+{
+ cyg_adc_device *device = chan->device;
+ synth_adc_info *info = device->dev_priv;
+ cyg_uint64 interval;
+
+ adc_diag("Setting rate to %d\n", rate);
+
+ interval = 1000000000000LL / rate;
+ interval /= (CYGNUM_HAL_RTC_NUMERATOR / CYGNUM_HAL_RTC_DENOMINATOR);
+
+ if (interval > 1000) {
+ info->alarm_interval = interval / 1000;
+ info->alarm_samples = 1;
+ } else {
+ info->alarm_interval = 1;
+ info->alarm_samples = 1000 / interval;
+ }
+
+ if (info->chan_mask)
+ cyg_alarm_initialize(info->alarm_handle,
+ cyg_current_time() + info->alarm_interval,
+ info->alarm_interval);
+
+ device->config.rate = rate;
+}
+
+static void
+alarm_handler(cyg_handle_t alarm, cyg_addrword_t data)
+{
+ cyg_adc_device *device = (cyg_adc_device *) data;
+ synth_adc_info *info = device->dev_priv;
+ cyg_adc_channel *chan;
+ synth_adc_channel_info *chan_info;
+ cyg_uint32 active_mask;
+ int i, j;
+
+ if (!info->chan_mask)
+ return;
+
+ active_mask = info->chan_mask;
+
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ if (active_mask & 0x01) {
+ chan = info->chan[i];
+ chan_info = &info->chan_info[chan->channel];
+ for (j = 0; j < info->alarm_samples; j++)
+ cyg_adc_receive_sample(chan, chan_info->get_sample(chan));
+ cyg_adc_wakeup(info->chan[i]);
+ }
+ active_mask >>= 1;
+ }
+}
+
+static cyg_adc_sample_t
+synth_adc_get_sample_const(cyg_adc_channel *chan)
+{
+ synth_adc_info *info = chan->device->dev_priv;
+ synth_adc_channel_info *chan_info = &info->chan_info[chan->channel];
+
+ return chan_info->const_value;
+}
+
+static cyg_adc_sample_t
+synth_adc_get_sample_random(cyg_adc_channel *chan)
+{
+ return rand() & SAMPLE_BITS;
+}
+
+static cyg_adc_sample_t
+synth_adc_get_sample_file(cyg_adc_channel *chan)
+{
+ synth_adc_info *info = chan->device->dev_priv;
+ synth_adc_channel_info *chan_info = &info->chan_info[chan->channel];
+ cyg_adc_sample_t sample;
+
+ sample = *chan_info->sample++;
+ if (chan_info->sample >= chan_info->base + chan_info->num_samples)
+ chan_info->sample = chan_info->base;
+
+ return sample;
+}
+
+//-----------------------------------------------------------------------------
+// Simple random number generator
+
+static cyg_uint32 rand(void)
+{
+ static cyg_uint32 seed;
+
+ seed = (seed * 1103515245) + 12345; // permutate seed
+
+ return seed;
+}
+