root / proj / src / uart.c @ 245
History | View | Annotate | Download (7.19 KB)
1 | 235 | up20180642 | #include <lcom/lcf.h> |
---|---|---|---|
2 | |||
3 | #include "uart.h" |
||
4 | |||
5 | #include "errors.h" |
||
6 | |||
7 | 241 | up20180642 | #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 |
||
17 | |||
18 | #define UART_DLL 0 |
||
19 | #define UART_DLM 1 |
||
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 |
||
26 | |||
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)) |
||
32 | |||
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) |
||
41 | |||
42 | 242 | up20180642 | #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 |
||
46 | |||
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)) |
||
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 )
|
||
56 | |||
57 | 235 | up20180642 | int uart_get_config(int base_addr, uart_config *config){ |
58 | int ret = SUCCESS;
|
||
59 | |||
60 | config->base_addr = base_addr; |
||
61 | |||
62 | 242 | up20180642 | if((ret = util_sys_inb(base_addr+UART_LCR, &config->lcr))) return ret; |
63 | 235 | up20180642 | |
64 | 242 | up20180642 | if((ret = util_sys_inb(base_addr+UART_IER, &config->ier))) return ret; |
65 | |||
66 | if((ret = uart_enable_divisor_latch (base_addr))) return ret; |
||
67 | 235 | up20180642 | if((ret = util_sys_inb(base_addr+UART_DLL, &config->dll ))) return ret; |
68 | if((ret = util_sys_inb(base_addr+UART_DLM, &config->dlm ))) return ret; |
||
69 | 242 | up20180642 | if((ret = uart_disable_divisor_latch(base_addr))) return ret; |
70 | 235 | up20180642 | |
71 | uart_parse_config(config); |
||
72 | return ret;
|
||
73 | } |
||
74 | void uart_parse_config(uart_config *config){
|
||
75 | 242 | up20180642 | /// LCR
|
76 | config->bits_per_char = UART_GET_BITS_PER_CHAR (config->lcr); |
||
77 | config->stop_bits = UART_GET_STOP_BITS (config->lcr); |
||
78 | config->parity = UART_GET_PARITY (config->lcr); |
||
79 | config->break_control = UART_GET_BREAK_CONTROL (config->lcr); |
||
80 | config->dlab = UART_GET_DLAB (config->lcr); |
||
81 | /// 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); |
||
86 | /// DIV LATCH
|
||
87 | config->divisor_latch = UART_GET_DIV_LATCH(config->dlm, config->dll); |
||
88 | 235 | up20180642 | } |
89 | void uart_print_config(uart_config config){
|
||
90 | 242 | up20180642 | 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 | 235 | up20180642 | if((config.parity&1) == 0) printf("no parity\n"); |
96 | else switch(config.parity){ |
||
97 | case uart_parity_odd : printf("odd parity\n" ); break; |
||
98 | case uart_parity_even: printf("even parity\n" ); break; |
||
99 | case uart_parity_par1: printf("parity bit is 1\n"); break; |
||
100 | case uart_parity_par0: printf("parity bit is 0\n"); break; |
||
101 | default : printf("invalid\n" ); break; |
||
102 | } |
||
103 | 242 | up20180642 | 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);
|
||
114 | 235 | up20180642 | } |
115 | |||
116 | int uart_enable_divisor_latch(int base_addr){ |
||
117 | int ret = SUCCESS;
|
||
118 | uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
||
119 | return uart_write_config(base_addr, conf | UART_DLAB);
|
||
120 | } |
||
121 | int uart_disable_divisor_latch(int base_addr){ |
||
122 | int ret = SUCCESS;
|
||
123 | uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
||
124 | return uart_write_config(base_addr, conf & (~UART_DLAB));
|
||
125 | } |
||
126 | |||
127 | int uart_write_config(int base_addr, uint8_t config){ |
||
128 | if(sys_outb(base_addr+UART_LCR, config)) return WRITE_ERROR; |
||
129 | return SUCCESS;
|
||
130 | } |
||
131 | int uart_set_bits_per_character(int base_addr, uint8_t bits_per_char){ |
||
132 | if(bits_per_char < 5 || bits_per_char > 8) return INVALID_ARG; |
||
133 | int ret = SUCCESS;
|
||
134 | bits_per_char = (bits_per_char-5)&0x3; |
||
135 | uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
||
136 | conf = (conf & (~UART_BITS_PER_CHAR)) | bits_per_char; |
||
137 | return uart_write_config(base_addr, conf);
|
||
138 | } |
||
139 | int uart_set_stop_bits(int base_addr, uint8_t stop){ |
||
140 | if(stop != 1 && stop != 2) return INVALID_ARG; |
||
141 | int ret = SUCCESS;
|
||
142 | stop -= 1;
|
||
143 | stop = (stop&1)<<2; |
||
144 | uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
||
145 | conf = (conf & (~UART_STOP_BITS)) | stop; |
||
146 | return uart_write_config(base_addr, conf);
|
||
147 | } |
||
148 | int uart_set_parity(int base_addr, uart_parity par){ |
||
149 | int ret = SUCCESS;
|
||
150 | uint8_t parity = par << 3;
|
||
151 | uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
||
152 | conf = (conf & (~UART_PARITY)) | parity; |
||
153 | return uart_write_config(base_addr, conf);
|
||
154 | } |
||
155 | 241 | up20180642 | int uart_set_bit_rate(int base_addr, float bit_rate){ |
156 | 235 | up20180642 | int ret = SUCCESS;
|
157 | uint16_t latch = UART_BITRATE/bit_rate; |
||
158 | 241 | up20180642 | uint8_t dll = UART_GET_DLL(latch); |
159 | uint8_t dlm = UART_GET_DLM(latch); |
||
160 | 235 | up20180642 | if((ret = uart_enable_divisor_latch(base_addr))) return ret; |
161 | if(sys_outb(base_addr+UART_DLL, dll)) return WRITE_ERROR; |
||
162 | if(sys_outb(base_addr+UART_DLM, dlm)) return WRITE_ERROR; |
||
163 | if((ret = util_sys_inb(base_addr+UART_DLM, &dlm))) return ret; |
||
164 | return SUCCESS;
|
||
165 | } |