#include <drv/adc.h>
#include <drv/clock_stm32.h>
#include <drv/gpio_stm32.h>
-#include <drv/irq_cm3.h>
#include <io/stm32.h>
-
struct stm32_adc *adc = (struct stm32_adc *)ADC1_BASE;
+#if CONFIG_KERN
+ #include <cfg/module.h>
+
+ #include <kern/proc.h>
+ #include <kern/signal.h>
+
+ #include <drv/irq_cm3.h>
+
+
+ #if !CONFIG_KERN_SIGNALS
+ #error Signals must be active to use ADC with kernel
+ #endif
+
+ /* Signal adc convertion end */
+ #define SIG_ADC_COMPLETE SIG_USER0
+
+ /* ADC waiting process */
+ static struct Process *adc_process;
+
+ /**
+ * ADC ISR.
+ * Simply signal the adc process that convertion is complete.
+ */
+ static DECLARE_ISR(adc_conversion_end_irq)
+ {
+ sig_post(adc_process, SIG_ADC_COMPLETE);
+
+ /* Clear the status bit */
+ adc->SR &= ~BV(SR_EOC);
+ }
+
+ static void adc_enable_irq(void)
+ {
+ /* Register the IRQ handler */
+ sysirq_setHandler(ADC_IRQHANDLER, adc_conversion_end_irq);
+ adc->CR1 |= BV(CR1_EOCIE);
+ }
+
+#endif /* CONFIG_KERN */
+
/**
* Select mux channel \a ch.
* Generally the stm32 cpu family allow us to program the order
adc->SQR3 = (ch & SQR3_SQ_MASK);
}
-static DECLARE_ISR(adc_redyRead)
-{
- kputs("end\n");
-}
/**
* Start an ADC convertion.
* If a kernel is present, preempt until convertion is complete, otherwise
*/
uint16_t adc_hw_read(void)
{
+ #if CONFIG_KERN
+ /* Ensure ADC is not already in use by another process */
+ ASSERT(adc_process == NULL);
+ adc_process = proc_current();
+ #endif
+
/* Start convertion */
adc->CR2 |= CR2_EXTTRIG_SWSTRT_SET;
- while (!(adc->SR & BV(SR_EOC)));
-
- /* Return the last converted data */
- return (adc->DR);
+ #if CONFIG_KERN
+ /* Ensure IRQs enabled. */
+ IRQ_ASSERT_ENABLED();
+ sig_wait(SIG_ADC_COMPLETE);
+
+ /* Prevent race condition in case of preemptive kernel */
+ uint16_t ret = adc->DR;
+ MEMORY_BARRIER;
+ adc_process = NULL;
+ return ret;
+ #else
+ /* Wait in polling until is done */
+ while (!(adc->SR & BV(SR_EOC)));
+
+ /* Return the last converted data */
+ return (adc->DR);
+ #endif
}
/**
adc->SMPR1 |= ((ADC_SAMPLETIME_239CYCLES5 << ADC_CHANNEL_16) |
(ADC_SAMPLETIME_239CYCLES5 << ADC_CHANNEL_17));
- /* Register the IRQ handler */
- sysirq_setHandler(ADC_IRQHANDLER, adc_redyRead);
- //adc->CR1 |= BV(CR1_EOCIE);
+ #if CONFIG_KERN
+ adc_enable_irq();
+ #endif
}