Project

General

Profile

Statistics
| Revision:

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
}