int adc_read_channel(enum adc_channel ch) { const struct adc_t *adc = adc_channels + ch; int value; int restore_watchdog = 0; mutex_lock(&adc_lock); if (adc_watchdog_enabled()) { restore_watchdog = 1; adc_disable_watchdog_no_lock(); } adc_configure(adc->channel); /* Clear flags */ STM32_ADC_ISR = 0xe; /* Start conversion */ STM32_ADC_CR |= 1 << 2; /* ADSTART */ /* Wait for end of conversion */ while (!(STM32_ADC_ISR & (1 << 2))) ; /* read converted value */ value = STM32_ADC_DR; if (restore_watchdog) adc_enable_watchdog_no_lock(); mutex_unlock(&adc_lock); return value * adc->factor_mul / adc->factor_div + adc->shift; }
static int adc_enable_watchdog_no_lock(void) { /* Fail if watchdog already enabled */ if (adc_watchdog_enabled()) return EC_ERROR_UNKNOWN; /* Set channel */ STM32_ADC_SQR3 = watchdog_ain_id; STM32_ADC_SQR1 = 0; STM32_ADC_CR1 = (STM32_ADC_CR1 & ~0x1f) | watchdog_ain_id; /* Clear interrupt bit */ STM32_ADC_SR &= ~0x1; /* AWDSGL=1, SCAN=1, AWDIE=1, AWDEN=1 */ STM32_ADC_CR1 |= (1 << 9) | (1 << 8) | (1 << 6) | (1 << 23); /* Disable DMA */ STM32_ADC_CR2 &= ~(1 << 8); /* CONT=1 */ STM32_ADC_CR2 |= (1 << 1); /* Start conversion */ STM32_ADC_CR2 |= (1 << 0); return EC_SUCCESS; }
static int adc_disable_watchdog_no_lock(void) { /* Fail if watchdog not running */ if (!adc_watchdog_enabled()) return EC_ERROR_UNKNOWN; /* AWDEN=0, AWDIE=0 */ STM32_ADC_CR1 &= ~(1 << 23) & ~(1 << 6); /* CONT=0 */ STM32_ADC_CR2 &= ~(1 << 1); return EC_SUCCESS; }
int adc_read_all_channels(int *data) { int i; uint32_t channels = 0; uint32_t raw_data[ADC_CH_COUNT]; const struct adc_t *adc; int restore_watchdog = 0; int ret = EC_SUCCESS; mutex_lock(&adc_lock); if (adc_watchdog_enabled()) { restore_watchdog = 1; adc_disable_watchdog_no_lock(); } /* Select all used channels */ for (i = 0; i < ADC_CH_COUNT; ++i) channels |= 1 << adc_channels[i].channel; STM32_ADC_CHSELR = channels; /* Enable DMA */ STM32_ADC_CFGR1 |= 0x1; dma_clear_isr(STM32_DMAC_ADC); dma_start_rx(&dma_adc_option, ADC_CH_COUNT, raw_data); /* Clear flags */ STM32_ADC_ISR = 0xe; STM32_ADC_CR |= 1 << 2; /* ADSTART */ if (dma_wait(STM32_DMAC_ADC)) { ret = EC_ERROR_UNKNOWN; goto fail; /* goto fail; goto fail; */ } for (i = 0; i < ADC_CH_COUNT; ++i) { adc = adc_channels + i; data[i] = (raw_data[i] & 0xffff) * adc->factor_mul / adc->factor_div + adc->shift; } fail: if (restore_watchdog) adc_enable_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_set_watchdog_delay(int delay_ms) { int resume_watchdog = 0; mutex_lock(&adc_lock); if (adc_watchdog_enabled()) { resume_watchdog = 1; adc_disable_watchdog_no_lock(); } watchdog_delay_ms = delay_ms; if (resume_watchdog) adc_enable_watchdog_no_lock(); mutex_unlock(&adc_lock); return EC_SUCCESS; }
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; }