Revision 275
implementing transmission with queues
uart.c | ||
---|---|---|
2 | 2 |
|
3 | 3 |
#include "uart.h" |
4 | 4 |
|
5 |
#include "queue.h" |
|
5 | 6 |
#include "errors.h" |
6 | 7 |
|
7 | 8 |
#define UART_BITRATE 115200 |
... | ... | |
78 | 79 |
#define UART_GET_FRAMING_ERROR (((n)&UART_FRAMING_ERROR )>>UART_FRAMING_ERROR_POS ) |
79 | 80 |
#define UART_GET_TRANSMITTER_EMPTY(n) (((n)&UART_TRANSMITTER_EMPTY )>>UART_TRANSMITTER_EMPTY_POS ) |
80 | 81 |
|
82 |
/// IIR |
|
83 |
#define UART_GET_IF_INT_PEND(n) (!((n)&1)) |
|
84 |
#define UART_GET_INT_PEND(n) (((n)&0xE)>>1) |
|
85 |
#define UART_INT_RX 0x2 //0b010 |
|
86 |
#define UART_INT_TX 0x1 //0b001 |
|
87 |
|
|
81 | 88 |
int (subscribe_uart_interrupt)(uint8_t interrupt_bit, int *interrupt_id) { |
82 | 89 |
if (interrupt_id == NULL) return 1; |
83 | 90 |
*interrupt_id = interrupt_bit; |
... | ... | |
110 | 117 |
static int uart_get_lsr(int base_addr, uint8_t *p){ |
111 | 118 |
return util_sys_inb(base_addr+UART_LSR, p); |
112 | 119 |
} |
120 |
static int uart_get_iir(int base_addr, uint8_t *p){ |
|
121 |
return util_sys_inb(base_addr+UART_IIR, p); |
|
122 |
} |
|
113 | 123 |
|
114 | 124 |
static int uart_enable_divisor_latch(int base_addr){ |
115 | 125 |
int ret = SUCCESS; |
... | ... | |
256 | 266 |
return uart_set_ier(base_addr, ier); |
257 | 267 |
} |
258 | 268 |
|
259 |
/*static*/ int uart_has_communication_error(int base_addr){ |
|
260 |
int ret; |
|
261 |
uint8_t lsr; |
|
262 |
if((ret = uart_get_lsr(base_addr, &lsr))) return 1; |
|
263 |
lsr &= (UART_OVERRUN_ERROR & |
|
264 |
UART_PARITY_ERROR & |
|
265 |
UART_FRAMING_ERROR); |
|
266 |
return (lsr ? 1 : 0); |
|
267 |
} |
|
268 |
|
|
269 | 269 |
#include "nctp.h" |
270 | 270 |
|
271 | 271 |
#define NCTP_START 0x80 |
272 | 272 |
#define NCTP_END 0xFF |
273 |
#define NCTP_TRIES 3 |
|
274 | 273 |
#define NCTP_OK 0xFF |
275 | 274 |
#define NCTP_NOK 0x00 |
276 | 275 |
#define NCTP_MAX_SIZE 1024 //in bytes |
277 | 276 |
|
278 |
int nctp_send_char_poll(int base_addr, uint8_t c){ |
|
279 |
for(int i = 0; i < NCTP_TRIES; ++i) |
|
280 |
if(uart_transmitter_empty(base_addr)) |
|
281 |
return uart_send_char(base_addr, c); |
|
282 |
return TIMEOUT_ERROR; |
|
283 |
} |
|
284 |
int nctp_get_char_poll (int base_addr, uint8_t *p){ |
|
285 |
for(int i = 0; i < NCTP_TRIES; ++i) |
|
286 |
if(uart_receiver_ready(base_addr)) |
|
287 |
return uart_get_char(base_addr, p); |
|
288 |
return TIMEOUT_ERROR; |
|
289 |
} |
|
277 |
queue_t *out = NULL; |
|
278 |
queue_t *in = NULL; |
|
290 | 279 |
|
291 |
int nctp_expect_ok(int base_addr){ |
|
292 |
int ret; |
|
293 |
uint8_t ok; |
|
294 |
if((ret = nctp_get_char_poll(base_addr, &ok))) return ret; |
|
295 |
int cnt = 0; |
|
296 |
while(ok){ |
|
297 |
cnt += ok&1; |
|
298 |
ok >>= 1; |
|
299 |
} |
|
300 |
if(cnt > 4) return SUCCESS; |
|
301 |
else return NOK; |
|
280 |
int nctp_init(void){ |
|
281 |
out = queue_ctor(); if(out == NULL) return NULL_PTR; |
|
282 |
in = queue_ctor(); if(in == NULL) return NULL_PTR; |
|
283 |
return SUCCESS; |
|
302 | 284 |
} |
303 |
|
|
304 |
int nctp_send_char_try(int base_addr, uint8_t c){ |
|
305 |
int ret; |
|
306 |
for(size_t k = 0; k < NCTP_TRIES; ++k){ |
|
307 |
if((ret = nctp_send_char_poll(base_addr, c))) return ret; |
|
308 |
return SUCCESS; |
|
309 |
//if(nctp_expect_ok(base_addr) == SUCCESS) return SUCCESS; |
|
285 |
int nctp_free(void){ |
|
286 |
while(!queue_empty(out)){ |
|
287 |
free(queue_top(out)); |
|
288 |
queue_pop(out); |
|
310 | 289 |
} |
311 |
return TRANS_FAILED; |
|
312 |
} |
|
313 |
int nctp_get_char_try (int base_addr, uint8_t *p){ |
|
314 |
int ret; |
|
315 |
for(size_t k = 0; k < NCTP_TRIES; ++k){ |
|
316 |
if((ret = nctp_get_char_poll (base_addr, p))) return ret; |
|
317 |
return SUCCESS; |
|
318 |
//if(!uart_has_communication_error(base_addr)) |
|
319 |
//return nctp_send_char_try(base_addr, NCTP_OK ); //If it does not have any errors |
|
290 |
while(!queue_empty(in)){ |
|
291 |
free(queue_top(in)); |
|
292 |
queue_pop(in); |
|
320 | 293 |
} |
321 |
if((ret = nctp_send_char_poll(base_addr, NCTP_NOK))) return ret; |
|
322 |
return TRANS_FAILED; |
|
294 |
return SUCCESS; |
|
323 | 295 |
} |
324 | 296 |
|
325 |
static int nctp_send_inner(int base_addr, size_t num, uint8_t* ptr[], size_t sz[]){
|
|
297 |
int nctp_send(size_t num, uint8_t* ptr[], size_t sz[]){
|
|
326 | 298 |
{ |
327 | 299 |
int cnt = 0; |
328 | 300 |
for(size_t i = 0; i < num; ++i){ |
... | ... | |
330 | 302 |
if(cnt > NCTP_MAX_SIZE) return TRANS_REFUSED; |
331 | 303 |
} |
332 | 304 |
} |
333 |
|
|
334 | 305 |
int ret; |
335 |
|
|
336 |
if((ret = nctp_send_char_try(base_addr, NCTP_START))) return ret;
|
|
306 |
uint8_t *tmp; |
|
307 |
tmp = malloc(sizeof(uint8_t)); *tmp = NCTP_START; queue_push(out, tmp);
|
|
337 | 308 |
for(size_t i = 0; i < num; ++i){ |
338 | 309 |
uint8_t *p = ptr[i]; size_t s = sz[i]; |
339 |
for(size_t j = 0; j < s; ++j, ++p) |
|
340 |
if((ret = nctp_send_char_try(base_addr, *p)))
|
|
341 |
return ret;
|
|
310 |
for(size_t j = 0; j < s; ++j, ++p){
|
|
311 |
tmp = malloc(sizeof(uint8_t)); *tmp = *p; queue_push(out, tmp);
|
|
312 |
}
|
|
342 | 313 |
} |
343 |
if((ret = nctp_send_char_try(base_addr, NCTP_END))) return ret; |
|
344 |
|
|
314 |
tmp = malloc(sizeof(uint8_t)); *tmp = NCTP_END; queue_push(out, tmp); |
|
315 |
if(uart_transmitter_empty(COM1_ADDR)){ |
|
316 |
if((ret = uart_send_char(COM1_ADDR, *(uint8_t*)queue_top(out)))) return ret; |
|
317 |
queue_pop(out); |
|
318 |
} |
|
345 | 319 |
return SUCCESS; |
346 | 320 |
} |
347 |
int nctp_send(int base_addr, size_t num, uint8_t* ptr[], size_t sz[]){ |
|
348 |
int ret; |
|
349 |
if((ret = uart_disable_int_rx(base_addr))) return ret; |
|
350 |
if((ret = uart_disable_int_tx(base_addr))) return ret; |
|
351 |
int r = nctp_send_inner(base_addr, num, ptr, sz); |
|
352 |
if((ret = uart_enable_int_rx(base_addr))) return ret; |
|
353 |
if((ret = uart_disable_int_tx(base_addr))) return ret; |
|
354 |
return r; |
|
321 |
|
|
322 |
static int nctp_transmit(void){ |
|
323 |
if(!queue_empty(out)){ |
|
324 |
int ret = uart_send_char(COM1_ADDR, *(uint8_t*)queue_top(out)); |
|
325 |
queue_pop(out); |
|
326 |
return ret; |
|
327 |
}else return SUCCESS; |
|
355 | 328 |
} |
356 |
|
|
357 |
static int nctp_get_inner(int base_addr, uint8_t **dest){ |
|
329 |
static void process(){ |
|
330 |
free(queue_top(in)); queue_pop(in); |
|
331 |
while(*(uint8_t*)queue_top(in) != NCTP_END){ |
|
332 |
printf("%c", *(uint8_t*)queue_top(in)); |
|
333 |
free(queue_top(in)); queue_pop(in); |
|
334 |
} |
|
335 |
free(queue_top(in)); queue_pop(in); |
|
336 |
} |
|
337 |
static int nctp_receive(void){ |
|
358 | 338 |
int ret; |
359 |
free(*dest); |
|
360 |
*dest = malloc(NCTP_MAX_SIZE*sizeof(uint8_t)); size_t i = 0; |
|
361 |
if(*dest == NULL) return NULL_PTR; |
|
362 | 339 |
uint8_t c; |
363 |
if((ret = nctp_get_char_try (base_addr, &c ))) return ret; |
|
364 |
while(true){ |
|
365 |
if(i >= NCTP_MAX_SIZE) return TRANS_REFUSED; |
|
366 |
if((ret = nctp_get_char_try (base_addr, &c))) return ret; |
|
367 |
if(c == NCTP_END) return SUCCESS; |
|
368 |
else (*dest)[i++] = c; |
|
340 |
while(uart_receiver_ready(COM1_ADDR)){ |
|
341 |
if((ret = uart_get_char(COM1_ADDR, &c))) return ret; |
|
342 |
uint8_t *tmp = malloc(sizeof(uint8_t)); *tmp = c; |
|
343 |
queue_push(in, tmp); |
|
344 |
if(c == NCTP_END) process(); |
|
369 | 345 |
} |
346 |
return SUCCESS; |
|
370 | 347 |
} |
371 |
int nctp_get(int base_addr, uint8_t **dest){ |
|
372 |
int ret; |
|
373 |
if((ret = uart_disable_int_rx(base_addr))) return ret; |
|
374 |
if((ret = uart_disable_int_tx(base_addr))) return ret; |
|
375 |
int r = nctp_get_inner(base_addr, dest); |
|
376 |
if((ret = uart_enable_int_rx(base_addr))) return ret; |
|
377 |
if((ret = uart_disable_int_tx(base_addr))) return ret; |
|
378 |
return r; |
|
348 |
|
|
349 |
int nctp_ih_err = SUCCESS; |
|
350 |
void nctp_ih(void){ |
|
351 |
uint8_t iir; |
|
352 |
if((nctp_ih_err = uart_get_iir(COM1_ADDR, &iir))) return; |
|
353 |
if(UART_GET_IF_INT_PEND(iir)){ |
|
354 |
switch(UART_GET_INT_PEND(iir)){ |
|
355 |
case UART_INT_RX: nctp_receive (); break; |
|
356 |
case UART_INT_TX: nctp_transmit(); break; |
|
357 |
default: break; |
|
358 |
} |
|
359 |
} |
|
379 | 360 |
} |
361 |
|
|
362 |
/// HLTP |
|
363 |
int hltp_send_string(const char *p){ |
|
364 |
uint8_t* ptr[1]; ptr[0] = (uint8_t*)p; |
|
365 |
size_t sz[1]; sz[0] = strlen(p)+1; |
|
366 |
return nctp_send(1, ptr, sz); |
|
367 |
} |
Also available in: Unified diff