altos/stm32f1: Add more IP block drivers
authorKeith Packard <keithp@keithp.com>
Thu, 30 Mar 2023 07:05:21 +0000 (00:05 -0700)
committerKeith Packard <keithp@keithp.com>
Thu, 1 Feb 2024 01:50:19 +0000 (17:50 -0800)
adc, beep, exti, i2c

Also hooked up data sampling bits in ao_timer.c

Signed-off-by: Keith Packard <keithp@keithp.com>
src/stm32f1/ao_adc_stm.c [new file with mode: 0644]
src/stm32f1/ao_arch.h
src/stm32f1/ao_arch_funcs.h
src/stm32f1/ao_beep_stm.c [new file with mode: 0644]
src/stm32f1/ao_exti_stm.c [new file with mode: 0644]
src/stm32f1/ao_i2c_stm.c [new file with mode: 0644]
src/stm32f1/ao_spi_stm.c
src/stm32f1/ao_timer.c
src/stm32f1/stm32f1.h

diff --git a/src/stm32f1/ao_adc_stm.c b/src/stm32f1/ao_adc_stm.c
new file mode 100644 (file)
index 0000000..f552d67
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_data.h>
+
+static uint8_t                 ao_adc_ready;
+
+#define AO_ADC_CR2_VAL         ((HAS_ADC_TEMP << STM_ADC_CR2_TSVREF) | \
+                                (0 << STM_ADC_CR2_SWSTART) |           \
+                                (0 << STM_ADC_CR2_JWSTART) |           \
+                                (0 << STM_ADC_CR2_EXTTRIG) |           \
+                                (0 << STM_ADC_CR2_EXTSEL) |            \
+                                (0 << STM_ADC_CR2_JEXTTRIG) | \
+                                (0 << STM_ADC_CR2_JEXTSEL) |           \
+                                (0 << STM_ADC_CR2_ALIGN) |             \
+                                (1 << STM_ADC_CR2_DMA) |               \
+                                (0 << STM_ADC_CR2_CONT) |              \
+                                (1 << STM_ADC_CR2_ADON))
+
+/*
+ * Callback from DMA ISR
+ *
+ * Mark time in ring, shut down DMA engine
+ */
+static void ao_adc_done(int index)
+{
+       (void) index;
+       AO_DATA_PRESENT(AO_DATA_ADC);
+       ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
+       ao_data_fill(ao_data_head);
+       ao_adc_ready = 1;
+}
+
+/*
+ * Start the ADC sequence using the DMA engine
+ */
+void
+ao_adc_poll(void)
+{
+       if (!ao_adc_ready)
+               return;
+       ao_adc_ready = 0;
+       stm_adc.sr = 0;
+       ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1),
+                           &stm_adc.dr,
+                           (void *) (&ao_data_ring[ao_data_head].adc),
+                           AO_NUM_ADC,
+                           (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_ADC1), ao_adc_done);
+       ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
+
+       stm_adc.cr2 = AO_ADC_CR2_VAL | (1 << STM_ADC_CR2_SWSTART);
+}
+
+#ifdef AO_ADC_SQ1_NAME
+static const char *ao_adc_name[AO_NUM_ADC] = {
+       AO_ADC_SQ1_NAME,
+#ifdef AO_ADC_SQ2_NAME
+       AO_ADC_SQ2_NAME,
+#endif
+#ifdef AO_ADC_SQ3_NAME
+       AO_ADC_SQ3_NAME,
+#endif
+#ifdef AO_ADC_SQ4_NAME
+       AO_ADC_SQ4_NAME,
+#endif
+#ifdef AO_ADC_SQ5_NAME
+       AO_ADC_SQ5_NAME,
+#endif
+#ifdef AO_ADC_SQ6_NAME
+       AO_ADC_SQ6_NAME,
+#endif
+#ifdef AO_ADC_SQ7_NAME
+       AO_ADC_SQ7_NAME,
+#endif
+#ifdef AO_ADC_SQ8_NAME
+       AO_ADC_SQ8_NAME,
+#endif
+#ifdef AO_ADC_SQ9_NAME
+       AO_ADC_SQ9_NAME,
+#endif
+#ifdef AO_ADC_SQ10_NAME
+       AO_ADC_SQ10_NAME,
+#endif
+#ifdef AO_ADC_SQ11_NAME
+       AO_ADC_SQ11_NAME,
+#endif
+#ifdef AO_ADC_SQ12_NAME
+       AO_ADC_SQ12_NAME,
+#endif
+#ifdef AO_ADC_SQ13_NAME
+       AO_ADC_SQ13_NAME,
+#endif
+#ifdef AO_ADC_SQ14_NAME
+       AO_ADC_SQ14_NAME,
+#endif
+#ifdef AO_ADC_SQ15_NAME
+       AO_ADC_SQ15_NAME,
+#endif
+#ifdef AO_ADC_SQ16_NAME
+       AO_ADC_SQ16_NAME,
+#endif
+#ifdef AO_ADC_SQ17_NAME
+       AO_ADC_SQ17_NAME,
+#endif
+#ifdef AO_ADC_SQ18_NAME
+       AO_ADC_SQ18_NAME,
+#endif
+#ifdef AO_ADC_SQ19_NAME
+       AO_ADC_SQ19_NAME,
+#endif
+#ifdef AO_ADC_SQ20_NAME
+       AO_ADC_SQ20_NAME,
+#endif
+#ifdef AO_ADC_SQ21_NAME
+       #error "too many ADC names"
+#endif
+};
+#endif
+
+static void
+ao_adc_dump(void) 
+{
+       struct ao_data  packet;
+#ifndef AO_ADC_DUMP
+       uint8_t i;
+       int16_t *d;
+#endif
+
+       ao_data_get(&packet);
+#ifdef AO_ADC_DUMP
+       AO_ADC_DUMP(&packet);
+#else
+       printf("tick: %5u",  packet.tick);
+       d = (int16_t *) (&packet.adc);
+       for (i = 0; i < AO_NUM_ADC; i++) {
+#ifdef AO_ADC_SQ1_NAME
+               if (ao_adc_name[i])
+                       printf (" %s: %5d", ao_adc_name[i], d[i]);
+               else            
+#endif
+                       printf (" %2d: %5d", i, d[i]);
+       }
+       printf("\n");
+#endif
+}
+
+const struct ao_cmds ao_adc_cmds[] = {
+       { ao_adc_dump,  "a\0Display current ADC values" },
+       { 0, NULL },
+};
+
+static inline void
+adc_pin_set(struct stm_gpio *gpio, int pin)
+{
+       ao_enable_port(gpio);
+       stm_gpio_conf(gpio, pin,
+                     STM_GPIO_CR_MODE_INPUT,
+                     STM_GPIO_CR_CNF_INPUT_ANALOG);
+}
+
+void
+ao_adc_init(void)
+{
+#ifdef AO_ADC_PIN0_PORT
+       adc_pin_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN);
+#endif
+#ifdef AO_ADC_PIN1_PORT
+       adc_pin_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN);
+#endif
+#ifdef AO_ADC_PIN2_PORT
+       adc_pin_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN);
+#endif
+#ifdef AO_ADC_PIN3_PORT
+       adc_pin_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN);
+#endif
+#ifdef AO_ADC_PIN4_PORT
+       adc_pin_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN);
+#endif
+#ifdef AO_ADC_PIN5_PORT
+       adc_pin_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN);
+#endif
+#ifdef AO_ADC_PIN6_PORT
+       adc_pin_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN);
+#endif
+#ifdef AO_ADC_PIN7_PORT
+       adc_pin_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN);
+#endif
+#ifdef AO_ADC_PIN8_PORT
+       adc_pin_set(AO_ADC_PIN8_PORT, AO_ADC_PIN8_PIN);
+#endif
+#ifdef AO_ADC_PIN9_PORT
+       adc_pin_set(AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN);
+#endif
+#ifdef AO_ADC_PIN10_PORT
+       adc_pin_set(AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN);
+#endif
+#ifdef AO_ADC_PIN11_PORT
+       adc_pin_set(AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN);
+#endif
+#ifdef AO_ADC_PIN12_PORT
+       adc_pin_set(AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN);
+#endif
+#ifdef AO_ADC_PIN13_PORT
+       adc_pin_set(AO_ADC_PIN13_PORT, AO_ADC_PIN13_PIN);
+#endif
+#ifdef AO_ADC_PIN14_PORT
+       adc_pin_set(AO_ADC_PIN14_PORT, AO_ADC_PIN14_PIN);
+#endif
+#ifdef AO_ADC_PIN15_PORT
+       adc_pin_set(AO_ADC_PIN15_PORT, AO_ADC_PIN15_PIN);
+#endif
+#ifdef AO_ADC_PIN16_PORT
+       adc_pin_set(AO_ADC_PIN16_PORT, AO_ADC_PIN16_PIN);
+#endif
+#ifdef AO_ADC_PIN17_PORT
+       adc_pin_set(AO_ADC_PIN17_PORT, AO_ADC_PIN17_PIN);
+#endif
+#ifdef AO_ADC_PIN18_PORT
+       adc_pin_set(AO_ADC_PIN18_PORT, AO_ADC_PIN18_PIN);
+#endif
+#ifdef AO_ADC_PIN19_PORT
+       adc_pin_set(AO_ADC_PIN19_PORT, AO_ADC_PIN19_PIN);
+#endif
+#ifdef AO_ADC_PIN20_PORT
+       adc_pin_set(AO_ADC_PIN20_PORT, AO_ADC_PIN20_PIN);
+#endif
+#ifdef AO_ADC_PIN21_PORT
+       adc_pin_set(AO_ADC_PIN21_PORT, AO_ADC_PIN21_PIN);
+#endif
+#ifdef AO_ADC_PIN22_PORT
+       adc_pin_set(AO_ADC_PIN22_PORT, AO_ADC_PIN22_PIN);
+#endif
+#ifdef AO_ADC_PIN23_PORT
+       adc_pin_set(AO_ADC_PIN23_PORT, AO_ADC_PIN23_PIN);
+#endif
+#ifdef AO_ADC_PIN24_PORT
+       #error "Too many ADC ports"
+#endif
+
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN);
+
+       /* Turn off ADC during configuration */
+       stm_adc.cr2 = 0;
+
+       stm_adc.cr1 = ((0 << STM_ADC_CR1_AWDEN ) |
+                      (0 << STM_ADC_CR1_JAWDEN ) |
+                      (STM_ADC_CR1_DUALMOD_INDEPENDENT << STM_ADC_CR1_DUALMOD ) |
+                      (0 << STM_ADC_CR1_DISCNUM ) |
+                      (0 << STM_ADC_CR1_JDISCEN ) |
+                      (0 << STM_ADC_CR1_DISCEN ) |
+                      (0 << STM_ADC_CR1_JAUTO ) |
+                      (0 << STM_ADC_CR1_AWDSGL ) |
+                      (1 << STM_ADC_CR1_SCAN ) |
+                      (0 << STM_ADC_CR1_JEOCIE ) |
+                      (0 << STM_ADC_CR1_AWDIE ) |
+                      (0 << STM_ADC_CR1_EOCIE ) |
+                      (0 << STM_ADC_CR1_AWDCH ));
+
+       /* 384 cycle sample time for everyone */
+       stm_adc.smpr1 = 0x3ffff;
+       stm_adc.smpr2 = 0x3fffffff;
+
+       stm_adc.sqr1 = ((AO_NUM_ADC - 1) << 20);
+#if AO_NUM_ADC > 0
+       stm_adc.sqr3 |= (AO_ADC_SQ1 << 0);
+#endif
+#if AO_NUM_ADC > 1
+       stm_adc.sqr3 |= (AO_ADC_SQ2 << 5);
+#endif
+#if AO_NUM_ADC > 2
+       stm_adc.sqr3 |= (AO_ADC_SQ3 << 10);
+#endif
+#if AO_NUM_ADC > 3
+       stm_adc.sqr3 |= (AO_ADC_SQ4 << 15);
+#endif
+#if AO_NUM_ADC > 4
+       stm_adc.sqr3 |= (AO_ADC_SQ5 << 20);
+#endif
+#if AO_NUM_ADC > 5
+       stm_adc.sqr3 |= (AO_ADC_SQ6 << 25);
+#endif
+#if AO_NUM_ADC > 6
+       stm_adc.sqr2 |= (AO_ADC_SQ7 << 0);
+#endif
+#if AO_NUM_ADC > 7
+       stm_adc.sqr2 |= (AO_ADC_SQ8 << 5);
+#endif
+#if AO_NUM_ADC > 8
+       stm_adc.sqr2 |= (AO_ADC_SQ9 << 10);
+#endif
+#if AO_NUM_ADC > 9
+       stm_adc.sqr2 |= (AO_ADC_SQ10 << 15);
+#endif
+#if AO_NUM_ADC > 10
+       stm_adc.sqr2 |= (AO_ADC_SQ11 << 20);
+#endif
+#if AO_NUM_ADC > 11
+       stm_adc.sqr2 |= (AO_ADC_SQ12 << 25);
+#endif
+#if AO_NUM_ADC > 12
+       stm_adc.sqr1 |= (AO_ADC_SQ13 << 0);
+#endif
+#if AO_NUM_ADC > 13
+       stm_adc.sqr1 |= (AO_ADC_SQ14 << 5);
+#endif
+#if AO_NUM_ADC > 14
+       stm_adc.sqr1 |= (AO_ADC_SQ15 << 10);
+#endif
+#if AO_NUM_ADC > 15
+       stm_adc.sqr1 |= (AO_ADC_SQ16 << 15);
+#endif
+#if AO_NUM_ADC > 15
+#error "too many ADC channels"
+#endif
+
+       /* Clear any stale status bits */
+       stm_adc.sr = 0;
+
+       ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
+
+       ao_cmd_register(&ao_adc_cmds[0]);
+
+       ao_adc_ready = 1;
+}
index 7e53f2269ed2901e2119708b8ca77e3b9a2dedca..b58e33f6fac9715b986915dfa406885df7db8690 100644 (file)
 #define AO_PCLK1       AO_APB1CLK
 #define AO_PCLK2       AO_APB2CLK
 
+#if AO_RCC_CFGR_PPRE1_DIV == STM_RCC_CFGR_PPRE1_DIV_1
+#define AO_TIM23467_CLK                AO_APB1CLK
+#else
+#define AO_TIM23467_CLK                (2 * AO_APB1CLK)
+#endif
+
+/* ADC maximum reported value */
+#define AO_ADC_MAX                     4095
+
 #define AO_BOOT_APPLICATION_BASE       ((uint32_t *) 0x08001000)
 #define AO_BOOT_APPLICATION_BOUND      ((uint32_t *) (0x08000000 + stm_flash_size()))
 #define AO_BOOT_LOADER_BASE            ((uint32_t *) 0x08000000)
index ad9ab2a6620407096ccd6b0186a1927a1b198720..0bc199c2f5a6a9e80b543aeaf2327ec0a20821c3 100644 (file)
@@ -510,6 +510,14 @@ ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index);
 void
 ao_spi_init(void);
 
+#define ao_spi_init_cs(port, mask) do {                                        \
+               uint8_t __bit__;                                        \
+               for (__bit__ = 0; __bit__ < 32; __bit__++) {            \
+                       if (mask & (1 << __bit__))                      \
+                               ao_enable_output(port, __bit__, 1); \
+               }                                                       \
+       } while (0)
+
 #define ao_spi_set_cs(reg,mask) ((reg)->bsrr = ((uint32_t) (mask)) << 16)
 #define ao_spi_clr_cs(reg,mask) ((reg)->bsrr = (mask))
 
@@ -535,4 +543,22 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
 #define ao_spi_get_bit(reg,bit,bus,speed) ao_spi_get_mask(reg,1<<(bit),bus,speed)
 #define ao_spi_put_bit(reg,bit,bus) ao_spi_put_mask(reg,1<<(bit),bus)
 
+void
+ao_i2c_get(uint8_t i2c_index);
+
+uint8_t
+ao_i2c_start(uint8_t i2c_index, uint16_t address);
+
+void
+ao_i2c_put(uint8_t i2c_index);
+
+uint8_t
+ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);
+
+uint8_t
+ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);
+
+void
+ao_i2c_init(void);
+
 #endif /* _AO_ARCH_FUNCS_H_ */
diff --git a/src/stm32f1/ao_beep_stm.c b/src/stm32f1/ao_beep_stm.c
new file mode 100644 (file)
index 0000000..73bdb8c
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_beep.h"
+
+#if BEEPER_TIMER == 2
+#define stm_beeper     stm_tim2
+#define RCC_BEEPER     STM_RCC_APB1ENR_TIM2EN
+#define BEEPER_AFR     STM_AFR_AF1
+#elif BEEPER_TIMER == 3
+#define stm_beeper     stm_tim3
+#define RCC_BEEPER     STM_RCC_APB1ENR_TIM3EN
+#define BEEPER_AFR     STM_AFR_AF2
+#elif BEEPER_TIMER == 4
+#define stm_beeper     stm_tim4
+#define RCC_BEEPER     STM_RCC_APB1ENR_TIM4EN
+#define BEEPER_AFR     STM_AFR_AF2
+#else
+#error BEEPER_TIMER must be 2, 3 or 4
+#endif
+
+void
+ao_beep(uint8_t beep)
+{
+       if (beep == 0) {
+               stm_beeper.cr1 = 0;
+               stm_rcc.apb1enr &= ~(1UL << RCC_BEEPER);
+       } else {
+               stm_rcc.apb1enr |= (1UL << RCC_BEEPER);
+
+               stm_beeper.cr2 = ((0 << STM_TIM234_CR2_TI1S) |
+                               (STM_TIM234_CR2_MMS_RESET << STM_TIM234_CR2_MMS) |
+                               (0 << STM_TIM234_CR2_CCDS));
+
+               /* Set prescaler to match cc1111 clocks
+                */
+               stm_beeper.psc = AO_TIM23467_CLK / 750000;
+
+               /* 1. Select the counter clock (internal, external, prescaler).
+                *
+                * Setting SMCR to zero means use the internal clock
+                */
+
+               stm_beeper.smcr = 0;
+
+               /* 2. Write the desired data in the TIMx_ARR and TIMx_CCRx registers. */
+               stm_beeper.arr = beep;
+#if BEEPER_CHANNEL == 1
+               stm_beeper.ccr1 = beep;
+#elif BEEPER_CHANNEL == 2
+               stm_beeper.ccr2 = beep;
+#elif BEEPER_CHANNEL == 3
+               stm_beeper.ccr3 = beep;
+#elif BEEPER_CHANNEL == 4
+               stm_beeper.ccr4 = beep;
+#else
+#error invalid BEEPER_CHANNEL
+#endif
+
+               /* 3. Set the CCxIE and/or CCxDE bits if an interrupt and/or a
+                * DMA request is to be generated.
+                */
+               /* don't want this */
+
+               /* 4. Select the output mode. For example, you must write
+                *  OCxM=011, OCxPE=0, CCxP=0 and CCxE=1 to toggle OCx output
+                *  pin when CNT matches CCRx, CCRx preload is not used, OCx
+                *  is enabled and active high.
+                */
+
+#define OC1M   (BEEPER_CHANNEL == 1 ? STM_TIM234_CCMR1_OC1M_TOGGLE : STM_TIM234_CCMR1_OC1M_FROZEN)
+#define OC2M   (BEEPER_CHANNEL == 2 ? STM_TIM234_CCMR1_OC2M_TOGGLE : STM_TIM234_CCMR1_OC2M_FROZEN)
+#define OC3M   (BEEPER_CHANNEL == 3 ? STM_TIM234_CCMR2_OC3M_TOGGLE : STM_TIM234_CCMR2_OC3M_FROZEN)
+#define OC4M   (BEEPER_CHANNEL == 4 ? STM_TIM234_CCMR2_OC4M_TOGGLE : STM_TIM234_CCMR2_OC4M_FROZEN)
+
+#define CCER(n)        (BEEPER_CHANNEL == (n) ? 1 : 0)
+
+#if BEEPER_CHANNEL == 1 || BEEPER_CHANNEL == 2
+               stm_beeper.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) |
+                                   (OC2M << STM_TIM234_CCMR1_OC2M) |
+                                   (0 << STM_TIM234_CCMR1_OC2PE) |
+                                   (0 << STM_TIM234_CCMR1_OC2FE) |
+                                   (STM_TIM234_CCMR1_CC2S_OUTPUT << STM_TIM234_CCMR1_CC2S) |
+
+                                   (0 << STM_TIM234_CCMR1_OC1CE) |
+                                   (OC1M << STM_TIM234_CCMR1_OC1M) |
+                                   (0 << STM_TIM234_CCMR1_OC1PE) |
+                                   (0 << STM_TIM234_CCMR1_OC1FE) |
+                                   (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S));
+#elif BEEPER_CHANNEL == 3 || BEEPER_CHANNEL == 4
+               stm_beeper.ccmr2 = ((0 << STM_TIM234_CCMR2_OC4CE) |
+                                   (OC4M << STM_TIM234_CCMR2_OC4M) |
+                                   (0 << STM_TIM234_CCMR2_OC4PE) |
+                                   (0 << STM_TIM234_CCMR2_OC4FE) |
+                                   (STM_TIM234_CCMR2_CC4S_OUTPUT << STM_TIM234_CCMR2_CC4S) |
+
+                                   (0 << STM_TIM234_CCMR2_OC3CE) |
+                                   (OC3M << STM_TIM234_CCMR2_OC3M) |
+                                   (0 << STM_TIM234_CCMR2_OC3PE) |
+                                   (0 << STM_TIM234_CCMR2_OC3FE) |
+                                   (STM_TIM234_CCMR2_CC3S_OUTPUT << STM_TIM234_CCMR2_CC3S));
+#else
+#error invalid BEEPER_CHANNEL
+#endif
+               stm_beeper.ccer = ((0 << STM_TIM234_CCER_CC4NP) |
+                                  (0 << STM_TIM234_CCER_CC4P) |
+                                  (CCER(4) << STM_TIM234_CCER_CC4E) |
+                                  (0 << STM_TIM234_CCER_CC3NP) |
+                                  (0 << STM_TIM234_CCER_CC3P) |
+                                  (CCER(3) << STM_TIM234_CCER_CC3E) |
+                                  (0 << STM_TIM234_CCER_CC2NP) |
+                                  (0 << STM_TIM234_CCER_CC2P) |
+                                  (CCER(2) << STM_TIM234_CCER_CC2E) |
+                                  (0 << STM_TIM234_CCER_CC1NP) |
+                                  (0 << STM_TIM234_CCER_CC1P) |
+                                  (CCER(1) << STM_TIM234_CCER_CC1E));
+
+               /* 5. Enable the counter by setting the CEN bit in the TIMx_CR1 register. */
+
+               stm_beeper.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) |
+                               (0 << STM_TIM234_CR1_ARPE) |
+                               (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) |
+                               (0 << STM_TIM234_CR1_DIR) |
+                               (0 << STM_TIM234_CR1_OPM) |
+                               (0 << STM_TIM234_CR1_URS) |
+                               (0 << STM_TIM234_CR1_UDIS) |
+                               (1 << STM_TIM234_CR1_CEN));
+
+               /* Update the values */
+               stm_beeper.egr = (1 << STM_TIM234_EGR_UG);
+       }
+}
+
+void
+ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks)
+{
+       ao_beep(beep);
+       ao_delay(ticks);
+       ao_beep(0);
+}
+
+void
+ao_beep_init(void)
+{
+       ao_enable_port(BEEPER_PORT);
+#if BEEPER_TIMER == 2
+       if (BEEPER_PORT == &stm_gpioa) {
+               switch (BEEPER_PIN) {
+               case 0:
+               case 1:
+               case 2:
+               case 3:
+                       stm_set_afio_mapr(STM_AFIO_MAPR_TIM2_REMAP,
+                                         STM_AFIO_MAPR_TIM2_REMAP_PA0_PA1_PA2_PA3,
+                                         STM_AFIO_MAPR_TIM2_REMAP_MASK);
+                       break;
+               default:
+                       ao_panic(AO_PANIC_CRASH);
+                       break;
+               }
+       }
+#elif BEEPER_TIMER == 3
+       ao_panic(AO_PANIC_CRASH);
+#elif BEEPER_TIMER == 4
+       ao_panic(AO_PANIC_CRASH);
+#endif
+       stm_gpio_conf(BEEPER_PORT, BEEPER_PIN,
+                     STM_GPIO_CR_MODE_OUTPUT_2MHZ,
+                     STM_GPIO_CR_CNF_OUTPUT_AF_PUSH_PULL);
+
+       /* Leave the timer off until requested */
+       stm_rcc.apb1enr &= ~(1UL << RCC_BEEPER);
+}
diff --git a/src/stm32f1/ao_exti_stm.c b/src/stm32f1/ao_exti_stm.c
new file mode 100644 (file)
index 0000000..b2157ef
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_exti.h>
+
+static void    (*ao_exti_callback[16])(void);
+
+uint32_t       ao_last_exti;
+
+static void ao_exti_one_isr(uint8_t pin) {
+       uint32_t        pending = (ao_last_exti = stm_exti.pr) & (1 << pin);
+
+       stm_exti.pr = pending;
+       if (pending && ao_exti_callback[pin])
+               (*ao_exti_callback[pin])();
+}
+
+static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) {
+       uint16_t        pending = (uint16_t) (ao_last_exti = stm_exti.pr) & mask;
+       uint8_t         pin;
+       static uint16_t last_mask;
+       static uint8_t  last_pin;
+
+       if (pending == last_mask) {
+               stm_exti.pr = last_mask;
+               (*ao_exti_callback[last_pin])();
+               return;
+       }
+       stm_exti.pr = pending;
+       for (pin = first; pin <= last; pin++)
+               if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) {
+                       last_mask = (1 << pin);
+                       last_pin = pin;
+                       (*ao_exti_callback[pin])();
+               }
+}
+
+void stm_exti0_isr(void) { ao_exti_one_isr(0); }
+void stm_exti1_isr(void) { ao_exti_one_isr(1); }
+void stm_exti2_isr(void) { ao_exti_one_isr(2); }
+void stm_exti3_isr(void) { ao_exti_one_isr(3); }
+void stm_exti4_isr(void) { ao_exti_one_isr(4); }
+void stm_exti9_5_isr(void) { ao_exti_range_isr(5, 9, 0x3e0); }
+void stm_exti15_10_isr(void) { ao_exti_range_isr(10, 15, 0xfc00); }
+
+void
+ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) {
+       uint32_t        mask = 1 << pin;
+       uint8_t         irq;
+       uint8_t         prio;
+
+       ao_exti_callback[pin] = callback;
+
+       /* configure gpio to interrupt routing */
+       stm_exticr_set(gpio, pin);
+
+       if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) {
+               /* configure pin as input, setting selected pull-up/down mode */
+               ao_enable_input(gpio, pin, mode);
+       }
+
+       /* Set interrupt mask and rising/falling mode */
+       stm_exti.imr &= ~mask;
+       if (mode & AO_EXTI_MODE_RISING)
+               stm_exti.rtsr |= mask;
+       else
+               stm_exti.rtsr &= ~mask;
+       if (mode & AO_EXTI_MODE_FALLING)
+               stm_exti.ftsr |= mask;
+       else
+               stm_exti.ftsr &= ~mask;
+
+       if (pin <= 4)
+               irq = STM_ISR_EXTI0_POS + pin;
+       else if (pin <= 9)
+               irq = STM_ISR_EXTI9_5_POS;
+       else
+               irq = STM_ISR_EXTI15_10_POS;
+
+       /* Set priority */
+       prio = AO_STM_NVIC_MED_PRIORITY;
+       if (mode & AO_EXTI_PRIORITY_LOW)
+               prio = AO_STM_NVIC_LOW_PRIORITY;
+       else if (mode & AO_EXTI_PRIORITY_HIGH)
+               prio = AO_STM_NVIC_HIGH_PRIORITY;
+
+       stm_nvic_set_priority(irq, prio);
+       stm_nvic_set_enable(irq);
+}
+
+void
+ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
+       (void) gpio;
+
+       uint32_t        mask = 1 << pin;
+
+       if (mode & AO_EXTI_MODE_RISING)
+               stm_exti.rtsr |= mask;
+       else
+               stm_exti.rtsr &= ~mask;
+       if (mode & AO_EXTI_MODE_FALLING)
+               stm_exti.ftsr |= mask;
+       else
+               stm_exti.ftsr &= ~mask;
+}
+
+void
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void)) {
+       (void) gpio;
+       ao_exti_callback[pin] = callback;
+}
+
+void
+ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) {
+       uint32_t        mask = (1 << pin);
+       (void) gpio;
+       stm_exti.pr = mask;
+       stm_exti.imr |= mask;
+}
+
+void
+ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) {
+       uint32_t        mask = (1 << pin);
+       (void) gpio;
+       stm_exti.imr &= ~mask;
+       stm_exti.pr = mask;
+}
+
+void
+ao_exti_init(void)
+{
+}
diff --git a/src/stm32f1/ao_i2c_stm.c b/src/stm32f1/ao_i2c_stm.c
new file mode 100644 (file)
index 0000000..e84f594
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_i2c_stm_info {
+       uint8_t tx_dma_index;
+       uint8_t rx_dma_index;
+       struct stm_i2c  *stm_i2c;
+};
+
+#define I2C_FAST       1
+
+#define I2C_TIMEOUT    100
+
+#define I2C_IDLE       0
+#define I2C_RUNNING    1
+#define I2C_ERROR      2
+
+static uint8_t ao_i2c_state[STM_NUM_I2C];
+static uint16_t        ao_i2c_addr[STM_NUM_I2C];
+uint8_t        ao_i2c_mutex[STM_NUM_I2C];
+
+# define I2C_HIGH_SLOW 5000    /* ns, 100kHz clock */
+#ifdef TELEMEGA
+# define I2C_HIGH_FAST 2000    /* ns, 167kHz clock */
+#else
+# define I2C_HIGH_FAST 1000    /* ns, 333kHz clock */
+#endif
+
+# define I2C_RISE_SLOW 500     /* ns */
+# define I2C_RISE_FAST 100     /* ns */
+
+/* Clock period in ns */
+#define CYCLES(period) (((period) * (AO_PCLK1 / 1000)) / 1000000)
+
+#define max(a,b)       ((a) > (b) ? (a) : (b))
+#define I2C_CCR_HIGH_SLOW      max(4,CYCLES(I2C_HIGH_SLOW))
+#define I2C_CCR_HIGH_FAST      max(4,CYCLES(I2C_HIGH_FAST))
+#define I2C_TRISE_SLOW         (CYCLES(I2C_RISE_SLOW) + 1)
+#define I2C_TRISE_FAST         (CYCLES(I2C_RISE_FAST) + 1)
+
+#if I2C_FAST
+#define I2C_TRISE      I2C_TRISE_FAST
+#define I2C_CCR_HIGH   I2C_CCR_HIGH_FAST
+#else
+#define I2C_TRISE      I2C_TRISE_SLOW
+#define I2C_CCR_HIGH   I2C_CCR_HIGH_SLOW
+#endif
+
+#define AO_STM_I2C_CR2_FREQ    (AO_APB1CLK / 1000000)
+
+#define AO_STM_I2C_CR1 ((0 << STM_I2C_CR1_SWRST) |     \
+                       (0 << STM_I2C_CR1_ALERT) |      \
+                       (0 << STM_I2C_CR1_PEC) |        \
+                       (0 << STM_I2C_CR1_POS) |        \
+                       (0 << STM_I2C_CR1_ACK) |        \
+                       (0 << STM_I2C_CR1_STOP) |       \
+                       (0 << STM_I2C_CR1_START) |      \
+                       (0 << STM_I2C_CR1_NOSTRETCH) |  \
+                       (0 << STM_I2C_CR1_ENGC) |       \
+                       (0 << STM_I2C_CR1_ENPEC) |      \
+                       (0 << STM_I2C_CR1_ENARP) |      \
+                       (0 << STM_I2C_CR1_SMBTYPE) |    \
+                       (0 << STM_I2C_CR1_SMBUS) |      \
+                       (1 << STM_I2C_CR1_PE))
+
+#define AO_STM_I2C_CR2  ((0 << STM_I2C_CR2_LAST) |                     \
+                        (0 << STM_I2C_CR2_DMAEN) |                     \
+                        (0 << STM_I2C_CR2_ITBUFEN) |                   \
+                        (0 << STM_I2C_CR2_ITEVTEN) |                   \
+                        (0 << STM_I2C_CR2_ITERREN) |                   \
+                        (AO_STM_I2C_CR2_FREQ << STM_I2C_CR2_FREQ))
+
+static const struct ao_i2c_stm_info    ao_i2c_stm_info[STM_NUM_I2C] = {
+       {
+               .tx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C1_TX),
+               .rx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C1_RX),
+               .stm_i2c = &stm_i2c1
+       },
+       {
+               .tx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C2_TX),
+               .rx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C2_RX),
+               .stm_i2c = &stm_i2c2
+       },
+};
+
+static uint8_t *ao_i2c_recv_data[STM_NUM_I2C];
+static uint16_t        ao_i2c_recv_len[STM_NUM_I2C];
+static uint16_t        ev_count;
+
+static void
+ao_i2c_ev_isr(uint8_t index)
+{
+       struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
+       uint32_t        sr1;
+
+       ++ev_count;
+       sr1 = stm_i2c->sr1;
+       if (sr1 & (1 << STM_I2C_SR1_SB))
+               stm_i2c->dr = ao_i2c_addr[index];
+       if (sr1 & (1 << STM_I2C_SR1_ADDR)) {
+               stm_i2c->cr2 &= ~(1UL << STM_I2C_CR2_ITEVTEN);
+               ao_i2c_state[index] = I2C_RUNNING;
+               ao_wakeup(&ao_i2c_state[index]);
+       }
+       if (sr1 & (1 << STM_I2C_SR1_BTF)) {
+               stm_i2c->cr2 &= ~(1UL << STM_I2C_CR2_ITEVTEN);
+               ao_wakeup(&ao_i2c_state[index]);
+       }
+       if (sr1 & (1 << STM_I2C_SR1_RXNE)) {
+               if (ao_i2c_recv_len[index]) {
+                       *(ao_i2c_recv_data[index]++) = (uint8_t) stm_i2c->dr;
+                       if (!--ao_i2c_recv_len[index])
+                               ao_wakeup(&ao_i2c_recv_len[index]);
+               }
+       }
+}
+
+void stm_i2c1_ev_isr(void) { ao_i2c_ev_isr(0); }
+void stm_i2c2_ev_isr(void) { ao_i2c_ev_isr(1); }
+
+static void
+ao_i2c_er_isr(uint8_t index)
+{
+       struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
+       uint32_t        sr1;
+
+       sr1 = stm_i2c->sr1;
+       if (sr1 & (1 << STM_I2C_SR1_AF)) {
+               ao_i2c_state[index] = I2C_ERROR;
+               stm_i2c->sr1 = sr1 & ~(1UL << STM_I2C_SR1_AF);
+               ao_wakeup(&ao_i2c_state[index]);
+       }
+}
+
+void stm_i2c1_er_isr(void) { ao_i2c_er_isr(0); }
+void stm_i2c2_er_isr(void) { ao_i2c_er_isr(1); }
+
+void
+ao_i2c_get(uint8_t index)
+{
+       struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
+       ao_mutex_get(&ao_i2c_mutex[index]);
+
+       stm_i2c->sr1 = 0;
+       stm_i2c->sr2 = 0;
+}
+
+void
+ao_i2c_put(uint8_t index)
+{
+       ao_mutex_put(&ao_i2c_mutex[index]);
+}
+
+uint8_t
+ao_i2c_start(uint8_t index, uint16_t addr)
+{
+       struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
+       int             t;
+
+       ao_i2c_state[index] = I2C_IDLE;
+       ao_i2c_addr[index] = addr;
+       stm_i2c->cr2 = AO_STM_I2C_CR2;
+       stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START);
+       for (t = 0; t < I2C_TIMEOUT; t++) {
+               if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_START)))
+                       break;
+       }
+       ao_arch_block_interrupts();
+       stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
+       ao_i2c_ev_isr(index);
+       while (ao_i2c_state[index] == I2C_IDLE)
+               if (ao_sleep_for(&ao_i2c_state[index], AO_MS_TO_TICKS(250)))
+                       break;
+       ao_arch_release_interrupts();
+       return ao_i2c_state[index] == I2C_RUNNING;
+}
+
+static void
+ao_i2c_wait_stop(uint8_t index)
+{
+       struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
+       int     t;
+
+       for (t = 0; t < I2C_TIMEOUT; t++) {
+               if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_STOP)))
+                       break;
+               ao_yield();
+       }
+       ao_i2c_state[index] = I2C_IDLE;
+}
+
+static void
+ao_i2c_wait_addr(uint8_t index)
+{
+       struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
+       int     t;
+
+       for (t = 0; t < I2C_TIMEOUT; t++)
+               if (!(stm_i2c->sr1 & (1 << STM_I2C_SR1_ADDR)))
+                       break;
+       if (t)
+               printf ("wait_addr %d\n", t);
+}
+
+uint8_t
+ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop)
+{
+       struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
+       uint8_t         tx_dma_index = ao_i2c_stm_info[index].tx_dma_index;
+
+       /* Clear any pending ADDR bit */
+       (void) stm_i2c->sr2;
+       ao_i2c_wait_addr(index);
+       stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN);
+       ao_dma_set_transfer(tx_dma_index,
+                           &stm_i2c->dr,
+                           block,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (1 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
+
+       ao_dma_start(tx_dma_index);
+       ao_arch_block_interrupts();
+       while (!ao_dma_done[tx_dma_index])
+               if (ao_sleep_for(&ao_dma_done[tx_dma_index], 1 + len))
+                       break;
+       ao_dma_done_transfer(tx_dma_index);
+       stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
+       while ((stm_i2c->sr1 & (1 << STM_I2C_SR1_BTF)) == 0)
+               if (ao_sleep_for(&ao_i2c_state[index], 1 + len))
+                       break;
+       stm_i2c->cr2 = AO_STM_I2C_CR2;
+       ao_arch_release_interrupts();
+       if (stop) {
+               stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
+               ao_i2c_wait_stop(index);
+       }
+       return true;
+}
+
+static void
+ao_i2c_recv_dma_isr(int index)
+{
+       int             i;
+       struct stm_i2c  *stm_i2c = NULL;
+
+       for (i = 0; i < STM_NUM_I2C; i++)
+               if (index == ao_i2c_stm_info[i].rx_dma_index) {
+                       stm_i2c = ao_i2c_stm_info[i].stm_i2c;
+                       break;
+               }
+       if (!stm_i2c)
+               return;
+       stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST);
+       ao_dma_done[index] = 1;
+       ao_wakeup(&ao_dma_done[index]);
+}
+
+uint8_t
+ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)
+{
+       struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
+       uint8_t         ret = true;
+
+       if (len == 0)
+               return true;
+       if (len == 1) {
+               ao_i2c_recv_data[index] = block;
+               ao_i2c_recv_len[index] = 1;
+               stm_i2c->cr1 = AO_STM_I2C_CR1;
+
+               /* Clear any pending ADDR bit */
+               stm_i2c->sr2;
+               ao_i2c_wait_addr(index);
+
+               /* Enable interrupts to transfer the byte */
+               stm_i2c->cr2 = (AO_STM_I2C_CR2 |
+                               (1 << STM_I2C_CR2_ITEVTEN) |
+                               (1 << STM_I2C_CR2_ITERREN) |
+                               (1 << STM_I2C_CR2_ITBUFEN));
+               if (stop)
+                       stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
+
+               ao_arch_block_interrupts();
+               while (ao_i2c_recv_len[index])
+                       if (ao_sleep_for(&ao_i2c_recv_len[index], 1))
+                               break;
+               ao_arch_release_interrupts();
+               ret = ao_i2c_recv_len[index] == 0;
+       } else {
+               uint8_t         rx_dma_index = ao_i2c_stm_info[index].rx_dma_index;
+               ao_dma_set_transfer(rx_dma_index,
+                                   &stm_i2c->dr,
+                                   block,
+                                   len,
+                                   (0 << STM_DMA_CCR_MEM2MEM) |
+                                   (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) |
+                                   (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                                   (STM_DMA_CCR_PSIZE_8 << 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));
+
+               /* XXX ao_i2c_recv_dma_isr hasn't ever been used, so it
+                * doesn't appear to be necessary. Testing with a device
+                * that uses i2c would really be useful here to discover
+                * whether this function is necessary or not.
+                */
+#if 0
+               ao_dma_set_isr(rx_dma_index, ao_i2c_recv_dma_isr);
+#else
+               (void) ao_i2c_recv_dma_isr;
+#endif
+               stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK);
+               stm_i2c->cr2 = AO_STM_I2C_CR2 |
+                       (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST);
+               /* Clear any pending ADDR bit */
+               (void) stm_i2c->sr2;
+               ao_i2c_wait_addr(index);
+
+               ao_dma_start(rx_dma_index);
+               ao_arch_block_interrupts();
+               while (!ao_dma_done[rx_dma_index])
+                       if (ao_sleep_for(&ao_dma_done[rx_dma_index], len))
+                               break;
+               ao_arch_release_interrupts();
+               ret = ao_dma_done[rx_dma_index];
+               ao_dma_done_transfer(rx_dma_index);
+               stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
+       }
+       if (stop)
+               ao_i2c_wait_stop(index);
+       return ret;
+}
+
+static void
+ao_i2c_channel_init(uint8_t index)
+{
+       struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
+       int i;
+
+       /* Turn I2C off while configuring */
+       stm_i2c->cr1 = (1 << STM_I2C_CR1_SWRST);
+       for (i = 0; i < 100; i++)
+               asm("nop");
+       stm_i2c->cr1 = 0;
+       stm_i2c->cr2 = AO_STM_I2C_CR2;
+
+       (void) stm_i2c->sr1;
+       (void) stm_i2c->sr2;
+       (void) stm_i2c->dr;
+
+       stm_i2c->sr1 = 0;
+       stm_i2c->sr2 = 0;
+
+       stm_i2c->ccr = ((I2C_FAST << STM_I2C_CCR_FS) |
+                       (0 << STM_I2C_CCR_DUTY) |
+                       (I2C_CCR_HIGH << STM_I2C_CCR_CCR));
+
+       stm_i2c->trise = I2C_TRISE;
+
+       stm_i2c->cr1 = AO_STM_I2C_CR1;
+}
+
+static inline void
+i2c_pin_set(struct stm_gpio *gpio, int pin)
+{
+       ao_enable_port(gpio);
+       stm_gpio_conf(gpio, pin,
+                     STM_GPIO_CR_MODE_OUTPUT_2MHZ,
+                     STM_GPIO_CR_CNF_OUTPUT_AF_OPEN_DRAIN);
+}
+
+void
+ao_i2c_init(void)
+{
+#if HAS_I2C_1
+# if I2C_1_PB6_PB7
+       stm_set_afio_mapr(STM_AFIO_MAPR_I2C1_REMAP,
+                         STM_AFIO_MAPR_I2C1_REMAP_PB6_PB7,
+                         STM_AFIO_MAPR_I2C1_REMAP_MASK);
+       i2c_pin_set(&stm_gpiob, 6);
+       i2c_pin_set(&stm_gpiob, 7);
+# else
+#  if I2C_1_PB8_PB9
+       stm_set_afio_mapr(STM_AFIO_MAPR_I2C1_REMAP,
+                         STM_AFIO_MAPR_I2C1_REMAP_PB8_PB9,
+                         STM_AFIO_MAPR_I2C1_REMAP_MASK);
+       i2c_pin_set(&stm_gpiob, 8);
+       i2c_pin_set(&stm_gpiob, 9);
+#  else
+#   error "No I2C_1 port configuration specified"
+#  endif
+# endif
+
+       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_I2C1EN);
+       ao_i2c_channel_init(0);
+
+       stm_nvic_set_enable(STM_ISR_I2C1_EV_POS);
+       stm_nvic_set_priority(STM_ISR_I2C1_EV_POS, AO_STM_NVIC_MED_PRIORITY);
+       stm_nvic_set_enable(STM_ISR_I2C1_ER_POS);
+       stm_nvic_set_priority(STM_ISR_I2C1_ER_POS, AO_STM_NVIC_MED_PRIORITY);
+#endif
+
+#if HAS_I2C_2
+# if I2C_2_PB10_PB11
+       i2c_pin_set(&stm_gpiob, 10);
+       i2c_pin_set(&stm_gpiob, 11);
+# else
+#  error "No I2C_2 port configuration specified"
+# endif
+       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_I2C2EN);
+       ao_i2c_channel_init(1);
+
+       stm_nvic_set_enable(STM_ISR_I2C2_EV_POS);
+       stm_nvic_set_priority(STM_ISR_I2C2_EV_POS, AO_STM_NVIC_MED_PRIORITY);
+       stm_nvic_set_enable(STM_ISR_I2C2_ER_POS);
+       stm_nvic_set_priority(STM_ISR_I2C2_ER_POS, AO_STM_NVIC_MED_PRIORITY);
+#endif
+}
index 0ec0110db6b3ac1b8438810f3b88c626a4bda8d1..20c189457440204436f25f6ee2e333cca71faa36 100644 (file)
@@ -347,6 +347,9 @@ ao_spi_enable_pin_config(uint8_t spi_pin_config)
        switch (spi_pin_config) {
 #if SPI_1_PA5_PA6_PA7
        case AO_SPI_1_PA5_PA6_PA7:
+               stm_set_afio_mapr(STM_AFIO_MAPR_SPI1_REMAP,
+                                 STM_AFIO_MAPR_SPI1_REMAP_PA4_PA5_PA6_PA7,
+                                 STM_AFIO_MAPR_SPI1_REMAP_MASK);
                stm_spi_output_enable(&stm_gpioa, 5, SPI_1_MODE_OUTPUT);
                stm_spi_input_enable(&stm_gpioa, 6);
                stm_spi_output_enable(&stm_gpioa, 7, SPI_1_MODE_OUTPUT);
@@ -354,6 +357,9 @@ ao_spi_enable_pin_config(uint8_t spi_pin_config)
 #endif
 #if SPI_1_PB3_PB4_PB5
        case AO_SPI_1_PB3_PB4_PB5:
+               stm_set_afio_mapr(STM_AFIO_MAPR_SPI1_REMAP,
+                                 STM_AFIO_MAPR_SPI1_REMAP_PA15_PB3_PB4_PB5,
+                                 STM_AFIO_MAPR_SPI1_REMAP_MASK);
                stm_spi_output_enable(&stm_gpiob, 3, SPI_1_MODE_OUTPUT);
                stm_spi_input_enable(&stm_gpiob, 4);
                stm_spi_output_enable(&stm_gpiob, 5, SPI_1_MODE_OUTPUT);
index 37c4e1df50cf9bd3e134538dcc26ab7f952fa83f..1368ab684cb4eabf4b846154a65e8b9809085131 100644 (file)
@@ -47,17 +47,47 @@ ao_time_ns(void)
                (uint64_t) val * (1000000000ULL / AO_SYSTICK);
 }
 
+#if AO_DATA_ALL
+volatile uint8_t       ao_data_interval = 1;
+volatile uint8_t       ao_data_count;
+#endif
+
 void stm_systick_isr(void)
 {
        if (stm_systick.ctrl & (1 << STM_SYSTICK_CTRL_COUNTFLAG)) {
                ++ao_tick_count;
                ao_task_check_alarm();
+#if AO_DATA_ALL
+               if (++ao_data_count == ao_data_interval && ao_data_interval) {
+                       ao_data_count = 0;
+#if HAS_FAKE_FLIGHT
+                       if (ao_fake_flight_active)
+                               ao_fake_flight_poll();
+                       else
+#endif
+                               ao_adc_poll();
+#if (AO_DATA_ALL & ~(AO_DATA_ADC))
+                       ao_wakeup((void *) &ao_data_count);
+#endif
+               }
+#endif
 #ifdef AO_TIMER_HOOK
                AO_TIMER_HOOK;
 #endif
        }
 }
 
+#if HAS_ADC
+void
+ao_timer_set_adc_interval(uint8_t interval)
+{
+       ao_arch_critical(
+               ao_data_interval = interval;
+               ao_data_count = 0;
+               );
+}
+#endif
+
 #define SYSTICK_RELOAD (AO_SYSTICK / 100 - 1)
 
 void
index cf7d0460b96d1c34b31019ef89c996e8c4837bf6..a5b579a0e54c6fbe6cdcad6a01195b1316718b15 100644 (file)
@@ -503,11 +503,11 @@ extern struct stm_gpio stm_gpioc;
 extern struct stm_gpio stm_gpiod;
 extern struct stm_gpio stm_gpioe;
 
-//#define stm_gpioe  (*((struct stm_gpio *) 0x40011800))
-//#define stm_gpiod  (*((struct stm_gpio *) 0x40011400))
-//#define stm_gpioc  (*((struct stm_gpio *) 0x40011000))
-//#define stm_gpiob  (*((struct stm_gpio *) 0x40010c00))
-//#define stm_gpioa  (*((struct stm_gpio *) 0x40010800))
+#define stm_gpioe  (*((struct stm_gpio *) 0x40011800))
+#define stm_gpiod  (*((struct stm_gpio *) 0x40011400))
+#define stm_gpioc  (*((struct stm_gpio *) 0x40011000))
+#define stm_gpiob  (*((struct stm_gpio *) 0x40010c00))
+#define stm_gpioa  (*((struct stm_gpio *) 0x40010800))
 
 struct stm_afio {
        vuint32_t       evcr;
@@ -518,7 +518,7 @@ struct stm_afio {
 
 extern struct stm_afio stm_afio;
 
-//#define stm_afio     (*((struct stm_afio *) 0x40010000))
+#define stm_afio       (*((struct stm_afio *) 0x40010000))
 
 #define STM_AFIO_MAPR_ADC2_ETRGREG_REMAP       20
 #define STM_AFIO_MAPR_ADC2_ETRGINJ_REMAP       19
@@ -570,6 +570,14 @@ extern struct stm_afio stm_afio;
 #define  STM_AFIO_MAPR_SPI1_REMAP_PA15_PB3_PB4_PB5     1
 #define  STM_AFIO_MAPR_SPI1_REMAP_MASK                 1
 
+#define STM_AFIO_EXTICR_PA             0
+#define STM_AFIO_EXTICR_PB             1
+#define STM_AFIO_EXTICR_PC             2
+#define STM_AFIO_EXTICR_PD             3
+#define STM_AFIO_EXTICR_PE             4
+#define STM_AFIO_EXTICR_PF             5
+#define STM_AFIO_EXTICR_PG             6
+
 static inline void
 stm_set_afio_mapr(uint8_t bit, uint32_t val, uint32_t mask) {
        uint32_t        mapr = stm_afio.mapr;
@@ -747,8 +755,7 @@ struct stm_usb {
 
 extern struct stm_usb stm_usb;
 
-
-//#define stm_usb (*((struct stm_usb *) 0x40005c00))
+#define stm_usb (*((struct stm_usb *) 0x40005c00))
 
 union stm_usb_bdt {
        struct {
@@ -927,8 +934,8 @@ struct stm_spi {
 
 extern struct stm_spi stm_spi1, stm_spi2;
 
-//#define stm_spi1 (*((struct stm_spi *) 0x40013000))
-//#define stm_spi2 (*((struct stm_spi *) 0x40003800))
+#define stm_spi1 (*((struct stm_spi *) 0x40013000))
+#define stm_spi2 (*((struct stm_spi *) 0x40003800))
 
 /* SPI channels go from 1 to 2, instead of 0 to 1 (sigh)
  */
@@ -979,7 +986,515 @@ extern struct stm_spi stm_spi1, stm_spi2;
 #define STM_SPI_SR_TXE         1
 #define STM_SPI_SR_RXNE                0
 
+#define STM_NUM_I2C    2
+
+#define STM_I2C_INDEX(channel) ((channel) - 1)
+
+struct stm_i2c {
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       vuint32_t       oar1;
+       vuint32_t       oar2;
+       vuint32_t       dr;
+       vuint32_t       sr1;
+       vuint32_t       sr2;
+       vuint32_t       ccr;
+       vuint32_t       trise;
+};
+
+extern struct stm_i2c stm_i2c1, stm_i2c2;
+
+#define stm_i2c1       (*((struct stm_i2c *) 0x40005400))
+#define stm_i2c2       (*((struct stm_i2c *) 0x40005800))
+
+#define STM_I2C_CR1_SWRST      15
+#define STM_I2C_CR1_ALERT      13
+#define STM_I2C_CR1_PEC                12
+#define STM_I2C_CR1_POS                11
+#define STM_I2C_CR1_ACK                10
+#define STM_I2C_CR1_STOP       9
+#define STM_I2C_CR1_START      8
+#define STM_I2C_CR1_NOSTRETCH  7
+#define STM_I2C_CR1_ENGC       6
+#define STM_I2C_CR1_ENPEC      5
+#define STM_I2C_CR1_ENARP      4
+#define STM_I2C_CR1_SMBTYPE    3
+#define STM_I2C_CR1_SMBUS      1
+#define STM_I2C_CR1_PE         0
+
+#define STM_I2C_CR2_LAST       12
+#define STM_I2C_CR2_DMAEN      11
+#define STM_I2C_CR2_ITBUFEN    10
+#define STM_I2C_CR2_ITEVTEN    9
+#define STM_I2C_CR2_ITERREN    8
+#define STM_I2C_CR2_FREQ       0
+#define  STM_I2C_CR2_FREQ_MASK         0x3fUL
+
+#define STM_I2C_SR1_SMBALERT   15
+#define STM_I2C_SR1_TIMEOUT    14
+#define STM_I2C_SR1_PECERR     12
+#define STM_I2C_SR1_OVR                11
+#define STM_I2C_SR1_AF         10
+#define STM_I2C_SR1_ARLO       9
+#define STM_I2C_SR1_BERR       8
+#define STM_I2C_SR1_TXE                7
+#define STM_I2C_SR1_RXNE       6
+#define STM_I2C_SR1_STOPF      4
+#define STM_I2C_SR1_ADD10      3
+#define STM_I2C_SR1_BTF                2
+#define STM_I2C_SR1_ADDR       1
+#define STM_I2C_SR1_SB         0
+
+#define STM_I2C_SR2_PEC                8
+#define  STM_I2C_SR2_PEC_MASK  0xff00UL
+#define STM_I2C_SR2_DUALF      7
+#define STM_I2C_SR2_SMBHOST    6
+#define STM_I2C_SR2_SMBDEFAULT 5
+#define STM_I2C_SR2_GENCALL    4
+#define STM_I2C_SR2_TRA                2
+#define STM_I2C_SR2_BUSY               1
+#define STM_I2C_SR2_MSL                0
+
+#define STM_I2C_CCR_FS         15
+#define STM_I2C_CCR_DUTY       14
+#define STM_I2C_CCR_CCR                0
+#define  STM_I2C_CCR_MASK      0x7ffUL
+
+struct stm_adc {
+       vuint32_t       sr;
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       vuint32_t       smpr1;
+
+       vuint32_t       smpr2;
+       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       jsqr;
+       vuint32_t       jdr1;
+
+       vuint32_t       jdr2;
+       vuint32_t       jdr3;
+       vuint32_t       jdr4;
+       vuint32_t       dr;
+};
+
+extern struct stm_adc stm_adc;
+
+#define stm_adc (*((struct stm_adc *) 0x40012400))
+
+#define STM_ADC_SQ_TEMP                16
+#define STM_ADC_SQ_V_REF       17
+
+#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_AWDEN       23
+#define STM_ADC_CR1_JAWDEN     22
+#define STM_ADC_CR1_DUALMOD    16
+# define STM_ADC_CR1_DUALMOD_INDEPENDENT               0
+# define STM_ADC_CR1_DUALMOD_COMB_REG_SIM_INJ_SIM      1
+# define STM_ADC_CR1_DUALMOD_COMB_REG_SIM_ALT_TRIG     2
+# define STM_ADC_CR1_DUALMOD_COMB_INJ_SIM_FAST_INT     3
+# define STM_ADC_CR1_DUALMOD_COMB_INJ_SIM_SLOW_INT     4
+# define STM_ADC_CR1_DUALMOD_INJ_SIM                   5
+# define STM_ADC_CR1_DUALMOD_REG_SIM                   6
+# define STM_ADC_CR1_DUALMOD_FAST_INT                  7
+# define STM_ADC_CR1_DUALMOD_SLOW_INT                  8
+# define STM_ADC_CR1_DUALMOD_ALT_TRIG                  9
+
+#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      7UL
+#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                0x1fUL
+
+#define STM_ADC_CR2_TSVREF     23
+#define STM_ADC_CR2_SWSTART    21
+#define STM_ADC_CR2_JWSTART    21
+#define STM_ADC_CR2_EXTTRIG    20
+#define STM_ADC_CR2_EXTSEL     17
+#define  STM_ADC_CR2_EXTSEL_TIM1_CC1   0
+#define  STM_ADC_CR2_EXTSEL_TIM1_CC2   1
+#define  STM_ADC_CR2_EXTSEL_TIM1_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_EXTI       6
+#define  STM_ADC_CR2_EXTSEL_SWSTART    7
+#define  STM_ADC_CR2_EXTSEL_MASK       7UL
+#define STM_ADC_CR2_JEXTTRIG   15
+#define STM_ADC_CR2_JEXTSEL    12
+#define  STM_ADC_CR2_JEXTSEL_TIM1_TRGO 0
+#define  STM_ADC_CR2_JEXTSEL_TIM1_CC4  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_EXTI_15   6
+#define  STM_ADC_CR2_JEXTSEL_JSWSTART  7
+#define  STM_ADC_CR2_JEXTSEL_MASK      7UL
+#define STM_ADC_CR2_ALIGN      11
+#define STM_ADC_CR2_DMA                8
+#define STM_ADC_CR2_RSTCAL     3
+#define STM_ADC_CR2_CAL                2
+#define STM_ADC_CR2_CONT       1
+#define STM_ADC_CR2_ADON       0
+
+struct stm_exti {
+       vuint32_t       imr;
+       vuint32_t       emr;
+       vuint32_t       rtsr;
+       vuint32_t       ftsr;
+
+       vuint32_t       swier;
+       vuint32_t       pr;
+};
+
+extern struct stm_exti stm_exti;
+
+#define stm_exti       (*((struct stm_exti *) 0x40010400))
+
+static inline void
+stm_exticr_set(struct stm_gpio *gpio, int pin) {
+       uint8_t reg = (uint8_t) (pin >> 2);
+       uint8_t shift = (pin & 3) << 2;
+       uint8_t val = 0;
+
+       /* Enable AFIO */
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_AFIOEN);
+
+       if (gpio == &stm_gpioa)
+               val = STM_AFIO_EXTICR_PA;
+       else if (gpio == &stm_gpiob)
+               val = STM_AFIO_EXTICR_PB;
+       else if (gpio == &stm_gpioc)
+               val = STM_AFIO_EXTICR_PC;
+       else if (gpio == &stm_gpiod)
+               val = STM_AFIO_EXTICR_PD;
+       else if (gpio == &stm_gpioe)
+               val = STM_AFIO_EXTICR_PE;
+
+       stm_afio.exticr[reg] = (stm_afio.exticr[reg] & (uint32_t) ~(0xf << shift)) | val << shift;
+}
+
+struct stm_tim234 {
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       vuint32_t       smcr;
+       vuint32_t       dier;
+
+       vuint32_t       sr;
+       vuint32_t       egr;
+       vuint32_t       ccmr1;
+       vuint32_t       ccmr2;
+
+       vuint32_t       ccer;
+       vuint32_t       cnt;
+       vuint32_t       psc;
+       vuint32_t       arr;
+
+       uint32_t        reserved_30;
+       vuint32_t       ccr1;
+       vuint32_t       ccr2;
+       vuint32_t       ccr3;
+
+       vuint32_t       ccr4;
+       uint32_t        reserved_44;
+       vuint32_t       dcr;
+       vuint32_t       dmar;
+};
 
+extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
+
+#define stm_tim2       (*((struct stm_tim234 *) 0x40000000))
+#define stm_tim3       (*((struct stm_tim234 *) 0x40000400))
+#define stm_tim4       (*((struct stm_tim234 *) 0x40000800))
+
+#define STM_TIM234_CR1_CKD     8
+#define  STM_TIM234_CR1_CKD_1          0
+#define  STM_TIM234_CR1_CKD_2          1
+#define  STM_TIM234_CR1_CKD_4          2
+#define  STM_TIM234_CR1_CKD_MASK       3UL
+#define STM_TIM234_CR1_ARPE    7
+#define STM_TIM234_CR1_CMS     5
+#define  STM_TIM234_CR1_CMS_EDGE       0
+#define  STM_TIM234_CR1_CMS_CENTER_1   1
+#define  STM_TIM234_CR1_CMS_CENTER_2   2
+#define  STM_TIM234_CR1_CMS_CENTER_3   3
+#define  STM_TIM234_CR1_CMS_MASK       3UL
+#define STM_TIM234_CR1_DIR     4
+#define  STM_TIM234_CR1_DIR_UP         0
+#define  STM_TIM234_CR1_DIR_DOWN       1
+#define STM_TIM234_CR1_OPM     3
+#define STM_TIM234_CR1_URS     2
+#define STM_TIM234_CR1_UDIS    1
+#define STM_TIM234_CR1_CEN     0
+
+#define STM_TIM234_CR2_TI1S    7
+#define STM_TIM234_CR2_MMS     4
+#define  STM_TIM234_CR2_MMS_RESET              0
+#define  STM_TIM234_CR2_MMS_ENABLE             1
+#define  STM_TIM234_CR2_MMS_UPDATE             2
+#define  STM_TIM234_CR2_MMS_COMPARE_PULSE      3
+#define  STM_TIM234_CR2_MMS_COMPARE_OC1REF     4
+#define  STM_TIM234_CR2_MMS_COMPARE_OC2REF     5
+#define  STM_TIM234_CR2_MMS_COMPARE_OC3REF     6
+#define  STM_TIM234_CR2_MMS_COMPARE_OC4REF     7
+#define  STM_TIM234_CR2_MMS_MASK               7UL
+#define STM_TIM234_CR2_CCDS    3
+
+#define STM_TIM234_SMCR_ETP    15
+#define STM_TIM234_SMCR_ECE    14
+#define STM_TIM234_SMCR_ETPS   12
+#define  STM_TIM234_SMCR_ETPS_OFF              0
+#define  STM_TIM234_SMCR_ETPS_DIV_2            1
+#define  STM_TIM234_SMCR_ETPS_DIV_4            2
+#define  STM_TIM234_SMCR_ETPS_DIV_8            3
+#define  STM_TIM234_SMCR_ETPS_MASK             3UL
+#define STM_TIM234_SMCR_ETF    8
+#define  STM_TIM234_SMCR_ETF_NONE              0
+#define  STM_TIM234_SMCR_ETF_INT_N_2           1
+#define  STM_TIM234_SMCR_ETF_INT_N_4           2
+#define  STM_TIM234_SMCR_ETF_INT_N_8           3
+#define  STM_TIM234_SMCR_ETF_DTS_2_N_6         4
+#define  STM_TIM234_SMCR_ETF_DTS_2_N_8         5
+#define  STM_TIM234_SMCR_ETF_DTS_4_N_6         6
+#define  STM_TIM234_SMCR_ETF_DTS_4_N_8         7
+#define  STM_TIM234_SMCR_ETF_DTS_8_N_6         8
+#define  STM_TIM234_SMCR_ETF_DTS_8_N_8         9
+#define  STM_TIM234_SMCR_ETF_DTS_16_N_5                10
+#define  STM_TIM234_SMCR_ETF_DTS_16_N_6                11
+#define  STM_TIM234_SMCR_ETF_DTS_16_N_8                12
+#define  STM_TIM234_SMCR_ETF_DTS_32_N_5                13
+#define  STM_TIM234_SMCR_ETF_DTS_32_N_6                14
+#define  STM_TIM234_SMCR_ETF_DTS_32_N_8                15
+#define  STM_TIM234_SMCR_ETF_MASK              15UL
+#define STM_TIM234_SMCR_MSM    7
+#define STM_TIM234_SMCR_TS     4
+#define  STM_TIM234_SMCR_TS_ITR0               0
+#define  STM_TIM234_SMCR_TS_ITR1               1
+#define  STM_TIM234_SMCR_TS_ITR2               2
+#define  STM_TIM234_SMCR_TS_ITR3               3
+#define  STM_TIM234_SMCR_TS_TI1F_ED            4
+#define  STM_TIM234_SMCR_TS_TI1FP1             5
+#define  STM_TIM234_SMCR_TS_TI2FP2             6
+#define  STM_TIM234_SMCR_TS_ETRF               7
+#define  STM_TIM234_SMCR_TS_MASK               7UL
+#define STM_TIM234_SMCR_SMS    0
+#define  STM_TIM234_SMCR_SMS_DISABLE           0
+#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_1    1
+#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_2    2
+#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_3    3
+#define  STM_TIM234_SMCR_SMS_RESET_MODE                4
+#define  STM_TIM234_SMCR_SMS_GATED_MODE                5
+#define  STM_TIM234_SMCR_SMS_TRIGGER_MODE      6
+#define  STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK    7
+#define  STM_TIM234_SMCR_SMS_MASK              7UL
+
+#define STM_TIM234_DIER_TDE            14
+#define STM_TIM234_DIER_CC4DE          12
+#define STM_TIM234_DIER_CC3DE          11
+#define STM_TIM234_DIER_CC2DE          10
+#define STM_TIM234_DIER_CC1DE          9
+#define STM_TIM234_DIER_UDE            8
+
+#define STM_TIM234_DIER_TIE            6
+#define STM_TIM234_DIER_CC4IE          4
+#define STM_TIM234_DIER_CC3IE          3
+#define STM_TIM234_DIER_CC2IE          2
+#define STM_TIM234_DIER_CC1IE          1
+#define STM_TIM234_DIER_UIE            0
+
+#define STM_TIM234_SR_CC4OF    12
+#define STM_TIM234_SR_CC3OF    11
+#define STM_TIM234_SR_CC2OF    10
+#define STM_TIM234_SR_CC1OF    9
+#define STM_TIM234_SR_TIF      6
+#define STM_TIM234_SR_CC4IF    4
+#define STM_TIM234_SR_CC3IF    3
+#define STM_TIM234_SR_CC2IF    2
+#define STM_TIM234_SR_CC1IF    1
+#define STM_TIM234_SR_UIF      0
+
+#define STM_TIM234_EGR_TG      6
+#define STM_TIM234_EGR_CC4G    4
+#define STM_TIM234_EGR_CC3G    3
+#define STM_TIM234_EGR_CC2G    2
+#define STM_TIM234_EGR_CC1G    1
+#define STM_TIM234_EGR_UG      0
+
+#define STM_TIM234_CCMR1_OC2CE 15
+#define STM_TIM234_CCMR1_OC2M  12
+#define  STM_TIM234_CCMR1_OC2M_FROZEN                  0
+#define  STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR1_OC2M_TOGGLE                  3
+#define  STM_TIM234_CCMR1_OC2M_FORCE_LOW               4
+#define  STM_TIM234_CCMR1_OC2M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR1_OC2M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR1_OC2M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR1_OC2M_MASK                    7UL
+#define STM_TIM234_CCMR1_OC2PE 11
+#define STM_TIM234_CCMR1_OC2FE 10
+#define STM_TIM234_CCMR1_CC2S  8
+#define  STM_TIM234_CCMR1_CC2S_OUTPUT                  0
+#define  STM_TIM234_CCMR1_CC2S_INPUT_TI2               1
+#define  STM_TIM234_CCMR1_CC2S_INPUT_TI1               2
+#define  STM_TIM234_CCMR1_CC2S_INPUT_TRC               3
+#define  STM_TIM234_CCMR1_CC2S_MASK                    3UL
+
+#define STM_TIM234_CCMR1_OC1CE 7
+#define STM_TIM234_CCMR1_OC1M  4
+#define  STM_TIM234_CCMR1_OC1M_FROZEN                  0
+#define  STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR1_OC1M_TOGGLE                  3
+#define  STM_TIM234_CCMR1_OC1M_FORCE_LOW               4
+#define  STM_TIM234_CCMR1_OC1M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR1_OC1M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR1_OC1M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR1_OC1M_MASK                    7UL
+#define STM_TIM234_CCMR1_OC1PE 3
+#define STM_TIM234_CCMR1_OC1FE 2
+#define STM_TIM234_CCMR1_CC1S  0
+#define  STM_TIM234_CCMR1_CC1S_OUTPUT                  0
+#define  STM_TIM234_CCMR1_CC1S_INPUT_TI1               1
+#define  STM_TIM234_CCMR1_CC1S_INPUT_TI2               2
+#define  STM_TIM234_CCMR1_CC1S_INPUT_TRC               3
+#define  STM_TIM234_CCMR1_CC1S_MASK                    3UL
+
+#define STM_TIM234_CCMR1_IC2F  12
+#define  STM_TIM234_CCMR1_IC2F_NONE                    0
+#define  STM_TIM234_CCMR1_IC2F_CK_INT_N_2              1
+#define  STM_TIM234_CCMR1_IC2F_CK_INT_N_4              2
+#define  STM_TIM234_CCMR1_IC2F_CK_INT_N_8              3
+#define  STM_TIM234_CCMR1_IC2F_DTS_2_N_6               4
+#define  STM_TIM234_CCMR1_IC2F_DTS_2_N_8               5
+#define  STM_TIM234_CCMR1_IC2F_DTS_4_N_6               6
+#define  STM_TIM234_CCMR1_IC2F_DTS_4_N_8               7
+#define  STM_TIM234_CCMR1_IC2F_DTS_8_N_6               8
+#define  STM_TIM234_CCMR1_IC2F_DTS_8_N_8               9
+#define  STM_TIM234_CCMR1_IC2F_DTS_16_N_5              10
+#define  STM_TIM234_CCMR1_IC2F_DTS_16_N_6              11
+#define  STM_TIM234_CCMR1_IC2F_DTS_16_N_8              12
+#define  STM_TIM234_CCMR1_IC2F_DTS_32_N_5              13
+#define  STM_TIM234_CCMR1_IC2F_DTS_32_N_6              14
+#define  STM_TIM234_CCMR1_IC2F_DTS_32_N_8              15
+#define STM_TIM234_CCMR1_IC2PSC        10
+#define  STM_TIM234_CCMR1_IC2PSC_NONE                  0
+#define  STM_TIM234_CCMR1_IC2PSC_2                     1
+#define  STM_TIM234_CCMR1_IC2PSC_4                     2
+#define  STM_TIM234_CCMR1_IC2PSC_8                     3
+#define STM_TIM234_CCMR1_IC1F  4
+#define  STM_TIM234_CCMR1_IC1F_NONE                    0
+#define  STM_TIM234_CCMR1_IC1F_CK_INT_N_2              1
+#define  STM_TIM234_CCMR1_IC1F_CK_INT_N_4              2
+#define  STM_TIM234_CCMR1_IC1F_CK_INT_N_8              3
+#define  STM_TIM234_CCMR1_IC1F_DTS_2_N_6               4
+#define  STM_TIM234_CCMR1_IC1F_DTS_2_N_8               5
+#define  STM_TIM234_CCMR1_IC1F_DTS_4_N_6               6
+#define  STM_TIM234_CCMR1_IC1F_DTS_4_N_8               7
+#define  STM_TIM234_CCMR1_IC1F_DTS_8_N_6               8
+#define  STM_TIM234_CCMR1_IC1F_DTS_8_N_8               9
+#define  STM_TIM234_CCMR1_IC1F_DTS_16_N_5              10
+#define  STM_TIM234_CCMR1_IC1F_DTS_16_N_6              11
+#define  STM_TIM234_CCMR1_IC1F_DTS_16_N_8              12
+#define  STM_TIM234_CCMR1_IC1F_DTS_32_N_5              13
+#define  STM_TIM234_CCMR1_IC1F_DTS_32_N_6              14
+#define  STM_TIM234_CCMR1_IC1F_DTS_32_N_8              15
+#define STM_TIM234_CCMR1_IC1PSC        2
+#define  STM_TIM234_CCMR1_IC1PSC_NONE                  0
+#define  STM_TIM234_CCMR1_IC1PSC_2                     1
+#define  STM_TIM234_CCMR1_IC1PSC_4                     2
+#define  STM_TIM234_CCMR1_IC1PSC_8                     3
+
+#define STM_TIM234_CCMR2_OC4CE 15
+#define STM_TIM234_CCMR2_OC4M  12
+#define  STM_TIM234_CCMR2_OC4M_FROZEN                  0
+#define  STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR2_OC4M_TOGGLE                  3
+#define  STM_TIM234_CCMR2_OC4M_FORCE_LOW               4
+#define  STM_TIM234_CCMR2_OC4M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR2_OC4M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR2_OC4M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR2_OC4M_MASK                    7UL
+#define STM_TIM234_CCMR2_OC4PE 11
+#define STM_TIM234_CCMR2_OC4FE 10
+#define STM_TIM234_CCMR2_CC4S  8
+#define  STM_TIM234_CCMR2_CC4S_OUTPUT                  0
+#define  STM_TIM234_CCMR2_CC4S_INPUT_TI4               1
+#define  STM_TIM234_CCMR2_CC4S_INPUT_TI3               2
+#define  STM_TIM234_CCMR2_CC4S_INPUT_TRC               3
+#define  STM_TIM234_CCMR2_CC4S_MASK                    3UL
+
+#define STM_TIM234_CCMR2_OC3CE 7
+#define STM_TIM234_CCMR2_OC3M  4
+#define  STM_TIM234_CCMR2_OC3M_FROZEN                  0
+#define  STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR2_OC3M_TOGGLE                  3
+#define  STM_TIM234_CCMR2_OC3M_FORCE_LOW               4
+#define  STM_TIM234_CCMR2_OC3M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR2_OC3M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR2_OC3M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR2_OC3M_MASK                    7UL
+#define STM_TIM234_CCMR2_OC3PE 3
+#define STM_TIM234_CCMR2_OC3FE 2
+#define STM_TIM234_CCMR2_CC3S  0
+#define  STM_TIM234_CCMR2_CC3S_OUTPUT                  0
+#define  STM_TIM234_CCMR2_CC3S_INPUT_TI3               1
+#define  STM_TIM234_CCMR2_CC3S_INPUT_TI4               2
+#define  STM_TIM234_CCMR2_CC3S_INPUT_TRC               3
+#define  STM_TIM234_CCMR2_CC3S_MASK                    3UL
+
+#define STM_TIM234_CCER_CC4NP  15
+#define STM_TIM234_CCER_CC4P   13
+#define  STM_TIM234_CCER_CC4P_ACTIVE_HIGH      0
+#define  STM_TIM234_CCER_CC4P_ACTIVE_LOW       1
+#define STM_TIM234_CCER_CC4E   12
+#define STM_TIM234_CCER_CC3NP  11
+#define STM_TIM234_CCER_CC3P   9
+#define  STM_TIM234_CCER_CC3P_ACTIVE_HIGH      0
+#define  STM_TIM234_CCER_CC3P_ACTIVE_LOW       1
+#define STM_TIM234_CCER_CC3E   8
+#define STM_TIM234_CCER_CC2NP  7
+#define STM_TIM234_CCER_CC2P   5
+#define  STM_TIM234_CCER_CC2P_ACTIVE_HIGH      0
+#define  STM_TIM234_CCER_CC2P_ACTIVE_LOW       1
+#define STM_TIM234_CCER_CC2E   4
+#define STM_TIM234_CCER_CC1NP  3
+#define STM_TIM234_CCER_CC1P   1
+#define  STM_TIM234_CCER_CC1P_ACTIVE_HIGH      0
+#define  STM_TIM234_CCER_CC1P_ACTIVE_LOW       1
+#define STM_TIM234_CCER_CC1E   0
 
 #define isr_decl(name) void stm_ ## name ## _isr(void)