--- /dev/null
+#include "util.h"
+
+#include <libopencm3/cm3/cortex.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/cm3/scb.h>
+#include <libopencm3/cm3/systick.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/usart.h>
+
+static void clock_setup(void)
+{
+ rcc_clock_setup_in_hse_8mhz_out_72mhz();
+
+ rcc_periph_clock_enable(RCC_GPIOB);
+ rcc_periph_clock_enable(RCC_GPIOC);
+ rcc_periph_clock_enable(RCC_USART1);
+ rcc_periph_clock_enable(RCC_USART3);
+
+ rcc_periph_reset_pulse(RST_GPIOB);
+ rcc_periph_reset_pulse(RST_GPIOC);
+ rcc_periph_reset_pulse(RST_USART1);
+ rcc_periph_reset_pulse(RST_USART3);
+}
+
+static void gpio_setup(void)
+{
+ // PC13 = BluePill LED
+ gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
+ gpio_clear(GPIOC, GPIO13);
+}
+
+static volatile u32 ms_ticks;
+
+void sys_tick_handler(void)
+{
+ ms_ticks++;
+}
+
+static void tick_setup(void)
+{
+ systick_set_frequency(1000, 72000000);
+ systick_counter_enable();
+ systick_interrupt_enable();
+}
+
+static void delay_ms(uint ms)
+{
+ u32 start_ticks = ms_ticks;
+ while (ms_ticks - start_ticks < ms)
+ ;
+}
+
+static void usart_setup(void)
+{
+ // Debugging USART
+ gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX);
+ gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
+
+ usart_set_baudrate(USART1, 115200);
+ usart_set_databits(USART1, 8);
+ usart_set_stopbits(USART1, USART_STOPBITS_1);
+ usart_set_mode(USART1, USART_MODE_TX);
+ usart_set_parity(USART1, USART_PARITY_NONE);
+ usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
+
+ usart_enable(USART1);
+
+ // BSB USART
+ gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART3_RX);
+ gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART3_TX);
+
+ usart_set_baudrate(USART3, 4800);
+ usart_set_databits(USART3, 8);
+ usart_set_stopbits(USART3, USART_STOPBITS_1);
+ usart_set_mode(USART3, USART_MODE_RX);
+ usart_set_parity(USART3, USART_PARITY_ODD);
+ usart_set_flow_control(USART3, USART_FLOWCONTROL_NONE);
+
+ usart_enable(USART3);
+}
+
+int main(void)
+{
+ clock_setup();
+ gpio_setup();
+ usart_setup();
+ tick_setup();
+ // This is needed when programming via serial boot loader, harmless otherwise.
+ SCB_VTOR = 0x08000000;
+ cm_enable_interrupts();
+
+ u32 start_ticks = ms_ticks;
+ for (;;) {
+ if (USART_SR(USART3) & USART_SR_RXNE) {
+ uint x = usart_recv(USART3);
+ debug_printf("%02x ", x);
+ }
+ if (ms_ticks - start_ticks >= 100) {
+ start_ticks = ms_ticks;
+ debug_led_toggle();
+ debug_putc(' ');
+ }
+ }
+
+ return 0;
+}