📄 serialm.nc
字号:
/* * SerialM.nc * David Moore <dcm@csail.mit.edu> * * Module to connect standard output to the serial port. Allows use * of printf() for debugging and status messages. * * Usage: * call Serial.SetStdoutSerial() to attach stdout to the Serial UART. * Any further commands that use stdout such as printf() will output * to the serial port. * * * Copyright (C) 2004 Massachusetts Institute of Technology * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */module SerialM { provides { interface Serial; } uses { interface HPLUART; interface Leds; }}implementation {#define IDLE 0xff#define BUF_LEN 32#define RECV_BUF_LEN 32 volatile uint8_t tx_head = IDLE; volatile uint8_t tx_tail = 0; uint8_t txbuf[BUF_LEN]; uint8_t rx_start = 0; uint8_t rx_end = 0; uint8_t rx_posted = 0; norace uint8_t rxbuf[RECV_BUF_LEN]; int put(char c) __attribute__ ((C,spontaneous)) { uint8_t start_tx = 0; uint8_t new_tx_tail = 0; uint8_t new_tx_head = 1; /* Do the busy wait if the tx buffer is full */ while (new_tx_head != IDLE && (new_tx_tail+1)%BUF_LEN == new_tx_head) { atomic { new_tx_tail = tx_tail; new_tx_head = tx_head; } } atomic { /* Initialize queue */ if (tx_head == IDLE) { txbuf[0] = c; tx_head = tx_tail = 0; start_tx = 1; } /* Enqueue */ else { txbuf[tx_tail] = c; tx_tail = (tx_tail+1)%BUF_LEN; } } if (start_tx) call HPLUART.put(txbuf[0]); return 0; } async event result_t HPLUART.putDone() { uint8_t do_tx = 0; uint8_t tx_ch = 0; atomic { if (tx_head == tx_tail || tx_head == IDLE) { tx_head = IDLE; } else { do_tx = 1; tx_ch = txbuf[tx_head]; tx_head = (tx_head+1)%BUF_LEN; } } if (do_tx) call HPLUART.put(tx_ch); return SUCCESS; }#ifndef PLATFORM_PC void outc(uint8_t c) { loop_until_bit_is_set(UCSR0A, UDRE); outp(c, UDR0); } void printbyte(uint8_t b) { uint8_t n; n = (b & 0xf0) >> 4; if (n <= 9) outc('0' + n); else outc(n - 10 + 'A'); n = (b & 0x0f); if (n <= 9) outc('0' + n); else outc(n - 10 + 'A'); outc(' '); } void stack_trace(uint8_t extra, uint16_t val) __attribute__ ((C,spontaneous)) { uint8_t * ptr = (uint8_t *) inw(SPL); /* Disable serial interrupts */ uint8_t tmp = inb(UCSR0B); outp((1 << RXEN) | (1 << TXEN), UCSR0B); outc('\n'); if (extra) { outc('<'); printbyte(val & 0xff); printbyte((val >> 8) & 0xff); outc('>'); } printbyte(inb(SPH)); printbyte(inb(SPL)); outc(':'); for (ptr += 27; ptr < (uint8_t *)0x1100; ptr++) { printbyte(*ptr); } outc('\n'); outp(tmp, UCSR0B); }#endif void boot_loader(uint8_t c) { __asm__ ("mov r24, %0\n\t" "call 0x1fc00\n\t" :: "r" (c)); } void task recv_str() { uint8_t len = 0; uint8_t s, end; uint8_t buf[RECV_BUF_LEN]; atomic { s = rx_start; end = rx_end; rx_posted = 0; } while (s != end) { buf[len] = rxbuf[s]; s++; if (s >= RECV_BUF_LEN) s = 0; if (buf[len] == '\0') { signal Serial.Receive(buf, len); len = 0; atomic rx_start = s; } else len++; } } async event result_t HPLUART.get(uint8_t data) { uint8_t full;#ifndef PLATFORM_PC if (data == 'q') stack_trace(0, 0); if (data == '0') { call Leds.redOn(); call Leds.greenOn(); boot_loader('0'); /* never returns */ }#endif atomic full = (((rx_end+1>=RECV_BUF_LEN)?(0):(rx_end+1)) == rx_start); if (data == '\n') { uint8_t p; atomic p = rx_posted; if (!p) { if (post recv_str()) atomic rx_posted = 1; } data = '\0'; if (full) { full = 0; atomic { if (rx_end == 0) rx_end = RECV_BUF_LEN; rx_end--; } } } if (data == '\r' || full) return SUCCESS; atomic { rxbuf[rx_end++] = data; if (rx_end >= RECV_BUF_LEN) rx_end = 0; } return SUCCESS; } command result_t Serial.SetStdoutSerial() {#ifndef PLATFORM_PC /* Initialize the serial port */ call HPLUART.init(); /* Use the put() function for any output to stdout. */ fdevopen(put, NULL, 0);#endif return SUCCESS; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -