#include "usart.h" #include "delay.h" #include "printf.h" #include "gpio.h" #include "clock.h" void set_usart1_clock_src(__IO rcc_t* rcc, usart_clk_src_t usart_clk_src) { rcc->ccip_r = rcc->ccip_r & (~0x03) | usart_clk_src; } void set_usart2_clock_src(__IO rcc_t* rcc, usart_clk_src_t usart_clk_src) { rcc->ccip_r = rcc->ccip_r & ~(0x03 << 2) | (usart_clk_src << 2); } void set_usart2_clock_enabled(__IO rcc_t* rcc, bool enable) { if (enable) { rcc->apb1en1_r |= BIT(17); } else { rcc->apb1en1_r &= ~BIT(17); } } void set_usart1_clock_enabled(__IO rcc_t* rcc, bool enable) { if (enable) { rcc->apb2en_r |= BIT(14); } else { rcc->apb2en_r &= ~BIT(14); } } void usart_set_parity(__IO usart_t* usart, usart_parity_t parity) { usart->c1.pce = !!parity; usart->c1.ps = parity & 1; } void usart_set_enabled(__IO usart_t* usart, usart_enable_t enabled) { if (!enabled) { usart->c1.ue = 0; } else { /* Set the rx enabled. */ union USART_CR1 tmp = usart->c1; tmp.re = !!(enabled & USART_ENABLE_RX); tmp.te = !!(enabled & USART_ENABLE_TX); tmp.ue = 1; usart->c1 = tmp; } } void usart_transmit_byte(__IO usart_t* usart, uint8_t byte) { usart->td_r = byte; /* Per the manual, when bit 7 of the IS register is set, then the usart * data has been sent to the shift register. * * This bit is cleared by writing to the TD register. */ while (!(usart->is_r & BIT(7))) ; } void usart_transmit_bytes(__IO usart_t* usart, const uint8_t* bytes, uint32_t n) { while (n --) { usart_transmit_byte(usart, *(bytes ++)); } } void usart_transmit_str(__IO usart_t* usart, const char* str) { while (*str) { if (*str == '\n') { usart_transmit_byte(usart, '\r'); } usart_transmit_byte(usart, *(str ++)); } } void usart_printf(__IO usart_t* usart, const char* fmt, ...) { printf_callback_t callback = (printf_callback_t) usart_transmit_byte; volatile void* closure = usart; va_list ap; va_start(ap, fmt); printf_format(fmt, callback, closure, ap); va_end(ap); } int usart2_enabled = 0; int is_usart2_enabled() { return usart2_enabled; } int enable_usart2(uint32_t baud_rate) { __IO gpio_port_t* port_a = enable_gpio(GPIO_PORT_A); enable_hsi(&RCC, true); // Turn on the clock for the USART2 peripheral set_usart2_clock_src(&RCC, USART_CLK_SRC_HSI16); set_usart2_clock_enabled(&RCC, true); // Configure the I/O pins. Will use PA2 as TX and PA15 as RX so setup for // alternate function set_gpio_pin_mode(port_a, PIN_2, MODE_ALTERNATE); set_gpio_pin_mode(port_a, PIN_15, MODE_ALTERNATE); set_gpio_alternate_function(port_a, PIN_2, AFN_7); set_gpio_alternate_function(port_a, PIN_15, AFN_3); // De-assert reset of USART2 RCC.apb1rst1_r &= ~BIT(17); // Configure the USART // disable USART first to allow setting of other control bits // This also disables parity checking and enables 16 times oversampling USART2.c1.r = 0; USART2.c2.r = 0; USART2.c3.r = 0; usart_set_divisor(&USART2, 16000000 / baud_rate); usart_set_enabled(&USART2, USART_ENABLE_TX | USART_ENABLE_RX); usart2_enabled = 1; }