Project

General

Profile

Revision 249

implementing uart. done with basic functions, still planning protocol

View differences:

proj/include/uart_macros.h
1
#ifndef UART_MACROS_H_INCLUDED
2
#define UART_MACROS_H_INCLUDED
3

  
4
#define UART_BITRATE        115200
5

  
6
#define COM1_ADDR           0x3F8
7
#define COM2_ADDR           0x2F8
8
#define COM1_IRQ            4
9
#define COM2_IRQ            3
10
#define COM1_VECTOR         0x0C
11
#define COM2_VECTOR         0x0B
12

  
13
typedef enum {
14
    uart_parity_none = 0x0,
15
    uart_parity_odd  = 0x1,
16
    uart_parity_even = 0x3,
17
    uart_parity_par1 = 0x5,
18
    uart_parity_par0 = 0x7
19
} uart_parity;
20

  
21
#endif //UART_MACROS_H_INCLUDED
22 0

  
proj/include/test7.h
1
#ifndef TEST7_H_INCLUDED
2
#define TEST7_H_INCLUDED
3

  
4
#include "uart.h"
5

  
1 6
int ser_test_conf(unsigned short base_addr);
2 7

  
3 8
int ser_test_set(unsigned short base_addr, unsigned long bits, unsigned long stop,
......
9 14
int ser_test_int(/* details to be provided */) ;
10 15

  
11 16
int ser_test_fifo(/* details to be provided */);
17

  
18
#endif //TEST7_H_INCLUDED
proj/include/uart.h
1 1
#ifndef UART_H_INCLUDED
2 2
#define UART_H_INCLUDED
3 3

  
4
#include "uart_macros.h"
4
#define COM1_ADDR           0x3F8
5
#define COM2_ADDR           0x2F8
6
#define COM1_IRQ            4
7
#define COM2_IRQ            3
8
#define COM1_VECTOR         0x0C
9
#define COM2_VECTOR         0x0B
5 10

  
11
typedef enum {
12
    uart_parity_none = 0x0,
13
    uart_parity_odd  = 0x1,
14
    uart_parity_even = 0x3,
15
    uart_parity_par1 = 0x5,
16
    uart_parity_par0 = 0x7
17
} uart_parity;
18

  
6 19
typedef struct {
7 20
    int     base_addr               ;
8 21
    uint8_t lcr                     ;
......
10 23
    uint8_t dlm                     ;
11 24
    uint8_t bits_per_char           ;
12 25
    uint8_t stop_bits               ;
13
    uint8_t parity                  ;
26
    uart_parity parity              ;
14 27
    uint8_t break_control         :1;
15 28
    uint8_t dlab                  :1;
16 29
    uint16_t divisor_latch          ;
......
34 47
int uart_set_parity            (int base_addr, uart_parity par          );
35 48
int uart_set_bit_rate          (int base_addr, float       bit_rate     );
36 49

  
50
int uart_get_char_poll   (int base_addr, uint8_t *p);
51
int uart_send_char_poll  (int base_addr, uint8_t  c);
52
int uart_send_memory_poll(int base_addr, void *str, size_t n);
53

  
37 54
#endif //UART_H_INCLUDED
proj/src/proj.c
30 30
#include "list.h"
31 31

  
32 32
#ifdef DIOGO
33
    #include "uart_macros.h"
34 33
    #include "test7.h"
35 34
#endif
36 35

  
......
159 158
        //UART
160 159
        unsigned long bits = 8;
161 160
        unsigned long stop = 2;
162
        long parity = -1;
161
        long parity = 0;
163 162
        unsigned long rate = 9600;
164
        unsigned char tx = 0;
163
        unsigned char tx = 1;
165 164
        int stringc = 2;
166
        char *strings[] = {"Hello", "world"};
167
        if((r = ser_test_conf(COM1_ADDR))) return r;
168
        if((r = ser_test_set(COM1_ADDR, bits, stop, parity, rate))) return r;
165
        char *strings[] = {"Hello", "world"}; (void)strings;
166
        //if((r = ser_test_conf(COM1_ADDR))) return r;
167
        //if((r = ser_test_set(COM1_ADDR, bits, stop, parity, rate))) return r;
169 168
        if((r = ser_test_poll(COM1_ADDR, tx, bits, stop, parity, rate, stringc, strings))) return r;
169
        printf("DONE\n");
170 170
    #endif
171 171
    #ifndef DIOGO
172 172
        ent_set_scale(DEFAULT_SCALE);
proj/src/test7.c
1 1
#include <lcom/lcf.h>
2 2

  
3 3
#include "errors.h"
4
#include "uart_macros.h"
5 4
#include "uart.h"
6 5

  
7 6
int ser_test_conf(unsigned short base_addr) {
......
36 35
	int ret = SUCCESS;
37 36
    if((ret = ser_test_set(base_addr, bits, stop, parity, rate))) return ret;
38 37
	if(tx == 0){
39
		/*
40
		char c;
41
		if((ret = uart_get_char(base_addr, &c))) return ret;
42
		while(c != '.'){
43
			printf("%c", c);
44
			if((ret = uart_get_char(base_addr, &c))) return ret;
38
		uint8_t c;
39
		if((ret = uart_get_char_poll(base_addr, &c))) return ret;
40
		while((char)c != '.'){
41
			printf("%c", (char)c);
42
			if((ret = uart_get_char_poll(base_addr, &c))) return ret;
45 43
		}
46
		*/
44
		printf("%c\n", (char)c);
47 45
	}else{
48
		/*
49 46
		for(int i = 0; i < stringc; ++i){
50
			int j = 0;
51
			while(stringc[i][j] != 0)
52
				if((ret = uart_send_char(base_addr, stringc[i][j]))) return ret;
53
			if(i+1 != stringc) if((ret = uart_send_char(base_addr, ' '))) return ret;
47
			size_t sz = strlen(strings[i]);
48
			if((ret = uart_send_memory_poll(base_addr, strings[i], sz))) return ret;
49
			if(i+1 != stringc) if((ret = uart_send_memory_poll(base_addr, " ", 1))) return ret;
54 50
		}
55
		if((ret = uart_send_char(base_addr, '.'))) return ret;
56
		*/
51
		if((ret = uart_send_memory_poll(base_addr, ".", 1))) return ret;
57 52
	}
58 53
	return SUCCESS;
59 54
}
proj/src/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
}
proj/protocol.md
1
# Serial port protocol
2

  
3
Transmission/reception is processed at 38400 bps, with chars of 8 bits and even parity.
4

  
5
## Transmission
6

  
7
Transmission is performed on request by the program. It is done in a synchronous fashion. When starting a transmission, reception interrupt notifications are suspended. On ending, reception interrupt notifications are re-activated.
8

  
9
### Transmission of a char
10

  
11
1. 1 polls the readiness of THR in intervals of 50 microseconds, one at the beginning and up to 10 retries (up to 11 polling operations, and 500 microseconds). If after all the retries 1 has not yet sent the char, transmission is aborted.
12

  
13
2. If the char is transmitted, 1 expects 2 to answer the same char for confirmation. 1 polls the fullness of RBR in intervals of 50 microseconds, one at the beginning and up to 10 retries. If after all the retries 1 has not yet received the answer, transmission is aborted.
14

  
15
3. If 1 gets the answer, it compares it with the char it sent. If they are different, go back to step 2.
16

  
17
4. If they are equal, 1 sends OK symbol 0xFF using only step 1., and char transmission is complete.
18

  
19
### Transmission of a string
20

  
21
If the string has more than 1024 chars, transmission is not even started.
22

  
23
1. For each char in the string, transmit them, plus a start symbol 0x80 and an end symbol 0xEF. If transmission fails for a given char, transmission of the string fails, and none of the following chars in the same transmission request are transmitted.
24

  
25
2. If all symbols are transmitted correctly, transmission is successfully terminated.
26

  
27
## Reception
28

  
29
Reception is made through interrupts. On a reception interrupt, 2 must handle the interrupt. On a reception interrupt, reception interrupt notifications are suspended, and on ending a reception notifications are re-activated.
30

  
31
### Reception of a char
32

  
33
1. Upon getting a reception interrupt, 2 grabs the char, and then polls the readiness of the THR in intervals of 50 microseconds, one at the beginning and up to 10 retries. If after 10 retries 2 has not sent the char, transmission is aborted.
34

  
35
2. If transmission is successful, 2 expects 1 to answer the OK symbol 0xFF, using only step 1. to get the OK. If the received symbol has less or equal to 4 bits set to 1, transmission is aborted.
36

  
37
3. If the received OK has at least 4 bits set to 1 then it is accepted.
38

  
39
### Reception of a string
40

  
41
1. 2 expects the first char to be the start char. If it is not, transmission is aborted.
42

  
43
2. If the first char is correct, all chars are received. If one of the char receptions fails (timeout), reception fails. If after receiving 1024 chars the end symbol is not received, transmission is aborted.
44

  
45
3. If all receptions are successful and the end symbol is received, transmission is successful.
0 46

  

Also available in: Unified diff