/** * UART RX Interrupt */ static void uart_recv_next_char(uint8_t num) { #ifdef CONFIG_MODULE_UART_9BITS if (uart_getconf_nbits() == 9) { int elt = 0; elt = uart_get_udr_9bits(num); if (CIRBUF_GET_FREELEN(&g_rx_fifo[num]) >= 2) { cirbuf_add_buf_head(&g_rx_fifo[num], (char *)&elt, 2); } if (rx_event[num]) ((event_9bits *)rx_event[num])(elt); } else #endif /* CONFIG_MODULE_UART_9BITS */ { char elt = 0; elt = uart_get_udr(num); if (!CIRBUF_IS_FULL(&g_rx_fifo[num])) { cirbuf_add_head(&g_rx_fifo[num], elt); } if (rx_event[num]) rx_event[num](elt); } }
int uart_send(uint8_t num, char c) { /* if cannot send the char */ if (uart_send_nowait(num, c) == -1) { /* if irq lock are masked and interrupt mode is on, we * have to poll the status register */ if (GLOBAL_IRQ_ARE_MASKED() && (*uart_regs[num].REGISTER_FOR_UART_IE & (1 << RXCIE)) ) { while( !(*uart_regs[num].ucsra & (1 << UDRE)) ); /* send the next char in the fifo to free a * place */ uart_send_next_char(num); cirbuf_add_head(&g_tx_fifo[num], c); } else { /* if irq are not locked, we can loop to emit */ while(uart_send_nowait(num, c) == -1); } } return 0; }
/* test cmdline_cirbuf char add/del functions */ static int test_cirbuf_char_add_del(void) { struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; char tmp[CMDLINE_TEST_BUFSIZE]; /* clear buffer */ memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); /* * initialize circular buffer */ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* * try to delete something from cirbuf. since it's empty, * these should fail. */ if (cirbuf_del_head_safe(&cb) == 0) { printf("Error: deleting from empty cirbuf head succeeded!\n"); return -1; } if (cirbuf_del_tail_safe(&cb) == 0) { printf("Error: deleting from empty cirbuf tail succeeded!\n"); return -1; } /* * add, verify and delete. these should pass. */ if (cirbuf_add_head_safe(&cb,'h') < 0) { printf("Error: adding to cirbuf head failed!\n"); return -1; } if (cirbuf_get_head(&cb) != 'h') { printf("Error: wrong head content!\n"); return -1; } if (cirbuf_del_head_safe(&cb) < 0) { printf("Error: deleting from cirbuf head failed!\n"); return -1; } if (cirbuf_add_tail_safe(&cb,'t') < 0) { printf("Error: adding to cirbuf tail failed!\n"); return -1; } if (cirbuf_get_tail(&cb) != 't') { printf("Error: wrong tail content!\n"); return -1; } if (cirbuf_del_tail_safe(&cb) < 0) { printf("Error: deleting from cirbuf tail failed!\n"); return -1; } /* do the same for unsafe versions. those are void. */ cirbuf_add_head(&cb,'h'); if (cirbuf_get_head(&cb) != 'h') { printf("Error: wrong head content!\n"); return -1; } cirbuf_del_head(&cb); /* test if char has been deleted. we can't call cirbuf_get_head * because it's unsafe, but we can call cirbuf_get_buf_head. */ if (cirbuf_get_buf_head(&cb, tmp, 1) > 0) { printf("Error: buffer should have been empty!\n"); return -1; } cirbuf_add_tail(&cb,'t'); if (cirbuf_get_tail(&cb) != 't') { printf("Error: wrong tail content!\n"); return -1; } cirbuf_del_tail(&cb); /* test if char has been deleted. we can't call cirbuf_get_tail * because it's unsafe, but we can call cirbuf_get_buf_tail. */ if (cirbuf_get_buf_tail(&cb, tmp, 1) > 0) { printf("Error: buffer should have been empty!\n"); return -1; } return 0; }