aboutsummaryrefslogtreecommitdiff
path: root/02-usart/src/arch/stm32l4xxx/peripherals/usart.c
diff options
context:
space:
mode:
Diffstat (limited to '02-usart/src/arch/stm32l4xxx/peripherals/usart.c')
-rw-r--r--02-usart/src/arch/stm32l4xxx/peripherals/usart.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/02-usart/src/arch/stm32l4xxx/peripherals/usart.c b/02-usart/src/arch/stm32l4xxx/peripherals/usart.c
new file mode 100644
index 0000000..d37eee2
--- /dev/null
+++ b/02-usart/src/arch/stm32l4xxx/peripherals/usart.c
@@ -0,0 +1,147 @@
+#include "arch/stm32l4xxx/peripherals/usart.h"
+#include "kern/delay.h"
+#include "kern/lib.h"
+#include <stdarg.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_printf(__IO usart_t* usart, const char* fmt, ...)
+{
+ va_list l;
+ union {
+ void* ptr;
+ char* str;
+ int i;
+ } b;
+ char buf[128];
+
+ va_start(l, fmt);
+
+ 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);
+}