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