aboutsummaryrefslogtreecommitdiff
path: root/src/arch/stm32l4xxx/peripherals/usart.c
blob: c6826719efa851712b26c1e3c04f1408f1ba151d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "arch/stm32l4xxx/peripherals/usart.h"

#include <stdarg.h>

#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);
}