This is what the disco board hooks up.
Signed-off-by: Keith Packard <keithp@keithp.com>
#define AO_SYSTICK (AO_HCLK)
#define AO_PANIC_DELAY_SCALE (AO_SYSCLK / 12000000)
+/* The stm32f413 implements only 4 bits of the priority fields? */
+
+#if AO_NONMASK_INTERRUPT
+#define AO_STM_NVIC_NONMASK_PRIORITY 0x00
+
+/* Set the basepri register to this value to mask all
+ * non-maskable priorities
+ */
+#define AO_STM_NVIC_BASEPRI_MASK 0x10
+#endif
+
+#define AO_STM_NVIC_HIGH_PRIORITY 0x40
+#define AO_STM_NVIC_MED_PRIORITY 0x80
+#define AO_STM_NVIC_LOW_PRIORITY 0xC0
+#define AO_STM_NVIC_CLOCK_PRIORITY 0xf0
+
+#define AO_GPIO_MODE_PULL_NONE 0
+#define AO_GPIO_MODE_PULL_UP 4
+#define AO_GPIO_MODE_PULL_DOWN 8
+
+/* usart stuff */
+
+#define AO_SERIAL_SPEED_4800 4800
+#define AO_SERIAL_SPEED_9600 9600
+#define AO_SERIAL_SPEED_19200 19200
+#define AO_SERIAL_SPEED_57600 57600
+#define AO_SERIAL_SPEED_115200 115200
+
#endif /* _AO_ARCH_H_ */
ao_gpio_set_mode(port, bit, mode); \
} while (0)
+/* usart */
+
+void
+ao_usart_init(void);
+
+
#endif /* _AO_ARCH_FUNCS_H_ */
isr(usart1)
isr(usart2)
isr(usart3)
-isr(exti5_10)
+isr(exti15_10)
isr(rtc_alarm)
isr(otg_fs_wkup)
isr(tim8_brk_tim12)
i(0xd4, usart1),
i(0xd8, usart2),
i(0xdc, usart3),
- i(0xe0, exti5_10),
+ i(0xe0, exti15_10),
i(0xe4, rtc_alarm),
i(0xe8, otg_fs_wkup),
i(0xec, tim8_brk_tim12),
i(0xf0, tim8_up_tim13),
+ i(0x15c, usart6),
};
--- /dev/null
+/*
+ * Copyright © 2018 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>
+
+/* ao_serial_stm.c */
+struct ao_stm_usart {
+ struct ao_fifo rx_fifo;
+ struct ao_fifo tx_fifo;
+ struct stm_usart *reg;
+ uint32_t clk;
+ uint8_t tx_running;
+ uint8_t draining;
+#if HAS_SERIAL_SW_FLOW
+ /* RTS - 0 if we have FIFO space, 1 if not
+ * CTS - 0 if we can send, 0 if not
+ */
+ struct stm_gpio *gpio_rts;
+ struct stm_gpio *gpio_cts;
+ uint8_t pin_rts;
+ uint8_t pin_cts;
+ uint8_t rts;
+#endif
+};
+
+static int
+_ao_usart_tx_start(struct ao_stm_usart *usart)
+{
+ if (!ao_fifo_empty(usart->tx_fifo)) {
+#if HAS_SERIAL_SW_FLOW
+ if (usart->gpio_cts && ao_gpio_get(usart->gpio_cts, usart->pin_cts) == 1) {
+ ao_exti_enable(usart->gpio_cts, usart->pin_cts);
+ return 0;
+ }
+#endif
+ if (usart->reg->sr & (1 << STM_USART_SR_TXE))
+ {
+ usart->tx_running = 1;
+ usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE);
+ ao_fifo_remove(usart->tx_fifo, usart->reg->dr);
+ ao_wakeup(&usart->tx_fifo);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#if HAS_SERIAL_SW_FLOW
+static void
+_ao_usart_cts(struct ao_stm_usart *usart)
+{
+ if (_ao_usart_tx_start(usart))
+ ao_exti_disable(usart->gpio_cts, usart->pin_cts);
+}
+#endif
+
+static void
+_ao_usart_rx(struct ao_stm_usart *usart, int is_stdin)
+{
+ if (usart->reg->sr & (1 << STM_USART_SR_RXNE)) {
+ if (!ao_fifo_full(usart->rx_fifo)) {
+ ao_fifo_insert(usart->rx_fifo, usart->reg->dr);
+ ao_wakeup(&usart->rx_fifo);
+ if (is_stdin)
+ ao_wakeup(&ao_stdin_ready);
+#if HAS_SERIAL_SW_FLOW
+ /* If the fifo is nearly full, turn off RTS and wait
+ * for it to drain a bunch
+ */
+ if (usart->gpio_rts && ao_fifo_mostly(usart->rx_fifo)) {
+ ao_gpio_set(usart->gpio_rts, usart->pin_rts, 1);
+ usart->rts = 0;
+ }
+#endif
+ } else {
+ usart->reg->cr1 &= ~(1 << STM_USART_CR1_RXNEIE);
+ }
+ }
+}
+
+static void
+ao_usart_isr(struct ao_stm_usart *usart, int is_stdin)
+{
+ _ao_usart_rx(usart, is_stdin);
+
+ if (!_ao_usart_tx_start(usart))
+ usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE);
+
+ if (usart->reg->sr & (1 << STM_USART_SR_TC)) {
+ usart->tx_running = 0;
+ usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE);
+ if (usart->draining) {
+ usart->draining = 0;
+ ao_wakeup(&usart->tx_fifo);
+ }
+ }
+}
+
+static int
+_ao_usart_pollchar(struct ao_stm_usart *usart)
+{
+ int c;
+
+ if (ao_fifo_empty(usart->rx_fifo))
+ c = AO_READ_AGAIN;
+ else {
+ uint8_t u;
+ ao_fifo_remove(usart->rx_fifo,u);
+ if ((usart->reg->cr1 & (1 << STM_USART_CR1_RXNEIE)) == 0) {
+ if (ao_fifo_barely(usart->rx_fifo))
+ usart->reg->cr1 |= (1 << STM_USART_CR1_RXNEIE);
+ }
+#if HAS_SERIAL_SW_FLOW
+ /* If we've cleared RTS, check if there's space now and turn it back on */
+ if (usart->gpio_rts && usart->rts == 0 && ao_fifo_barely(usart->rx_fifo)) {
+ ao_gpio_set(usart->gpio_rts, usart->pin_rts, 0);
+ usart->rts = 1;
+ }
+#endif
+ c = u;
+ }
+ return c;
+}
+
+static char
+ao_usart_getchar(struct ao_stm_usart *usart)
+{
+ int c;
+ ao_arch_block_interrupts();
+ while ((c = _ao_usart_pollchar(usart)) == AO_READ_AGAIN)
+ ao_sleep(&usart->rx_fifo);
+ ao_arch_release_interrupts();
+ return (char) c;
+}
+
+static inline uint8_t
+_ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout)
+{
+ return ao_sleep_for(&usart->rx_fifo, timeout);
+}
+
+static void
+ao_usart_putchar(struct ao_stm_usart *usart, char c)
+{
+ ao_arch_block_interrupts();
+ while (ao_fifo_full(usart->tx_fifo))
+ ao_sleep(&usart->tx_fifo);
+ ao_fifo_insert(usart->tx_fifo, c);
+ _ao_usart_tx_start(usart);
+ ao_arch_release_interrupts();
+}
+
+static void
+ao_usart_drain(struct ao_stm_usart *usart)
+{
+ ao_arch_block_interrupts();
+ while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) {
+ usart->draining = 1;
+ ao_sleep(&usart->tx_fifo);
+ }
+ ao_arch_release_interrupts();
+}
+
+static void
+ao_usart_set_speed(struct ao_stm_usart *usart, uint32_t speed)
+{
+ if (speed > 115200)
+ return;
+ usart->reg->brr = usart->clk / speed;
+}
+
+static void
+_ao_usart_init(struct ao_stm_usart *usart, int hw_flow)
+{
+ usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) |
+ (1 << STM_USART_CR1_UE) |
+ (0 << STM_USART_CR1_M) |
+ (0 << STM_USART_CR1_WAKE) |
+ (0 << STM_USART_CR1_PCE) |
+ (0 << STM_USART_CR1_PS) |
+ (0 << STM_USART_CR1_PEIE) |
+ (0 << STM_USART_CR1_TXEIE) |
+ (0 << STM_USART_CR1_TCIE) |
+ (1 << STM_USART_CR1_RXNEIE) |
+ (0 << STM_USART_CR1_IDLEIE) |
+ (1 << STM_USART_CR1_TE) |
+ (1 << STM_USART_CR1_RE) |
+ (0 << STM_USART_CR1_RWU) |
+ (0 << STM_USART_CR1_SBK));
+
+ usart->reg->cr2 = ((0 << STM_USART_CR2_LINEN) |
+ (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) |
+ (0 << STM_USART_CR2_CLKEN) |
+ (0 << STM_USART_CR2_CPOL) |
+ (0 << STM_USART_CR2_CPHA) |
+ (0 << STM_USART_CR2_LBCL) |
+ (0 << STM_USART_CR2_LBDIE) |
+ (0 << STM_USART_CR2_LBDL) |
+ (0 << STM_USART_CR2_ADD));
+
+ usart->reg->cr3 = ((0 << STM_USART_CR3_ONEBIT) |
+ (0 << STM_USART_CR3_CTSIE) |
+ (0 << STM_USART_CR3_CTSE) |
+ (0 << STM_USART_CR3_RTSE) |
+ (0 << STM_USART_CR3_DMAT) |
+ (0 << STM_USART_CR3_DMAR) |
+ (0 << STM_USART_CR3_SCEN) |
+ (0 << STM_USART_CR3_NACK) |
+ (0 << STM_USART_CR3_HDSEL) |
+ (0 << STM_USART_CR3_IRLP) |
+ (0 << STM_USART_CR3_IREN) |
+ (0 << STM_USART_CR3_EIE));
+
+ if (hw_flow)
+ usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) |
+ (1 << STM_USART_CR3_RTSE));
+
+ /* Pick a 9600 baud rate */
+ ao_usart_set_speed(usart, 9600);
+}
+
+#if HAS_SERIAL_HW_FLOW
+static void
+ao_usart_set_flow(struct ao_stm_usart *usart)
+{
+}
+#endif
+
+#if HAS_SERIAL_6
+
+struct ao_stm_usart ao_stm_usart6;
+
+void stm_usart6_isr(void) { ao_usart_isr(&ao_stm_usart6, USE_SERIAL_6_STDIN); }
+
+char
+ao_serial6_getchar(void)
+{
+ return ao_usart_getchar(&ao_stm_usart6);
+}
+
+void
+ao_serial6_putchar(char c)
+{
+ ao_usart_putchar(&ao_stm_usart6, c);
+}
+
+int
+_ao_serial6_pollchar(void)
+{
+ return _ao_usart_pollchar(&ao_stm_usart6);
+}
+
+uint8_t
+_ao_serial6_sleep_for(uint16_t timeout)
+{
+ return _ao_usart_sleep_for(&ao_stm_usart6, timeout);
+}
+
+void
+ao_serial6_set_speed(uint32_t speed)
+{
+ ao_usart_drain(&ao_stm_usart6);
+ ao_usart_set_speed(&ao_stm_usart6, speed);
+}
+
+void
+ao_serial6_drain(void)
+{
+ ao_usart_drain(&ao_stm_usart6);
+}
+#endif /* HAS_SERIAL_6 */
+
+#if HAS_SERIAL_SW_FLOW
+static void
+ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart,
+ void (*isr)(void),
+ struct stm_gpio *port_rts,
+ int pin_rts,
+ struct stm_gpio *port_cts,
+ int pin_cts)
+{
+ /* Pull RTS low to note that there's space in the FIFO */
+ ao_enable_output(port_rts, pin_rts, 0);
+ usart->gpio_rts = port_rts;
+ usart->pin_rts = pin_rts;
+ usart->rts = 1;
+
+ ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr);
+ usart->gpio_cts = port_cts;
+ usart->pin_cts = pin_cts;
+}
+#endif
+
+void
+ao_usart_init(void)
+{
+#if HAS_SERIAL_6
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART6EN);
+
+ ao_stm_usart6.reg = &stm_usart6;
+ ao_stm_usart6.clk = AO_P2CLK;
+
+ ao_enable_port(SERIAL_6_RX_PORT);
+ ao_enable_port(SERIAL_6_TX_PORT);
+
+ stm_afr_set(SERIAL_6_RX_PORT, SERIAL_6_RX_PIN, STM_AFR_AF8);
+ stm_afr_set(SERIAL_6_TX_PORT, SERIAL_6_TX_PIN, STM_AFR_AF8);
+
+ stm_nvic_set_enable(STM_ISR_USART6_POS);
+ stm_nvic_set_priority(STM_ISR_USART6_POS, AO_STM_NVIC_MED_PRIORITY);
+
+ _ao_usart_init(&ao_stm_usart6, USE_SERIAL_6_FLOW && !USE_SERIAL_6_SW_FLOW);
+
+# if USE_SERIAL_6_FLOW
+# if USE_SERIAL_6_SW_FLOW
+ ao_serial_set_sw_rts_cts(&ao_stm_usart6,
+ ao_serial6_cts,
+ SERIAL_6_PORT_RTS,
+ SERIAL_6_PIN_RTS,
+ SERIAL_6_PORT_CTS,
+ SERIAL_6_PIN_CTS);
+# else
+ stm_afr_set(SERIAL_6_PORT_RTS, SERIAL_6_PIN_RTS, STM_AFR_AF8);
+ stm_afr_set(SERIAL_6_PORT_CTS, SERIAL_6_PIN_CTS, STM_AFR_AF8);
+# endif
+#endif
+
+#if USE_SERIAL_6_STDIN && !DELAY_SERIAL_6_STDIN
+ ao_add_stdio(_ao_serial6_pollchar,
+ ao_serial6_putchar,
+ NULL);
+#endif
+#endif
+}
stm_uart7 = 0x40007800;
stm_uart8 = 0x40007c00;
+stm_tim1 = 0x40010000;
+stm_tim8 = 0x40010400;
+stm_usart1 = 0x40011000;
+stm_usart6 = 0x40011400;
+stm_uart9 = 0x40011800;
+stm_uart10 = 0x40011c00;
+stm_adc = 0x40012000;
+stm_sdio = 0x40012c00;
+stm_spi1 = 0x40013000;
+stm_spi4 = 0x40013400;
+stm_syscfg = 0x40013800;
+stm_exti = 0x40013c00;
+stm_tim9 = 0x40014000;
+stm_tim10 = 0x40014400;
+stm_tim11 = 0x40014800;
+stm_spi5 = 0x40015000;
+stm_sai1 = 0x40015800;
+stm_dfsdm1 = 0x40016000;
+stm_dfsdm2 = 0x40016400;
+
stm_gpioa = 0x40020000;
stm_gpiob = 0x40020400;
stm_gpioc = 0x40020800;
#define STM_RCC_APB1ENR_TIM3EN 1
#define STM_RCC_APB1ENR_TIM2EN 0
+#define STM_RCC_APB2ENR_DFSDM2EN 25
+#define STM_RCC_APB2ENR_DFSDM1EN 24
+#define STM_RCC_APB2ENR_SAI1EN 22
+#define STM_RCC_APB2ENR_SPI5EN 20
+#define STM_RCC_APB2ENR_TIM11EN 18
+#define STM_RCC_APB2ENR_TIM10EN 17
+#define STM_RCC_APB2ENR_TIM9EN 16
+#define STM_RCC_APB2ENR_EXITEN 15
+#define STM_RCC_APB2ENR_SYSCFGEN 14
+#define STM_RCC_APB2ENR_SPI4EN 13
+#define STM_RCC_APB2ENR_SPI1EN 12
+#define STM_RCC_APB2ENR_SDIOEN 11
+#define STM_RCC_APB2ENR_ADC1EN 8
+#define STM_RCC_APB2ENR_UART10EN 7
+#define STM_RCC_APB2ENR_UART9EN 5
+#define STM_RCC_APB2ENR_USART6EN 5
+#define STM_RCC_APB2ENR_USART1EN 4
+#define STM_RCC_APB2ENR_TIM8EN 1
+#define STM_RCC_APB2ENR_TIM1EN 0
+
#define STM_RCC_CSR_RMVF 24
struct stm_ictr {
stm_nvic_enabled(int irq) {
return IRQ_BOOL(stm_nvic.iser[IRQ_REG(irq)], irq);
}
-
+
static inline void
stm_nvic_set_pending(int irq) {
stm_nvic.ispr[IRQ_REG(irq)] = IRQ_MASK(irq);
return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0);
}
+#define isr(name) void stm_ ## name ## _isr(void)
+
+isr(nmi);
+isr(hardfault);
+isr(memmanage);
+isr(busfault);
+isr(usagefault);
+isr(svc);
+isr(debugmon);
+isr(pendsv);
+isr(systick);
+isr(wwdg);
+isr(pvd);
+isr(tamper_stamp);
+isr(rtc_wkup);
+isr(flash);
+isr(rcc);
+isr(exti0);
+isr(exti1);
+isr(exti2);
+isr(exti3);
+isr(exti4);
+isr(dma1_stream0);
+isr(dma1_stream1);
+isr(dma1_stream2);
+isr(dma1_stream3);
+isr(dma1_stream4);
+isr(dma1_stream5);
+isr(dma1_stream6);
+isr(adc);
+isr(can1_tx);
+isr(can1_rx0);
+isr(can1_rx1);
+isr(can1_sce);
+isr(exti9_5);
+isr(tim1_brk_tim9);
+isr(tim1_up_tim10);
+isr(tim_trg_com_tim11);
+isr(tim1_cc);
+isr(tim2);
+isr(tim3);
+isr(tim4);
+isr(i2c1_evt);
+isr(i2c1_err);
+isr(i2c2_evt);
+isr(i2c2_err);
+isr(spi1);
+isr(spi2);
+isr(usart1);
+isr(usart2);
+isr(usart3);
+isr(exti15_10);
+isr(rtc_alarm);
+isr(otg_fs_wkup);
+isr(tim8_brk_tim12);
+isr(tim8_up_tim13);
+isr(tim8_trg_com_tim14);
+isr(tim8_cc);
+isr(dma1_stream7);
+isr(fsmc);
+isr(sdio);
+isr(tim5);
+isr(spi3);
+isr(uart4);
+isr(uart5);
+isr(tim6_glb_it);
+isr(tim7);
+isr(dma2_stream0);
+isr(dma2_stream1);
+isr(dma2_stream2);
+isr(dma2_stream3);
+isr(dma2_stream4);
+isr(dfsdm1_flt0);
+isr(dfsdm1_flt1);
+isr(can2_tx);
+isr(can2_rx0);
+isr(can2_rx1);
+isr(can2_sce);
+isr(otg_fs);
+isr(dma2_stream5);
+isr(dma2_stream6);
+isr(dma2_stream7);
+isr(usart6);
+isr(i2c3_ev);
+isr(i2c3_er);
+isr(can3_tx);
+isr(can3_rx0);
+isr(can3_rx1);
+isr(can3_sce);
+isr(crypto);
+isr(rng);
+isr(fpu);
+isr(uart7);
+isr(uart8);
+isr(spi4);
+isr(spi5);
+isr(sai1);
+isr(uart9);
+isr(uart10);
+isr(quad_spi);
+isr(i2cfmp1_ev);
+isr(i2cfmp1_er);
+isr(exti23);
+isr(dfsdm2_flt0);
+isr(dfsdm2_flt1);
+isr(dfsdm2_flt2);
+isr(dfsdm2_flt3);
+
+#undef isr
+
+#define STM_ISR_WWDG_POS 0
+#define STM_ISR_PVD_POS 1
+#define STM_ISR_TAMPER_STAMP_POS 2
+#define STM_ISR_RTC_WKUP_POS 3
+#define STM_ISR_FLASH_POS 4
+#define STM_ISR_RCC_POS 5
+#define STM_ISR_EXTI0_POS 6
+#define STM_ISR_EXTI1_POS 7
+#define STM_ISR_EXTI2_POS 8
+#define STM_ISR_EXTI3_POS 9
+#define STM_ISR_EXTI4_POS 10
+#define STM_ISR_DMA1_STREAM0_POS 11
+#define STM_ISR_DMA1_STREAM1_POS 12
+#define STM_ISR_DMA1_STREAM2_POS 13
+#define STM_ISR_DMA1_STREAM3_POS 14
+#define STM_ISR_DMA1_STREAM4_POS 15
+#define STM_ISR_DMA1_STREAM5_POS 16
+#define STM_ISR_DMA1_STREAM6_POS 17
+#define STM_ISR_ADC_POS 18
+#define STM_ISR_CAN1_TX_POS 19
+#define STM_ISR_CAN1_RX0_POS 20
+#define STM_ISR_CAN1_RX1_POS 21
+#define STM_ISR_CAN1_SCE_POS 22
+#define STM_ISR_EXTI9_5_POS 23
+#define STM_ISR_USART1_POS 37
+#define STM_ISR_USART2_POS 38
+#define STM_ISR_USART3_POS 39
+#define STM_ISR_UART4_POS 52
+#define STM_ISR_UART5_POS 53
+#define STM_ISR_USART6_POS 71
+#define STM_ISR_UART7_POS 82
+#define STM_ISR_UART9_POS 88
+#define STM_ISR_UART10_POS 89
+
+#define STM_ISR_EXTI15_10_POS 40
+
struct stm_flash {
vuint32_t acr;
vuint32_t keyr;
#define STM_SCB_CPACR_FP0 STM_SCB_CPACR_CP(10)
#define STM_SCB_CPACR_FP1 STM_SCB_CPACR_CP(11)
+#define STM_SCB_AIRCR_VECTKEY 16
+#define STM_SCB_AIRCR_VECTKEY_KEY 0x05fa
+#define STM_SCB_AIRCR_PRIGROUP 8
+#define STM_SCB_AIRCR_SYSRESETREQ 2
+#define STM_SCB_AIRCR_VECTCLRACTIVE 1
+#define STM_SCB_AIRCR_VECTRESET 0
+
/* The SYSTICK starts at 0xe000e010 */
struct stm_systick {
#define STM_SYSTICK_CSR_CLKSOURCE_AHB 1
#define STM_SYSTICK_CSR_COUNTFLAG 16
+#define STM_SYSCFG_EXTICR_PA 0
+#define STM_SYSCFG_EXTICR_PB 1
+#define STM_SYSCFG_EXTICR_PC 2
+#define STM_SYSCFG_EXTICR_PD 3
+#define STM_SYSCFG_EXTICR_PE 4
+#define STM_SYSCFG_EXTICR_PF 5
+#define STM_SYSCFG_EXTICR_PG 6
+#define STM_SYSCFG_EXTICR_PH 7
+
+struct stm_syscfg {
+ vuint32_t memrmp;
+ vuint32_t pmc;
+ vuint32_t exticr[4];
+};
+
+extern struct stm_syscfg stm_syscfg;
+
+#define stm_syscfg (*((struct stm_syscfg *) 0x40013800))
+
+#define STM_SYSCFG_MEMRMP_MEM_MODE 0
+#define STM_SYSCFG_MEMRMP_MEM_MODE_MAIN_FLASH 0
+#define STM_SYSCFG_MEMRMP_MEM_MODE_SYSTEM_FLASH 1
+#define STM_SYSCFG_MEMRMP_MEM_MODE_SRAM 3
+#define STM_SYSCFG_MEMRMP_MEM_MODE_MASK 3
+
+#define STM_SYSCFG_PMC_ADC1DC2 0
+
+static inline void
+stm_exticr_set(struct stm_gpio *gpio, int pin) {
+ uint8_t reg = pin >> 2;
+ uint8_t shift = (pin & 3) << 2;
+ uint8_t val = 0;
+
+ /* Enable SYSCFG */
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN);
+
+ if (gpio == &stm_gpioa)
+ val = STM_SYSCFG_EXTICR_PA;
+ else if (gpio == &stm_gpiob)
+ val = STM_SYSCFG_EXTICR_PB;
+ else if (gpio == &stm_gpioc)
+ val = STM_SYSCFG_EXTICR_PC;
+ else if (gpio == &stm_gpiod)
+ val = STM_SYSCFG_EXTICR_PD;
+ else if (gpio == &stm_gpioe)
+ val = STM_SYSCFG_EXTICR_PE;
+ else if (gpio == &stm_gpiof)
+ val = STM_SYSCFG_EXTICR_PF;
+ else if (gpio == &stm_gpiog)
+ val = STM_SYSCFG_EXTICR_PG;
+ else if (gpio == &stm_gpioh)
+ val = STM_SYSCFG_EXTICR_PH;
+
+ stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift;
+}
+
+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 *) 0x40013c00))
+
+struct stm_usart {
+ vuint32_t sr; /* status register */
+ vuint32_t dr; /* data register */
+ vuint32_t brr; /* baud rate register */
+ vuint32_t cr1; /* control register 1 */
+
+ vuint32_t cr2; /* control register 2 */
+ vuint32_t cr3; /* control register 3 */
+ vuint32_t gtpr; /* guard time and prescaler */
+};
+
+extern struct stm_usart stm_usart6;
+
+#define stm_usart6 (*((struct stm_usart *) 0x40011400))
+
+#define STM_USART_SR_CTS (9) /* CTS flag */
+#define STM_USART_SR_LBD (8) /* LIN break detection flag */
+#define STM_USART_SR_TXE (7) /* Transmit data register empty */
+#define STM_USART_SR_TC (6) /* Transmission complete */
+#define STM_USART_SR_RXNE (5) /* Read data register not empty */
+#define STM_USART_SR_IDLE (4) /* IDLE line detected */
+#define STM_USART_SR_ORE (3) /* Overrun error */
+#define STM_USART_SR_NF (2) /* Noise detected flag */
+#define STM_USART_SR_FE (1) /* Framing error */
+#define STM_USART_SR_PE (0) /* Parity error */
+
+#define STM_USART_CR1_OVER8 (15) /* Oversampling mode */
+#define STM_USART_CR1_UE (13) /* USART enable */
+#define STM_USART_CR1_M (12) /* Word length */
+#define STM_USART_CR1_WAKE (11) /* Wakeup method */
+#define STM_USART_CR1_PCE (10) /* Parity control enable */
+#define STM_USART_CR1_PS (9) /* Parity selection */
+#define STM_USART_CR1_PEIE (8) /* PE interrupt enable */
+#define STM_USART_CR1_TXEIE (7) /* TXE interrupt enable */
+#define STM_USART_CR1_TCIE (6) /* Transmission complete interrupt enable */
+#define STM_USART_CR1_RXNEIE (5) /* RXNE interrupt enable */
+#define STM_USART_CR1_IDLEIE (4) /* IDLE interrupt enable */
+#define STM_USART_CR1_TE (3) /* Transmitter enable */
+#define STM_USART_CR1_RE (2) /* Receiver enable */
+#define STM_USART_CR1_RWU (1) /* Receiver wakeup */
+#define STM_USART_CR1_SBK (0) /* Send break */
+
+#define STM_USART_CR2_LINEN (14) /* LIN mode enable */
+#define STM_USART_CR2_STOP (12) /* STOP bits */
+#define STM_USART_CR2_STOP_MASK 3
+#define STM_USART_CR2_STOP_1 0
+#define STM_USART_CR2_STOP_0_5 1
+#define STM_USART_CR2_STOP_2 2
+#define STM_USART_CR2_STOP_1_5 3
+
+#define STM_USART_CR2_CLKEN (11) /* Clock enable */
+#define STM_USART_CR2_CPOL (10) /* Clock polarity */
+#define STM_USART_CR2_CPHA (9) /* Clock phase */
+#define STM_USART_CR2_LBCL (8) /* Last bit clock pulse */
+#define STM_USART_CR2_LBDIE (6) /* LIN break detection interrupt enable */
+#define STM_USART_CR2_LBDL (5) /* lin break detection length */
+#define STM_USART_CR2_ADD (0)
+#define STM_USART_CR2_ADD_MASK 0xf
+
+#define STM_USART_CR3_ONEBIT (11) /* One sample bit method enable */
+#define STM_USART_CR3_CTSIE (10) /* CTS interrupt enable */
+#define STM_USART_CR3_CTSE (9) /* CTS enable */
+#define STM_USART_CR3_RTSE (8) /* RTS enable */
+#define STM_USART_CR3_DMAT (7) /* DMA enable transmitter */
+#define STM_USART_CR3_DMAR (6) /* DMA enable receiver */
+#define STM_USART_CR3_SCEN (5) /* Smartcard mode enable */
+#define STM_USART_CR3_NACK (4) /* Smartcard NACK enable */
+#define STM_USART_CR3_HDSEL (3) /* Half-duplex selection */
+#define STM_USART_CR3_IRLP (2) /* IrDA low-power */
+#define STM_USART_CR3_IREN (1) /* IrDA mode enable */
+#define STM_USART_CR3_EIE (0) /* Error interrupt enable */
+
/* Errata 2.1.5
Delay after an RCC peripheral clock enabling