int adc_disable_watchdog(void) { int ret; if (!adc_powered()) return EC_ERROR_UNKNOWN; mutex_lock(&adc_lock); ret = adc_disable_watchdog_no_lock(); mutex_unlock(&adc_lock); return ret; }
int adc_read_all_channels(int *data) { int i; int16_t raw_data[ADC_CH_COUNT]; const struct adc_t *adc; int restore_watchdog = 0; int ret = EC_SUCCESS; if (!adc_powered()) return EC_ERROR_UNKNOWN; mutex_lock(&adc_lock); if (adc_watchdog_enabled()) { restore_watchdog = 1; adc_disable_watchdog_no_lock(); } adc_configure_all(); dma_clear_isr(STM32_DMAC_ADC); dma_start_rx(&dma_adc_option, ADC_CH_COUNT, raw_data); /* Start conversion */ STM32_ADC_CR2 |= (1 << 0); /* ADON */ if (dma_wait(STM32_DMAC_ADC)) { ret = EC_ERROR_UNKNOWN; goto exit_all_channels; } for (i = 0; i < ADC_CH_COUNT; ++i) { adc = adc_channels + i; data[i] = raw_data[i] * adc->factor_mul / adc->factor_div + adc->shift; } exit_all_channels: dma_disable(STM32_DMAC_ADC); if (restore_watchdog) adc_enable_watchdog_no_lock(); mutex_unlock(&adc_lock); return ret; }
int adc_enable_watchdog(int ain_id, int high, int low) { int ret; if (!adc_powered()) return EC_ERROR_UNKNOWN; mutex_lock(&adc_lock); watchdog_ain_id = ain_id; /* Set thresholds */ STM32_ADC_HTR = high & 0xfff; STM32_ADC_LTR = low & 0xfff; ret = adc_enable_watchdog_no_lock(); mutex_unlock(&adc_lock); return ret; }
int adc_read_channel(enum adc_channel ch) { const struct adc_t *adc = adc_channels + ch; int value; int restore_watchdog = 0; timestamp_t deadline; if (!adc_powered()) return EC_ERROR_UNKNOWN; mutex_lock(&adc_lock); if (adc_watchdog_enabled()) { restore_watchdog = 1; adc_disable_watchdog_no_lock(); } adc_configure(adc->channel); /* Clear EOC bit */ STM32_ADC_SR &= ~(1 << 1); /* Start conversion */ STM32_ADC_CR2 |= (1 << 0); /* ADON */ /* Wait for EOC bit set */ deadline.val = get_time().val + ADC_SINGLE_READ_TIMEOUT; value = ADC_READ_ERROR; do { if (adc_conversion_ended()) { value = STM32_ADC_DR & ADC_READ_MAX; break; } } while (!timestamp_expired(deadline, NULL)); if (restore_watchdog) adc_enable_watchdog_no_lock(); mutex_unlock(&adc_lock); return (value == ADC_READ_ERROR) ? ADC_READ_ERROR : value * adc->factor_mul / adc->factor_div + adc->shift; }
static void adc_init(void) { /* * Enable ADC clock. * APB2 clock is 16MHz. ADC clock prescaler is /2. * So the ADC clock is 8MHz. */ STM32_RCC_APB2ENR |= (1 << 9); /* * ADC clock is divided with respect to AHB, so no delay needed * here. If ADC clock is the same as AHB, a dummy read on ADC * register is needed here. */ if (!adc_powered()) { /* Power on ADC module */ STM32_ADC_CR2 |= (1 << 0); /* ADON */ /* Reset calibration */ STM32_ADC_CR2 |= (1 << 3); /* RSTCAL */ while (STM32_ADC_CR2 & (1 << 3)) ; /* A/D Calibrate */ STM32_ADC_CR2 |= (1 << 2); /* CAL */ while (STM32_ADC_CR2 & (1 << 2)) ; } /* Set right alignment */ STM32_ADC_CR2 &= ~(1 << 11); /* * Set sample time of all channels to 13.5 cycles. * Conversion takes 15.75 us. */ STM32_ADC_SMPR1 = 0x00492492; STM32_ADC_SMPR2 = 0x12492492; }
static void adc_init(void) { /* * Enable ADC clock. * APB2 clock is 16MHz. ADC clock prescaler is /2. * So the ADC clock is 8MHz. */ STM32_RCC_APB2ENR |= (1 << 9); /* * ADC clock is divided with respect to AHB, so no delay needed * here. If ADC clock is the same as AHB, a dummy read on ADC * register is needed here. */ if (!adc_powered()) { /* Power on ADC module */ STM32_ADC_CR2 |= (1 << 0); /* ADON */ /* Reset calibration */ STM32_ADC_CR2 |= (1 << 3); /* RSTCAL */ while (STM32_ADC_CR2 & (1 << 3)) ; /* A/D Calibrate */ STM32_ADC_CR2 |= (1 << 2); /* CAL */ while (STM32_ADC_CR2 & (1 << 2)) ; } /* Set right alignment */ STM32_ADC_CR2 &= ~(1 << 11); /* Set sample time of all channels */ STM32_ADC_SMPR1 = SMPR1_EXPAND(CONFIG_ADC_SAMPLE_TIME); STM32_ADC_SMPR2 = SMPR2_EXPAND(CONFIG_ADC_SAMPLE_TIME); }