--- /dev/null
+/*
+ * 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;
+}
#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)
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))
#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_ */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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)
+{
+}
--- /dev/null
+/*
+ * 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
+}
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);
#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);
(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
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;
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
#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;
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 {
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)
*/
#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)