root / proj / src / libs / uart / src / uart.c @ 385
History | View | Annotate | Download (18 KB)
1 | 235 | up20180642 | #include <lcom/lcf.h> |
---|---|---|---|
2 | |||
3 | #include "uart.h" |
||
4 | |||
5 | 275 | up20180642 | #include "queue.h" |
6 | 235 | up20180642 | #include "errors.h" |
7 | |||
8 | 249 | up20180642 | #define UART_BITRATE 115200 |
9 | #define UART_WAIT 20 //microseconds |
||
10 | 241 | up20180642 | |
11 | 249 | up20180642 | #define UART_RBR 0 |
12 | #define UART_THR 0 |
||
13 | #define UART_IER 1 |
||
14 | #define UART_IIR 2 |
||
15 | #define UART_FCR 2 |
||
16 | #define UART_LCR 3 |
||
17 | #define UART_MCR 4 |
||
18 | #define UART_LSR 5 |
||
19 | #define UART_MSR 6 |
||
20 | #define UART_SR 7 |
||
21 | 241 | up20180642 | |
22 | 249 | up20180642 | #define UART_DLL 0 |
23 | #define UART_DLM 1 |
||
24 | 241 | up20180642 | |
25 | 249 | up20180642 | /// LCR
|
26 | 277 | up20180642 | #define UART_BITS_PER_CHAR_POS 0 |
27 | 249 | up20180642 | #define UART_STOP_BITS_POS 2 |
28 | #define UART_PARITY_POS 3 |
||
29 | #define UART_BREAK_CONTROL_POS 6 |
||
30 | #define UART_DLAB_POS 7 |
||
31 | 241 | up20180642 | |
32 | 249 | up20180642 | #define UART_BITS_PER_CHAR (BIT(0) | BIT(1)) |
33 | #define UART_STOP_BITS (BIT(2)) |
||
34 | #define UART_PARITY (BIT(3) | BIT(4) | BIT(5)) |
||
35 | #define UART_BREAK_CONTROL (BIT(6)) |
||
36 | #define UART_DLAB (BIT(7)) |
||
37 | 241 | up20180642 | |
38 | 249 | up20180642 | #define UART_GET_BITS_PER_CHAR(n) (((n)&UART_BITS_PER_CHAR) + 5) |
39 | #define UART_GET_STOP_BITS(n) (((n)&UART_STOP_BITS)? 2 : 1) |
||
40 | #define UART_GET_PARITY(n) (((n)&UART_PARITY )>>UART_PARITY_POS )
|
||
41 | #define UART_GET_BREAK_CONTROL(n) (((n)&UART_BREAK_CONTROL)>>UART_BREAK_CONTROL_POS)
|
||
42 | #define UART_GET_DLAB(n) (((n)&UART_DLAB )>>UART_DLAB_POS )
|
||
43 | #define UART_GET_DIV_LATCH(m,l) ((m)<<8 | (l)) |
||
44 | #define UART_GET_DLL(n) ((n)&0xFF) |
||
45 | #define UART_GET_DLM(n) (((n)>>8)&0xFF) |
||
46 | 242 | up20180642 | |
47 | 249 | up20180642 | /// IER
|
48 | 252 | up20180642 | #define UART_INT_EN_RX_POS 0 |
49 | #define UART_INT_EN_TX_POS 1 |
||
50 | 249 | up20180642 | #define UART_INT_EN_RECEIVER_LINE_STAT_POS 2 |
51 | #define UART_INT_EN_MODEM_STAT_POS 3 |
||
52 | 242 | up20180642 | |
53 | 252 | up20180642 | #define UART_INT_EN_RX (BIT(0)) |
54 | #define UART_INT_EN_TX (BIT(1)) |
||
55 | 249 | up20180642 | #define UART_INT_EN_RECEIVER_LINE_STAT (BIT(2)) |
56 | #define UART_INT_EN_MODEM_STAT (BIT(3)) |
||
57 | 242 | up20180642 | |
58 | 252 | up20180642 | #define UART_GET_INT_EN_RX(n) (((n)&UART_INT_EN_RX )>>UART_INT_EN_RX_POS )
|
59 | #define UART_GET_INT_EN_TX(n) (((n)&UART_INT_EN_TX )>>UART_INT_EN_TX_POS )
|
||
60 | #define UART_GET_INT_EN_RECEIVER_LINE_STAT(n) (((n)&UART_INT_EN_RECEIVER_LINE_STAT)>>UART_INT_EN_RECEIVER_LINE_STAT_POS)
|
||
61 | #define UART_GET_INT_EN_MODEM_STAT(n) (((n)&UART_INT_EN_MODEM_STAT )>>UART_INT_EN_MODEM_STAT_POS )
|
||
62 | 249 | up20180642 | |
63 | /// LSR
|
||
64 | #define UART_RECEIVER_READY_POS 0 |
||
65 | 261 | up20180642 | #define UART_OVERRUN_ERROR_POS 1 |
66 | #define UART_PARITY_ERROR_POS 2 |
||
67 | #define UART_FRAMING_ERROR_POS 3 |
||
68 | 249 | up20180642 | #define UART_TRANSMITTER_EMPTY_POS 5 |
69 | |||
70 | #define UART_RECEIVER_READY (BIT(0)) |
||
71 | 261 | up20180642 | #define UART_OVERRUN_ERROR (BIT(1)) |
72 | #define UART_PARITY_ERROR (BIT(2)) |
||
73 | #define UART_FRAMING_ERROR (BIT(3)) |
||
74 | 249 | up20180642 | #define UART_TRANSMITTER_EMPTY (BIT(5)) |
75 | |||
76 | #define UART_GET_RECEIVER_READY(n) (((n)&UART_RECEIVER_READY )>>UART_RECEIVER_READY_POS )
|
||
77 | 261 | up20180642 | #define UART_GET_OVERRUN_ERROR (((n)&UART_OVERRUN_ERROR )>>UART_OVERRUN_ERROR_POS )
|
78 | #define UART_GET_PARITY_ERROR (((n)&UART_PARITY_ERROR )>>UART_PARITY_ERROR_POS )
|
||
79 | #define UART_GET_FRAMING_ERROR (((n)&UART_FRAMING_ERROR )>>UART_FRAMING_ERROR_POS )
|
||
80 | 249 | up20180642 | #define UART_GET_TRANSMITTER_EMPTY(n) (((n)&UART_TRANSMITTER_EMPTY )>>UART_TRANSMITTER_EMPTY_POS )
|
81 | |||
82 | 275 | up20180642 | /// IIR
|
83 | 277 | up20180642 | #define UART_INT_PEND_POS 1 |
84 | #define UART_INT_PEND (BIT(3)|BIT(2)|BIT(1)) |
||
85 | |||
86 | 377 | up20180642 | /// FCR
|
87 | #define UART_EN_FIFOS_POS 0 |
||
88 | #define UART_CLEAR_RCVR_POS 1 |
||
89 | #define UART_CLEAR_XMIT_POS 2 |
||
90 | #define UART_FIFO_TRIGGER_POS 6 |
||
91 | |||
92 | #define UART_EN_FIFOS (BIT(0)) |
||
93 | #define UART_CLEAR_RCVR (BIT(1)) |
||
94 | #define UART_CLEAR_XMIT (BIT(2)) |
||
95 | #define UART_FIFO_TRIGGER (BIT(6)|BIT(7)) |
||
96 | |||
97 | #define UART_TRIGGER_LEVEL01 (0<<UART_FIFO_TRIGGER_POS) |
||
98 | #define UART_TRIGGER_LEVEL04 (1<<UART_FIFO_TRIGGER_POS) |
||
99 | #define UART_TRIGGER_LEVEL08 (2<<UART_FIFO_TRIGGER_POS) |
||
100 | #define UART_TRIGGER_LEVEL14 (3<<UART_FIFO_TRIGGER_POS) |
||
101 | |||
102 | 275 | up20180642 | #define UART_GET_IF_INT_PEND(n) (!((n)&1)) |
103 | 277 | up20180642 | typedef enum { |
104 | uart_int_receiver_line_stat = ( BIT(1) | BIT(0)), |
||
105 | uart_int_rx = ( BIT(1) ),
|
||
106 | uart_int_char_timeout_fifo = (BIT(2) | BIT(1) ), |
||
107 | uart_int_tx = ( BIT(0)),
|
||
108 | uart_int_modem_stat = (0)
|
||
109 | } uart_int_code; |
||
110 | #define UART_GET_INT_PEND(n) ((uart_int_code)(((n)&UART_INT_PEND)>>UART_INT_PEND_POS))
|
||
111 | 275 | up20180642 | |
112 | 263 | up20180642 | int (subscribe_uart_interrupt)(uint8_t interrupt_bit, int *interrupt_id) { |
113 | if (interrupt_id == NULL) return 1; |
||
114 | *interrupt_id = interrupt_bit; |
||
115 | return (sys_irqsetpolicy(COM1_IRQ, IRQ_REENABLE | IRQ_EXCLUSIVE, interrupt_id));
|
||
116 | } |
||
117 | |||
118 | 252 | up20180642 | static void uart_parse_config(uart_config *config){ |
119 | /// LCR
|
||
120 | config->bits_per_char = UART_GET_BITS_PER_CHAR (config->lcr); |
||
121 | config->stop_bits = UART_GET_STOP_BITS (config->lcr); |
||
122 | config->parity = UART_GET_PARITY (config->lcr); if((config->parity & BIT(0)) == 0) config->parity = uart_parity_none; |
||
123 | config->break_control = UART_GET_BREAK_CONTROL (config->lcr); |
||
124 | config->dlab = UART_GET_DLAB (config->lcr); |
||
125 | /// IER
|
||
126 | config->received_data_int = UART_GET_INT_EN_RX (config->ier); |
||
127 | config->transmitter_empty_int = UART_GET_INT_EN_TX (config->ier); |
||
128 | config->receiver_line_stat_int = UART_GET_INT_EN_RECEIVER_LINE_STAT(config->ier); |
||
129 | config->modem_stat_int = UART_GET_INT_EN_MODEM_STAT (config->ier); |
||
130 | /// DIV LATCH
|
||
131 | 324 | up20180642 | config->divisor_latch = (uint16_t)UART_GET_DIV_LATCH(config->dlm, config->dll); |
132 | 252 | up20180642 | } |
133 | |||
134 | static int uart_get_lcr(int base_addr, uint8_t *p){ |
||
135 | return util_sys_inb(base_addr+UART_LCR, p);
|
||
136 | } |
||
137 | static int uart_set_lcr(int base_addr, uint8_t config){ |
||
138 | if(sys_outb(base_addr+UART_LCR, config)) return WRITE_ERROR; |
||
139 | return SUCCESS;
|
||
140 | } |
||
141 | static int uart_get_lsr(int base_addr, uint8_t *p){ |
||
142 | return util_sys_inb(base_addr+UART_LSR, p);
|
||
143 | } |
||
144 | 275 | up20180642 | static int uart_get_iir(int base_addr, uint8_t *p){ |
145 | return util_sys_inb(base_addr+UART_IIR, p);
|
||
146 | } |
||
147 | 252 | up20180642 | |
148 | static int uart_enable_divisor_latch(int base_addr){ |
||
149 | int ret = SUCCESS;
|
||
150 | uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret; |
||
151 | return uart_set_lcr(base_addr, conf | UART_DLAB);
|
||
152 | } |
||
153 | static int uart_disable_divisor_latch(int base_addr){ |
||
154 | int ret = SUCCESS;
|
||
155 | uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret; |
||
156 | return uart_set_lcr(base_addr, conf & (~UART_DLAB));
|
||
157 | } |
||
158 | |||
159 | static int uart_get_ier(int base_addr, uint8_t *p){ |
||
160 | int ret;
|
||
161 | if((ret = uart_disable_divisor_latch(base_addr))) return ret; |
||
162 | return util_sys_inb(base_addr+UART_IER, p);
|
||
163 | } |
||
164 | static int uart_set_ier(int base_addr, uint8_t n){ |
||
165 | int ret;
|
||
166 | if((ret = uart_disable_divisor_latch(base_addr))) return ret; |
||
167 | if(sys_outb(base_addr+UART_IER, n)) return WRITE_ERROR; |
||
168 | return SUCCESS;
|
||
169 | } |
||
170 | |||
171 | 235 | up20180642 | int uart_get_config(int base_addr, uart_config *config){ |
172 | int ret = SUCCESS;
|
||
173 | |||
174 | config->base_addr = base_addr; |
||
175 | |||
176 | 252 | up20180642 | if((ret = uart_get_lcr(base_addr, &config->lcr))) return ret; |
177 | 235 | up20180642 | |
178 | 252 | up20180642 | if((ret = uart_get_ier(base_addr, &config->ier))) return ret; |
179 | 242 | up20180642 | |
180 | if((ret = uart_enable_divisor_latch (base_addr))) return ret; |
||
181 | 235 | up20180642 | if((ret = util_sys_inb(base_addr+UART_DLL, &config->dll ))) return ret; |
182 | if((ret = util_sys_inb(base_addr+UART_DLM, &config->dlm ))) return ret; |
||
183 | 242 | up20180642 | if((ret = uart_disable_divisor_latch(base_addr))) return ret; |
184 | 235 | up20180642 | |
185 | uart_parse_config(config); |
||
186 | return ret;
|
||
187 | } |
||
188 | void uart_print_config(uart_config config){
|
||
189 | 249 | up20180642 | |
190 | printf("%s configuration:\n", (config.base_addr == COM1_ADDR ? "COM1" : "COM2")); |
||
191 | printf("\tLCR = 0x%X: %d bits per char\t %d stop bits\t", config.lcr, config.bits_per_char, config.stop_bits);
|
||
192 | if((config.parity&BIT(0)) == 0) printf("NO parity\n"); |
||
193 | 235 | up20180642 | else switch(config.parity){ |
194 | 324 | up20180642 | case uart_parity_none: printf("NO parity\n" ); break; |
195 | 249 | up20180642 | case uart_parity_odd : printf("ODD parity\n" ); break; |
196 | case uart_parity_even: printf("EVEN parity\n" ); break; |
||
197 | 235 | up20180642 | case uart_parity_par1: printf("parity bit is 1\n"); break; |
198 | case uart_parity_par0: printf("parity bit is 0\n"); break; |
||
199 | 324 | up20180642 | //default : printf("invalid\n" ); break;
|
200 | 235 | up20180642 | } |
201 | 249 | up20180642 | printf("\tDLM = 0x%02X DLL=0x%02X: bitrate = %d bps\n", config.dlm, config.dll, UART_BITRATE/config.divisor_latch);
|
202 | printf("\tIER = 0x%02X: Rx interrupts: %s\tTx interrupts: %s\n", config.ier,
|
||
203 | (config.received_data_int ? "ENABLED":"DISABLED"), |
||
204 | (config.transmitter_empty_int ? "ENABLED":"DISABLED")); |
||
205 | 235 | up20180642 | } |
206 | |||
207 | int uart_set_bits_per_character(int base_addr, uint8_t bits_per_char){ |
||
208 | if(bits_per_char < 5 || bits_per_char > 8) return INVALID_ARG; |
||
209 | int ret = SUCCESS;
|
||
210 | bits_per_char = (bits_per_char-5)&0x3; |
||
211 | 252 | up20180642 | uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret; |
212 | 235 | up20180642 | conf = (conf & (~UART_BITS_PER_CHAR)) | bits_per_char; |
213 | 252 | up20180642 | return uart_set_lcr(base_addr, conf);
|
214 | 235 | up20180642 | } |
215 | int uart_set_stop_bits(int base_addr, uint8_t stop){ |
||
216 | if(stop != 1 && stop != 2) return INVALID_ARG; |
||
217 | int ret = SUCCESS;
|
||
218 | stop -= 1;
|
||
219 | 324 | up20180642 | stop = (uint8_t)((stop&1)<<2); |
220 | 252 | up20180642 | uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret; |
221 | 235 | up20180642 | conf = (conf & (~UART_STOP_BITS)) | stop; |
222 | 252 | up20180642 | return uart_set_lcr(base_addr, conf);
|
223 | 235 | up20180642 | } |
224 | int uart_set_parity(int base_addr, uart_parity par){ |
||
225 | int ret = SUCCESS;
|
||
226 | 324 | up20180642 | uint8_t parity = (uint8_t)(par << 3);
|
227 | 252 | up20180642 | uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret; |
228 | 235 | up20180642 | conf = (conf & (~UART_PARITY)) | parity; |
229 | 252 | up20180642 | return uart_set_lcr(base_addr, conf);
|
230 | 235 | up20180642 | } |
231 | 328 | up20180642 | int uart_set_bit_rate(int base_addr, uint32_t bit_rate){ |
232 | 235 | up20180642 | int ret = SUCCESS;
|
233 | 324 | up20180642 | uint16_t latch = (uint16_t)(UART_BITRATE/bit_rate); |
234 | 241 | up20180642 | uint8_t dll = UART_GET_DLL(latch); |
235 | uint8_t dlm = UART_GET_DLM(latch); |
||
236 | 235 | up20180642 | if((ret = uart_enable_divisor_latch(base_addr))) return ret; |
237 | if(sys_outb(base_addr+UART_DLL, dll)) return WRITE_ERROR; |
||
238 | if(sys_outb(base_addr+UART_DLM, dlm)) return WRITE_ERROR; |
||
239 | 249 | up20180642 | if((ret = uart_disable_divisor_latch(base_addr))) return ret; |
240 | 235 | up20180642 | return SUCCESS;
|
241 | } |
||
242 | 249 | up20180642 | |
243 | 252 | up20180642 | static int uart_get_char(int base_addr, uint8_t *p){ |
244 | 249 | up20180642 | int ret;
|
245 | if((ret = uart_disable_divisor_latch(base_addr))) return ret; |
||
246 | return util_sys_inb(base_addr+UART_RBR, p);
|
||
247 | } |
||
248 | 252 | up20180642 | static int uart_send_char(int base_addr, uint8_t c){ |
249 | 249 | up20180642 | int ret;
|
250 | if((ret = uart_disable_divisor_latch(base_addr))) return ret; |
||
251 | 252 | up20180642 | if(sys_outb(base_addr+UART_THR, c)) return WRITE_ERROR; |
252 | 249 | up20180642 | return SUCCESS;
|
253 | } |
||
254 | 252 | up20180642 | static int uart_receiver_ready(int base_addr){ |
255 | 249 | up20180642 | uint8_t lsr; |
256 | if(uart_get_lsr(base_addr, &lsr)) return false; |
||
257 | return UART_GET_RECEIVER_READY(lsr);
|
||
258 | } |
||
259 | 252 | up20180642 | static int uart_transmitter_empty(int base_addr){ |
260 | 249 | up20180642 | uint8_t lsr; |
261 | if(uart_get_lsr(base_addr, &lsr)) return false; |
||
262 | return UART_GET_TRANSMITTER_EMPTY(lsr);
|
||
263 | } |
||
264 | 252 | up20180642 | |
265 | int uart_enable_int_rx(int base_addr){ |
||
266 | int ret;
|
||
267 | uint8_t ier; |
||
268 | if((ret = uart_get_ier(base_addr, &ier))) return ret; |
||
269 | ier |= UART_INT_EN_RX; |
||
270 | return uart_set_ier(base_addr, ier);
|
||
271 | } |
||
272 | int uart_disable_int_rx(int base_addr){ |
||
273 | int ret;
|
||
274 | uint8_t ier; |
||
275 | if((ret = uart_get_ier(base_addr, &ier))) return ret; |
||
276 | ier &= ~UART_INT_EN_RX; |
||
277 | return uart_set_ier(base_addr, ier);
|
||
278 | } |
||
279 | int uart_enable_int_tx(int base_addr){ |
||
280 | int ret;
|
||
281 | uint8_t ier; |
||
282 | if((ret = uart_get_ier(base_addr, &ier))) return ret; |
||
283 | ier |= UART_INT_EN_TX; |
||
284 | return uart_set_ier(base_addr, ier);
|
||
285 | } |
||
286 | int uart_disable_int_tx(int base_addr){ |
||
287 | int ret;
|
||
288 | uint8_t ier; |
||
289 | if((ret = uart_get_ier(base_addr, &ier))) return ret; |
||
290 | ier &= ~UART_INT_EN_TX; |
||
291 | return uart_set_ier(base_addr, ier);
|
||
292 | } |
||
293 | |||
294 | 377 | up20180642 | static int uart_set_fcr(int base_addr, uint8_t n){ |
295 | if(sys_outb(base_addr+UART_FCR, n)) return WRITE_ERROR; |
||
296 | return SUCCESS;
|
||
297 | } |
||
298 | static int uart_enable_fifos(int base_addr, uint8_t trigger_lvl){ |
||
299 | uint8_t fcr = UART_EN_FIFOS | UART_CLEAR_RCVR | UART_CLEAR_XMIT; |
||
300 | switch(trigger_lvl){
|
||
301 | case 1: fcr |= UART_TRIGGER_LEVEL01; break; |
||
302 | case 4: fcr |= UART_TRIGGER_LEVEL04; break; |
||
303 | case 8: fcr |= UART_TRIGGER_LEVEL08; break; |
||
304 | case 14: fcr |= UART_TRIGGER_LEVEL14; break; |
||
305 | default: return INVALID_ARG; |
||
306 | } |
||
307 | return uart_set_fcr(base_addr, fcr);
|
||
308 | } |
||
309 | static int uart_disable_fifos(int base_addr){ |
||
310 | return uart_set_fcr(base_addr, UART_CLEAR_RCVR | UART_CLEAR_XMIT);
|
||
311 | } |
||
312 | |||
313 | 283 | up20180642 | /// NCTP
|
314 | 261 | up20180642 | |
315 | 344 | up20180642 | //#define NCTP_START 0x80
|
316 | //#define NCTP_END 0xFF
|
||
317 | 261 | up20180642 | #define NCTP_OK 0xFF |
318 | #define NCTP_NOK 0x00 |
||
319 | 384 | up20180642 | #define NCTP_ALIGN 4 |
320 | 377 | up20180642 | #define NCTP_FILLER 0x4E |
321 | 261 | up20180642 | |
322 | 324 | up20180642 | static queue_t *out = NULL; |
323 | static queue_t *in = NULL; |
||
324 | static void (*process)(const uint8_t*, const size_t) = NULL; |
||
325 | 261 | up20180642 | |
326 | 298 | up20180642 | int nctp_init(void){ |
327 | 275 | up20180642 | out = queue_ctor(); if(out == NULL) return NULL_PTR; |
328 | in = queue_ctor(); if(in == NULL) return NULL_PTR; |
||
329 | 377 | up20180642 | //return SUCCESS;
|
330 | return uart_enable_fifos(COM1_ADDR, NCTP_ALIGN);
|
||
331 | 297 | up20180642 | } |
332 | 298 | up20180642 | int nctp_dump(void){ |
333 | int ret;
|
||
334 | if((ret = nctp_free())) return ret; |
||
335 | return nctp_init();
|
||
336 | } |
||
337 | 297 | up20180642 | int nctp_set_processor(void (*proc_func)(const uint8_t*, const size_t)){ |
338 | 287 | up20180642 | process = proc_func; |
339 | 275 | up20180642 | return SUCCESS;
|
340 | 261 | up20180642 | } |
341 | 275 | up20180642 | int nctp_free(void){ |
342 | 377 | up20180642 | int ret = SUCCESS; int r; |
343 | 275 | up20180642 | while(!queue_empty(out)){
|
344 | free(queue_top(out)); |
||
345 | queue_pop(out); |
||
346 | 377 | up20180642 | } queue_dtor(out); |
347 | 275 | up20180642 | while(!queue_empty(in)){
|
348 | free(queue_top(in)); |
||
349 | queue_pop(in); |
||
350 | 377 | up20180642 | } queue_dtor(in); |
351 | if((r = uart_disable_fifos(COM1_ADDR))) ret = r;
|
||
352 | return ret;
|
||
353 | 261 | up20180642 | } |
354 | |||
355 | 325 | up20180642 | int nctp_send(size_t num, const uint8_t *const *ptr, const size_t *const sz){ |
356 | 261 | up20180642 | int ret;
|
357 | 344 | up20180642 | uint16_t sz_total = 0;{
|
358 | for(size_t i = 0; i < num; ++i) |
||
359 | sz_total += sz[i]; |
||
360 | } |
||
361 | 275 | up20180642 | uint8_t *tmp; |
362 | 344 | up20180642 | tmp = malloc(sizeof(uint8_t)); *tmp = *((uint8_t*)(&sz_total)+0); queue_push(out, tmp); |
363 | tmp = malloc(sizeof(uint8_t)); *tmp = *((uint8_t*)(&sz_total)+1); queue_push(out, tmp); |
||
364 | 261 | up20180642 | for(size_t i = 0; i < num; ++i){ |
365 | 325 | up20180642 | const uint8_t *p = ptr[i]; const size_t s = sz[i]; |
366 | 275 | up20180642 | for(size_t j = 0; j < s; ++j, ++p){ |
367 | tmp = malloc(sizeof(uint8_t)); *tmp = *p; queue_push(out, tmp);
|
||
368 | } |
||
369 | 261 | up20180642 | } |
370 | 377 | up20180642 | uint32_t total_message = sz_total+2;
|
371 | uint32_t num_fillers = (NCTP_ALIGN - total_message%NCTP_ALIGN)%NCTP_ALIGN; |
||
372 | for(size_t i = 0; i < num_fillers; ++i){ |
||
373 | tmp = malloc(sizeof(uint8_t)); *tmp = NCTP_FILLER; queue_push(out, tmp);
|
||
374 | } |
||
375 | 344 | up20180642 | |
376 | 275 | up20180642 | if(uart_transmitter_empty(COM1_ADDR)){
|
377 | if((ret = uart_send_char(COM1_ADDR, *(uint8_t*)queue_top(out)))) return ret; |
||
378 | queue_pop(out); |
||
379 | } |
||
380 | 249 | up20180642 | return SUCCESS;
|
381 | } |
||
382 | 275 | up20180642 | static int nctp_transmit(void){ |
383 | 377 | up20180642 | while(!queue_empty(out) && uart_transmitter_empty(COM1_ADDR)){
|
384 | 275 | up20180642 | int ret = uart_send_char(COM1_ADDR, *(uint8_t*)queue_top(out));
|
385 | queue_pop(out); |
||
386 | 377 | up20180642 | if(ret) return ret; |
387 | //return ret;
|
||
388 | }/*else*/ return SUCCESS; |
||
389 | 269 | up20180642 | } |
390 | 278 | up20180642 | |
391 | 385 | up20180642 | static void nctp_process_received(){ |
392 | 344 | up20180642 | uint16_t sz = 0;{
|
393 | uint8_t sz0 = *(uint8_t*)queue_top(in); free(queue_top(in)); queue_pop(in); |
||
394 | uint8_t sz1 = *(uint8_t*)queue_top(in); free(queue_top(in)); queue_pop(in); |
||
395 | *((uint8_t*)(&sz)+0) = sz0;
|
||
396 | *((uint8_t*)(&sz)+1) = sz1;
|
||
397 | } |
||
398 | uint8_t *p = malloc(sz*sizeof(uint8_t));
|
||
399 | for(uint16_t i = 0; i < sz; ++i){ |
||
400 | p[i] = *(uint8_t*)queue_top(in); |
||
401 | 275 | up20180642 | free(queue_top(in)); queue_pop(in); |
402 | 344 | up20180642 | } |
403 | if(process != NULL) process(p, sz); |
||
404 | 287 | up20180642 | free(p); |
405 | 275 | up20180642 | } |
406 | 344 | up20180642 | |
407 | static int num_bytes_to_receive = 0; |
||
408 | static uint16_t szbytes_to_receive = 0; |
||
409 | static uint8_t size0 = 0; |
||
410 | 377 | up20180642 | static uint8_t received_so_far = 0; |
411 | 275 | up20180642 | static int nctp_receive(void){ |
412 | 249 | up20180642 | int ret;
|
413 | 261 | up20180642 | uint8_t c; |
414 | 344 | up20180642 | int counter_to_process = 0; |
415 | |||
416 | 275 | up20180642 | while(uart_receiver_ready(COM1_ADDR)){
|
417 | if((ret = uart_get_char(COM1_ADDR, &c))) return ret; |
||
418 | uint8_t *tmp = malloc(sizeof(uint8_t)); *tmp = c;
|
||
419 | 344 | up20180642 | |
420 | if (szbytes_to_receive){ // gotta receive 2nd size byte and update num_bytes |
||
421 | *((uint8_t*)(&num_bytes_to_receive)+0) = size0;
|
||
422 | *((uint8_t*)(&num_bytes_to_receive)+1) = c;
|
||
423 | szbytes_to_receive = 0;
|
||
424 | } else if(num_bytes_to_receive > 0){ |
||
425 | /* Now I know there are no more size bytes to receive.
|
||
426 | 377 | up20180642 | * If there are normal bytes to receive, do this*/
|
427 | 344 | up20180642 | --num_bytes_to_receive; |
428 | if(num_bytes_to_receive == 0) ++counter_to_process; |
||
429 | } else {
|
||
430 | /* Now I know I am not expecting anything.
|
||
431 | 377 | up20180642 | * The fact I received something means it is a filler, or the 1st size byte.
|
432 | * If received_so_far == 0, then it is not a filler, but rather the 1st size byte. */
|
||
433 | if(received_so_far == 0){ |
||
434 | size0 = c; |
||
435 | szbytes_to_receive = 1;
|
||
436 | }else{
|
||
437 | received_so_far = (received_so_far+1)%NCTP_ALIGN;
|
||
438 | continue;
|
||
439 | } |
||
440 | 344 | up20180642 | } |
441 | 377 | up20180642 | queue_push(in, tmp); |
442 | received_so_far = (received_so_far+1)%NCTP_ALIGN;
|
||
443 | 261 | up20180642 | } |
444 | 344 | up20180642 | while(counter_to_process-- > 0) nctp_process_received(); |
445 | 275 | up20180642 | return SUCCESS;
|
446 | 249 | up20180642 | } |
447 | 275 | up20180642 | |
448 | 323 | up20180642 | static int nctp_ih_err = SUCCESS; |
449 | int (nctp_get_ih_error)(void){ return nctp_ih_err; } |
||
450 | 385 | up20180642 | void nctp_ih(void){ |
451 | 275 | up20180642 | uint8_t iir; |
452 | if((nctp_ih_err = uart_get_iir(COM1_ADDR, &iir))) return; |
||
453 | if(UART_GET_IF_INT_PEND(iir)){
|
||
454 | switch(UART_GET_INT_PEND(iir)){
|
||
455 | 385 | up20180642 | case uart_int_rx: nctp_receive (); break; |
456 | case uart_int_tx: nctp_transmit(); break; |
||
457 | case uart_int_receiver_line_stat: break; |
||
458 | case uart_int_modem_stat: break; |
||
459 | case uart_int_char_timeout_fifo: nctp_receive (); break; |
||
460 | 324 | up20180642 | //default: break;
|
461 | 275 | up20180642 | } |
462 | } |
||
463 | 269 | up20180642 | } |