altos/stmf0: Add ADC and DMA APIs
authorKeith Packard <keithp@keithp.com>
Tue, 27 Jan 2015 06:14:57 +0000 (22:14 -0800)
committerKeith Packard <keithp@keithp.com>
Tue, 27 Jan 2015 06:14:57 +0000 (22:14 -0800)
The ADC api is what USBtrng wants; a way to repeatedly read a single
ADC input as fast as possible.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/stmf0/ao_adc_fast.c [new file with mode: 0644]
src/stmf0/ao_adc_fast.h [new file with mode: 0644]
src/stmf0/ao_dma_stm.c [new file with mode: 0644]
src/stmf0/ao_interrupt.c
src/stmf0/stm32f0.h

diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c
new file mode 100644 (file)
index 0000000..5885ae4
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_adc_fast.h>
+
+static uint8_t                 ao_adc_done;
+
+/*
+ * Callback from DMA ISR
+ *
+ * Mark time in ring, shut down DMA engine
+ */
+static void ao_adc_dma_done(int index)
+{
+       (void) index;
+       ao_adc_done = 1;
+       ao_wakeup(&ao_adc_done);
+}
+
+/*
+ * Start the ADC sequence using the DMA engine
+ */
+void
+ao_adc_read(uint16_t *dest, int len)
+{
+       ao_adc_done = 0;
+       stm_adc.isr = 0;
+       ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1),
+                           &stm_adc.dr,
+                           dest,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_16 << STM_DMA_CCR_PSIZE) |
+                           (1 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+       ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done);
+       ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
+
+       stm_adc.cr |= (1 << STM_ADC_CR_ADSTART);
+       ao_arch_block_interrupts();
+       while (!ao_adc_done)
+               ao_sleep(&ao_adc_done);
+       ao_arch_release_interrupts();
+
+       ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
+
+       stm_adc.cr |= (1 << STM_ADC_CR_ADSTP);
+       while ((stm_adc.cr & (1 << STM_ADC_CR_ADSTP)) != 0)
+               ;
+}
+
+void
+ao_adc_init(void)
+{
+       uint32_t        chselr;
+       int             i;
+
+       /* Reset ADC */
+       stm_rcc.apb2rstr |= (1 << STM_RCC_APB2RSTR_ADCRST);
+       stm_rcc.apb2rstr &= ~(1 << STM_RCC_APB2RSTR_ADCRST);
+
+       /* Turn on ADC pins */
+       stm_rcc.ahbenr |= AO_ADC_RCC_AHBENR;
+
+#ifdef AO_ADC_PIN0_PORT
+       stm_moder_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN1_PORT
+       stm_moder_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN2_PORT
+       stm_moder_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN3_PORT
+       stm_moder_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN4_PORT
+       stm_moder_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN5_PORT
+       stm_moder_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN6_PORT
+       stm_moder_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN7_PORT
+       stm_moder_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN24_PORT
+       #error "Too many ADC ports"
+#endif
+
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADCEN);
+
+       chselr = 0;
+#if AO_NUM_ADC > 0
+       chselr |= (1 << AO_ADC_PIN0_CH);
+#endif
+#if AO_NUM_ADC > 1
+       chselr |= (1 << AO_ADC_PIN1_CH);
+#endif
+#if AO_NUM_ADC > 2
+       chselr |= (1 << AO_ADC_PIN2_CH);
+#endif
+#if AO_NUM_ADC > 3
+       chselr |= (1 << AO_ADC_PIN3_CH);
+#endif
+#if AO_NUM_ADC > 4
+       chselr |= (1 << AO_ADC_PIN4_CH);
+#endif
+#if AO_NUM_ADC > 5
+       chselr |= (1 << AO_ADC_PIN5_CH);
+#endif
+#if AO_NUM_ADC > 6
+       chselr |= (1 << AO_ADC_PIN6_CH);
+#endif
+#if AO_NUM_ADC > 7
+       chselr |= (1 << AO_ADC_PIN7_CH);
+#endif
+#if AO_NUM_ADC > 8
+#error Need more ADC defines
+#endif
+       stm_adc.chselr = chselr;
+
+       /* Set the clock */
+       stm_adc.cfgr2 = STM_ADC_CFGR2_CKMODE_PCLK_2 << STM_ADC_CFGR2_CKMODE;
+
+       /* Shortest sample time */
+       stm_adc.smpr = STM_ADC_SMPR_SMP_1_5 << STM_ADC_SMPR_SMP;
+
+       /* Calibrate */
+       stm_adc.cr |= (1 << STM_ADC_CR_ADCAL);
+       for (i = 0; i < 0xf000; i++) {
+               if ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) == 0)
+                       break;
+       }
+
+       /* Enable */
+       stm_adc.cr |= (1 << STM_ADC_CR_ADEN);
+       while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 0)
+               ;
+
+       stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) |
+                        (0 << STM_ADC_CFGR1_AWDEN) |
+                        (0 << STM_ADC_CFGR1_AWDSGL) |
+                        (0 << STM_ADC_CFGR1_DISCEN) |
+                        (0 << STM_ADC_CFGR1_AUTOOFF) |
+                        (1 << STM_ADC_CFGR1_WAIT) |
+                        (1 << STM_ADC_CFGR1_CONT) |
+                        (0 << STM_ADC_CFGR1_OVRMOD) |
+                        (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) |
+                        (0 << STM_ADC_CFGR1_ALIGN) |
+                        (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) |
+                        (STM_ADC_CFGR1_SCANDIR_UP << STM_ADC_CFGR1_SCANDIR) |
+                        (STM_ADC_CFGR1_DMACFG_ONESHOT << STM_ADC_CFGR1_DMACFG) |
+                        (1 << STM_ADC_CFGR1_DMAEN));
+       stm_adc.ccr = 0;
+
+       /* Clear any stale status bits */
+       stm_adc.isr = 0;
+
+       /* Turn on syscfg */
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
+       /* Set ADC to use DMA channel 1 (option 1) */
+       stm_syscfg.cfgr1 &= ~(1 << STM_SYSCFG_CFGR1_ADC_DMA_RMP);
+
+       ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
+}
diff --git a/src/stmf0/ao_adc_fast.h b/src/stmf0/ao_adc_fast.h
new file mode 100644 (file)
index 0000000..a2408d1
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_ADC_FAST_H_
+#define _AO_ADC_FAST_H_
+
+void
+ao_adc_read(uint16_t *dest, int len);
+
+void
+ao_adc_init(void);
+
+#endif /* _AO_ADC_FAST_H_ */
diff --git a/src/stmf0/ao_dma_stm.c b/src/stmf0/ao_dma_stm.c
new file mode 100644 (file)
index 0000000..78fabe1
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+struct ao_dma_config {
+       void            (*isr)(int index);
+};
+
+uint8_t ao_dma_done[STM_NUM_DMA];
+
+static struct ao_dma_config ao_dma_config[STM_NUM_DMA];
+static uint8_t ao_dma_allocated[STM_NUM_DMA];
+static uint8_t ao_dma_mutex[STM_NUM_DMA];
+static uint8_t ao_dma_active;
+
+#define id(ch)         STM_DMA_INDEX(ch)
+#define id_mask(id)    (STM_DMA_ISR_MASK << (id))
+#define ch_mask(ch)    id_mask(id(ch))
+
+static void
+ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
+       /* Get channel interrupt bits */
+       uint32_t        isr = stm_dma.isr & mask;
+       uint8_t         index;
+
+       /* Ack them */
+       stm_dma.ifcr = isr;
+       for (index = low_index; index <= high_index; index++) {
+               if (isr & id_mask(index)) {
+                       if (ao_dma_config[index].isr)
+                               (*ao_dma_config[index].isr)(index);
+                       else {
+                               ao_dma_done[index] = 1;
+                               ao_wakeup(&ao_dma_done[index]);
+                       }
+               }
+       }
+}
+
+void stm_dma_ch1_isr(void) { ao_dma_isr(id(1), id(1), ch_mask(1)); }
+void stm_dma_ch2_3_isr(void) { ao_dma_isr(id(2), id(3), ch_mask(2) | ch_mask(3)); }
+void stm_dma1_ch4_5_6_isr(void) { ao_dma_isr(id(4), id(6), ch_mask(4) | ch_mask(5) | ch_mask(6)); }
+
+void
+ao_dma_set_transfer(uint8_t            index,
+                   volatile void       *peripheral,
+                   void                *memory,
+                   uint16_t            count,
+                   uint32_t            ccr)
+{
+       if (ao_dma_allocated[index]) {
+               if (ao_dma_mutex[index])
+                       ao_panic(AO_PANIC_DMA);
+               ao_dma_mutex[index] = 1;
+       } else
+               ao_mutex_get(&ao_dma_mutex[index]);
+       ao_arch_critical(
+               if (ao_dma_active++ == 0)
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN);
+               );
+       stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE);
+       stm_dma.channel[index].cndtr = count;
+       stm_dma.channel[index].cpar = peripheral;
+       stm_dma.channel[index].cmar = memory;
+       ao_dma_config[index].isr = NULL;
+}
+
+void
+ao_dma_set_isr(uint8_t index, void (*isr)(int))
+{
+       ao_dma_config[index].isr = isr;
+}
+
+void
+ao_dma_start(uint8_t index)
+{
+       ao_dma_done[index] = 0;
+       stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN);
+}
+
+void
+ao_dma_done_transfer(uint8_t index)
+{
+       stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
+       ao_arch_critical(
+               if (--ao_dma_active == 0)
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMAEN);
+               );
+       if (ao_dma_allocated[index])
+               ao_dma_mutex[index] = 0;
+       else
+               ao_mutex_put(&ao_dma_mutex[index]);
+}
+
+void
+ao_dma_abort(uint8_t index)
+{
+       stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
+       ao_wakeup(&ao_dma_done[index]);
+}
+
+void
+ao_dma_alloc(uint8_t index)
+{
+       if (ao_dma_allocated[index])
+               ao_panic(AO_PANIC_DMA);
+       ao_dma_allocated[index] = 1;
+}
+
+#define STM_NUM_DMA_ISR        3
+
+void
+ao_dma_init(void)
+{
+       int     isr_id;
+       int     index;
+
+       for (isr_id = 0; isr_id < STM_NUM_DMA_ISR; isr_id++) {
+               stm_nvic_set_enable(STM_ISR_DMA_CH1_POS + isr_id);
+               stm_nvic_set_priority(STM_ISR_DMA_CH1_POS + isr_id, 4);
+       }
+       for (index = 0; index < STM_NUM_DMA; index++) {
+               ao_dma_allocated[index] = 0;
+               ao_dma_mutex[index] = 0;
+       }
+}
index b6a3147f37ae36207de805a30943d563be319819..c6d8ef348febc6e8c05862f00c3d7905fc7428c3 100644 (file)
@@ -74,6 +74,9 @@ void start(void)
        }
 #endif
 #if RELOCATE_INTERRUPT
+       /* Turn on syscfg */
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
        memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__);
        stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |
                (STM_SYSCFG_CFGR1_MEM_MODE_SRAM << STM_SYSCFG_CFGR1_MEM_MODE);
@@ -112,8 +115,8 @@ isr(exti2_3)
 isr(exti4_15)
 isr(tsc)
 isr(dma_ch1)
-isr(dma_ch2_3_dma2_ch1_2)
-isr(dma_ch4_5_6_7_dma2_ch3_4_5)
+isr(dma_ch2_3)
+isr(dma_ch4_5_6)
 isr(adc_comp)
 isr(tim1_brk_up_trg_com)
 isr(tim1_cc)
@@ -157,8 +160,8 @@ const void *stm_interrupt_vector[] = {
        i(0x5c, exti4_15),
        i(0x60, tsc),
        i(0x64, dma_ch1),
-       i(0x68, dma_ch2_3_dma2_ch1_2),
-       i(0x6c, dma_ch4_5_6_7_dma2_ch3_4_5),
+       i(0x68, dma_ch2_3),
+       i(0x6c, dma_ch4_5_6),
        i(0x70, adc_comp),
        i(0x74, tim1_brk_up_trg_com),
        i(0x78, tim1_cc),
index 504db4337d7ccce38150042c6608672263748fcb..456f7631a76a4d107170bd566a25159b8ffebb4a 100644 (file)
@@ -587,6 +587,19 @@ extern struct stm_rcc stm_rcc;
 #define  STM_RCC_CFGR_SW_HSI48         3
 #define  STM_RCC_CFGR_SW_MASK          3
 
+#define STM_RCC_APB2RSTR_DBGMCURST     22
+#define STM_RCC_APB2RSTR_TIM17RST      18
+#define STM_RCC_APB2RSTR_TIM16RST      17
+#define STM_RCC_APB2RSTR_TIM15RST      16
+#define STM_RCC_APB2RSTR_USART1RST     14
+#define STM_RCC_APB2RSTR_SPI1RST       12
+#define STM_RCC_APB2RSTR_TIM1RST       11
+#define STM_RCC_APB2RSTR_ADCRST                9
+#define STM_RCC_APB2RSTR_USART8RST     7
+#define STM_RCC_APB2RSTR_USART7RST     6
+#define STM_RCC_APB2RSTR_USART6RST     5
+#define STM_RCC_APB2RSTR_SYSCFGRST     1
+
 #define STM_RCC_APB1RSTR_CECRST                30
 #define STM_RCC_APB1RSTR_DACRST                29
 #define STM_RCC_APB1RSTR_PWRRST                28
@@ -618,7 +631,7 @@ extern struct stm_rcc stm_rcc;
 #define STM_RCC_AHBENR_FLITFEN 4
 #define STM_RCC_AHBENR_SRAMEN  2
 #define STM_RCC_AHBENR_DMA2EN  1
-#define STM_RCC_AHBENR_DMAEM   0
+#define STM_RCC_AHBENR_DMAEN   0
 
 #define STM_RCC_APB2ENR_DBGMCUEN       22
 #define STM_RCC_APB2ENR_TIM17EN                18
@@ -1262,7 +1275,7 @@ struct stm_dma_channel {
        vuint32_t       reserved;
 };
 
-#define STM_NUM_DMA    7
+#define STM_NUM_DMA    6
 
 struct stm_dma {
        vuint32_t               isr;
@@ -1272,7 +1285,7 @@ struct stm_dma {
 
 extern struct stm_dma stm_dma;
 
-/* DMA channels go from 1 to 7, instead of 0 to 6 (sigh)
+/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh)
  */
 
 #define STM_DMA_INDEX(channel)         ((channel) - 1)
@@ -1323,39 +1336,70 @@ extern struct stm_dma stm_dma;
 #define STM_DMA_CCR_TCIE               (1)
 #define STM_DMA_CCR_EN                 (0)
 
-#define STM_DMA_CHANNEL_ADC1           1
+/* DMA channel assignments. When a peripheral has multiple channels
+ * (indicated with _<number>), then it can be configured to either
+ * channel using syscfg.cfgr1
+ */
+
+#define STM_DMA_CHANNEL_ADC_1          1
+#define STM_DMA_CHANNEL_ADC_2          2
+
 #define STM_DMA_CHANNEL_SPI1_RX                2
 #define STM_DMA_CHANNEL_SPI1_TX                3
+
 #define STM_DMA_CHANNEL_SPI2_RX                4
 #define STM_DMA_CHANNEL_SPI2_TX                5
-#define STM_DMA_CHANNEL_USART3_TX      2
-#define STM_DMA_CHANNEL_USART3_RX      3
-#define STM_DMA_CHANNEL_USART1_TX      4
-#define STM_DMA_CHANNEL_USART1_RX      5
-#define STM_DMA_CHANNEL_USART2_RX      6
-#define STM_DMA_CHANNEL_USART2_TX      7
+
+#define STM_DMA_CHANNEL_USART1_TX_1    2
+#define STM_DMA_CHANNEL_USART1_RX_1    3
+#define STM_DMA_CHANNEL_USART1_TX_2    4
+#define STM_DMA_CHANNEL_USART1_RX_2    5
+
+#define STM_DMA_CHANNEL_USART2_RX      4
+#define STM_DMA_CHANNEL_USART2_TX      5
+
+#define STM_DMA_CHANNEL_I2C1_TX                2
+#define STM_DMA_CHANNEL_I2C1_RX                3
+
 #define STM_DMA_CHANNEL_I2C2_TX                4
 #define STM_DMA_CHANNEL_I2C2_RX                5
-#define STM_DMA_CHANNEL_I2C1_TX                6
-#define STM_DMA_CHANNEL_I2C1_RX                7
+
+#define STM_DMA_CHANNEL_TIM1_CH1       2
+#define STM_DMA_CHANNEL_TIM1_CH2       3
+#define STM_DMA_CHANNEL_TIM1_CH4       4
+#define STM_DMA_CHANNEL_TIM1_TRIG      4
+#define STM_DMA_CHANNEL_TIM1_COM       4
+#define STM_DMA_CHANNEL_TIM1_CH3       5
+#define STM_DMA_CHANNEL_TIM1_UP                5
+
 #define STM_DMA_CHANNEL_TIM2_CH3       1
 #define STM_DMA_CHANNEL_TIM2_UP                2
+#define STM_DMA_CHANNEL_TIM2_CH2       3
+#define STM_DMA_CHANNEL_TIM2_CH4       4
 #define STM_DMA_CHANNEL_TIM2_CH1       5
-#define STM_DMA_CHANNEL_TIM2_CH2       7
-#define STM_DMA_CHANNEL_TIM2_CH4       7
+
 #define STM_DMA_CHANNEL_TIM3_CH3       2
 #define STM_DMA_CHANNEL_TIM3_CH4       3
 #define STM_DMA_CHANNEL_TIM3_UP                3
-#define STM_DMA_CHANNEL_TIM3_CH1       6
-#define STM_DMA_CHANNEL_TIM3_TRIG      6
-#define STM_DMA_CHANNEL_TIM4_CH1       1
-#define STM_DMA_CHANNEL_TIM4_CH2       4
-#define STM_DMA_CHANNEL_TIM4_CH3       5
-#define STM_DMA_CHANNEL_TIM4_UP                7
-#define STM_DMA_CHANNEL_TIM6_UP_DA     2
-#define STM_DMA_CHANNEL_C_CHANNEL1     2
-#define STM_DMA_CHANNEL_TIM7_UP_DA     3
-#define STM_DMA_CHANNEL_C_CHANNEL2     3
+#define STM_DMA_CHANNEL_TIM3_CH1       4
+#define STM_DMA_CHANNEL_TIM3_TRIG      4
+
+#define STM_DMA_CHANNEL_TIM6_UP_DAC    2
+
+#define STM_DMA_CHANNEL_TIM15_CH1      5
+#define STM_DMA_CHANNEL_TIM15_UP       5
+#define STM_DMA_CHANNEL_TIM15_TRIG     5
+#define STM_DMA_CHANNEL_TIM15_COM      5
+
+#define STM_DMA_CHANNEL_TIM16_CH1_1    3
+#define STM_DMA_CHANNEL_TIM16_UP_1     3
+#define STM_DMA_CHANNEL_TIM16_CH1_2    4
+#define STM_DMA_CHANNEL_TIM16_UP_2     4
+
+#define STM_DMA_CHANNEL_TIM17_CH1_1    1
+#define STM_DMA_CHANNEL_TIM17_UP_1     1
+#define STM_DMA_CHANNEL_TIM17_CH1_2    2
+#define STM_DMA_CHANNEL_TIM17_UP_2     2
 
 /*
  * Only spi channel 1 and 2 can use DMA
@@ -1419,143 +1463,103 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3;
 #define STM_SPI_SR_RXNE                0
 
 struct stm_adc {
-       vuint32_t       sr;
-       vuint32_t       cr1;
-       vuint32_t       cr2;
-       vuint32_t       smpr1;
-       vuint32_t       smpr2;
-       vuint32_t       smpr3;
-       vuint32_t       jofr1;
-       vuint32_t       jofr2;
-       vuint32_t       jofr3;
-       vuint32_t       jofr4;
-       vuint32_t       htr;
-       vuint32_t       ltr;
-       vuint32_t       sqr1;
-       vuint32_t       sqr2;
-       vuint32_t       sqr3;
-       vuint32_t       sqr4;
-       vuint32_t       sqr5;
-       vuint32_t       jsqr;
-       vuint32_t       jdr1;
-       vuint32_t       jdr2;
-       vuint32_t       jdr3;
-       vuint32_t       jdr4;
+       vuint32_t       isr;
+       vuint32_t       ier;
+       vuint32_t       cr;
+       vuint32_t       cfgr1;
+
+       vuint32_t       cfgr2;
+       vuint32_t       smpr;
+       vuint32_t       r_18;
+       vuint32_t       r_1c;
+
+       vuint32_t       tr;
+       vuint32_t       r_24;
+       vuint32_t       chselr;
+       vuint32_t       r_2c;
+
+       vuint32_t       r_30[4];
+
        vuint32_t       dr;
-       uint8_t         reserved[0x300 - 0x5c];
-       vuint32_t       csr;
+
+       uint8_t         r_44[0x308 - 0x44];
        vuint32_t       ccr;
 };
 
 extern struct stm_adc stm_adc;
 
-#define STM_ADC_SR_JCNR                9
-#define STM_ADC_SR_RCNR                8
-#define STM_ADC_SR_ADONS       6
-#define STM_ADC_SR_OVR         5
-#define STM_ADC_SR_STRT                4
-#define STM_ADC_SR_JSTRT       3
-#define STM_ADC_SR_JEOC                2
-#define STM_ADC_SR_EOC         1
-#define STM_ADC_SR_AWD         0
-
-#define STM_ADC_CR1_OVRIE      26
-#define STM_ADC_CR1_RES                24
-#define  STM_ADC_CR1_RES_12            0
-#define  STM_ADC_CR1_RES_10            1
-#define  STM_ADC_CR1_RES_8             2
-#define  STM_ADC_CR1_RES_6             3
-#define  STM_ADC_CR1_RES_MASK          3
-#define STM_ADC_CR1_AWDEN       23
-#define STM_ADC_CR1_JAWDEN     22
-#define STM_ADC_CR1_PDI                17
-#define STM_ADC_CR1_PDD                16
-#define STM_ADC_CR1_DISCNUM    13
-#define  STM_ADC_CR1_DISCNUM_1         0
-#define  STM_ADC_CR1_DISCNUM_2         1
-#define  STM_ADC_CR1_DISCNUM_3         2
-#define  STM_ADC_CR1_DISCNUM_4         3
-#define  STM_ADC_CR1_DISCNUM_5         4
-#define  STM_ADC_CR1_DISCNUM_6         5
-#define  STM_ADC_CR1_DISCNUM_7         6
-#define  STM_ADC_CR1_DISCNUM_8         7
-#define  STM_ADC_CR1_DISCNUM_MASK      7
-#define STM_ADC_CR1_JDISCEN    12
-#define STM_ADC_CR1_DISCEN     11
-#define STM_ADC_CR1_JAUTO      10
-#define STM_ADC_CR1_AWDSGL     9
-#define STM_ADC_CR1_SCAN       8
-#define STM_ADC_CR1_JEOCIE     7
-#define STM_ADC_CR1_AWDIE      6
-#define STM_ADC_CR1_EOCIE      5
-#define STM_ADC_CR1_AWDCH      0
-#define  STM_ADC_CR1_AWDCH_MASK                0x1f
-
-#define STM_ADC_CR2_SWSTART    30
-#define STM_ADC_CR2_EXTEN      28
-#define  STM_ADC_CR2_EXTEN_DISABLE     0
-#define  STM_ADC_CR2_EXTEN_RISING      1
-#define  STM_ADC_CR2_EXTEN_FALLING     2
-#define  STM_ADC_CR2_EXTEN_BOTH                3
-#define  STM_ADC_CR2_EXTEN_MASK                3
-#define STM_ADC_CR2_EXTSEL     24
-#define  STM_ADC_CR2_EXTSEL_TIM9_CC2   0
-#define  STM_ADC_CR2_EXTSEL_TIM9_TRGO  1
-#define  STM_ADC_CR2_EXTSEL_TIM2_CC3   2
-#define  STM_ADC_CR2_EXTSEL_TIM2_CC2   3
-#define  STM_ADC_CR2_EXTSEL_TIM3_TRGO  4
-#define  STM_ADC_CR2_EXTSEL_TIM4_CC4   5
-#define  STM_ADC_CR2_EXTSEL_TIM2_TRGO  6
-#define  STM_ADC_CR2_EXTSEL_TIM3_CC1   7
-#define  STM_ADC_CR2_EXTSEL_TIM3_CC3   8
-#define  STM_ADC_CR2_EXTSEL_TIM4_TRGO  9
-#define  STM_ADC_CR2_EXTSEL_TIM6_TRGO  10
-#define  STM_ADC_CR2_EXTSEL_EXTI_11    15
-#define  STM_ADC_CR2_EXTSEL_MASK       15
-#define STM_ADC_CR2_JWSTART    22
-#define STM_ADC_CR2_JEXTEN     20
-#define  STM_ADC_CR2_JEXTEN_DISABLE    0
-#define  STM_ADC_CR2_JEXTEN_RISING     1
-#define  STM_ADC_CR2_JEXTEN_FALLING    2
-#define  STM_ADC_CR2_JEXTEN_BOTH       3
-#define  STM_ADC_CR2_JEXTEN_MASK       3
-#define STM_ADC_CR2_JEXTSEL    16
-#define  STM_ADC_CR2_JEXTSEL_TIM9_CC1  0
-#define  STM_ADC_CR2_JEXTSEL_TIM9_TRGO 1
-#define  STM_ADC_CR2_JEXTSEL_TIM2_TRGO 2
-#define  STM_ADC_CR2_JEXTSEL_TIM2_CC1  3
-#define  STM_ADC_CR2_JEXTSEL_TIM3_CC4  4
-#define  STM_ADC_CR2_JEXTSEL_TIM4_TRGO 5
-#define  STM_ADC_CR2_JEXTSEL_TIM4_CC1  6
-#define  STM_ADC_CR2_JEXTSEL_TIM4_CC2  7
-#define  STM_ADC_CR2_JEXTSEL_TIM4_CC3  8
-#define  STM_ADC_CR2_JEXTSEL_TIM10_CC1 9
-#define  STM_ADC_CR2_JEXTSEL_TIM7_TRGO 10
-#define  STM_ADC_CR2_JEXTSEL_EXTI_15   15
-#define  STM_ADC_CR2_JEXTSEL_MASK      15
-#define STM_ADC_CR2_ALIGN      11
-#define STM_ADC_CR2_EOCS       10
-#define STM_ADC_CR2_DDS                9
-#define STM_ADC_CR2_DMA                8
-#define STM_ADC_CR2_DELS       4
-#define  STM_ADC_CR2_DELS_NONE         0
-#define  STM_ADC_CR2_DELS_UNTIL_READ   1
-#define  STM_ADC_CR2_DELS_7            2
-#define  STM_ADC_CR2_DELS_15           3
-#define  STM_ADC_CR2_DELS_31           4
-#define  STM_ADC_CR2_DELS_63           5
-#define  STM_ADC_CR2_DELS_127          6
-#define  STM_ADC_CR2_DELS_255          7
-#define  STM_ADC_CR2_DELS_MASK         7
-#define STM_ADC_CR2_CONT       1
-#define STM_ADC_CR2_ADON       0
-
-#define STM_ADC_CCR_TSVREFE    23
-#define STM_ADC_CCR_ADCPRE     16
-#define  STM_ADC_CCR_ADCPRE_HSI_1      0
-#define  STM_ADC_CCR_ADCPRE_HSI_2      1
-#define  STM_ADC_CCR_ADCPRE_HSI_4      2
-#define  STM_ADC_CCR_ADCPRE_MASK       3
+#define STM_ADC_ISR_AWD                7
+#define STM_ADC_ISR_OVR                4
+#define STM_ADC_ISR_EOSEQ      3
+#define STM_ADC_ISR_EOC                2
+#define STM_ADC_ISR_EOSMP      1
+#define STM_ADC_ISR_ADRDY      0
+
+#define STM_ADC_IER_AWDIE      7
+#define STM_ADC_IER_OVRIE      4
+#define STM_ADC_IER_EOSEQIE    3
+#define STM_ADC_IER_EOCIE      2
+#define STM_ADC_IER_EOSMPIE    1
+#define STM_ADC_IER_ADRDYIE    0
+
+#define STM_ADC_CR_ADCAL       31
+#define STM_ADC_CR_ADSTP       4
+#define STM_ADC_CR_ADSTART     2
+#define STM_ADC_CR_ADDIS       1
+#define STM_ADC_CR_ADEN                0
+
+#define STM_ADC_CFGR1_AWDCH    26
+#define STM_ADC_CFGR1_AWDEN    23
+#define STM_ADC_CFGR1_AWDSGL   22
+#define STM_ADC_CFGR1_DISCEN   16
+#define STM_ADC_CFGR1_AUTOOFF  15
+#define STM_ADC_CFGR1_WAIT     14
+#define STM_ADC_CFGR1_CONT     13
+#define STM_ADC_CFGR1_OVRMOD   12
+#define STM_ADC_CFGR1_EXTEN    10
+#define  STM_ADC_CFGR1_EXTEN_DISABLE   0
+#define  STM_ADC_CFGR1_EXTEN_RISING    1
+#define  STM_ADC_CFGR1_EXTEN_FALLING   2
+#define  STM_ADC_CFGR1_EXTEN_BOTH      3
+#define  STM_ADC_CFGR1_EXTEN_MASK      3
+
+#define STM_ADC_CFGR1_EXTSEL   6
+#define STM_ADC_CFGR1_ALIGN    5
+#define STM_ADC_CFGR1_RES      3
+#define  STM_ADC_CFGR1_RES_12          0
+#define  STM_ADC_CFGR1_RES_10          1
+#define  STM_ADC_CFGR1_RES_8           2
+#define  STM_ADC_CFGR1_RES_6           3
+#define  STM_ADC_CFGR1_RES_MASK                3
+#define STM_ADC_CFGR1_SCANDIR  2
+#define  STM_ADC_CFGR1_SCANDIR_UP      0
+#define  STM_ADC_CFGR1_SCANDIR_DOWN    1
+#define STM_ADC_CFGR1_DMACFG   1
+#define  STM_ADC_CFGR1_DMACFG_ONESHOT  0
+#define  STM_ADC_CFGR1_DMACFG_CIRCULAR 1
+#define STM_ADC_CFGR1_DMAEN    0
+
+#define STM_ADC_CFGR2_CKMODE   30
+#define  STM_ADC_CFGR2_CKMODE_ADCCLK   0
+#define  STM_ADC_CFGR2_CKMODE_PCLK_2   1
+#define  STM_ADC_CFGR2_CKMODE_PCLK_4   2
+
+#define STM_ADC_SMPR_SMP       0
+#define  STM_ADC_SMPR_SMP_1_5          0
+#define  STM_ADC_SMPR_SMP_7_5          1
+#define  STM_ADC_SMPR_SMP_13_5         2
+#define  STM_ADC_SMPR_SMP_28_5         3
+#define  STM_ADC_SMPR_SMP_41_5         4
+#define  STM_ADC_SMPR_SMP_55_5         5
+#define  STM_ADC_SMPR_SMP_71_5         6
+#define  STM_ADC_SMPR_SMP_239_5                7
+
+#define STM_ADC_TR_HT          16
+#define STM_ADC_TR_LT          0
+
+#define STM_ADC_CCR_VBATEN     24
+#define STM_ADC_CCR_TSEN       23
+#define STM_ADC_CCR_VREFEN     22
 
 struct stm_cal {
        uint16_t        ts_cal_cold;    /* 30°C */