Mercurial > nand-ecoscentric
changeset 2842:8fe6d83b6d48
Add STM32 and synthetic target ADC drivers.
Also, some changes in Cortex-M and STM32 HALs.
See ChangeLogs for details.
line wrap: on
line diff
--- a/packages/ChangeLog +++ b/packages/ChangeLog @@ -1,3 +1,7 @@ +2009-03-04 Nick Garnett <nickg@ecoscentric.com> + + * ecos.db: Add ADC synthetic driver. Add STM32 ADC driver. + 2009-02-12 John Dallaway <john@dallaway.org.uk> * ecos.db: Make CYGPKG_DEVS_FLASH_SPI_M25PXX a hardware package.
new file mode 100644 --- /dev/null +++ b/packages/devs/adc/cortexm/stm32/current/ChangeLog @@ -0,0 +1,31 @@ +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 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#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/devs/adc/cortexm/stm32/current/cdl/adc_stm32.cdl @@ -0,0 +1,237 @@ +# ==================================================================== +# +# adc_stm32.cdl +# +# eCos STM32 ADC configuration data +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2009 Free Software Foundation, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later +## version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License +## along with eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Simon Kallweit <simon.kallweit@intefo.ch> +# Contributors: +# Date: 2009-02-24 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + + +cdl_package CYGPKG_DEVS_ADC_CORTEXM_STM32 { + display "ST STM32 ADC device driver" + + parent CYGPKG_IO_ADC_DEVICES + active_if CYGPKG_IO_ADC_DEVICES + active_if CYGPKG_HAL_CORTEXM_STM32 + requires {CYGNUM_IO_ADC_SAMPLE_SIZE >= 12} + description " + This option enables the ADC device drivers for the ST STM32. The STM32 + has up to 3 ADC devices. The driver supports both ADC1 and ADC3. ADC2 + is not supported as it does cover the same inputs as ADC2 and does not + support DMA directly." + + include_dir cyg/io + compile -library=libextras.a adc_stm32.c + + cdl_option CYGNUM_DEVS_ADC_CORTEXM_STM32_CLOCK_DIV { + display "ADC clock divider" + flavor data + legal_values { 2 4 6 8 } + default_value 8 + description " + This option specifies the level of debug data output by + the STM32 ADC device driver. A value of 0 signifies + no debug data output; 1 signifies normal debug data + output. If an overrun occurred then this can only be + detected by debug output messages." + } + + cdl_component CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1 { + display "ADC1" + 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." + } + } + } + } +}
new file mode 100644 --- /dev/null +++ b/packages/devs/adc/cortexm/stm32/current/src/adc1.inl @@ -0,0 +1,161 @@ +//========================================================================== +// +// 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 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
new file mode 100644 --- /dev/null +++ b/packages/devs/adc/cortexm/stm32/current/src/adc3.inl @@ -0,0 +1,153 @@ +//========================================================================== +// +// 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 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
new file mode 100644 --- /dev/null +++ b/packages/devs/adc/cortexm/stm32/current/src/adc_stm32.c @@ -0,0 +1,614 @@ +//========================================================================== +// +// adc_stm32.c +// +// ADC driver for STM32 on chip ADC +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Simon Kallweit <simon.kallweit@intefo.ch> +// Contributors: +// Date: 2009-02-24 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/system.h> +#include <pkgconf/devs_adc_cortexm_stm32.h> + +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_ass.h> +#include <cyg/io/adc.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_io.h> +#include <cyg/hal/hal_intr.h> +#include <cyg/hal/drv_api.h> + +//----------------------------------------------------------------------------- +// Diagnostic support +// Switch the #if to 1 to generate some diagnostic messages. + +#if 0 +#include <cyg/infra/diag.h> +#define adc_diag( __fmt, ... ) diag_printf("ADC: %30s[%4d]: " __fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__ ); +#else +#define adc_diag( __fmt, ... ) +#endif + + +//----------------------------------------------------------------------------- +// STM32 ADC device setup + +typedef struct stm32_adc_setup { + CYG_ADDRESS adc_base; // ADC registers base address + CYG_ADDRESS dma_base; // DMA registers base address + cyg_vector_t dma_int_vector; // DMA interrupt vector + cyg_priority_t dma_int_pri; // DMA interrupt priority + cyg_uint8 dma_channel; // DMA channel to use + CYG_ADDRESS tim_base; // Timer registers base address + const cyg_uint32 *pins; // ADC associated GPIO pins + cyg_uint8 extsel; // ADC EXTSEL value (timer event) + cyg_uint32 sample_time; // ADC sampling time in us +} stm32_adc_setup; + +//----------------------------------------------------------------------------- +// STM32 ADC device + +typedef struct stm32_adc_info { + const stm32_adc_setup *setup; // ADC setup + cyg_handle_t dma_int_handle; // DMA interrupt handle + cyg_interrupt dma_int_data; // DMA interrupt data + cyg_uint16 *dma_buf; // DMA buffer + cyg_adc_channel *chan[18]; // Channel references by channel no + cyg_uint32 chan_mask; // Channel mask +} stm32_adc_info; + +//----------------------------------------------------------------------------- +// API function call forward references + +static bool stm32_adc_init(struct cyg_devtab_entry *tab); +static Cyg_ErrNo stm32_adc_lookup(struct cyg_devtab_entry **tab, + struct cyg_devtab_entry *sub_tab, + const char *name); + +static void stm32_adc_enable(cyg_adc_channel *chan); +static void stm32_adc_disable(cyg_adc_channel *chan); +static void stm32_adc_set_rate(cyg_adc_channel *chan, cyg_uint32 rate); + +static cyg_uint32 stm32_dma_isr(cyg_vector_t vector, cyg_addrword_t data); +static void stm32_dma_dsr(cyg_vector_t vector, cyg_ucount32 count, + cyg_addrword_t data); + +static void stm32_adc_init_clock(void); +static void stm32_adc_init_device(cyg_adc_device *device); +static void stm32_adc_update_sequence(cyg_adc_device *device); + +CYG_ADC_FUNCTIONS(stm32_adc_funs, + stm32_adc_enable, + stm32_adc_disable, + stm32_adc_set_rate); + +//----------------------------------------------------------------------------- +// STM32 ADC channel instance macro + +#define STM32_ADC_CHANNEL(_device_, _chan_) \ +CYG_ADC_CHANNEL( \ + stm32_adc##_device_##_channel##_chan_, \ + _chan_, \ + CYGDAT_DEVS_ADC_CORTEXM_STM32_ADC##_device_##_CHANNEL##_chan_##_BUFSIZE,\ + &stm32_adc_device##_device_ \ +); \ +DEVTAB_ENTRY( \ + stm32_adc##_device_##_channel##_chan_##_device, \ + CYGDAT_DEVS_ADC_CORTEXM_STM32_ADC##_device_##_CHANNEL##_chan_##_NAME, \ + 0, \ + &cyg_io_adc_devio, \ + stm32_adc_init, \ + stm32_adc_lookup, \ + &stm32_adc##_device_##_channel##_chan_ \ +); + +//----------------------------------------------------------------------------- +// STM32 ADC device instances + +#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC1 +#include "adc1.inl" +#endif + +#ifdef CYGHWR_DEVS_ADC_CORTEXM_STM32_ADC3 +#include "adc3.inl" +#endif + +static cyg_bool initialized; +static cyg_uint32 adc_clock; + +__externC cyg_uint32 hal_stm32_pclk1; +__externC cyg_uint32 hal_stm32_pclk2; + +//----------------------------------------------------------------------------- +// This function is called from the device IO infrastructure to initialize the +// device. It should perform any work needed to start up the device, short of +// actually starting the generation of samples. This function will be called +// for each channel, so if there is initialization that only needs to be done +// once, such as creating and interrupt object, then care should be taken to do +// this. This function should also call cyg_adc_device_init() to initialize the +// generic parts of the driver. + +static bool +stm32_adc_init(struct cyg_devtab_entry *tab) +{ + cyg_adc_channel *chan = (cyg_adc_channel *) tab->priv; + cyg_adc_device *device = chan->device; + stm32_adc_info *info = device->dev_priv; + + adc_diag("Initializing device\n"); + + // Initialize ADC clock + if (!initialized) { + stm32_adc_init_clock(); + initialized = true; + } + + // Keep reference to channel + info->chan[chan->channel] = chan; + + if (!info->dma_int_handle) { + // Initialize ADC device + stm32_adc_init_device(device); + + // Set default rate + stm32_adc_set_rate(chan, chan->device->config.rate); + + // Initialize DMA interrupt + cyg_drv_interrupt_create(info->setup->dma_int_vector, + info->setup->dma_int_pri, + (cyg_addrword_t) device, + &stm32_dma_isr, + &stm32_dma_dsr, + &info->dma_int_handle, + &info->dma_int_data); + cyg_drv_interrupt_attach(info->dma_int_handle); + cyg_drv_interrupt_unmask(info->setup->dma_int_vector); + } + + // Initialize generic parts of ADC device + cyg_adc_device_init(device); + + return true; +} + +//----------------------------------------------------------------------------- +// This function is called when a client looks up or opens a channel. It should +// call cyg_adc_channel_init() to initialize the generic part of the channel. +// It should also perform any operations needed to start the channel generating +// samples. + +static Cyg_ErrNo +stm32_adc_lookup(struct cyg_devtab_entry **tab, + struct cyg_devtab_entry *sub_tab, + const char *name) +{ + cyg_adc_channel *chan = (cyg_adc_channel *) (*tab)->priv; + stm32_adc_info *info = chan->device->dev_priv; + cyg_uint32 cr; + + adc_diag("Opening device\n"); + + // Configure the input pin, if available + if (info->setup->pins[chan->channel] != CYGHWR_HAL_STM32_GPIO_NONE) + CYGHWR_HAL_STM32_GPIO_SET(info->setup->pins[chan->channel]); + + // Activate temperature and VREF if necessary + if (chan->channel >= 16) { + HAL_READ_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + cr |= CYGHWR_HAL_STM32_ADC_CR2_TSVREFE; + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + } + + // Initialize generic parts of the channel + cyg_adc_channel_init(chan); + + // The generic ADC manual says: When a channel is first looked up or + // opened, then it is automatically enabled and samples start to + // accumulate - so we start the channel now + chan->enabled = true; + stm32_adc_enable(chan); + + return ENOERR; +} + +//----------------------------------------------------------------------------- +// This function is called from the generic ADC package to enable the channel +// in response to a CYG_IO_SET_CONFIG_ADC_ENABLE config operation. It should +// take any steps needed to start the channel generating samples + +static void +stm32_adc_enable(cyg_adc_channel *chan) +{ + stm32_adc_info *info = chan->device->dev_priv; + cyg_uint32 cr; + cyg_bool start; + + adc_diag("Enabling channel\n"); + + start = !info->chan_mask; + + // Update the scanning sequence + info->chan_mask |= (1 << chan->channel); + stm32_adc_update_sequence(chan->device); + + // Start scanning when first channel was activated + if (start) { + // Enable timer + adc_diag("Starting scanning\n"); + HAL_READ_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR1, cr); + cr |= CYGHWR_HAL_STM32_TIM_CR1_CEN; + HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR1, cr); + } +} + +//----------------------------------------------------------------------------- +// This function is called from the generic ADC package to enable the channel +// in response to a CYG_IO_SET_CONFIG_ADC_DISABLE config operation. It should +// take any steps needed to stop the channel generating samples. + +static void +stm32_adc_disable(cyg_adc_channel *chan) +{ + stm32_adc_info *info = chan->device->dev_priv; + cyg_uint32 cr; + + adc_diag("Disabling channel\n"); + + // Update scanning sequence + info->chan_mask &= ~(1 << chan->channel); + stm32_adc_update_sequence(chan->device); + + // Stop scanning when no channel is active + if (!info->chan_mask) { + // Disable timer + adc_diag("Stopping scanning\n"); + HAL_READ_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR1, cr); + cr &= ~CYGHWR_HAL_STM32_TIM_CR1_CEN; + HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR1, cr); + } +} + +//----------------------------------------------------------------------------- +// This function is called from the generic ADC package to enable the channel +// in response to a CYG_IO_SET_CONFIG_ADC_RATE config operation. It should take +// any steps needed to change the sample rate of the channel, or of the entire +// device. We use a timer channel to generate the interrupts for sampling the +// analog channels + +static void +stm32_adc_set_rate( cyg_adc_channel *chan, cyg_uint32 rate) +{ + cyg_adc_device *device = chan->device; + stm32_adc_info *info = device->dev_priv; + cyg_uint32 clock; + cyg_uint32 period, prescaler; + cyg_uint32 cr; + + adc_diag("Setting rate to %d\n", rate); + + device->config.rate = rate; + + clock = hal_stm32_timer_clock(info->setup->tim_base); + + period = clock / rate; + prescaler = (period / 0x10000) + 1; + period = period / prescaler; + + HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_PSC, + prescaler - 1); + HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_ARR, + period - 1); + + // Set direction = down, clock divider = 1 + cr = CYGHWR_HAL_STM32_TIM_CR1_DIR | CYGHWR_HAL_STM32_TIM_CR1_CKD_1; + HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR1, cr); + + // Reinitialize timer + cr = CYGHWR_HAL_STM32_TIM_EGR_UG; + HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_EGR, cr); + + // Enable generation of TRGO event + cr = CYGHWR_HAL_STM32_TIM_CR2_MMS_UPDATE; + HAL_WRITE_UINT32(info->setup->tim_base + CYGHWR_HAL_STM32_TIM_CR2, cr); +} + +//----------------------------------------------------------------------------- +// This function is the ISR attached to the ADC device's DMA channel interrupt +// vector. It is responsible for reading samples from the DMA buffer and +// passing them on to the generic layer. + +static cyg_uint32 +stm32_dma_isr(cyg_vector_t vector, cyg_addrword_t data) +{ + cyg_adc_device *device = (cyg_adc_device *) data; + stm32_adc_info *info = (stm32_adc_info *) device->dev_priv; + cyg_uint32 chan_active = info->chan_mask; + cyg_uint16 *sample = info->dma_buf; + cyg_adc_channel **chan = info->chan; + cyg_uint32 res = 0; + + while (chan_active) { + if (chan_active & 0x1) + res |= (CYG_ISR_HANDLED | + cyg_adc_receive_sample(*chan, *sample++ & 0xfff)); + chan_active >>= 1; + chan++; + } + + HAL_WRITE_UINT32(info->setup->dma_base + CYGHWR_HAL_STM32_DMA_IFCR, + CYGHWR_HAL_STM32_DMA_IFCR_MASK(info->setup->dma_channel)); + + cyg_drv_interrupt_acknowledge(vector); + + return res; +} + +//----------------------------------------------------------------------------- +// This function is the DSR attached to the ADC device's DMA channel interrupt +// vector. It is called by the kernel if the ISR return value contains the +// CYG_ISR_CALL_DSR bit. It needs to call cyg_adc_wakeup() for each channel +// that has its wakeup field set. + +static void +stm32_dma_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + cyg_adc_device *device = (cyg_adc_device *) data; + stm32_adc_info *info = (stm32_adc_info *) device->dev_priv; + cyg_uint32 chan_active = info->chan_mask; + cyg_adc_channel **chan = info->chan; + + while (chan_active) { + if (chan_active & 0x1) + if ((*chan)->wakeup) + cyg_adc_wakeup(*chan); + chan_active >>= 1; + chan++; + } +} + +//----------------------------------------------------------------------------- +// Initializes the ADC system clock. + +static void +stm32_adc_init_clock(void) +{ + CYG_ADDRESS rcc = CYGHWR_HAL_STM32_RCC; + cyg_uint32 cfgr; + + adc_diag("Initializing ADC system clock\n"); + + HAL_READ_UINT32(rcc + CYGHWR_HAL_STM32_RCC_CFGR, cfgr); + cfgr &= ~CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_XXX; + +#if CYGNUM_DEVS_ADC_CORTEXM_STM32_CLOCK_DIV == 2 + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_2; + adc_clock = hal_stm32_pclk2 / 2; +#elif CYGNUM_DEVS_ADC_CORTEXM_STM32_CLOCK_DIV == 4 + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_4; + adc_clock = hal_stm32_pclk2 / 4; +#elif CYGNUM_DEVS_ADC_CORTEXM_STM32_CLOCK_DIV == 6 + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_6; + adc_clock = hal_stm32_pclk2 / 6; +#elif CYGNUM_DEVS_ADC_CORTEXM_STM32_CLOCK_DIV == 8 + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_8; + adc_clock = hal_stm32_pclk2 / 8; +#endif + + HAL_READ_UINT32(rcc + CYGHWR_HAL_STM32_RCC_CFGR, cfgr); +} + +//----------------------------------------------------------------------------- +// Initializes an ADC device. + +static void +stm32_adc_init_device(cyg_adc_device *device) +{ + stm32_adc_info *info = device->dev_priv; + cyg_uint32 cr; + cyg_uint64 tmp; + cyg_uint32 cycles; + cyg_uint32 smpr; + int i; + + static const cyg_uint32 cycles_table[] = + { 15, 75, 135, 285, 415, 555, 715, 2395 }; + + // Make sure ADC is powered on + cr = CYGHWR_HAL_STM32_ADC_CR2_ADON; + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + + // Reset calibration + cr |= CYGHWR_HAL_STM32_ADC_CR2_RSTCAL; + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + do { + HAL_READ_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + } while (cr & CYGHWR_HAL_STM32_ADC_CR2_RSTCAL); + + // Do calibration + cr |= CYGHWR_HAL_STM32_ADC_CR2_CAL; + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + do { + HAL_READ_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + } while (cr & CYGHWR_HAL_STM32_ADC_CR2_CAL); + + // Power off ADC + cr &= CYGHWR_HAL_STM32_ADC_CR2_ADON; + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + + // Enable external triggering and DMA + cr |= CYGHWR_HAL_STM32_ADC_CR2_DMA | + CYGHWR_HAL_STM32_ADC_CR2_EXTTRIG | + CYGHWR_HAL_STM32_ADC_CR2_EXTSEL(info->setup->extsel); + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + + // Enable scanning + cr = CYGHWR_HAL_STM32_ADC_CR1_SCAN; + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR1, cr); + + // Setup DMA channel + HAL_WRITE_UINT32(info->setup->dma_base + + CYGHWR_HAL_STM32_DMA_CPAR(info->setup->dma_channel), + info->setup->adc_base + CYGHWR_HAL_STM32_ADC_DR); + HAL_WRITE_UINT32(info->setup->dma_base + + CYGHWR_HAL_STM32_DMA_CMAR(info->setup->dma_channel), + (CYG_ADDRESS) info->dma_buf); + HAL_WRITE_UINT32(info->setup->dma_base + + CYGHWR_HAL_STM32_DMA_CNDTR(info->setup->dma_channel), + 0); + HAL_WRITE_UINT32(info->setup->dma_base + + CYGHWR_HAL_STM32_DMA_CCR(info->setup->dma_channel), + CYGHWR_HAL_STM32_DMA_CCR_TCIE | + CYGHWR_HAL_STM32_DMA_CCR_TEIE | + CYGHWR_HAL_STM32_DMA_CCR_CIRC | + CYGHWR_HAL_STM32_DMA_CCR_MINC | + CYGHWR_HAL_STM32_DMA_CCR_PSIZE16 | + CYGHWR_HAL_STM32_DMA_CCR_MSIZE16); + + // Compute duration of a single cycle in pico-seconds + tmp = 1000000000000LL / adc_clock; + // Compute tenths of cycles for target sample time + tmp = (info->setup->sample_time * 1000000 * 10) / tmp; + cycles = tmp; + + adc_diag("Setting ADC sample time to %d us (%d.%d cycles)\n", + info->setup->sample_time, cycles / 10, cycles % 10); + + // Find best matching SMPR value + if (cycles > cycles_table[7]) { + adc_diag("ADC sample time too long\n"); + smpr = 7; + } else { + for (smpr = 7; smpr > 0; smpr--) + if (cycles > cycles_table[smpr]) + break; + } + + // Expand SMPR value to all channels + for (i = 0; i < 10; i++) + smpr |= smpr << 3; + + // Set sampling time + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_SMPR1, smpr); + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_SMPR2, smpr); +} + +//----------------------------------------------------------------------------- +// Updates the sequence for the regular group. ADC and DMA are disabled during +// the update. The sequence registers and DMA count registers are rewritten. +// Note: As the regular group consists of 16 channels max, we cannot activate +// the theoretical maximum of 18 channels (analog ins + temperature/VREF). + +static void +stm32_adc_update_sequence(cyg_adc_device *device) +{ + stm32_adc_info *info = device->dev_priv; + int i; + int count = 0; + cyg_uint32 cr; + cyg_uint32 sqr1 = 0; + cyg_uint32 sqr2 = 0; + cyg_uint32 sqr3 = 0; + + adc_diag("Updateing regular group\n"); + + // Disable ADC + HAL_READ_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + cr &= ~CYGHWR_HAL_STM32_ADC_CR2_ADON; + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + + // Disable DMA + HAL_READ_UINT32(info->setup->dma_base + + CYGHWR_HAL_STM32_DMA_CCR(info->setup->dma_channel), cr); + cr &= ~CYGHWR_HAL_STM32_DMA_CCR_EN; + HAL_WRITE_UINT32(info->setup->dma_base + + CYGHWR_HAL_STM32_DMA_CCR(info->setup->dma_channel), cr); + + // Initialize scanning sequence (regular group) + for (i = 0; i < 18; i++) { + if (!(info->chan_mask & (1 << i))) + continue; + + if (count < 6) { + sqr3 |= CYGHWR_HAL_STM32_ADC_SQRx_SQ(count, i); + } else if (count < 12) { + sqr2 |= CYGHWR_HAL_STM32_ADC_SQRx_SQ(count - 6, i); + } else if (count < 16) { + sqr1 |= CYGHWR_HAL_STM32_ADC_SQRx_SQ(count - 12, i); + } else { + CYG_FAIL("Too many active channels\n"); + } + count++; + } + + sqr1 |= CYGHWR_HAL_STM32_ADC_SQR1_L(count - 1); + + adc_diag("sqr1: %p sqr2: %p sqr3: %p\n", + (void *) sqr1, (void *) sqr2, (void *) sqr3); + + // Write sequence registers + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_SQR1, sqr1); + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_SQR2, sqr2); + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_SQR3, sqr3); + + // Update DMA + HAL_WRITE_UINT32(info->setup->dma_base + + CYGHWR_HAL_STM32_DMA_CNDTR(info->setup->dma_channel), + count); + + // Enable DMA + HAL_READ_UINT32(info->setup->dma_base + + CYGHWR_HAL_STM32_DMA_CCR(info->setup->dma_channel), cr); + cr |= CYGHWR_HAL_STM32_DMA_CCR_EN; + HAL_WRITE_UINT32(info->setup->dma_base + + CYGHWR_HAL_STM32_DMA_CCR(info->setup->dma_channel), cr); + + // Enable ADC + HAL_READ_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); + cr |= CYGHWR_HAL_STM32_ADC_CR2_ADON; + HAL_WRITE_UINT32(info->setup->adc_base + CYGHWR_HAL_STM32_ADC_CR2, cr); +} + +//----------------------------------------------------------------------------- +// End of adc_stm32.c
new file mode 100644 --- /dev/null +++ b/packages/devs/adc/synth/current/ChangeLog @@ -0,0 +1,29 @@ +2009-02-27 Simon Kallweit <simon.kallweit@intefo.ch> + + * Synthethic ADC driver package created + * cdl/adc_synth.cdl + * src/adc_synth.c + +//=========================================================================== +// ####GPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 or (at your option) any +// later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., 51 Franklin Street, +// Fifth Floor, Boston, MA 02110-1301, USA. +// ------------------------------------------- +// ####GPLCOPYRIGHTEND#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/devs/adc/synth/current/cdl/adc_synth.cdl @@ -0,0 +1,158 @@ +# ==================================================================== +# +# adc_synth.cdl +# +# eCos Synthethic 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 + } + } + } +}
new file mode 100644 --- /dev/null +++ b/packages/devs/adc/synth/current/src/adc_synth.c @@ -0,0 +1,482 @@ +//========================================================================== +// +// adc_synth.c +// +// ADC driver for Synthethic 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; + +//----------------------------------------------------------------------------- +// Synthethic 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); + +//----------------------------------------------------------------------------- +// Synthethic 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, \ +} + +//----------------------------------------------------------------------------- +// Synthethic 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_ \ +); + +//----------------------------------------------------------------------------- +// Synthethic 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; +} +
--- a/packages/ecos.db +++ b/packages/ecos.db @@ -2421,6 +2421,15 @@ package CYGPKG_DEVS_ADC_ARM_LPC24XX { ADC provided by the LPC24xx processor family." } +package CYGPKG_DEVS_ADC_SYNTH { + alias { "Synthethic ADC driver" adc_synth } + hardware + directory devs/adc/synth + script adc_synth.cdl + description " + This package provides an ADC driver for the Synthethic target." +} + package CYGPKG_IO_ADC { alias { "Generic ADC support" adc io_adc } directory io/adc @@ -5630,7 +5639,8 @@ target linux { CYGPKG_DEVS_ETH_ECOSYNTH CYGPKG_DEVS_WATCHDOG_SYNTH CYGPKG_DEVS_WALLCLOCK_SYNTH - CYGPKG_DEVS_FRAMEBUF_SYNTH + CYGPKG_DEVS_FRAMEBUF_SYNTH + CYGPKG_DEVS_ADC_SYNTH } description " The linux target provides the @@ -6848,6 +6858,16 @@ package CYGPKG_DEVS_WALLCLOCK_STM32 { STM32 controller and compatibles" } +package CYGPKG_DEVS_ADC_CORTEXM_STM32 { + alias { "STM32 ADC driver" adc_stm32 } + hardware + directory devs/adc/cortexm/stm32 + script adc_stm32.cdl + description " + This package provides a driver for the ADC interfaces found on the + ST STM32 microcontroller family." +} + target stm3210e_eval { alias { "ST STM3210E EVAL board" stm3210e } packages { CYGPKG_HAL_CORTEXM @@ -6860,6 +6880,7 @@ target stm3210e_eval { CYGPKG_DEVS_WALLCLOCK_STM32 CYGPKG_IO_SPI CYGPKG_DEVS_SPI_CORTEXM_STM32 + CYGPKG_DEVS_ADC_CORTEXM_STM32 } description "The stm3210e_eval target provides the packages needed to run eCos on the STM3210E EVAL board."
--- a/packages/hal/cortexm/arch/current/ChangeLog +++ b/packages/hal/cortexm/arch/current/ChangeLog @@ -1,3 +1,7 @@ +2009-02-27 Simon Kallweit <simon.kallweit@intefo.ch> + + * include/hal_io.h: Added system control register definitions + 2009-02-13 Nick Garnett <nickg@ecoscentric.com> * include/hal_arch.h: Add include for var_arch.h.
--- a/packages/hal/cortexm/arch/current/include/hal_io.h +++ b/packages/hal/cortexm/arch/current/include/hal_io.h @@ -190,6 +190,12 @@ #define CYGARC_REG_NVIC_AIRCR_VECTCLRACTIVE BIT_(1) #define CYGARC_REG_NVIC_AIRCR_VECTRESET BIT_(0) +// SCR + +#define CYGARC_REG_NVIC_SCR_SLEEPONEXIT BIT_(1) +#define CYGARC_REG_NVIC_SCR_DEEPSLEEP BIT_(2) +#define CYGARC_REG_NVIC_SCR_SEVONPEND BIT_(4) + // SHCSR #define CYGARC_REG_NVIC_SHCSR_USGFAULTENA BIT_(18)
--- a/packages/hal/cortexm/stm32/var/current/ChangeLog +++ b/packages/hal/cortexm/stm32/var/current/ChangeLog @@ -1,3 +1,15 @@ +2009-02-27 Simon Kallweit <simon.kallweit@intefo.ch> + + * include/var_io.h: + Add mask for CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE. + Fixed CYGHWR_HAL_STM32_RTC_CRL_ALRF. + Add register definitions for ADC. + Add additional timer registers. + * src/stm32_mis.c: + Moved system clock initialization into it's own function, so it can + be called after wakeup from sleep modes. + Added hal_stm32_timer_clock() to get current clock of timers. + 2009-02-10 Chris Holgate <chris@zynaptic.com> * include/var_io.h: Add mask for CYGHWR_HAL_STM32_AFIO_MAPR_SWJ.
--- a/packages/hal/cortexm/stm32/var/current/include/var_io.h +++ b/packages/hal/cortexm/stm32/var/current/include/var_io.h @@ -177,6 +177,7 @@ #define CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_4 VALUE_(14,1) #define CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_6 VALUE_(14,2) #define CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_8 VALUE_(14,3) +#define CYGHWR_HAL_STM32_RCC_CFGR_ADCPRE_XXX VALUE_(14,3) #define CYGHWR_HAL_STM32_RCC_CFGR_PLLSRC_HSI 0 #define CYGHWR_HAL_STM32_RCC_CFGR_PLLSRC_HSE BIT_(16) #define CYGHWR_HAL_STM32_RCC_CFGR_PLLXTPRE BIT_(17) @@ -279,7 +280,7 @@ // CRL fields #define CYGHWR_HAL_STM32_RTC_CRL_SECF BIT_(0) -#define CYGHWR_HAL_STM32_RTC_CRL_ALRCF BIT_(1) +#define CYGHWR_HAL_STM32_RTC_CRL_ALRF BIT_(1) #define CYGHWR_HAL_STM32_RTC_CRL_OWF BIT_(2) #define CYGHWR_HAL_STM32_RTC_CRL_RSF BIT_(3) #define CYGHWR_HAL_STM32_RTC_CRL_CNF BIT_(4) @@ -607,6 +608,159 @@ #endif //============================================================================= +// ADCs + +#define CYGHWR_HAL_STM32_ADC_SR 0x00 +#define CYGHWR_HAL_STM32_ADC_CR1 0x04 +#define CYGHWR_HAL_STM32_ADC_CR2 0x08 +#define CYGHWR_HAL_STM32_ADC_SMPR1 0x0C +#define CYGHWR_HAL_STM32_ADC_SMPR2 0x10 +#define CYGHWR_HAL_STM32_ADC_JOFR(__x) 0x14 + ((__x) << 2) +#define CYGHWR_HAL_STM32_ADC_HTR 0x24 +#define CYGHWR_HAL_STM32_ADC_LTR 0x28 +#define CYGHWR_HAL_STM32_ADC_SQR1 0x2C +#define CYGHWR_HAL_STM32_ADC_SQR2 0x30 +#define CYGHWR_HAL_STM32_ADC_SQR3 0x34 +#define CYGHWR_HAL_STM32_ADC_JSQR 0x38 +#define CYGHWR_HAL_STM32_ADC_JDR(__x) 0x3C + ((__x) << 2) +#define CYGHWR_HAL_STM32_ADC_DR 0x4C + +// SR fields + +#define CYGHWR_HAL_STM32_ADC_SR_AWD BIT_(0) +#define CYGHWR_HAL_STM32_ADC_SR_EOC BIT_(1) +#define CYGHWR_HAL_STM32_ADC_SR_JEOC BIT_(2) +#define CYGHWR_HAL_STM32_ADC_SR_JSTRT BIT_(3) +#define CYGHWR_HAL_STM32_ADC_SR_STRT BIT_(4) + +// CR1 fields + +#define CYGHWR_HAL_STM32_ADC_CR1_AWDCH(__x) VALUE_(0,(__x)) +#define CYGHWR_HAL_STM32_ADC_CR1_EOCIE BIT_(5) +#define CYGHWR_HAL_STM32_ADC_CR1_AWDIE BIT_(6) +#define CYGHWR_HAL_STM32_ADC_CR1_JEOCIE BIT_(7) +#define CYGHWR_HAL_STM32_ADC_CR1_SCAN BIT_(8) +#define CYGHWR_HAL_STM32_ADC_CR1_AWDSGL BIT_(9) +#define CYGHWR_HAL_STM32_ADC_CR1_JAUTO BIT_(10) +#define CYGHWR_HAL_STM32_ADC_CR1_DISCEN BIT_(11) +#define CYGHWR_HAL_STM32_ADC_CR1_JDISCEN BIT_(12) +#define CYGHWR_HAL_STM32_ADC_CR1_DISCNUM(__x) VALUE_(13,(__x)) +#define CYGHWR_HAL_STM32_ADC_CR1_DUALMODE(__x) VALUE_(16,(__x)) +#define CYGHWR_HAL_STM32_ADC_CR1_JAWDEN BIT_(22) +#define CYGHWR_HAL_STM32_ADC_CR1_AWDEN BIT_(23) + +// CR2 fields + +#define CYGHWR_HAL_STM32_ADC_CR2_ADON BIT_(0) +#define CYGHWR_HAL_STM32_ADC_CR2_CONT BIT_(1) +#define CYGHWR_HAL_STM32_ADC_CR2_CAL BIT_(2) +#define CYGHWR_HAL_STM32_ADC_CR2_RSTCAL BIT_(3) +#define CYGHWR_HAL_STM32_ADC_CR2_DMA BIT_(8) +#define CYGHWR_HAL_STM32_ADC_CR2_ALIGN BIT_(11) +#define CYGHWR_HAL_STM32_ADC_CR2_JEXTSEL(__x) VALUE_(12,(__x)) +#define CYGHWR_HAL_STM32_ADC_CR2_JEXTTRIG BIT_(15) +#define CYGHWR_HAL_STM32_ADC_CR2_EXTSEL(__x) VALUE_(17,(__x)) +#define CYGHWR_HAL_STM32_ADC_CR2_EXTTRIG BIT_(20) +#define CYGHWR_HAL_STM32_ADC_CR2_JSWSTART BIT_(21) +#define CYGHWR_HAL_STM32_ADC_CR2_SWSTART BIT_(22) +#define CYGHWR_HAL_STM32_ADC_CR2_TSVREFE BIT_(23) + +// SMPRx fields + +#define CYGHWR_HAL_STM32_ADC_SMPRx_SMP(__x, __y) VALUE_((__x) * 3, (__y)) + +// SQRx fields + +#define CYGHWR_HAL_STM32_ADC_SQR1_L(__x) VALUE_(20, (__x)) +#define CYGHWR_HAL_STM32_ADC_SQRx_SQ(__x, __y) VALUE_((__x) * 5, (__y)) + +// JSQR fields + +#define CYGHWR_HAL_STM32_ADC_JSQR_SQ(__x, __y) VALUE_((__x) * 5, (__y)) + +// ADC GPIO pins + +#define CYGHWR_HAL_STM32_ADC123_IN0 CYGHWR_HAL_STM32_GPIO( A, 0, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC123_IN1 CYGHWR_HAL_STM32_GPIO( A, 1, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC123_IN2 CYGHWR_HAL_STM32_GPIO( A, 2, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC123_IN3 CYGHWR_HAL_STM32_GPIO( A, 3, IN, ANALOG ) + +#define CYGHWR_HAL_STM32_ADC12_IN4 CYGHWR_HAL_STM32_GPIO( A, 4, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC12_IN5 CYGHWR_HAL_STM32_GPIO( A, 5, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC12_IN6 CYGHWR_HAL_STM32_GPIO( A, 6, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC12_IN7 CYGHWR_HAL_STM32_GPIO( A, 7, IN, ANALOG ) + +#define CYGHWR_HAL_STM32_ADC12_IN8 CYGHWR_HAL_STM32_GPIO( B, 0, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC12_IN9 CYGHWR_HAL_STM32_GPIO( B, 1, IN, ANALOG ) + +#define CYGHWR_HAL_STM32_ADC3_IN4 CYGHWR_HAL_STM32_GPIO( F, 6, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC3_IN5 CYGHWR_HAL_STM32_GPIO( F, 7, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC3_IN6 CYGHWR_HAL_STM32_GPIO( F, 8, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC3_IN7 CYGHWR_HAL_STM32_GPIO( F, 9, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC3_IN8 CYGHWR_HAL_STM32_GPIO( F, 10, IN, ANALOG ) + +#define CYGHWR_HAL_STM32_ADC123_IN10 CYGHWR_HAL_STM32_GPIO( C, 0, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC123_IN11 CYGHWR_HAL_STM32_GPIO( C, 1, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC123_IN12 CYGHWR_HAL_STM32_GPIO( C, 2, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC123_IN13 CYGHWR_HAL_STM32_GPIO( C, 3, IN, ANALOG ) + +#define CYGHWR_HAL_STM32_ADC12_IN14 CYGHWR_HAL_STM32_GPIO( C, 4, IN, ANALOG ) +#define CYGHWR_HAL_STM32_ADC12_IN15 CYGHWR_HAL_STM32_GPIO( C, 5, IN, ANALOG ) + +// ADC1 GPIO pin aliases + +#define CYGHWR_HAL_STM32_ADC1_IN0 CYGHWR_HAL_STM32_ADC123_IN0 +#define CYGHWR_HAL_STM32_ADC1_IN1 CYGHWR_HAL_STM32_ADC123_IN1 +#define CYGHWR_HAL_STM32_ADC1_IN2 CYGHWR_HAL_STM32_ADC123_IN2 +#define CYGHWR_HAL_STM32_ADC1_IN3 CYGHWR_HAL_STM32_ADC123_IN3 +#define CYGHWR_HAL_STM32_ADC1_IN4 CYGHWR_HAL_STM32_ADC12_IN4 +#define CYGHWR_HAL_STM32_ADC1_IN5 CYGHWR_HAL_STM32_ADC12_IN5 +#define CYGHWR_HAL_STM32_ADC1_IN6 CYGHWR_HAL_STM32_ADC12_IN6 +#define CYGHWR_HAL_STM32_ADC1_IN7 CYGHWR_HAL_STM32_ADC12_IN7 +#define CYGHWR_HAL_STM32_ADC1_IN8 CYGHWR_HAL_STM32_ADC12_IN8 +#define CYGHWR_HAL_STM32_ADC1_IN9 CYGHWR_HAL_STM32_ADC12_IN9 +#define CYGHWR_HAL_STM32_ADC1_IN10 CYGHWR_HAL_STM32_ADC123_IN10 +#define CYGHWR_HAL_STM32_ADC1_IN11 CYGHWR_HAL_STM32_ADC123_IN11 +#define CYGHWR_HAL_STM32_ADC1_IN12 CYGHWR_HAL_STM32_ADC123_IN12 +#define CYGHWR_HAL_STM32_ADC1_IN13 CYGHWR_HAL_STM32_ADC123_IN13 +#define CYGHWR_HAL_STM32_ADC1_IN14 CYGHWR_HAL_STM32_ADC12_IN14 +#define CYGHWR_HAL_STM32_ADC1_IN15 CYGHWR_HAL_STM32_ADC12_IN15 + +// ADC2 GPIO pin aliases + +#define CYGHWR_HAL_STM32_ADC2_IN0 CYGHWR_HAL_STM32_ADC123_IN0 +#define CYGHWR_HAL_STM32_ADC2_IN1 CYGHWR_HAL_STM32_ADC123_IN1 +#define CYGHWR_HAL_STM32_ADC2_IN2 CYGHWR_HAL_STM32_ADC123_IN2 +#define CYGHWR_HAL_STM32_ADC2_IN3 CYGHWR_HAL_STM32_ADC123_IN3 +#define CYGHWR_HAL_STM32_ADC2_IN4 CYGHWR_HAL_STM32_ADC12_IN4 +#define CYGHWR_HAL_STM32_ADC2_IN5 CYGHWR_HAL_STM32_ADC12_IN5 +#define CYGHWR_HAL_STM32_ADC2_IN6 CYGHWR_HAL_STM32_ADC12_IN6 +#define CYGHWR_HAL_STM32_ADC2_IN7 CYGHWR_HAL_STM32_ADC12_IN7 +#define CYGHWR_HAL_STM32_ADC2_IN8 CYGHWR_HAL_STM32_ADC12_IN8 +#define CYGHWR_HAL_STM32_ADC2_IN9 CYGHWR_HAL_STM32_ADC12_IN9 +#define CYGHWR_HAL_STM32_ADC2_IN10 CYGHWR_HAL_STM32_ADC123_IN10 +#define CYGHWR_HAL_STM32_ADC2_IN11 CYGHWR_HAL_STM32_ADC123_IN11 +#define CYGHWR_HAL_STM32_ADC2_IN12 CYGHWR_HAL_STM32_ADC123_IN12 +#define CYGHWR_HAL_STM32_ADC2_IN13 CYGHWR_HAL_STM32_ADC123_IN13 +#define CYGHWR_HAL_STM32_ADC2_IN14 CYGHWR_HAL_STM32_ADC12_IN14 +#define CYGHWR_HAL_STM32_ADC2_IN15 CYGHWR_HAL_STM32_ADC12_IN15 + +// ADC3 GPIO pin aliases + +#define CYGHWR_HAL_STM32_ADC3_IN0 CYGHWR_HAL_STM32_ADC123_IN0 +#define CYGHWR_HAL_STM32_ADC3_IN1 CYGHWR_HAL_STM32_ADC123_IN1 +#define CYGHWR_HAL_STM32_ADC3_IN2 CYGHWR_HAL_STM32_ADC123_IN2 +#define CYGHWR_HAL_STM32_ADC3_IN3 CYGHWR_HAL_STM32_ADC123_IN3 +// Inputs 4 - 8 are already defined +#define CYGHWR_HAL_STM32_ADC3_IN9 CYGHWR_HAL_STM32_GPIO_NONE +#define CYGHWR_HAL_STM32_ADC3_IN10 CYGHWR_HAL_STM32_ADC123_IN10 +#define CYGHWR_HAL_STM32_ADC3_IN11 CYGHWR_HAL_STM32_ADC123_IN11 +#define CYGHWR_HAL_STM32_ADC3_IN12 CYGHWR_HAL_STM32_ADC123_IN12 +#define CYGHWR_HAL_STM32_ADC3_IN13 CYGHWR_HAL_STM32_ADC123_IN13 +#define CYGHWR_HAL_STM32_ADC3_IN14 CYGHWR_HAL_STM32_GPIO_NONE +#define CYGHWR_HAL_STM32_ADC3_IN15 CYGHWR_HAL_STM32_GPIO_NONE + +//============================================================================= // SPI interface register definitions. #define CYGHWR_HAL_STM32_SPI_CR1 0x00 @@ -768,15 +922,27 @@ #define CYGHWR_HAL_STM32_TIM_DIER 0x0C #define CYGHWR_HAL_STM32_TIM_SR 0x10 #define CYGHWR_HAL_STM32_TIM_EGR 0x14 +#define CYGHWR_HAL_STM32_TIM_CCMR1 0x18 +#define CYGHWR_HAL_STM32_TIM_CCMR2 0x1C +#define CYGHWR_HAL_STM32_TIM_CCER 0x20 #define CYGHWR_HAL_STM32_TIM_CNT 0x24 #define CYGHWR_HAL_STM32_TIM_PSC 0x28 #define CYGHWR_HAL_STM32_TIM_ARR 0x2C +#define CYGHWR_HAL_STM32_TIM_CCR1 0x34 +#define CYGHWR_HAL_STM32_TIM_CCR2 0x38 +#define CYGHWR_HAL_STM32_TIM_CCR3 0x3C +#define CYGHWR_HAL_STM32_TIM_CCR4 0x40 #define CYGHWR_HAL_STM32_TIM_CR1_CEN BIT_(0) #define CYGHWR_HAL_STM32_TIM_CR1_UDIS BIT_(1) #define CYGHWR_HAL_STM32_TIM_CR1_URS BIT_(2) #define CYGHWR_HAL_STM32_TIM_CR1_OPM BIT_(3) +#define CYGHWR_HAL_STM32_TIM_CR1_DIR BIT_(4) #define CYGHWR_HAL_STM32_TIM_CR1_ARPE BIT_(7) +#define CYGHWR_HAL_STM32_TIM_CR1_CKD_1 VALUE_(8,0) +#define CYGHWR_HAL_STM32_TIM_CR1_CKD_2 VALUE_(8,1) +#define CYGHWR_HAL_STM32_TIM_CR1_CKD_4 VALUE_(8,2) +#define CYGHWR_HAL_STM32_TIM_CR1_CKD_XXX VALUE_(8,3) #define CYGHWR_HAL_STM32_TIM_CR2_MMS_RESET VALUE_(4,0) #define CYGHWR_HAL_STM32_TIM_CR2_MMS_ENABLE VALUE_(4,1) @@ -789,6 +955,12 @@ #define CYGHWR_HAL_STM32_TIM_EGR_UG BIT_(0) +#ifndef __ASSEMBLER__ + +__externC cyg_uint32 hal_stm32_timer_clock( CYG_ADDRESS base ); + +#endif + //============================================================================= // Flash controller @@ -867,8 +1039,12 @@ // Functions and macros to reset the backup domain as well as // enable/disable backup domain write protection. +#ifndef __ASSEMBLER__ + __externC void hal_stm32_bd_protect( int protect ); +#endif + #define CYGHWR_HAL_STM32_BD_RESET() \ CYG_MACRO_START \ HAL_WRITE_UINT32(CYGHWR_HAL_STM32_RCC+CYGHWR_HAL_STM32_RCC_BDCR, \
--- a/packages/hal/cortexm/stm32/var/current/src/stm32_misc.c +++ b/packages/hal/cortexm/stm32/var/current/src/stm32_misc.c @@ -122,6 +122,7 @@ cyg_uint32 hal_stm32_pclk1; cyg_uint32 hal_stm32_pclk2; cyg_uint32 hal_cortexm_systick_clock; +void hal_start_clocks( void ); cyg_uint32 hal_exti_isr( cyg_uint32 vector, CYG_ADDRWORD data ); //========================================================================== @@ -131,93 +132,16 @@ void hal_variant_init( void ) CYG_ADDRESS rcc = CYGHWR_HAL_STM32_RCC; // Enable all devices in RCC - { - HAL_WRITE_UINT32( CYGHWR_HAL_STM32_RCC+CYGHWR_HAL_STM32_RCC_APB2ENR, 0xFFFFFFFF ); - HAL_WRITE_UINT32( CYGHWR_HAL_STM32_RCC+CYGHWR_HAL_STM32_RCC_APB1ENR, 0xFFFFFFFF ); - } - + HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_APB2ENR, 0xFFFFFFFF ); + HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_APB1ENR, 0xFFFFFFFF ); #if 1 //!defined(CYG_HAL_STARTUP_RAM) - // Set up clocks from configuration. In the future this should be moved to a - // function so that clock rates can be changed at runtime. - { - cyg_uint32 cr, cfgr; - - // Reset RCC - - HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, 0x00000001 ); - - // Start up HSE clock - - HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); - cr &= CYGHWR_HAL_STM32_RCC_CR_HSEON|CYGHWR_HAL_STM32_RCC_CR_HSEBYP; - HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); - - HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); - cr |= CYGHWR_HAL_STM32_RCC_CR_HSEON; - HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); - - // Wait for HSE clock to startup - do - { - HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); - } while( !(cr & CYGHWR_HAL_STM32_RCC_CR_HSERDY) ); - -// HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CFGR, cfgr ); - - // Configure clocks - - hal_stm32_sysclk = CYGARC_HAL_CORTEXM_STM32_INPUT_CLOCK; - - cfgr = 0; - -#if defined(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_SOURCE_HSE) - cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PLLSRC_HSE; -#elif defined(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_SOURCE_HSE_HALF) - cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PLLSRC_HSE | - CYGHWR_HAL_STM32_RCC_CFGR_PLLXTPRE; - hal_stm32_sysclk /= 2; -#elif defined(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_SOURCE_HSI_HALF) - hal_stm32_sysclk /= 2; -#endif - - cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PLLMUL(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_MUL); - cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_HPRE; - cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PPRE1; - cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PPRE2; - - HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CFGR, cfgr ); - - // Enable the PLL and wait for it to lock - - cr |= CYGHWR_HAL_STM32_RCC_CR_PLLON; - - HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); - do - { - HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); - } while( !(cr & CYGHWR_HAL_STM32_RCC_CR_PLLRDY) ); - - // Now switch to use PLL as SYSCLK - - cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_SW_PLL; - - HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CFGR, cfgr ); - - // Calculate clocks from configuration - - hal_stm32_sysclk *= CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_MUL; - hal_stm32_hclk = hal_stm32_sysclk / CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV; - hal_stm32_pclk1 = hal_stm32_hclk / CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV; - hal_stm32_pclk2 = hal_stm32_hclk / CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV; - hal_cortexm_systick_clock = hal_stm32_hclk / 8; - } + hal_start_clocks(); #endif // Attach EXTI springboard to interrupt vectors HAL_INTERRUPT_ATTACH( CYGNUM_HAL_INTERRUPT_EXTI9_5, hal_exti_isr, 0, 0 ); HAL_INTERRUPT_ATTACH( CYGNUM_HAL_INTERRUPT_EXTI15_10, hal_exti_isr, 0, 0 ); - #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT hal_if_init(); @@ -225,6 +149,91 @@ void hal_variant_init( void ) } //========================================================================== +// Setup up system clocks +// +// Set up clocks from configuration. In the future this should be extended so +// that clock rates can be changed at runtime. + +void hal_start_clocks( void ) +{ + CYG_ADDRESS rcc = CYGHWR_HAL_STM32_RCC; + cyg_uint32 cr, cfgr; + + // Reset RCC + + HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, 0x00000001 ); + + // Start up HSE clock + + HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); + cr &= CYGHWR_HAL_STM32_RCC_CR_HSEON|CYGHWR_HAL_STM32_RCC_CR_HSEBYP; + HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); + + HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); + cr |= CYGHWR_HAL_STM32_RCC_CR_HSEON; + HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); + + // Wait for HSE clock to startup + + do + { + HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); + } while( !(cr & CYGHWR_HAL_STM32_RCC_CR_HSERDY) ); + + // Configure clocks + + hal_stm32_sysclk = CYGARC_HAL_CORTEXM_STM32_INPUT_CLOCK; + + cfgr = 0; + +#if defined(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_SOURCE_HSE) + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PLLSRC_HSE; +#elif defined(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_SOURCE_HSE_HALF) + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PLLSRC_HSE | + CYGHWR_HAL_STM32_RCC_CFGR_PLLXTPRE; + hal_stm32_sysclk /= 2; +#elif defined(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_SOURCE_HSI_HALF) + hal_stm32_sysclk /= 2; +#endif + + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PLLMUL(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_MUL); + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_HPRE; + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PPRE1; + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PPRE2; + + HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CFGR, cfgr ); + + // Enable the PLL and wait for it to lock + + cr |= CYGHWR_HAL_STM32_RCC_CR_PLLON; + + HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); + do + { + HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); + } while( !(cr & CYGHWR_HAL_STM32_RCC_CR_PLLRDY) ); + + // Now switch to use PLL as SYSCLK + + cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_SW_PLL; + + HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CFGR, cfgr ); + do + { + HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CFGR, cfgr ); + } while( (cfgr & CYGHWR_HAL_STM32_RCC_CFGR_SWS_XXX) != + CYGHWR_HAL_STM32_RCC_CFGR_SWS_PLL ); + + // Calculate clocks from configuration + + hal_stm32_sysclk *= CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_MUL; + hal_stm32_hclk = hal_stm32_sysclk / CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV; + hal_stm32_pclk1 = hal_stm32_hclk / CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV; + hal_stm32_pclk2 = hal_stm32_hclk / CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV; + hal_cortexm_systick_clock = hal_stm32_hclk / 8; +} + +//========================================================================== // ISR springboard // // This is attached to the ISR table entries for EXTI9_5 and EXTI15_10 @@ -354,4 +363,28 @@ void hal_stm32_uart_setbaud( cyg_uint32 } //========================================================================== +// Timer clock rate +// +// Returns the current timer clock rate of a timer. + +cyg_uint32 hal_stm32_timer_clock( CYG_ADDRESS base ) +{ + if( base == CYGHWR_HAL_STM32_TIM1 || + base == CYGHWR_HAL_STM32_TIM8 ) + { +#if CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV == 1 + return hal_stm32_pclk2; +#else + return hal_stm32_pclk2 << 1; +#endif + } else { +#if CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV == 1 + return hal_stm32_pclk1; +#else + return hal_stm32_pclk1 << 1; +#endif + } +} + +//========================================================================== // EOF stm32_misc.c
--- a/packages/io/adc/current/ChangeLog +++ b/packages/io/adc/current/ChangeLog @@ -1,3 +1,10 @@ +2009-03-02 Simon Kallweit <simon.kallweit@intefo.ch> + + * cdl/io_adc.cdl: + * tests/adc1.c: + * tests/adc2.c: + Added generic ADC device driver tests. + 2008-12-30 John Dallaway <john@dallaway.org.uk> * cdl/io_adc.cdl: Reference per-package documentation.
--- a/packages/io/adc/current/cdl/io_adc.cdl +++ b/packages/io/adc/current/cdl/io_adc.cdl @@ -92,4 +92,23 @@ cdl_package CYGPKG_IO_ADC { ADC devices." } + cdl_component CYGPKG_IO_ADC_TESTS { + display "ADC device driver tests" + flavor data + no_define + calculated { "tests/adc1 tests/adc2" } + description " + This option specifies the set of tests for the ADC device drivers." + + + cdl_option CYGNUM_IO_ADC_PERFORMANCE_TEST_RATE { + display "ADC performance test rate" + flavor data + legal_values 1 to 10000 + default_value 1000 + description " + This option specifies the sampling rate used for the ADC device + driver performance test." + } + } }
new file mode 100644 --- /dev/null +++ b/packages/io/adc/current/tests/adc1.c @@ -0,0 +1,194 @@ +//========================================================================== +// +// adc1.c +// +// ADC test +// +//========================================================================== +// ####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-03-02 +// Description: ADC test +//####DESCRIPTIONEND#### + +#include <pkgconf/system.h> + +#include <cyg/infra/testcase.h> +#include <cyg/infra/cyg_ass.h> +#include <cyg/infra/diag.h> +#include <cyg/hal/hal_diag.h> +#include <cyg/hal/hal_arch.h> + +// Package requirements +#if defined(CYGPKG_IO_ADC) && defined(CYGPKG_KERNEL) + +#include <pkgconf/kernel.h> +#include <cyg/io/io.h> +#include <cyg/io/devtab.h> +#include <cyg/io/adc.h> + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include <cyg/kernel/kapi.h> + +#define TEST_RATE 100 // Data acquisition rate for test +#define TEST_SAMPLES 10 // Number of samples to acquire + +// Thread data +cyg_handle_t thread_handle; +cyg_thread thread_data; +cyg_uint8 thread_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; + +static void +test_channel(const char *dev, cyg_io_handle_t channel) +{ + Cyg_ErrNo res; + cyg_uint32 cfg_data; + cyg_uint32 len; + cyg_adc_sample_t sample; + int count; + + diag_printf("\nTesting ADC channel '%s'\n", dev); + + // Disable channel + res = cyg_io_set_config(channel, CYG_IO_SET_CONFIG_ADC_DISABLE, 0, 0); + if (res != ENOERR) + CYG_TEST_FAIL_FINISH("Failed to disable ADC channel"); + + // Make channel non-blocking + cfg_data = 0; + len = sizeof(cfg_data); + res = cyg_io_set_config(channel, CYG_IO_SET_CONFIG_READ_BLOCKING, + &cfg_data, &len); + if (res != ENOERR) + CYG_TEST_FAIL_FINISH("Failed to make ADC channel non-blocking"); + + // Set channel sampling rate + cfg_data = TEST_RATE; + len = sizeof(cfg_data); + res = cyg_io_set_config(channel, CYG_IO_SET_CONFIG_ADC_RATE, + &cfg_data, &len); + if (res != ENOERR) + CYG_TEST_FAIL_FINISH("Failed to set ADC channel sampling rate"); + + // Flush channel + do { + len = sizeof(sample); + res = cyg_io_read(channel, &sample, &len); + } while (res == ENOERR); + + // Enable channel + res = cyg_io_set_config(channel, CYG_IO_SET_CONFIG_ADC_ENABLE, 0, 0); + if (res != ENOERR) + CYG_TEST_FAIL_FINISH("Failed to enable ADC channel"); + + // Read from channel + count = 0; + while (count < TEST_SAMPLES) { + len = sizeof(sample); + res = cyg_io_read(channel, &sample, &len); + if (res == ENOERR) { + diag_printf("%d\n", sample); + count++; + } + } + + // Disable channel + res = cyg_io_set_config(channel, CYG_IO_SET_CONFIG_ADC_DISABLE, 0, 0); + if (res != ENOERR) + CYG_TEST_FAIL_FINISH("Failed to disable ADC channel"); +} + +static void +adc_thread(cyg_addrword_t data) +{ + cyg_io_handle_t channel; + cyg_devtab_entry_t *t; + + CYG_TEST_INFO("ADC test"); + + for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++) { + if (t->handlers != &cyg_io_adc_devio) + continue; + if (cyg_io_lookup(t->name, &channel) == ENOERR) { + test_channel(t->name, channel); + } else { + CYG_TEST_FAIL_FINISH("Cannot open ADC channel"); + } + } + + 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, + "adc1", + thread_stack, + sizeof(thread_stack), + &thread_handle, + &thread_data + ); + cyg_thread_resume(thread_handle); + cyg_scheduler_start(); +} + +#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
new file mode 100644 --- /dev/null +++ b/packages/io/adc/current/tests/adc2.c @@ -0,0 +1,280 @@ +//========================================================================== +// +// adc2.c +// +// ADC performance test +// +//========================================================================== +// ####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-03-02 +// Description: ADC performance test +//####DESCRIPTIONEND#### + +#include <pkgconf/system.h> + +#include <cyg/infra/testcase.h> +#include <cyg/infra/cyg_ass.h> +#include <cyg/infra/diag.h> +#include <cyg/hal/hal_diag.h> +#include <cyg/hal/hal_arch.h> + +// Package requirements +#if defined(CYGPKG_IO_ADC) && defined(CYGPKG_KERNEL) + +#include <pkgconf/kernel.h> +#include <cyg/io/io.h> +#include <cyg/io/devtab.h> +#include <cyg/io/adc.h> + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include <cyg/kernel/kapi.h> + +#define MAX_CHANNELS 64 // Max channels to test + +#define TICKS_PER_SECOND \ + (1000000000 / (CYGNUM_HAL_RTC_NUMERATOR / CYGNUM_HAL_RTC_DENOMINATOR)) + +// ADC test channel +typedef struct test_channel { + const char *dev; // ADC channel device name + cyg_io_handle_t handle; // ADC channel handle + cyg_uint32 count; // Sample counter +} test_channel; + +// ADC test channels +static test_channel test_channels[MAX_CHANNELS]; + +// Thread data +cyg_handle_t thread_handle; +cyg_thread thread_data; +cyg_uint8 thread_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; + +static void +adc_thread(cyg_addrword_t data) +{ + cyg_uint32 num = 0; + cyg_devtab_entry_t *t; + test_channel *chan; + cyg_adc_sample_t sample; + Cyg_ErrNo res; + 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; + + CYG_TEST_INFO("ADC performance test"); + + // This test reads samples from all enabled ADC channels. Each second, the + // number of already acquired samples is printed. After 10 seconds, all ADC + // channels are stpped and each ADC buffer is read until empty. If the + // number of acquired samples is much smaller than the number of expected + // samples, the rate is too high. + + CYG_TEST_INFO("Opening available ADC channels"); + + for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++) { + if (t->handlers != &cyg_io_adc_devio) + continue; + chan = &test_channels[num++]; + chan->dev = t->name; + if (cyg_io_lookup(chan->dev, &chan->handle) != ENOERR) + CYG_TEST_FAIL_FINISH("Cannot open ADC channel"); + } + + diag_printf("Opened %d ADC channels\n", num); + + CYG_TEST_INFO("Preparing ADC channels for test"); + + for (i = 0; i < num; i++) { + chan = &test_channels[i]; + + // Disable channel + res = cyg_io_set_config(chan->handle, CYG_IO_SET_CONFIG_ADC_DISABLE, 0, 0); + if (res != ENOERR) + CYG_TEST_FAIL_FINISH("Failed to disable ADC channel"); + + // Make channel non-blocking + cfg_data = 0; + len = sizeof(cfg_data); + res = cyg_io_set_config(chan->handle, + CYG_IO_SET_CONFIG_READ_BLOCKING, + &cfg_data, &len); + if (res != ENOERR) + CYG_TEST_FAIL_FINISH("Failed to make ADC channel non-blocking"); + + // Set channel sampling rate + cfg_data = CYGNUM_IO_ADC_PERFORMANCE_TEST_RATE; + len = sizeof(cfg_data); + res = cyg_io_set_config(chan->handle, + CYG_IO_SET_CONFIG_ADC_RATE, + &cfg_data, &len); + if (res != ENOERR) + CYG_TEST_FAIL_FINISH("Failed to set ADC channel sampling rate"); + + // Flush channel + do { + len = sizeof(sample); + res = cyg_io_read(chan->handle, &sample, &len); + } while (res == ENOERR); + chan->count = 0; + } + + CYG_TEST_INFO("Starting measurement"); + + for (i = 0; i < num; i++) { + chan = &test_channels[i]; + + // Enable channel + res = cyg_io_set_config(chan->handle, CYG_IO_SET_CONFIG_ADC_ENABLE, 0, 0); + if (res != ENOERR) + CYG_TEST_FAIL_FINISH("Failed to enabled ADC channel"); + } + + start_time = cyg_current_time(); + do { + for (i = 0; i < num; i++) { + chan = &test_channels[i]; + + // Read & count samples + do { + cyg_uint32 len = sizeof(sample); + res = cyg_io_read(chan->handle, &sample, &len); + if (res == ENOERR) + chan->count++; + } while (res == ENOERR); + } + + // 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) >= TICKS_PER_SECOND) { + start_time = end_time; + diag_printf("\n"); + for (i = 0; i < num; i++) { + chan = &test_channels[i]; + diag_printf("%-20s\t= %d\n", chan->dev, chan->count); + } + seconds++; + } + } while (seconds < 10); + + for (i = 0; i < num; i++) { + chan = &test_channels[i]; + + // Disable channel + res = cyg_io_set_config(chan->handle, CYG_IO_SET_CONFIG_ADC_DISABLE, 0, 0); + if (res != ENOERR) + CYG_TEST_FAIL_FINISH("Failed to disable ADC channel"); + } + + end_time = cyg_current_time(); + + for (i = 0; i < num; i++) { + chan = &test_channels[i]; + + // Count remainding samples + do { + len = sizeof(sample); + res = cyg_io_read(chan->handle, &sample, &len); + if (res == ENOERR) + chan->count++; + } while (res == ENOERR); + } + + CYG_TEST_INFO("Finished measurement"); + + diag_printf("\n\n----------------------------------------\n"); + + final_seconds = (end_time - start_time) + (seconds * TICKS_PER_SECOND); + final_seconds /= TICKS_PER_SECOND; + samples_expected = final_seconds * CYGNUM_IO_ADC_PERFORMANCE_TEST_RATE; + diag_printf("Samples expected after %d milliseconds: %d\n", + (unsigned int) (final_seconds * 1000), samples_expected); + + diag_printf("Samples read (per channel):\n"); + for (i = 0; i < num; i++) { + chan = &test_channels[i]; + diag_printf("%-20s\t= %d\n", chan->dev, chan->count); + } + + CYG_TEST_PASS_FINISH("ADC performance 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, + "adc2", + thread_stack, + sizeof(thread_stack), + &thread_handle, + &thread_data + ); + cyg_thread_resume(thread_handle); + cyg_scheduler_start(); +} + +#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
