From: Keith Packard Date: Thu, 30 Mar 2023 07:05:21 +0000 (-0700) Subject: altos/stm32f1: Add more IP block drivers X-Git-Tag: 1.9.18~2^2~74 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=1cad5ca2525fbe067f897871bc2c4dc45a13e85a altos/stm32f1: Add more IP block drivers adc, beep, exti, i2c Also hooked up data sampling bits in ao_timer.c Signed-off-by: Keith Packard --- diff --git a/src/stm32f1/ao_adc_stm.c b/src/stm32f1/ao_adc_stm.c new file mode 100644 index 00000000..f552d67d --- /dev/null +++ b/src/stm32f1/ao_adc_stm.c @@ -0,0 +1,348 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +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; +} diff --git a/src/stm32f1/ao_arch.h b/src/stm32f1/ao_arch.h index 7e53f226..b58e33f6 100644 --- a/src/stm32f1/ao_arch.h +++ b/src/stm32f1/ao_arch.h @@ -58,6 +58,15 @@ #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) diff --git a/src/stm32f1/ao_arch_funcs.h b/src/stm32f1/ao_arch_funcs.h index ad9ab2a6..0bc199c2 100644 --- a/src/stm32f1/ao_arch_funcs.h +++ b/src/stm32f1/ao_arch_funcs.h @@ -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 index 00000000..73bdb8cf --- /dev/null +++ b/src/stm32f1/ao_beep_stm.c @@ -0,0 +1,189 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 index 00000000..b2157efd --- /dev/null +++ b/src/stm32f1/ao_exti_stm.c @@ -0,0 +1,148 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +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 index 00000000..e84f594b --- /dev/null +++ b/src/stm32f1/ao_i2c_stm.c @@ -0,0 +1,444 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +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 +} diff --git a/src/stm32f1/ao_spi_stm.c b/src/stm32f1/ao_spi_stm.c index 0ec0110d..20c18945 100644 --- a/src/stm32f1/ao_spi_stm.c +++ b/src/stm32f1/ao_spi_stm.c @@ -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); diff --git a/src/stm32f1/ao_timer.c b/src/stm32f1/ao_timer.c index 37c4e1df..1368ab68 100644 --- a/src/stm32f1/ao_timer.c +++ b/src/stm32f1/ao_timer.c @@ -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 diff --git a/src/stm32f1/stm32f1.h b/src/stm32f1/stm32f1.h index cf7d0460..a5b579a0 100644 --- a/src/stm32f1/stm32f1.h +++ b/src/stm32f1/stm32f1.h @@ -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)