diff options
Diffstat (limited to 'apps/drivers/stm32/adc')
-rw-r--r-- | apps/drivers/stm32/adc/Makefile | 43 | ||||
-rw-r--r-- | apps/drivers/stm32/adc/adc.cpp | 387 |
2 files changed, 0 insertions, 430 deletions
diff --git a/apps/drivers/stm32/adc/Makefile b/apps/drivers/stm32/adc/Makefile deleted file mode 100644 index 443bc0623..000000000 --- a/apps/drivers/stm32/adc/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -############################################################################ -# -# Copyright (C) 2012 PX4 Development Team. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name PX4 nor the names of its contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -############################################################################ - -# -# STM32 ADC driver -# - -APPNAME = adc -PRIORITY = SCHED_PRIORITY_DEFAULT -STACKSIZE = 2048 -INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common - -include $(APPDIR)/mk/app.mk diff --git a/apps/drivers/stm32/adc/adc.cpp b/apps/drivers/stm32/adc/adc.cpp deleted file mode 100644 index 911def943..000000000 --- a/apps/drivers/stm32/adc/adc.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/**************************************************************************** - * - * Copyright (C) 2012 PX4 Development Team. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/** - * @file adc.cpp - * - * Driver for the STM32 ADC. - * - * This is a low-rate driver, designed for sampling things like voltages - * and so forth. It avoids the gross complexity of the NuttX ADC driver. - */ - -#include <nuttx/config.h> -#include <drivers/device/device.h> - -#include <sys/types.h> -#include <stdint.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> -#include <unistd.h> - -#include <arch/board/board.h> -#include <drivers/drv_hrt.h> -#include <drivers/drv_adc.h> - -#include <arch/stm32/chip.h> -#include <stm32_internal.h> -#include <stm32_gpio.h> - -#include <systemlib/err.h> -#include <systemlib/perf_counter.h> - -/* - * Register accessors. - * For now, no reason not to just use ADC1. - */ -#define REG(_reg) (*(volatile uint32_t *)(STM32_ADC1_BASE + _reg)) - -#define rSR REG(STM32_ADC_SR_OFFSET) -#define rCR1 REG(STM32_ADC_CR1_OFFSET) -#define rCR2 REG(STM32_ADC_CR2_OFFSET) -#define rSMPR1 REG(STM32_ADC_SMPR1_OFFSET) -#define rSMPR2 REG(STM32_ADC_SMPR2_OFFSET) -#define rJOFR1 REG(STM32_ADC_JOFR1_OFFSET) -#define rJOFR2 REG(STM32_ADC_JOFR2_OFFSET) -#define rJOFR3 REG(STM32_ADC_JOFR3_OFFSET) -#define rJOFR4 REG(STM32_ADC_JOFR4_OFFSET) -#define rHTR REG(STM32_ADC_HTR_OFFSET) -#define rLTR REG(STM32_ADC_LTR_OFFSET) -#define rSQR1 REG(STM32_ADC_SQR1_OFFSET) -#define rSQR2 REG(STM32_ADC_SQR2_OFFSET) -#define rSQR3 REG(STM32_ADC_SQR3_OFFSET) -#define rJSQR REG(STM32_ADC_JSQR_OFFSET) -#define rJDR1 REG(STM32_ADC_JDR1_OFFSET) -#define rJDR2 REG(STM32_ADC_JDR2_OFFSET) -#define rJDR3 REG(STM32_ADC_JDR3_OFFSET) -#define rJDR4 REG(STM32_ADC_JDR4_OFFSET) -#define rDR REG(STM32_ADC_DR_OFFSET) - -#ifdef STM32_ADC_CCR -# define rCCR REG(STM32_ADC_CCR_OFFSET) -#endif - -class ADC : public device::CDev -{ -public: - ADC(uint32_t channels); - ~ADC(); - - virtual int init(); - - virtual int ioctl(file *filp, int cmd, unsigned long arg); - virtual ssize_t read(file *filp, char *buffer, size_t len); - -protected: - virtual int open_first(struct file *filp); - virtual int close_last(struct file *filp); - -private: - static const hrt_abstime _tickrate = 10000; /**< 100Hz base rate */ - - hrt_call _call; - perf_counter_t _sample_perf; - - unsigned _channel_count; - adc_msg_s *_samples; /**< sample buffer */ - - /** work trampoline */ - static void _tick_trampoline(void *arg); - - /** worker function */ - void _tick(); - - /** - * Sample a single channel and return the measured value. - * - * @param channel The channel to sample. - * @return The sampled value, or 0xffff if - * sampling failed. - */ - uint16_t _sample(unsigned channel); - -}; - -ADC::ADC(uint32_t channels) : - CDev("adc", ADC_DEVICE_PATH), - _sample_perf(perf_alloc(PC_ELAPSED, "ADC samples")), - _channel_count(0), - _samples(nullptr) -{ - _debug_enabled = true; - - /* always enable the temperature sensor */ - channels |= 1 << 16; - - /* allocate the sample array */ - for (unsigned i = 0; i < 32; i++) { - if (channels & (1 << i)) { - _channel_count++; - } - } - _samples = new adc_msg_s[_channel_count]; - - /* prefill the channel numbers in the sample array */ - if (_samples != nullptr) { - unsigned index = 0; - for (unsigned i = 0; i < 32; i++) { - if (channels & (1 << i)) { - _samples[index].am_channel = i; - _samples[index].am_data = 0; - index++; - } - } - } -} - -ADC::~ADC() -{ - if (_samples != nullptr) - delete _samples; -} - -int -ADC::init() -{ - /* do calibration if supported */ -#ifdef ADC_CR2_CAL - rCR2 |= ADC_CR2_CAL; - usleep(100); - if (rCR2 & ADC_CR2_CAL) - return -1; -#endif - - /* arbitrarily configure all channels for 55 cycle sample time */ - rSMPR1 = 0b00000011011011011011011011011011; - rSMPR2 = 0b00011011011011011011011011011011; - - /* XXX for F2/4, might want to select 12-bit mode? */ - rCR1 = 0; - - /* enable the temperature sensor / Vrefint channel if supported*/ - rCR2 = -#ifdef ADC_CR2_TSVREFE - /* enable the temperature sensor in CR2 */ - ADC_CR2_TSVREFE | -#endif - 0; - -#ifdef ADC_CCR_TSVREFE - /* enable temperature sensor in CCR */ - rCCR = ADC_CCR_TSVREFE; -#endif - - /* configure for a single-channel sequence */ - rSQR1 = 0; - rSQR2 = 0; - rSQR3 = 0; /* will be updated with the channel each tick */ - - /* power-cycle the ADC and turn it on */ - rCR2 &= ~ADC_CR2_ADON; - usleep(10); - rCR2 |= ADC_CR2_ADON; - usleep(10); - rCR2 |= ADC_CR2_ADON; - usleep(10); - - /* kick off a sample and wait for it to complete */ - hrt_abstime now = hrt_absolute_time(); - rCR2 |= ADC_CR2_SWSTART; - while (!(rSR & ADC_SR_EOC)) { - - /* don't wait for more than 500us, since that means something broke - should reset here if we see this */ - if ((hrt_absolute_time() - now) > 500) { - log("sample timeout"); - return -1; - return 0xffff; - } - } - - - debug("init done"); - - /* create the device node */ - return CDev::init(); -} - -int -ADC::ioctl(file *filp, int cmd, unsigned long arg) -{ - return -ENOTTY; -} - -ssize_t -ADC::read(file *filp, char *buffer, size_t len) -{ - const size_t maxsize = sizeof(adc_msg_s) * _channel_count; - - if (len > maxsize) - len = maxsize; - - /* block interrupts while copying samples to avoid racing with an update */ - irqstate_t flags = irqsave(); - memcpy(buffer, _samples, len); - irqrestore(flags); - - return len; -} - -int -ADC::open_first(struct file *filp) -{ - /* get fresh data */ - _tick(); - - /* and schedule regular updates */ - hrt_call_every(&_call, _tickrate, _tickrate, _tick_trampoline, this); - - return 0; -} - -int -ADC::close_last(struct file *filp) -{ - hrt_cancel(&_call); - return 0; -} - -void -ADC::_tick_trampoline(void *arg) -{ - ((ADC *)arg)->_tick(); -} - -void -ADC::_tick() -{ - /* scan the channel set and sample each */ - for (unsigned i = 0; i < _channel_count; i++) - _samples[i].am_data = _sample(_samples[i].am_channel); -} - -uint16_t -ADC::_sample(unsigned channel) -{ - perf_begin(_sample_perf); - - /* clear any previous EOC */ - if (rSR & ADC_SR_EOC) - rSR &= ~ADC_SR_EOC; - - /* run a single conversion right now - should take about 60 cycles (a few microseconds) max */ - rSQR3 = channel; - rCR2 |= ADC_CR2_SWSTART; - - /* wait for the conversion to complete */ - hrt_abstime now = hrt_absolute_time(); - while (!(rSR & ADC_SR_EOC)) { - - /* don't wait for more than 50us, since that means something broke - should reset here if we see this */ - if ((hrt_absolute_time() - now) > 50) { - log("sample timeout"); - return 0xffff; - } - } - - /* read the result and clear EOC */ - uint16_t result = rDR; - - perf_end(_sample_perf); - return result; -} - -/* - * Driver 'main' command. - */ -extern "C" __EXPORT int adc_main(int argc, char *argv[]); - -namespace -{ -ADC *g_adc; - -void -test(void) -{ - - int fd = open(ADC_DEVICE_PATH, O_RDONLY); - if (fd < 0) - err(1, "can't open ADC device"); - - for (unsigned i = 0; i < 50; i++) { - adc_msg_s data[8]; - ssize_t count = read(fd, data, sizeof(data)); - - if (count < 0) - errx(1, "read error"); - - unsigned channels = count / sizeof(data[0]); - - for (unsigned j = 0; j < channels; j++) { - printf ("%d: %u ", data[j].am_channel, data[j].am_data); - } - - printf("\n"); - usleep(500000); - } - - exit(0); -} -} - -int -adc_main(int argc, char *argv[]) -{ - if (g_adc == nullptr) { - /* XXX this hardcodes the default channel set for PX4FMU - should be configurable */ - g_adc = new ADC((1 << 10) | (1 << 11) | (1 << 12) | (1 << 13)); - - if (g_adc == nullptr) - errx(1, "couldn't allocate the ADC driver"); - - if (g_adc->init() != OK) { - delete g_adc; - errx(1, "ADC init failed"); - } - } - - if (argc > 1) { - if (!strcmp(argv[1], "test")) - test(); - } - - exit(0); -} |