aboutsummaryrefslogtreecommitdiffstats
path: root/src/stm32
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2019-08-15 22:48:07 -0400
committerKevin O'Connor <kevin@koconnor.net>2019-08-15 23:21:41 -0400
commit4ec6db7a87b2f0b0e033b87ca912818dc84cbe2f (patch)
treec7ad2e8bde695f1c6a2dd1ea4164d98fb8c04f93 /src/stm32
parentd3bd4f9622d422ad135418cb7f91672cd46bcf78 (diff)
downloadkutter-4ec6db7a87b2f0b0e033b87ca912818dc84cbe2f.tar.gz
kutter-4ec6db7a87b2f0b0e033b87ca912818dc84cbe2f.tar.xz
kutter-4ec6db7a87b2f0b0e033b87ca912818dc84cbe2f.zip
stm32: Add support for additional ADC3 ports on stm32f4
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/stm32')
-rw-r--r--src/stm32/adc.c61
-rw-r--r--src/stm32/gpio.h1
2 files changed, 42 insertions, 20 deletions
diff --git a/src/stm32/adc.c b/src/stm32/adc.c
index b24b9e06..b6aa14b8 100644
--- a/src/stm32/adc.c
+++ b/src/stm32/adc.c
@@ -19,7 +19,13 @@ static const uint8_t adc_pins[] = {
GPIO('A', 0), GPIO('A', 1), GPIO('A', 2), GPIO('A', 3),
GPIO('A', 4), GPIO('A', 5), GPIO('A', 6), GPIO('A', 7),
GPIO('B', 0), GPIO('B', 1), GPIO('C', 0), GPIO('C', 1),
- GPIO('C', 2), GPIO('C', 3), GPIO('C', 4), GPIO('C', 5)
+ GPIO('C', 2), GPIO('C', 3), GPIO('C', 4), GPIO('C', 5),
+#if CONFIG_MACH_STM32F4
+ 0x00, 0x00, 0x00, 0x00,
+ GPIO('F', 6), GPIO('F', 7), GPIO('F', 8), GPIO('F', 9),
+ GPIO('F', 10), GPIO('F', 3), 0x00, 0x00,
+ 0x00, 0x00, GPIO('F', 4), GPIO('F', 5),
+#endif
};
#if CONFIG_MACH_STM32F1
@@ -40,30 +46,42 @@ gpio_adc_setup(uint32_t pin)
break;
}
+ // Determine which ADC block to use
+ ADC_TypeDef *adc = ADC1;
+ uint32_t adc_base = ADC1_BASE;
+#if CONFIG_MACH_STM32F4
+ if (chan >= 16) {
+ // On the STM32F4, some ADC channels are only available from ADC3
+ adc = ADC3;
+ adc_base += 0x800;
+ chan -= 16;
+ }
+#endif
+
// Enable the ADC
- if (!is_enabled_pclock(ADC1_BASE)) {
- enable_pclock(ADC1_BASE);
+ if (!is_enabled_pclock(adc_base)) {
+ enable_pclock(adc_base);
uint32_t aticks = 3; // 2.5-3.2us (depending on stm32 chip)
- ADC1->SMPR1 = (aticks | (aticks << 3) | (aticks << 6) | (aticks << 9)
- | (aticks << 12) | (aticks << 15) | (aticks << 18)
- | (aticks << 21) | (aticks << 24));
- ADC1->SMPR2 = (aticks | (aticks << 3) | (aticks << 6) | (aticks << 9)
- | (aticks << 12) | (aticks << 15) | (aticks << 18)
- | (aticks << 21) | (aticks << 24) | (aticks << 27));
- ADC1->CR2 = CR2_FLAGS;
+ adc->SMPR1 = (aticks | (aticks << 3) | (aticks << 6) | (aticks << 9)
+ | (aticks << 12) | (aticks << 15) | (aticks << 18)
+ | (aticks << 21) | (aticks << 24));
+ adc->SMPR2 = (aticks | (aticks << 3) | (aticks << 6) | (aticks << 9)
+ | (aticks << 12) | (aticks << 15) | (aticks << 18)
+ | (aticks << 21) | (aticks << 24) | (aticks << 27));
+ adc->CR2 = CR2_FLAGS;
#if CONFIG_MACH_STM32F1
// Perform calibration
udelay(timer_from_us(1));
- ADC1->CR2 = ADC_CR2_CAL | CR2_FLAGS;
- while (ADC1->CR2 & ADC_CR2_CAL)
+ adc->CR2 = ADC_CR2_CAL | CR2_FLAGS;
+ while (adc->CR2 & ADC_CR2_CAL)
;
#endif
}
gpio_peripheral(pin, GPIO_ANALOG, 0);
- return (struct gpio_adc){ .chan = chan };
+ return (struct gpio_adc){ .adc = adc, .chan = chan };
}
// Try to sample a value. Returns zero if sample ready, otherwise
@@ -72,17 +90,18 @@ gpio_adc_setup(uint32_t pin)
uint32_t
gpio_adc_sample(struct gpio_adc g)
{
- uint32_t sr = ADC1->SR;
+ ADC_TypeDef *adc = g.adc;
+ uint32_t sr = adc->SR;
if (sr & ADC_SR_STRT) {
- if (!(sr & ADC_SR_EOC) || ADC1->SQR3 != g.chan)
+ if (!(sr & ADC_SR_EOC) || adc->SQR3 != g.chan)
// Conversion still in progress or busy on another channel
goto need_delay;
// Conversion ready
return 0;
}
// Start sample
- ADC1->SQR3 = g.chan;
- ADC1->CR2 = ADC_CR2_SWSTART | CR2_FLAGS;
+ adc->SQR3 = g.chan;
+ adc->CR2 = ADC_CR2_SWSTART | CR2_FLAGS;
need_delay:
return timer_from_us(10);
@@ -92,16 +111,18 @@ need_delay:
uint16_t
gpio_adc_read(struct gpio_adc g)
{
- ADC1->SR = ~ADC_SR_STRT;
- return ADC1->DR;
+ ADC_TypeDef *adc = g.adc;
+ adc->SR = ~ADC_SR_STRT;
+ return adc->DR;
}
// Cancel a sample that may have been started with gpio_adc_sample()
void
gpio_adc_cancel_sample(struct gpio_adc g)
{
+ ADC_TypeDef *adc = g.adc;
irqstatus_t flag = irq_save();
- if (ADC1->SR & ADC_SR_STRT && ADC1->SQR3 == g.chan)
+ if (adc->SR & ADC_SR_STRT && adc->SQR3 == g.chan)
gpio_adc_read(g);
irq_restore(flag);
}
diff --git a/src/stm32/gpio.h b/src/stm32/gpio.h
index c7602504..ad8a9979 100644
--- a/src/stm32/gpio.h
+++ b/src/stm32/gpio.h
@@ -22,6 +22,7 @@ void gpio_in_reset(struct gpio_in g, int32_t pull_up);
uint8_t gpio_in_read(struct gpio_in g);
struct gpio_adc {
+ void *adc;
uint32_t chan;
};
struct gpio_adc gpio_adc_setup(uint32_t pin);