__interrupt void USCI0TX_ISR(void) { if (uart_start_tx()!=0) { UART_TX_LED_OFF(); IE2 &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt } }
// uart put char function int uart_putc(char c) { #ifdef UART_TX_BUFMASK unsigned int new_ptr = (uart_tx_inptr+1)&UART_TX_BUFMASK; #else int new_ptr = (uart_tx_inptr+1)%UART_TX_BUFLEN; #endif if (new_ptr==uart_tx_outptr) return -1; // buffer full uart_tx_buffer[new_ptr] = c; uart_tx_inptr=new_ptr; if (!uart_tx_transmitt) return uart_start_tx(); // return ok (if buffer not empty) return 0; // return ok }
static void console_queue_char(char ch) { struct console_tty *ct = &console_tty; int sr; OS_ENTER_CRITICAL(sr); while (CONSOLE_HEAD_INC(&ct->ct_tx) == ct->ct_tx.cr_tail) { /* TX needs to drain */ uart_start_tx(ct->ct_dev); OS_EXIT_CRITICAL(sr); if (os_started()) { os_time_delay(1); } OS_ENTER_CRITICAL(sr); } console_add_char(&ct->ct_tx, ch); OS_EXIT_CRITICAL(sr); }
size_t console_file_write(void *arg, const char *str, size_t cnt) { struct console_tty *ct = &console_tty; int i; if (!ct->ct_write_char) { return cnt; } for (i = 0; i < cnt; i++) { if (str[i] == '\n') { ct->ct_write_char('\r'); } ct->ct_write_char(str[i]); } if (cnt > 0) { console_is_midline = str[cnt - 1] != '\n'; } uart_start_tx(ct->ct_dev); return cnt; }
static int console_rx_char(void *arg, uint8_t data) { struct console_tty *ct = (struct console_tty *)arg; struct console_ring *tx = &ct->ct_tx; struct console_ring *rx = &ct->ct_rx; int tx_space = 0; int i; #if MYNEWT_VAL(CONSOLE_HIST_ENABLE) uint8_t tx_buf[MYNEWT_VAL(CONSOLE_RX_BUF_SIZE)]; #else uint8_t tx_buf[3]; #endif if (CONSOLE_HEAD_INC(&ct->ct_rx) == ct->ct_rx.cr_tail) { /* * RX queue full. Reader must drain this. */ if (ct->ct_rx_cb) { ct->ct_rx_cb(); } return -1; } /* echo */ switch (data) { case '\r': case '\n': /* * linefeed */ tx_buf[0] = '\n'; tx_buf[1] = '\r'; tx_space = 2; console_add_char(rx, '\n'); #if MYNEWT_VAL(CONSOLE_HIST_ENABLE) console_hist_add(rx); #endif if (ct->ct_rx_cb) { ct->ct_rx_cb(); } break; case CONSOLE_ESC: ct->ct_esc_seq = 1; goto out; case '[': if (ct->ct_esc_seq == 1) { ct->ct_esc_seq = 2; goto out; } else { goto queue_char; } break; case CONSOLE_LEFT: if (ct->ct_esc_seq == 2) { goto backspace; } else { goto queue_char; } break; case CONSOLE_UP: case CONSOLE_DOWN: if (ct->ct_esc_seq != 2) { goto queue_char; } #if MYNEWT_VAL(CONSOLE_HIST_ENABLE) tx_space = console_hist_move(rx, tx_buf, data); tx_buf[tx_space] = 0; ct->ct_esc_seq = 0; /* * when moving up, stop on oldest history entry * when moving down, let it delete input before leaving... */ if (data == CONSOLE_UP && tx_space == 0) { goto out; } if (!ct->ct_echo_off) { /* HACK: clean line by backspacing up to maximum possible space */ for (i = 0; i < MYNEWT_VAL(CONSOLE_TX_BUF_SIZE); i++) { if (console_buf_space(tx) < 3) { console_tx_flush(ct, 3); } console_add_char(tx, '\b'); console_add_char(tx, ' '); console_add_char(tx, '\b'); uart_start_tx(ct->ct_dev); } if (tx_space == 0) { goto out; } } else { goto queue_char; } break; #else ct->ct_esc_seq = 0; goto out; #endif case CONSOLE_RIGHT: if (ct->ct_esc_seq == 2) { data = ' '; /* add space */ } goto queue_char; case '\b': case CONSOLE_DEL: backspace: /* * backspace */ ct->ct_esc_seq = 0; if (console_pull_char_head(rx) == 0) { /* * Only wipe out char if we can pull stuff off from head. */ tx_buf[0] = '\b'; tx_buf[1] = ' '; tx_buf[2] = '\b'; tx_space = 3; } else { goto out; } break; default: queue_char: tx_buf[0] = data; tx_space = 1; ct->ct_esc_seq = 0; console_add_char(rx, data); break; } if (!ct->ct_echo_off) { if (console_buf_space(tx) < tx_space) { console_tx_flush(ct, tx_space); } for (i = 0; i < tx_space; i++) { console_add_char(tx, tx_buf[i]); } uart_start_tx(ct->ct_dev); } out: return 0; }
/* * Called by mgmt to queue packet out to UART. */ static int nmgr_uart_out(struct nmgr_transport *nt, struct os_mbuf *m) { struct nmgr_uart_state *nus = (struct nmgr_uart_state *)nt; struct os_mbuf_pkthdr *mpkt; struct os_mbuf *n; char tmp_buf[12]; uint16_t crc; char *dst; int off; int boff; int slen; int sr; int rc; int last; int tx_sz; assert(OS_MBUF_IS_PKTHDR(m)); mpkt = OS_MBUF_PKTHDR(m); off = 0; crc = CRC16_INITIAL_CRC; for (n = m; n; n = SLIST_NEXT(n, om_next)) { crc = crc16_ccitt(crc, n->om_data, n->om_len); } crc = htons(crc); dst = os_mbuf_extend(m, sizeof(crc)); if (!dst) { goto err; } memcpy(dst, &crc, sizeof(crc)); n = os_msys_get(SHELL_NLIP_MAX_FRAME, 0); if (!n || OS_MBUF_TRAILINGSPACE(n) < 32) { goto err; } while (off < mpkt->omp_len) { tx_sz = 2; dst = os_mbuf_extend(n, 2); if (off == 0) { *(uint16_t *)dst = htons(SHELL_NLIP_PKT); *(uint16_t *)tmp_buf = htons(mpkt->omp_len); boff = 2; } else { *(uint16_t *)dst = htons(SHELL_NLIP_DATA); boff = 0; } while (off < mpkt->omp_len) { slen = mpkt->omp_len - off; last = 1; if (slen > sizeof(tmp_buf) + boff) { slen = sizeof(tmp_buf) - boff; last = 0; } if (tx_sz + BASE64_ENCODE_SIZE(slen + boff) >= 124) { break; } rc = os_mbuf_copydata(m, off, slen, tmp_buf + boff); assert(rc == 0); off += slen; slen += boff; dst = os_mbuf_extend(n, BASE64_ENCODE_SIZE(slen)); if (!dst) { goto err; } tx_sz += base64_encode(tmp_buf, slen, dst, last); boff = 0; } if (os_mbuf_append(n, "\n", 1)) { goto err; } } os_mbuf_free_chain(m); OS_ENTER_CRITICAL(sr); if (!nus->nus_tx) { nus->nus_tx = n; uart_start_tx(nus->nus_dev); } else { os_mbuf_concat(nus->nus_tx, n); } OS_EXIT_CRITICAL(sr); return 0; err: os_mbuf_free_chain(m); os_mbuf_free_chain(n); return -1; }