Revision 249
implementing uart. done with basic functions, still planning protocol
uart.c | ||
---|---|---|
4 | 4 |
|
5 | 5 |
#include "errors.h" |
6 | 6 |
|
7 |
#define UART_RBR 0 |
|
8 |
#define UART_THR 0 |
|
9 |
#define UART_IER 1 |
|
10 |
#define UART_IIR 2 |
|
11 |
#define UART_FCR 2 |
|
12 |
#define UART_LCR 3 |
|
13 |
#define UART_MCR 4 |
|
14 |
#define UART_LSR 5 |
|
15 |
#define UART_MSR 6 |
|
16 |
#define UART_SR 7 |
|
7 |
#define UART_BITRATE 115200 |
|
8 |
#define UART_WAIT 20 //microseconds |
|
17 | 9 |
|
18 |
#define UART_DLL 0 |
|
19 |
#define UART_DLM 1 |
|
10 |
#define UART_RBR 0 |
|
11 |
#define UART_THR 0 |
|
12 |
#define UART_IER 1 |
|
13 |
#define UART_IIR 2 |
|
14 |
#define UART_FCR 2 |
|
15 |
#define UART_LCR 3 |
|
16 |
#define UART_MCR 4 |
|
17 |
#define UART_LSR 5 |
|
18 |
#define UART_MSR 6 |
|
19 |
#define UART_SR 7 |
|
20 | 20 |
|
21 |
#define UART_BITS_PER_CHAR_POS 0 |
|
22 |
#define UART_STOP_BITS_POS 2 |
|
23 |
#define UART_PARITY_POS 3 |
|
24 |
#define UART_BREAK_CONTROL_POS 6 |
|
25 |
#define UART_DLAB_POS 7 |
|
21 |
#define UART_DLL 0 |
|
22 |
#define UART_DLM 1 |
|
26 | 23 |
|
27 |
#define UART_BITS_PER_CHAR (BIT(0) | BIT(1)) |
|
28 |
#define UART_STOP_BITS (BIT(2)) |
|
29 |
#define UART_PARITY (BIT(3) | BIT(4) | BIT(5)) |
|
30 |
#define UART_BREAK_CONTROL (BIT(6)) |
|
31 |
#define UART_DLAB (BIT(7)) |
|
24 |
/// LCR |
|
25 |
#define UART_BITS_PER_CHAR_POS 0 |
|
26 |
#define UART_STOP_BITS_POS 2 |
|
27 |
#define UART_PARITY_POS 3 |
|
28 |
#define UART_BREAK_CONTROL_POS 6 |
|
29 |
#define UART_DLAB_POS 7 |
|
32 | 30 |
|
33 |
#define UART_GET_BITS_PER_CHAR(n) (((n)&UART_BITS_PER_CHAR) + 5) |
|
34 |
#define UART_GET_STOP_BITS(n) (((n)&UART_STOP_BITS)? 2 : 1) |
|
35 |
#define UART_GET_PARITY(n) (((n)&UART_PARITY )>>UART_PARITY_POS ) |
|
36 |
#define UART_GET_BREAK_CONTROL(n) (((n)&UART_BREAK_CONTROL)>>UART_BREAK_CONTROL_POS) |
|
37 |
#define UART_GET_DLAB(n) (((n)&UART_DLAB )>>UART_DLAB_POS ) |
|
38 |
#define UART_GET_DIV_LATCH(m,l) ((m)<<8 | (l)) |
|
39 |
#define UART_GET_DLL(n) ((n)&0xFF) |
|
40 |
#define UART_GET_DLM(n) (((n)>>8)&0xFF) |
|
31 |
#define UART_BITS_PER_CHAR (BIT(0) | BIT(1)) |
|
32 |
#define UART_STOP_BITS (BIT(2)) |
|
33 |
#define UART_PARITY (BIT(3) | BIT(4) | BIT(5)) |
|
34 |
#define UART_BREAK_CONTROL (BIT(6)) |
|
35 |
#define UART_DLAB (BIT(7)) |
|
41 | 36 |
|
42 |
#define UART_RECEIVED_DATA_POS 0 |
|
43 |
#define UART_TRANSMITTER_EMPTY_POS 1 |
|
44 |
#define UART_RECEIVER_LINE_STAT_POS 2 |
|
45 |
#define UART_MODEM_STAT_POS 3 |
|
37 |
#define UART_GET_BITS_PER_CHAR(n) (((n)&UART_BITS_PER_CHAR) + 5) |
|
38 |
#define UART_GET_STOP_BITS(n) (((n)&UART_STOP_BITS)? 2 : 1) |
|
39 |
#define UART_GET_PARITY(n) (((n)&UART_PARITY )>>UART_PARITY_POS ) |
|
40 |
#define UART_GET_BREAK_CONTROL(n) (((n)&UART_BREAK_CONTROL)>>UART_BREAK_CONTROL_POS) |
|
41 |
#define UART_GET_DLAB(n) (((n)&UART_DLAB )>>UART_DLAB_POS ) |
|
42 |
#define UART_GET_DIV_LATCH(m,l) ((m)<<8 | (l)) |
|
43 |
#define UART_GET_DLL(n) ((n)&0xFF) |
|
44 |
#define UART_GET_DLM(n) (((n)>>8)&0xFF) |
|
46 | 45 |
|
47 |
#define UART_RECEIVED_DATA (BIT(0)) |
|
48 |
#define UART_TRANSMITTER_EMPTY (BIT(1)) |
|
49 |
#define UART_RECEIVER_LINE_STAT (BIT(2)) |
|
50 |
#define UART_MODEM_STAT (BIT(3)) |
|
46 |
/// IER |
|
47 |
#define UART_INT_EN_RECEIVED_DATA_POS 0 |
|
48 |
#define UART_INT_EN_TRANSMITTER_EMPTY_POS 1 |
|
49 |
#define UART_INT_EN_RECEIVER_LINE_STAT_POS 2 |
|
50 |
#define UART_INT_EN_MODEM_STAT_POS 3 |
|
51 | 51 |
|
52 |
#define UART_GET_RECEIVED_DATA(n) (((n)&UART_RECEIVED_DATA )>>UART_RECEIVED_DATA_POS )
|
|
53 |
#define UART_GET_TRANSMITTER_EMPTY(n) (((n)&UART_TRANSMITTER_EMPTY )>>UART_TRANSMITTER_EMPTY_POS )
|
|
54 |
#define UART_GET_RECEIVER_LINE_STAT(n) (((n)&UART_RECEIVER_LINE_STAT)>>UART_RECEIVER_LINE_STAT_POS)
|
|
55 |
#define UART_GET_MODEM_STAT(n) (((n)&UART_MODEM_STAT )>>UART_MODEM_STAT_POS )
|
|
52 |
#define UART_INT_EN_RECEIVED_DATA (BIT(0))
|
|
53 |
#define UART_INT_EN_TRANSMITTER_EMPTY (BIT(1))
|
|
54 |
#define UART_INT_EN_RECEIVER_LINE_STAT (BIT(2))
|
|
55 |
#define UART_INT_EN_MODEM_STAT (BIT(3))
|
|
56 | 56 |
|
57 |
#define UART_INT_EN_GET_RECEIVED_DATA(n) (((n)&UART_INT_EN_RECEIVED_DATA )>>UART_INT_EN_RECEIVED_DATA_POS ) |
|
58 |
#define UART_INT_EN_GET_TRANSMITTER_EMPTY(n) (((n)&UART_INT_EN_TRANSMITTER_EMPTY )>>UART_INT_EN_TRANSMITTER_EMPTY_POS ) |
|
59 |
#define UART_INT_EN_GET_RECEIVER_LINE_STAT(n) (((n)&UART_INT_EN_RECEIVER_LINE_STAT)>>UART_INT_EN_RECEIVER_LINE_STAT_POS) |
|
60 |
#define UART_INT_EN_GET_MODEM_STAT(n) (((n)&UART_INT_EN_MODEM_STAT )>>UART_INT_EN_MODEM_STAT_POS ) |
|
61 |
|
|
62 |
/// LSR |
|
63 |
#define UART_RECEIVER_READY_POS 0 |
|
64 |
#define UART_TRANSMITTER_EMPTY_POS 5 |
|
65 |
|
|
66 |
#define UART_RECEIVER_READY (BIT(0)) |
|
67 |
#define UART_TRANSMITTER_EMPTY (BIT(5)) |
|
68 |
|
|
69 |
#define UART_GET_RECEIVER_READY(n) (((n)&UART_RECEIVER_READY )>>UART_RECEIVER_READY_POS ) |
|
70 |
#define UART_GET_TRANSMITTER_EMPTY(n) (((n)&UART_TRANSMITTER_EMPTY )>>UART_TRANSMITTER_EMPTY_POS ) |
|
71 |
|
|
57 | 72 |
int uart_get_config(int base_addr, uart_config *config){ |
58 | 73 |
int ret = SUCCESS; |
59 | 74 |
|
... | ... | |
75 | 90 |
/// LCR |
76 | 91 |
config->bits_per_char = UART_GET_BITS_PER_CHAR (config->lcr); |
77 | 92 |
config->stop_bits = UART_GET_STOP_BITS (config->lcr); |
78 |
config->parity = UART_GET_PARITY (config->lcr); |
|
93 |
config->parity = UART_GET_PARITY (config->lcr); if((config->parity & BIT(0)) == 0) config->parity = uart_parity_none;
|
|
79 | 94 |
config->break_control = UART_GET_BREAK_CONTROL (config->lcr); |
80 | 95 |
config->dlab = UART_GET_DLAB (config->lcr); |
81 | 96 |
/// IER |
82 |
config->received_data_int = UART_GET_RECEIVED_DATA (config->ier); |
|
83 |
config->transmitter_empty_int = UART_GET_TRANSMITTER_EMPTY (config->ier); |
|
84 |
config->receiver_line_stat_int = UART_GET_RECEIVER_LINE_STAT(config->ier); |
|
85 |
config->modem_stat_int = UART_GET_MODEM_STAT (config->ier); |
|
97 |
config->received_data_int = UART_INT_EN_GET_RECEIVED_DATA (config->ier);
|
|
98 |
config->transmitter_empty_int = UART_INT_EN_GET_TRANSMITTER_EMPTY (config->ier);
|
|
99 |
config->receiver_line_stat_int = UART_INT_EN_GET_RECEIVER_LINE_STAT(config->ier);
|
|
100 |
config->modem_stat_int = UART_INT_EN_GET_MODEM_STAT (config->ier);
|
|
86 | 101 |
/// DIV LATCH |
87 | 102 |
config->divisor_latch = UART_GET_DIV_LATCH(config->dlm, config->dll); |
88 | 103 |
} |
89 | 104 |
void uart_print_config(uart_config config){ |
90 |
printf("Base address : 0x%X\n", config.base_addr); |
|
91 |
printf(" LCR configuration : 0x%02X\n", config.lcr); |
|
92 |
printf(" Number of bits per char : %d\n", config.bits_per_char); |
|
93 |
printf(" Number of stop bits : %d\n", config.stop_bits); |
|
94 |
printf(" Parity : "); |
|
95 |
if((config.parity&1) == 0) printf("no parity\n"); |
|
105 |
|
|
106 |
printf("%s configuration:\n", (config.base_addr == COM1_ADDR ? "COM1" : "COM2")); |
|
107 |
printf("\tLCR = 0x%X: %d bits per char\t %d stop bits\t", config.lcr, config.bits_per_char, config.stop_bits); |
|
108 |
if((config.parity&BIT(0)) == 0) printf("NO parity\n"); |
|
96 | 109 |
else switch(config.parity){ |
97 |
case uart_parity_odd : printf("odd parity\n" ); break;
|
|
98 |
case uart_parity_even: printf("even parity\n" ); break;
|
|
110 |
case uart_parity_odd : printf("ODD parity\n" ); break;
|
|
111 |
case uart_parity_even: printf("EVEN parity\n" ); break;
|
|
99 | 112 |
case uart_parity_par1: printf("parity bit is 1\n"); break; |
100 | 113 |
case uart_parity_par0: printf("parity bit is 0\n"); break; |
101 | 114 |
default : printf("invalid\n" ); break; |
102 | 115 |
} |
103 |
printf(" Break control : %d\n", config.break_control); |
|
104 |
printf(" DLAB : %d\n", config.dlab); |
|
105 |
|
|
106 |
printf(" IER configuration : 0x%02X\n", config.ier); |
|
107 |
printf(" Received data interrupts enabled : %d\n", config.received_data_int); |
|
108 |
printf(" Transmitter empty interrupts enabled : %d\n", config.transmitter_empty_int); |
|
109 |
printf(" Receiver line status interrupts enabled: %d\n", config.receiver_line_stat_int); |
|
110 |
printf(" Modem status interrupts enabled : %d\n", config.modem_stat_int); |
|
111 |
|
|
112 |
printf(" Divisor latch (DLM & DLL) : %d\n", config.divisor_latch); |
|
113 |
printf(" Bit rate : %d\n", UART_BITRATE/config.divisor_latch); |
|
116 |
printf("\tDLM = 0x%02X DLL=0x%02X: bitrate = %d bps\n", config.dlm, config.dll, UART_BITRATE/config.divisor_latch); |
|
117 |
printf("\tIER = 0x%02X: Rx interrupts: %s\tTx interrupts: %s\n", config.ier, |
|
118 |
(config.received_data_int ? "ENABLED":"DISABLED"), |
|
119 |
(config.transmitter_empty_int ? "ENABLED":"DISABLED")); |
|
114 | 120 |
} |
115 | 121 |
|
116 | 122 |
int uart_enable_divisor_latch(int base_addr){ |
... | ... | |
160 | 166 |
if((ret = uart_enable_divisor_latch(base_addr))) return ret; |
161 | 167 |
if(sys_outb(base_addr+UART_DLL, dll)) return WRITE_ERROR; |
162 | 168 |
if(sys_outb(base_addr+UART_DLM, dlm)) return WRITE_ERROR; |
163 |
if((ret = util_sys_inb(base_addr+UART_DLM, &dlm))) return ret;
|
|
169 |
if((ret = uart_disable_divisor_latch(base_addr))) return ret;
|
|
164 | 170 |
return SUCCESS; |
165 | 171 |
} |
172 |
|
|
173 |
/// PRIVATE |
|
174 |
int uart_get_lsr(int base_addr, uint8_t *p){ |
|
175 |
return util_sys_inb(base_addr+UART_LSR, p); |
|
176 |
} |
|
177 |
/** |
|
178 |
* @brief Get char from RBR. |
|
179 |
*/ |
|
180 |
int uart_get_char(int base_addr, uint8_t *p){ |
|
181 |
int ret; |
|
182 |
if((ret = uart_disable_divisor_latch(base_addr))) return ret; |
|
183 |
return util_sys_inb(base_addr+UART_RBR, p); |
|
184 |
} |
|
185 |
int uart_send_char(int base_addr, uint8_t c){ |
|
186 |
int ret; |
|
187 |
if((ret = uart_disable_divisor_latch(base_addr))) return ret; |
|
188 |
if(sys_outb(base_addr, c)) return WRITE_ERROR; |
|
189 |
return SUCCESS; |
|
190 |
} |
|
191 |
int uart_receiver_ready(int base_addr){ |
|
192 |
uint8_t lsr; |
|
193 |
if(uart_get_lsr(base_addr, &lsr)) return false; |
|
194 |
return UART_GET_RECEIVER_READY(lsr); |
|
195 |
} |
|
196 |
int uart_transmitter_empty(int base_addr){ |
|
197 |
uint8_t lsr; |
|
198 |
if(uart_get_lsr(base_addr, &lsr)) return false; |
|
199 |
return UART_GET_TRANSMITTER_EMPTY(lsr); |
|
200 |
} |
|
201 |
///PUBLIC |
|
202 |
int uart_get_char_poll(int base_addr, uint8_t *p){ |
|
203 |
int ret; |
|
204 |
while(!uart_receiver_ready(base_addr)){} |
|
205 |
if((ret = uart_get_char(base_addr, p))) return ret; |
|
206 |
return SUCCESS; |
|
207 |
} |
|
208 |
int uart_send_char_poll(int base_addr, uint8_t c){ |
|
209 |
int ret; |
|
210 |
while(!uart_transmitter_empty(base_addr)){} |
|
211 |
if((ret = uart_send_char(base_addr, c))) return ret; |
|
212 |
return SUCCESS; |
|
213 |
} |
|
214 |
int uart_send_memory_poll(int base_addr, void *str, size_t n){ |
|
215 |
int ret; |
|
216 |
uint8_t *p = str; |
|
217 |
for(size_t i = 0; i < n; ++i, ++p){ |
|
218 |
if((ret = uart_send_char_poll(base_addr, *p))) return ret; |
|
219 |
} |
|
220 |
return SUCCESS; |
|
221 |
} |
Also available in: Unified diff