#include "arch/stm32l4xxx/peripherals/usart.h" #include #include "kern/delay.h" #include "kern/lib.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) { uint32_t c_r1 = usart->c_r1; c_r1 &= ~(0x3 << 9); c_r1 |= parity; usart->c_r1 = c_r1; } void usart_set_enabled(__IO usart_t* usart, usart_enable_t enabled) { if (!enabled) { regset(usart->c_r1, usart_ue, 0); } else { /* Set the rx enabled. */ regset(usart->c_r1, usart_re, !!(enabled & USART_ENABLE_RX)); regset(usart->c_r1, usart_te, !!(enabled & USART_ENABLE_TX)); regset(usart->c_r1, usart_ue, 1); } } void usart_transmit_byte_sync(__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_sync( __IO usart_t* usart, const uint8_t* bytes, uint32_t n) { while (n--) { usart_transmit_byte_sync(usart, *(bytes++)); } } void usart_transmit_str_sync(__IO usart_t* usart, const char* str) { while (*str) { if (*str == '\n') { usart_transmit_byte_sync(usart, '\r'); } usart_transmit_byte_sync(usart, *(str++)); } } void usart_enable_dma(__IO usart_t* usart, usart_enable_t enabled) { switch (enabled) { case USART_ENABLE_DISABLED: regset(usart->c_r3, usart_dmar, 0); regset(usart->c_r3, usart_dmat, 0); break; case USART_ENABLE_TX: regset(usart->c_r3, usart_dmat, 1); break; case USART_ENABLE_RX: regset(usart->c_r3, usart_dmar, 1); break; }; } void usart_vprintf(__IO usart_t* usart, const char* fmt, va_list l) { union { void* ptr; char* str; int i; } b; char buf[128]; while (*fmt != 0) { if (*fmt == '%') { switch (*(++fmt)) { case 0: goto end; case '%': usart_transmit_byte_sync(usart, '%'); break; case 'p': b.ptr = va_arg(l, void*); hexify(ptr2reg(b.ptr), buf); usart_transmit_str_sync(usart, "0x"); usart_transmit_str_sync(usart, buf); break; case 'd': case 'i': b.i = va_arg(l, int); decimalify(b.i, buf); usart_transmit_str_sync(usart, buf); break; case 's': b.str = va_arg(l, char*); usart_transmit_str_sync(usart, b.str); } ++fmt; } else { if (*fmt == '\n') { usart_transmit_byte_sync(usart, '\r'); } usart_transmit_byte_sync(usart, *(fmt++)); } } end: va_end(l); } void usart_printf(__IO usart_t* usart, const char* fmt, ...) { va_list l; va_start(l, fmt); usart_vprintf(usart, fmt, l); }