From 314ed649e840e0f398bf5d1f66cc01db6f8aec01 Mon Sep 17 00:00:00 2001 From: asterix Date: Mon, 21 Mar 2011 17:56:21 +0000 Subject: [PATCH] Add adc implementation for sam3x. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4785 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/cortex-m3/drv/adc_sam3.c | 149 ++++++++++++++++++++++++++++ bertos/cpu/cortex-m3/drv/adc_sam3.h | 65 ++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 bertos/cpu/cortex-m3/drv/adc_sam3.c create mode 100644 bertos/cpu/cortex-m3/drv/adc_sam3.h diff --git a/bertos/cpu/cortex-m3/drv/adc_sam3.c b/bertos/cpu/cortex-m3/drv/adc_sam3.c new file mode 100644 index 00000000..7dd48bf6 --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/adc_sam3.c @@ -0,0 +1,149 @@ +/** + * \file + * + * + * \brief ADC hardware-specific implementation + * + * \author Daniele Basile + */ + + +#include "adc_sam3.h" + +#include "cfg/cfg_adc.h" + +#include +#include + +// Define log settings for cfg/log.h. +#define LOG_LEVEL ADC_LOG_LEVEL +#define LOG_FORMAT ADC_LOG_FORMAT +#include + +#include +#include + +#include + +#include + +#include + + +static Event data_ready; +static uint32_t data; + +/** + * ADC ISR. + */ +static DECLARE_ISR(adc_conversion_end_irq) +{ + data = 0; + if (ADC_ISR & BV(ADC_DRDY)) + { + data = ADC_LDATA; + event_do(&data_ready); + } +} + +/** + * Select mux channel \a ch. + */ +void adc_hw_select_ch(uint8_t ch) +{ + /* Disable all channels */ + ADC_CHDR = ADC_CH_MASK; + /* Enable select channel */ + ADC_CHER = BV(ch); +} + + +/** + * Start an ADC convertion. + */ +uint16_t adc_hw_read(void) +{ + ADC_CR = BV(ADC_START); + event_wait(&data_ready); + return(data); +} + +/** + * Init ADC hardware. + */ +void adc_hw_init(void) +{ + /* Make sure that interrupt are enabled */ + IRQ_ASSERT_ENABLED(); + + /* Initialize the dataready event */ + event_initGeneric(&data_ready); + + /* Clock ADC peripheral */ + pmc_periphEnable(ADC_ID); + + + /* Reset adc controller */ + ADC_CR = ADC_SWRST; + + /* + * Set adc mode register: + * - Disable hardware trigger and enable software trigger. + * - Select normal mode. + */ + ADC_MR = 0; + + /* Set ADC_BITS bit convertion resolution. */ + #if ADC_BITS == 12 + ADC_MR &= ~BV(ADC_LOWRES); + #elif ADC_BITS == 10 + ADC_MR |= BV(ADC_LOWRES); + #else + #error No select bit resolution is supported to this CPU + #endif + + /* Setup ADC */ + LOG_INFO("Computed ADC_CLOCK %ld\n", ADC_CLOCK); + ADC_MR |= ((ADC_PRESCALER << ADC_PRESCALER_SHIFT) & ADC_PRESCALER_MASK); + LOG_INFO("prescaler[%ld]\n", ADC_PRESCALER); + ADC_MR |= ((ADC_SUT512 << ADC_STARTUP_SHIFT) & ADC_STARTUP_MASK); + LOG_INFO("starup[%d]\n", ADC_SUT512); + ADC_MR |= ((ADC_AST17 << ADC_SETTLING_SHIFT) & ADC_SETTLING_MASK); + LOG_INFO("sttime[%d]\n", ADC_AST17); + ADC_MR |= ((0 << ADC_TRACKTIM_SHIFT) & ADC_TRACKTIM_MASK); + LOG_INFO("tracking[%d]\n", 0); + ADC_MR |= ((1 << ADC_TRANSFER_SHIFT) & ADC_TRANSFER_MASK); + LOG_INFO("tranfer[%d]\n", 1); + + /* Register and enable irq for adc. */ + sysirq_setHandler(INT_ADC, adc_conversion_end_irq); + ADC_IER = BV(ADC_DRDY); +} diff --git a/bertos/cpu/cortex-m3/drv/adc_sam3.h b/bertos/cpu/cortex-m3/drv/adc_sam3.h new file mode 100644 index 00000000..1a6ca532 --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/adc_sam3.h @@ -0,0 +1,65 @@ +/** + * \file + * + * + * \brief ADC hardware-specific definition + * + * \author Daniele Basile + */ + +#ifndef DRV_ADC_AT91_H +#define DRV_ADC_AT91_H + +#include + +#include "cfg/cfg_adc.h" + +#include + +/** + * ADC config define. + */ +#define ADC_MUX_MAXCH 16 //Max number of channel for ADC. +#define ADC_BITS 12 //Bit resolution for ADC converter. + +/** + * Macro for computing correct value to write into ADC + * register. + */ +#define ADC_PRESCALER (DIV_ROUNDUP(CPU_FREQ, 2 * CONFIG_ADC_CLOCK) - 1) +#define ADC_CLOCK (CPU_FREQ / ((ADC_PRESCALER + 1) * 2)) +#define ADC_STARTUPTIME (((CONFIG_ADC_STARTUP_TIME * ADC_COMPUTED_CLOCK) / 8000000UL) - 1) + +void adc_hw_select_ch(uint8_t ch); +uint16_t adc_hw_read(void); +void adc_hw_init(void); + +#endif /* DRV_ADC_AT91_H */ -- 2.25.1