root / proj / src / uart.c @ 237
History | View | Annotate | Download (4.04 KB)
1 | 235 | up20180642 | #include <lcom/lcf.h> |
---|---|---|---|
2 | |||
3 | #include "uart.h" |
||
4 | |||
5 | #include "errors.h" |
||
6 | |||
7 | int uart_get_config(int base_addr, uart_config *config){ |
||
8 | int ret = SUCCESS;
|
||
9 | |||
10 | config->base_addr = base_addr; |
||
11 | |||
12 | if((ret = util_sys_inb(base_addr+UART_LCR, &config->config))) return ret; |
||
13 | |||
14 | if((ret = uart_enable_divisor_latch(base_addr))) return ret; |
||
15 | if((ret = util_sys_inb(base_addr+UART_DLL, &config->dll ))) return ret; |
||
16 | if((ret = util_sys_inb(base_addr+UART_DLM, &config->dlm ))) return ret; |
||
17 | |||
18 | uart_parse_config(config); |
||
19 | return ret;
|
||
20 | } |
||
21 | void uart_parse_config(uart_config *config){
|
||
22 | config->bits_per_char = UART_GET_BITS_PER_CHAR(config->config); |
||
23 | config->stop_bits = UART_GET_STOP_BITS (config->config); |
||
24 | config->parity = UART_GET_PARITY (config->config); |
||
25 | config->break_control = UART_GET_BREAK_CONTROL(config->config); |
||
26 | config->divisor_latch = config->dlm<<8 | config->dll;
|
||
27 | } |
||
28 | void uart_print_config(uart_config config){
|
||
29 | printf("Base address: 0x%X\n", config.base_addr);
|
||
30 | printf("Configuration: 0x%02X\n", config.config);
|
||
31 | printf("Number of bits per char: %d\n", config.bits_per_char);
|
||
32 | printf("Number of stop bits: %d\n", config.stop_bits);
|
||
33 | printf("Parity: ");
|
||
34 | if((config.parity&1) == 0) printf("no parity\n"); |
||
35 | else switch(config.parity){ |
||
36 | case uart_parity_odd : printf("odd parity\n" ); break; |
||
37 | case uart_parity_even: printf("even parity\n" ); break; |
||
38 | case uart_parity_par1: printf("parity bit is 1\n"); break; |
||
39 | case uart_parity_par0: printf("parity bit is 0\n"); break; |
||
40 | default : printf("invalid\n" ); break; |
||
41 | } |
||
42 | printf("Break control: %d\n", config.break_control);
|
||
43 | printf("Divisor latch: %d\n", config.divisor_latch);
|
||
44 | printf("Bit rate (x1000): %d\n", 1000*(uint32_t)UART_BITRATE/config.divisor_latch); |
||
45 | } |
||
46 | |||
47 | int uart_enable_divisor_latch(int base_addr){ |
||
48 | int ret = SUCCESS;
|
||
49 | uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
||
50 | return uart_write_config(base_addr, conf | UART_DLAB);
|
||
51 | } |
||
52 | int uart_disable_divisor_latch(int base_addr){ |
||
53 | int ret = SUCCESS;
|
||
54 | uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
||
55 | return uart_write_config(base_addr, conf & (~UART_DLAB));
|
||
56 | } |
||
57 | |||
58 | int uart_write_config(int base_addr, uint8_t config){ |
||
59 | printf("WRITING CONFIG 0x%02X TO 0x%X\n", config, base_addr);
|
||
60 | if(sys_outb(base_addr+UART_LCR, config)) return WRITE_ERROR; |
||
61 | return SUCCESS;
|
||
62 | } |
||
63 | int uart_set_bits_per_character(int base_addr, uint8_t bits_per_char){ |
||
64 | if(bits_per_char < 5 || bits_per_char > 8) return INVALID_ARG; |
||
65 | int ret = SUCCESS;
|
||
66 | bits_per_char = (bits_per_char-5)&0x3; |
||
67 | uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
||
68 | conf = (conf & (~UART_BITS_PER_CHAR)) | bits_per_char; |
||
69 | return uart_write_config(base_addr, conf);
|
||
70 | } |
||
71 | int uart_set_stop_bits(int base_addr, uint8_t stop){ |
||
72 | if(stop != 1 && stop != 2) return INVALID_ARG; |
||
73 | int ret = SUCCESS;
|
||
74 | stop -= 1;
|
||
75 | stop = (stop&1)<<2; |
||
76 | uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
||
77 | conf = (conf & (~UART_STOP_BITS)) | stop; |
||
78 | return uart_write_config(base_addr, conf);
|
||
79 | } |
||
80 | int uart_set_parity(int base_addr, uart_parity par){ |
||
81 | int ret = SUCCESS;
|
||
82 | uint8_t parity = par << 3;
|
||
83 | uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
||
84 | conf = (conf & (~UART_PARITY)) | parity; |
||
85 | return uart_write_config(base_addr, conf);
|
||
86 | } |
||
87 | int uart_set_bit_rate(int base_addr, float bit_rate){ printf("%s, L82\n", __func__); |
||
88 | int ret = SUCCESS;
|
||
89 | uint16_t latch = UART_BITRATE/bit_rate; |
||
90 | uint8_t dll = latch&0xFF;
|
||
91 | uint8_t dlm = (latch>>8)&0xFF; |
||
92 | if((ret = uart_enable_divisor_latch(base_addr))) return ret; |
||
93 | printf("dlm,dll=0x%02X%02X\n", dlm, dll);
|
||
94 | if(sys_outb(base_addr+UART_DLL, dll)) return WRITE_ERROR; |
||
95 | if(sys_outb(base_addr+UART_DLM, dlm)) return WRITE_ERROR; |
||
96 | if((ret = util_sys_inb(base_addr+UART_DLM, &dlm))) return ret; |
||
97 | printf("dlm=0x%02X\n", dlm);
|
||
98 | printf("%s, L91\n", __func__);
|
||
99 | return SUCCESS;
|
||
100 | } |