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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
|
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-07-15 Emuzit first version
*/
#ifndef __CH56X_UART_H__
#define __CH56X_UART_H__
#include "soc.h"
#include "ch56x_gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
#define UART_RXD0_ALT GET_PIN(A, 5)
#define UART_TXD0_ALT GET_PIN(A, 6)
#define UART_RXD0_PIN GET_PIN(B, 5)
#define UART_TXD0_PIN GET_PIN(B, 6)
#define UART_RXD1_PIN GET_PIN(A, 7)
#define UART_TXD1_PIN GET_PIN(A, 8)
#define UART_RXD2_PIN GET_PIN(A, 2)
#define UART_TXD2_PIN GET_PIN(A, 3)
#define UART_RXD3_PIN GET_PIN(B, 3)
#define UART_TXD3_PIN GET_PIN(B, 4)
#ifndef UART_FIFO_SIZE
#define UART_FIFO_SIZE 8
#endif
#ifndef UART_RECV_RDY_SZ
#define UART_RECV_RDY_SZ 7 // FIFO trigger level for rx data available
#endif
union _uart_mcr
{
uint8_t reg;
struct
{
uint8_t dtr : 1; // B.0 : RW, DTR output (UART0 only)
uint8_t rts : 1; // B.1 : RW, RTS output (UART0 only)
uint8_t out1 : 1; // B.2 : RW, user defined modem control (UART0 only)
uint8_t int_oe : 1; // B.3 : RW, interrupt output enable / OUT2
uint8_t loop : 1; // B.4 : RW, enable internal loop test (UART0 only)
uint8_t au_flow_en : 1; // B.5 : RW, enable CTS/RTS autoflow control
uint8_t tnow : 1; // B.6 : RW, enable DTR TNOW output (UART0 only)
uint8_t half : 1; // B.7 : RW, enable half-duplex mode (UART0 only)
};
};
#define RB_MCR_DTR 0x01
#define RB_MCR_RTS 0x02
#define RB_MCR_OUT1 0x04
#define RB_MCR_OUT2 0x08
#define RB_MCR_INT_OE 0x08
#define RB_MCR_LOOP 0x10
#define RB_MCR_AU_FLOW_EN 0x20
#define RB_MCR_TNOW 0x40
#define RB_MCR_HALF 0x80
union _uart_ier
{
uint8_t reg;
struct
{
uint8_t recv_rdy : 1; // B.0 : RW, enable rx data ready intr
uint8_t thr_empty : 1; // B.1 : RW, enable THR empty intr
uint8_t line_stat : 1; // B.2 : RW, enable rx line status intr
uint8_t modem_chg : 1; // B.3 : RW, enable modem status change intr (UART0 only)
uint8_t dtr_en : 1; // B.4 : RW, DTR/TNOW output pin enable (UART0 only)
uint8_t rts_en : 1; // B.5 : RW, RTS output pin enable (UART0 only)
uint8_t txd_en : 1; // B.6 : RW, TXD pin enable
uint8_t reset : 1; // B.7 : WZ, software reset control, active high, auto clear
};
};
#define RB_IER_RECV_RDY 0x01
#define RB_IER_THR_EMPTY 0x02
#define RB_IER_LINE_STAT 0x04
#define RB_IER_MODEM_CHG 0x08
#define RB_IER_DTR_EN 0x10
#define RB_IER_RTS_EN 0x20
#define RB_IER_TXD_EN 0x40
#define RB_IER_RESET 0x80
union _uart_fcr
{
uint8_t reg;
struct
{
uint8_t fifo_en : 1; // B.0 : RW, FIFO enable
uint8_t rx_fifo_clr : 1; // B.1 : WZ, write 1 to clear rx FIFO, auto clear
uint8_t tx_fifo_clr : 1; // B.2 : WZ, write 1 to clear tx FIFO, auto clear
uint8_t resv_3 : 3;
uint8_t fifo_trig : 2; // B.7-6 : RW, rx FIFO trigger level, 1/2/4/7 bytes
};
};
#define RB_FCR_FIFO_EN 0x01
#define RB_FCR_RX_FIFO_CLR 0x02
#define RB_FCR_TX_FIFO_CLR 0x04
#define RB_FCR_FIFO_TRIG 0xc0
#define UART_1BYTE_TRIG 0
#define UART_2BYTE_TRIG 1
#define UART_4BYTE_TRIG 2
#define UART_7BYTE_TRIG 3
union _uart_lcr
{
uint8_t reg;
struct
{
uint8_t word_sz : 2; // B.1-0 : RW, word bit length, 5/6/7/8 bits
uint8_t stop_bit : 1; // B.2 : RW, stop bit length, 1/2 bits
uint8_t par_en : 1; // B.3 : RW, parity enable
uint8_t par_mod : 2; // B.5-4 : RW, parity mode, odd/even/mark/space
uint8_t break_en : 1; // B.6 : RW, force BREAK line condition
uint8_t dlab : 1; // B.7 : RW, user defined general purpose bit
};
};
#define RB_LCR_WORD_SZ 0x03
#define RB_LCR_STOP_BIT 0x04
#define RB_LCR_PAR_EN 0x08
#define RB_LCR_PAR_MOD 0x30
#define RB_LCR_BREAK_EN 0x40
#define RB_LCR_DLAB 0x80
#define RB_LCR_GP_BIT 0x80
#define LCR_DATA_BITS_5 0
#define LCR_DATA_BITS_6 1
#define LCR_DATA_BITS_7 2
#define LCR_DATA_BITS_8 3
#define LCR_STOP_BITS_1 0
#define LCR_STOP_BITS_2 1
#define LCR_PARITY_ODD 0
#define LCR_PARITY_EVEN 1
#define LCR_PARITY_MARK 2
#define LCR_PARITY_SPACE 3
union _uart_iir
{
uint8_t reg;
struct
{
uint8_t int_mask : 4; // B.3-0 : RO, interrupt mask (intr if B.0 is 0)
uint8_t resv_4 : 2;
uint8_t fifo_id : 2; // B.7-6 : RO, FIFO enabled flag
};
};
#define RB_IIR_NO_INT 0x01
#define RB_IIR_INT_MASK 0x0f
#define RB_IIR_FIFO_ID 0xc0
/* RB_IIR_INT_MASK (IIR bits 3:0) definition
*/
#define UART_II_SLV_ADDR 0x0e // UART0 slave address match interrupt
#define UART_II_LINE_STAT 0x06 // rx line status interrupt
#define UART_II_RECV_RDY 0x04 // rx data available interrupt
#define UART_II_RECV_TOUT 0x0c // rx fifo timeout interrupt
#define UART_II_THR_EMPTY 0x02 // THR empty interrupt
#define UART_II_MODEM_CHG 0x00 // UART0 modem status change interrupt
#define UART_II_NO_INTER 0x01 // no interrupt pending
union _uart_lsr
{
uint8_t reg;
struct
{
uint8_t data_rdy : 1; // B.0 : RO, rx FIFO data ready
uint8_t over_err : 1; // B.1 : RZ, rx FIFO data overrun
uint8_t par_err : 1; // B.2 : RZ, rx parity error
uint8_t frame_err : 1; // B.3 : RZ, rx frame error
uint8_t break_err : 1; // B.4 : RZ, rx BREAK detected
uint8_t tx_fifo_emp : 1; // B.5 : RO, tx FIFO empty
uint8_t tx_all_emp : 1; // B.6 : RO, THR/TSR all empty
uint8_t err_rx_fifo : 1; // B.7 : RO, PAR/FRAME/BREAK ERR in rx FIFO
};
};
#define RB_LSR_DATA_RDY 0x01
#define RB_LSR_OVER_ERR 0x02
#define RB_LSR_PAR_ERR 0x04
#define RB_LSR_FRAME_ERR 0x08
#define RB_LSR_BREAK_ERR 0x10
#define RB_LSR_TX_FIFO_EMP 0x20
#define RB_LSR_TX_ALL_EMP 0x40
#define RB_LSR_ERR_RX_FIFO 0x80
union _uart_msr
{
uint8_t reg;
struct
{
uint8_t cts_chg : 1; // B.0 : RZ, CTS input changed
uint8_t dsr_chg : 1; // B.1 : RZ, DSR input changed
uint8_t ri_chg : 1; // B.2 : RZ, RI input changed
uint8_t dcd_chg : 1; // B.3 : RZ, DCD input changed
uint8_t cts : 1; // B.4 : RO, CTS action status
uint8_t dsr : 1; // B.5 : RO, DSR action status
uint8_t ri : 1; // B.6 : RO, RI action status
uint8_t dcd : 1; // B.7 : RO, DCD action status
};
};
#define RB_MSR_CTS_CHG 0x01
#define RB_MSR_DSR_CHG 0x02
#define RB_MSR_RI_CHG 0x04
#define RB_MSR_DCD_CHG 0x08
#define RB_MSR_CTS 0x10
#define RB_MSR_DSR 0x20
#define RB_MSR_RI 0x40
#define RB_MSR_DCD 0x80
/*
* 0x00 R8_UARTx_MCR: Modem Control Register
* 0x01 R8_UARTx_IER: Interrupt Enable Register
* 0x02 R8_UARTx_FCR: FIFO Control Register
* 0x03 R8_UARTx_LCR: Line Control Register
* 0x04 R8_UARTx_IIR: Interrupt Identification Register
* 0x05 R8_UARTx_LSR: Line Status Register
* 0x06 R8_UARTx_MSR: Modem Status Register (UART0 only)
* 0x08 R8_UARTx_RBR: Rx Buffer Register
* 0x08 R8_UARTx_THR: Tx Hold Register
* 0x0a R8_UARTx_RFC: Rx FIFO count register
* 0x0b R8_UARTx_TFC: Tx FIFO count register
* 0x0c R16_UARTx_DL: Divisor Latch
* 0x0e R8_UARTx_DIV: frequency pre divider
* 0x0f R8_UARTx_ADR: Address Register (UART0 only)
*
* CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test.
* Be careful for those with side effect for read (e.g. RBR, IIR).
*/
struct uart_registers
{
union _uart_mcr MCR;
union _uart_ier IER;
union _uart_fcr FCR;
union _uart_lcr LCR;
union _uart_iir IIR;
union _uart_lsr LSR;
union _uart_lsr MSR;
uint8_t resv_7;
union
{
uint8_t RBR;
uint8_t THR;
};
uint8_t resv_9;
uint8_t RFC;
uint8_t TFC;
uint16_t DL;
uint8_t DIV;
uint8_t ADR;
} __packed;
CHECK_STRUCT_SIZE(struct uart_registers, 0x10);
int rt_hw_uart_init(void);
#ifdef __cplusplus
}
#endif
#endif
|