Newer
Older
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
#include "esp32-c3-uart-interface.h"
static void init_uart_enable_clk(){
// enable the clock for UART RAM by setting SYSTEM_UART_MEM_CLK_EN to 1;
// enable APB_CLK for UARTn by setting SYSTEM_UARTn_CLK_EN to 1;
uint32_t perip_clk_en0_reg = *C3_SYSTEM_PERIP_CLK_EN0_REG;
perip_clk_en0_reg |= 1<<24;
perip_clk_en0_reg |= 1<<5;
perip_clk_en0_reg |= 1<<2;
*C3_SYSTEM_PERIP_CLK_EN0_REG = perip_clk_en0_reg;
}
static void init_uart_toggle_rst(){
// Detailed steps explained in 26.5.2.1
// for resetting and initilizing of uart
// get current regestry values
uint32_t rx_filt_reg = *C3_UART_RX_FILT_REG;
uint32_t core_value = *C3_UART_CLK_CONF_REG;
// clear UARTn_RST
rx_filt_reg &= (uint32_t)~(1<<5);
rx_filt_reg &= (uint32_t)~(1<<2);
*C3_UART_RX_FILT_REG = rx_filt_reg;
// set UART_RST_CORE
core_value |= 1<<23;
*C3_UART_CLK_CONF_REG = core_value;
// set UARTn_RST
rx_filt_reg |= 1<<5;
rx_filt_reg |= 1<<2;
*C3_UART_RX_FILT_REG = rx_filt_reg;
// clear UARTn_RST
rx_filt_reg &= (uint32_t)~(1<<5);
rx_filt_reg &= (uint32_t)~(1<<2);
*C3_UART_RX_FILT_REG = rx_filt_reg;
// clear UART_RST_CORE
core_value &= (uint32_t)~(1<<23);
*C3_UART_CLK_CONF_REG = core_value;
}
static void init_uart_clear_update(){
// enable register synchronization by clearing UART_UPDATE_CTRL.
uint32_t id_value = *C3_UART_ID_REG;
id_value &= (uint32_t)~(1<<30);
*C3_UART_ID_REG = id_value;
}
static void config_clock_freq(){
//freq = clock source rate / (UART_SCLK_DIV_NUM+UART_SCLK_DIV_A/UART_SCLK_DIV_B)
// baud rate = freq / (UART_CLKDIV + UART_CLKDIV_FRAG / 16)
// select the clock source via UART_SCLK_SEL;
uint32_t clockSelect = *C3_UART_CLK_CONF_REG;
// making sure we start with 0
clockSelect &= (uint32_t)~(1<<20);
clockSelect &= (uint32_t)~(1<<21);
// 01 is ABP_CLK with 80 MHz
// 10 is RC_FAST_CLK with default of 17.5 MHz
// 11 is XTAL_CLK with 40 MHz
clockSelect |= 1<<20;
*C3_UART_CLK_CONF_REG = clockSelect;
// selected ABP_CLK with 80 MHz
// dividing clock to 6 Mhz (divisor should be 13+1/3)
// UART_SCLK_DIV_NUM
clockSelect |= 1<<12;
clockSelect |= 1<<14;
clockSelect |= 1<<15;
// UART_SCLK_DIV_A
clockSelect |= 1<<6;
// UART_SCLK_DIV_B
clockSelect |= 1<<1;
clockSelect |= 1<<0;
*C3_UART_CLK_CONF_REG = clockSelect;
// calculate Baud rate to be 9600 (6Mhz/625)
uint32_t baudRateDivs = *C3_UART_CLKDIV_REG;
baudRateDivs |= 1<<0;
baudRateDivs |= 1<<4;
baudRateDivs |= 1<<5;
baudRateDivs |= 1<<6;
baudRateDivs |= 1<<9;
*C3_UART_CLKDIV_REG = baudRateDivs;
}
static void disable_parity(){
uint32_t uart_conf_reg = *C3_UART_CONF0_REG;
uart_conf_reg &= (uint32_t)~(1<<0);
uart_conf_reg &= (uint32_t)~(1<<1);
*C3_UART_CONF0_REG = uart_conf_reg;
}
static void set_max_data_lenght(){
uint32_t uart_conf_reg = *C3_UART_CONF0_REG;
uart_conf_reg |= (1<<2);
uart_conf_reg |= (1<<3);
*C3_UART_CONF0_REG = uart_conf_reg;
}
void config_uart(){
printf("Try to config %d\n", 1);
// wait for UART_REG_UPDATE to become 0, which indicates the completion of the last synchronization;
uint32_t reg_update = *C3_UART_ID_REG;
if ((bool)(reg_update & (uint32_t)(1<<31))){
return;
}
printf("Ready to config %d\n", 1);
// configure static registers (if any) following Section 26.5.1.2;
// set clock freq to 6MHz
// baud rate to 9600
config_clock_freq();
// configure data length via UART_BIT_NUM;
set_max_data_lenght();
// configure odd or even parity check via UART_PARITY_EN and UART_PARITY;
disable_parity();
// synchronize the configured values to the Core Clock domain by writing 1 to UART_REG_UPDATE.
reg_update |= (uint32_t)(1<<31);
*C3_UART_ID_REG = reg_update;
}
void enable_uart_transmitter(){
// configure TX FIFO’s empty threshold via UART_TXFIFO_EMPTY_THRHD;
// disable UART_TXFIFO_EMPTY_INT interrupt by clearing UART_TXFIFO_EMPTY_INT_ENA;
// write data to be sent to UART_RXFIFO_RD_BYTE;
// clear UART_TXFIFO_EMPTY_INT interrupt by setting UART_TXFIFO_EMPTY_INT_CLR;
// enable UART_TXFIFO_EMPTY_INT interrupt by setting UART_TXFIFO_EMPTY_INT_ENA;
// detect UART_TXFIFO_EMPTY_INT and wait for the completion of data transmission.
}
void reset_uart(){
// 26.4.1 Clock and Reset
init_uart_enable_clk();
init_uart_toggle_rst();
}
void init_uart(){
// from technical reference manual 543 f
init_uart_enable_clk();
init_uart_toggle_rst();
init_uart_clear_update();
}