Project

General

Profile

Revision 252

made some more changes to uart

View differences:

lab7/lab7.conf
1
service lab7
2
{
3
	system
4
		DEVIO
5
		IRQCTL
6
		IOPENABLE
7
		;
8
	ipc
9
		SYSTEM
10
		rs
11
		vm
12
		pm
13
		vfs
14
		;
15
	io
16
		40:4
17
		60
18
		61
19
		64
20
		70:2
21
		3f8:8
22
		;		
23
	irq
24
		0         # TIMER 0 IRQ 
25
		1         # KBD IRQ
26
		4         # COM1
27
		8         # RTC_IRQ
28
		12        # AUX IRQ
29
		;	
30
	uid	0		
31
		;
32
};
0 33

  
proj/include/uart.h
35 35
} uart_config;
36 36

  
37 37
int uart_get_config(int base_addr, uart_config *config);
38
void uart_parse_config(uart_config *config);
39 38
void uart_print_config(uart_config config);
40 39

  
41
int uart_enable_divisor_latch (int base_addr);
42
int uart_disable_divisor_latch(int base_addr);
43

  
44
int uart_write_config          (int base_addr, uint8_t     config       );
45 40
int uart_set_bits_per_character(int base_addr, uint8_t     bits_per_char);
46 41
int uart_set_stop_bits         (int base_addr, uint8_t     stop         );
47 42
int uart_set_parity            (int base_addr, uart_parity par          );
48 43
int uart_set_bit_rate          (int base_addr, float       bit_rate     );
49 44

  
45
int uart_enable_int_rx (int base_addr);
46
int uart_disable_int_rx(int base_addr);
47
int uart_enable_int_tx (int base_addr);
48
int uart_disable_int_tx(int base_addr);
49

  
50 50
int uart_get_char_poll   (int base_addr, uint8_t *p);
51 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 52

  
54 53
#endif //UART_H_INCLUDED
proj/src/proj.c
162 162
        unsigned long stop = 2;
163 163
        long parity = 0;
164 164
        unsigned long rate = 9600;
165
        unsigned char tx = 1;
166
        int stringc = 2;
165
        unsigned char tx = 0; (void)tx;
166
        int stringc = 2; (void)stringc;
167 167
        char *strings[] = {"Hello", "world"}; (void)strings;
168
        //if((r = ser_test_set(COM1_ADDR, bits, stop, parity, rate))) return r;
168 169
        //if((r = ser_test_conf(COM1_ADDR))) return r;
169
        //if((r = ser_test_set(COM1_ADDR, bits, stop, parity, rate))) return r;
170 170
        if((r = ser_test_poll(COM1_ADDR, tx, bits, stop, parity, rate, stringc, strings))) return r;
171 171
        printf("DONE\n");
172 172
    #endif
proj/src/test7.c
34 34
                    int stringc, char *strings[]) {
35 35
	int ret = SUCCESS;
36 36
    if((ret = ser_test_set(base_addr, bits, stop, parity, rate))) return ret;
37
	if((ret = uart_disable_int_rx(base_addr))) return ret;
38
	if((ret = uart_disable_int_tx(base_addr))) return ret;
37 39
	if(tx == 0){
38 40
		uint8_t c;
39 41
		if((ret = uart_get_char_poll(base_addr, &c))) return ret;
......
44 46
		printf("%c\n", (char)c);
45 47
	}else{
46 48
		for(int i = 0; i < stringc; ++i){
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;
49
			for(int j = 0; strings[i][j] != 0; ++j)
50
				if((ret = uart_send_char_poll(base_addr, strings[i][j])))
51
					return ret;
52
			if(i+1 != stringc)
53
				if((ret = uart_send_char_poll(base_addr, ' '))) return ret;
50 54
		}
51
		if((ret = uart_send_memory_poll(base_addr, ".", 1))) return ret;
55
		if((ret = uart_send_char_poll(base_addr, '.'))) return ret;
52 56
	}
53 57
	return SUCCESS;
54 58
}
proj/src/uart.c
44 44
#define UART_GET_DLM(n)                         (((n)>>8)&0xFF)
45 45

  
46 46
/// IER
47
#define UART_INT_EN_RECEIVED_DATA_POS           0
48
#define UART_INT_EN_TRANSMITTER_EMPTY_POS       1
47
#define UART_INT_EN_RX_POS                      0
48
#define UART_INT_EN_TX_POS                      1
49 49
#define UART_INT_EN_RECEIVER_LINE_STAT_POS      2
50 50
#define UART_INT_EN_MODEM_STAT_POS              3
51 51

  
52
#define UART_INT_EN_RECEIVED_DATA               (BIT(0))
53
#define UART_INT_EN_TRANSMITTER_EMPTY           (BIT(1))
52
#define UART_INT_EN_RX                          (BIT(0))
53
#define UART_INT_EN_TX                          (BIT(1))
54 54
#define UART_INT_EN_RECEIVER_LINE_STAT          (BIT(2))
55 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        )
57
#define UART_GET_INT_EN_RX(n)                   (((n)&UART_INT_EN_RX                )>>UART_INT_EN_RX_POS                )
58
#define UART_GET_INT_EN_TX(n)                   (((n)&UART_INT_EN_TX                )>>UART_INT_EN_TX_POS                )
59
#define UART_GET_INT_EN_RECEIVER_LINE_STAT(n)   (((n)&UART_INT_EN_RECEIVER_LINE_STAT)>>UART_INT_EN_RECEIVER_LINE_STAT_POS)
60
#define UART_GET_INT_EN_MODEM_STAT(n)           (((n)&UART_INT_EN_MODEM_STAT        )>>UART_INT_EN_MODEM_STAT_POS        )
61 61

  
62 62
/// LSR
63 63
#define UART_RECEIVER_READY_POS                 0
......
69 69
#define UART_GET_RECEIVER_READY(n)              (((n)&UART_RECEIVER_READY           )>>UART_RECEIVER_READY_POS           )
70 70
#define UART_GET_TRANSMITTER_EMPTY(n)           (((n)&UART_TRANSMITTER_EMPTY        )>>UART_TRANSMITTER_EMPTY_POS        )
71 71

  
72
static void uart_parse_config(uart_config *config){
73
    /// LCR
74
    config->bits_per_char          = UART_GET_BITS_PER_CHAR     (config->lcr);
75
    config->stop_bits              = UART_GET_STOP_BITS         (config->lcr);
76
    config->parity                 = UART_GET_PARITY            (config->lcr); if((config->parity & BIT(0)) == 0) config->parity = uart_parity_none;
77
    config->break_control          = UART_GET_BREAK_CONTROL     (config->lcr);
78
    config->dlab                   = UART_GET_DLAB              (config->lcr);
79
    /// IER
80
    config->received_data_int      = UART_GET_INT_EN_RX                (config->ier);
81
    config->transmitter_empty_int  = UART_GET_INT_EN_TX                (config->ier);
82
    config->receiver_line_stat_int = UART_GET_INT_EN_RECEIVER_LINE_STAT(config->ier);
83
    config->modem_stat_int         = UART_GET_INT_EN_MODEM_STAT        (config->ier);
84
    /// DIV LATCH
85
    config->divisor_latch          = UART_GET_DIV_LATCH(config->dlm, config->dll);
86
}
87

  
88
static int uart_get_lcr(int base_addr, uint8_t *p){
89
    return util_sys_inb(base_addr+UART_LCR, p);
90
}
91
static int uart_set_lcr(int base_addr, uint8_t config){
92
    if(sys_outb(base_addr+UART_LCR, config)) return WRITE_ERROR;
93
    return SUCCESS;
94
}
95
static int uart_get_lsr(int base_addr, uint8_t *p){
96
    return util_sys_inb(base_addr+UART_LSR, p);
97
}
98

  
99
static int uart_enable_divisor_latch(int base_addr){
100
    int ret = SUCCESS;
101
    uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret;
102
    return uart_set_lcr(base_addr, conf | UART_DLAB);
103
}
104
static int uart_disable_divisor_latch(int base_addr){
105
    int ret = SUCCESS;
106
    uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret;
107
    return uart_set_lcr(base_addr, conf & (~UART_DLAB));
108
}
109

  
110
static int uart_get_ier(int base_addr, uint8_t *p){
111
    int ret;
112
    if((ret = uart_disable_divisor_latch(base_addr))) return ret;
113
    return util_sys_inb(base_addr+UART_IER, p);
114
}
115
static int uart_set_ier(int base_addr, uint8_t n){
116
    int ret;
117
    if((ret = uart_disable_divisor_latch(base_addr))) return ret;
118
    if(sys_outb(base_addr+UART_IER, n)) return WRITE_ERROR;
119
    return SUCCESS;
120
}
121

  
72 122
int uart_get_config(int base_addr, uart_config *config){
73 123
    int ret = SUCCESS;
74 124

  
75 125
    config->base_addr = base_addr;
76 126

  
77
    if((ret = util_sys_inb(base_addr+UART_LCR, &config->lcr))) return ret;
127
    if((ret = uart_get_lcr(base_addr, &config->lcr))) return ret;
78 128

  
79
    if((ret = util_sys_inb(base_addr+UART_IER, &config->ier))) return ret;
129
    if((ret = uart_get_ier(base_addr, &config->ier))) return ret;
80 130

  
81 131
    if((ret = uart_enable_divisor_latch (base_addr))) return ret;
82 132
    if((ret = util_sys_inb(base_addr+UART_DLL, &config->dll   ))) return ret;
......
86 136
    uart_parse_config(config);
87 137
    return ret;
88 138
}
89
void uart_parse_config(uart_config *config){
90
    /// LCR
91
    config->bits_per_char          = UART_GET_BITS_PER_CHAR     (config->lcr);
92
    config->stop_bits              = UART_GET_STOP_BITS         (config->lcr);
93
    config->parity                 = UART_GET_PARITY            (config->lcr); if((config->parity & BIT(0)) == 0) config->parity = uart_parity_none;
94
    config->break_control          = UART_GET_BREAK_CONTROL     (config->lcr);
95
    config->dlab                   = UART_GET_DLAB              (config->lcr);
96
    /// 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);
101
    /// DIV LATCH
102
    config->divisor_latch          = UART_GET_DIV_LATCH(config->dlm, config->dll);
103
}
104 139
void uart_print_config(uart_config config){
105 140

  
106 141
    printf("%s configuration:\n", (config.base_addr == COM1_ADDR ? "COM1" : "COM2"));
......
119 154
        (config.transmitter_empty_int ? "ENABLED":"DISABLED"));
120 155
}
121 156

  
122
int uart_enable_divisor_latch(int base_addr){
123
    int ret = SUCCESS;
124
    uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
125
    return uart_write_config(base_addr, conf | UART_DLAB);
126
}
127
int uart_disable_divisor_latch(int base_addr){
128
    int ret = SUCCESS;
129
    uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
130
    return uart_write_config(base_addr, conf & (~UART_DLAB));
131
}
132

  
133
int uart_write_config(int base_addr, uint8_t config){
134
    if(sys_outb(base_addr+UART_LCR, config)) return WRITE_ERROR;
135
    return SUCCESS;
136
}
137 157
int uart_set_bits_per_character(int base_addr, uint8_t bits_per_char){
138 158
    if(bits_per_char < 5 || bits_per_char > 8) return INVALID_ARG;
139 159
    int ret = SUCCESS;
140 160
    bits_per_char = (bits_per_char-5)&0x3;
141
    uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
161
    uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret;
142 162
    conf = (conf & (~UART_BITS_PER_CHAR)) | bits_per_char;
143
    return uart_write_config(base_addr, conf);
163
    return uart_set_lcr(base_addr, conf);
144 164
}
145 165
int uart_set_stop_bits(int base_addr, uint8_t stop){
146 166
    if(stop != 1 && stop != 2) return INVALID_ARG;
147 167
    int ret = SUCCESS;
148 168
    stop -= 1;
149 169
    stop = (stop&1)<<2;
150
    uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
170
    uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret;
151 171
    conf = (conf & (~UART_STOP_BITS)) | stop;
152
    return uart_write_config(base_addr, conf);
172
    return uart_set_lcr(base_addr, conf);
153 173
}
154 174
int uart_set_parity(int base_addr, uart_parity par){
155 175
    int ret = SUCCESS;
156 176
    uint8_t parity = par << 3;
157
    uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
177
    uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret;
158 178
    conf = (conf & (~UART_PARITY)) | parity;
159
    return uart_write_config(base_addr, conf);
179
    return uart_set_lcr(base_addr, conf);
160 180
}
161 181
int uart_set_bit_rate(int base_addr, float bit_rate){
162 182
    int ret = SUCCESS;
......
170 190
    return SUCCESS;
171 191
}
172 192

  
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){
193
static int uart_get_char(int base_addr, uint8_t *p){
181 194
    int ret;
182 195
    if((ret = uart_disable_divisor_latch(base_addr))) return ret;
183 196
    return util_sys_inb(base_addr+UART_RBR, p);
184 197
}
185
int uart_send_char(int base_addr, uint8_t c){
198
static int uart_send_char(int base_addr, uint8_t c){
186 199
    int ret;
187 200
    if((ret = uart_disable_divisor_latch(base_addr))) return ret;
188
    if(sys_outb(base_addr, c)) return WRITE_ERROR;
201
    if(sys_outb(base_addr+UART_THR, c)) return WRITE_ERROR;
189 202
    return SUCCESS;
190 203
}
191
int uart_receiver_ready(int base_addr){
204
static int uart_receiver_ready(int base_addr){
192 205
    uint8_t lsr;
193 206
    if(uart_get_lsr(base_addr, &lsr)) return false;
194 207
    return UART_GET_RECEIVER_READY(lsr);
195 208
}
196
int uart_transmitter_empty(int base_addr){
209
static int uart_transmitter_empty(int base_addr){
197 210
    uint8_t lsr;
198 211
    if(uart_get_lsr(base_addr, &lsr)) return false;
199 212
    return UART_GET_TRANSMITTER_EMPTY(lsr);
200 213
}
201
///PUBLIC
214

  
215
int uart_enable_int_rx(int base_addr){
216
    int ret;
217
    uint8_t ier;
218
    if((ret = uart_get_ier(base_addr, &ier))) return ret;
219
    ier |= UART_INT_EN_RX;
220
    return uart_set_ier(base_addr, ier);
221
}
222
int uart_disable_int_rx(int base_addr){
223
    int ret;
224
    uint8_t ier;
225
    if((ret = uart_get_ier(base_addr, &ier))) return ret;
226
    ier &= ~UART_INT_EN_RX;
227
    return uart_set_ier(base_addr, ier);
228
}
229
int uart_enable_int_tx(int base_addr){
230
    int ret;
231
    uint8_t ier;
232
    if((ret = uart_get_ier(base_addr, &ier))) return ret;
233
    ier |= UART_INT_EN_TX;
234
    return uart_set_ier(base_addr, ier);
235
}
236
int uart_disable_int_tx(int base_addr){
237
    int ret;
238
    uint8_t ier;
239
    if((ret = uart_get_ier(base_addr, &ier))) return ret;
240
    ier &= ~UART_INT_EN_TX;
241
    return uart_set_ier(base_addr, ier);
242
}
243

  
202 244
int uart_get_char_poll(int base_addr, uint8_t *p){
203 245
    int ret;
204 246
    while(!uart_receiver_ready(base_addr)){}
......
211 253
    if((ret = uart_send_char(base_addr, c))) return ret;
212 254
    return SUCCESS;
213 255
}
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/protocol2.md
1
# Non-critical serial port protocol
2

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

  
5
OK = 0xFF
6

  
7
FAIL = 0x00
8

  
9
## Transmission
10

  
11
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.
12

  
13
### Transmission of a char
14

  
15
1. 1 polls the readiness of THR in intervals of 10 microseconds, one at the beginning and up to 2 retries (up to 3 polling operations, and 20 microseconds). If after all the retries 1 has not yet sent the char, transmission is aborted.
16

  
17
2. If the char is transmitted, 1 expects 2 to answer with OK. 1 polls the fullness of RBR in intervals of 10 microseconds, one at the beginning and up to 2 retries. If after all the retries 1 has not yet received the answer, transmission is aborted.
18

  
19
3. If 1 gets the answer, it counts the number of 1s. If #1 > 4, it is considered that it was accepted. Otherwise, it attempts to resend another 2 times.
20

  
21
### Transmission of a string
22

  
23
If the string has more than 1024 chars, transmission is not even started.
24

  
25
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 is aborted, and none of the following chars in the same transmission request are transmitted. The transmitter waits at least
26

  
27
2. If all symbols are transmitted correctly, transmission is successfully terminated.
28

  
29
## Reception
30

  
31
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.
32

  
33
### Reception of a char
34

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

  
37
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.
38

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

  
41
### Reception of a string
42

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

  
45
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.
46

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

  

Also available in: Unified diff