📄 ahdlcavr.c
字号:
* If we are still connected to a network, fetch the next * character from the buffer. */ while (dcb->dcb_rd_idx == dcb->dcb_rx_idx) { if (dev->dev_icb == 0) break; /* TODO: Check for idle timeout. */ if (NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout)) { continue; } } /* * Leave loop if network interface is detached */ if (dev->dev_icb == 0) break; /* * If RAW mode is active, we are not allowing any data encapsulation * processing. So we just sleep for a while. */ if (dcb->dcb_modeflags & UART_MF_RAWMODE) { /* * It is a must to sleep here, because if we just yield it could create * too much processing in here and stall processing elsewhere. This gives * opportunity to other threads to process incoming data from USART. */ NutSleep(100); continue; } /* * Read next character from input buffer */ ch = dcb->dcb_rx_buf[dcb->dcb_rd_idx++]; if (inframe) { if (ch != AHDLC_FLAG) { if (ch == AHDLC_ESCAPE) { escaped = 1; continue; } if (escaped) { ch ^= AHDLC_TRANS; escaped = 0; } /* * Unless the peer lied to us about the negotiated MRU, * we should never get a frame which is too long. If it * happens, toss it away and grab the next incoming one. */ if (rxcnt++ < dcb->dcb_rx_mru) { /* Update calculated checksum and store character in buffer. */ tbx = (u_short) ((u_char) rxfcs ^ ch) << 1; rxfcs >>= 8; rxfcs ^= ((u_short) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1); *rxptr++ = ch; } else inframe = 0; continue; } if (rxcnt > 6 && rxfcs == AHDLC_GOODFCS) { /* * If the frame checksum is valid, create a NETBUF * and pass it to the network specific receive handler. */ rxcnt -= 2; if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, rxcnt)) != 0) { memcpy(nb->nb_dl.vp, rxbuf, rxcnt); (*ifn->if_recv) (netdev, nb); } } } /* * If frame flag is received, resync frame processing */ if (ch == AHDLC_FLAG) { inframe = 1; escaped = 0; rxptr = rxbuf; rxcnt = 0; rxfcs = AHDLC_INITFCS; } } /* Signal the link driver that we are down. */ netdev->dev_ioctl(netdev, LCP_LOWERDOWN, 0); /* Disconnected, clean up. */ if (rxbuf) { NutHeapFree(rxbuf); rxbuf = 0; } }}/* * \param dev Indicates the UART device. * * \return 0 on success, -1 otherwise. */static int AhdlcAvrGetStatus(NUTDEVICE * dev, u_long * status){ AHDLCDCB *dcb = dev->dev_dcb; u_char us; *status = 0;#ifdef __AVR_ENHANCED__ if (dev->dev_base) {#ifdef UART1_CTS_BIT if (bit_is_set(UART1_CTS_PIN, UART1_CTS_BIT)) *status |= UART_CTSDISABLED; else *status |= UART_CTSENABLED;#endif#ifdef UART1_RTS_BIT if (bit_is_set(UART1_RTS_PORT, UART1_RTS_BIT)) *status |= UART_RTSDISABLED; else *status |= UART_RTSENABLED;#endif#ifdef UART1_DTR_BIT if (bit_is_set(UART1_DTR_PORT, UART1_DTR_BIT)) *status |= UART_DTRDISABLED; else *status |= UART_DTRENABLED;#endif us = inp(UCSR1A); } else#endif /* __AVR_ENHANCED__ */ {#ifdef UART0_CTS_BIT if (bit_is_set(UART0_CTS_PIN, UART0_CTS_BIT)) *status |= UART_CTSDISABLED; else *status |= UART_CTSENABLED;#endif#ifdef UART0_RTS_BIT if (bit_is_set(UART0_RTS_PORT, UART0_RTS_BIT)) *status |= UART_RTSDISABLED; else *status |= UART_RTSENABLED;#endif#ifdef UART0_DTR_BIT if (bit_is_set(UART0_DTR_PORT, UART0_DTR_BIT)) *status |= UART_DTRDISABLED; else *status |= UART_DTRENABLED;#endif us = inp(USR); } if (us & FE) *status |= UART_FRAMINGERROR; if (us & DOR) *status |= UART_OVERRUNERROR; if (dcb->dcb_tx_idx == dcb->dcb_wr_idx) *status |= UART_TXBUFFEREMPTY; if (dcb->dcb_rd_idx == dcb->dcb_rx_idx) *status |= UART_RXBUFFEREMPTY; return 0;}/* * \param dev Indicates the UART device. * * \return 0 on success, -1 otherwise. */static int AhdlcAvrSetStatus(NUTDEVICE * dev, u_long status){#ifdef __AVR_ENHANCED__ if (dev->dev_base) {#ifdef UART1_RTS_BIT if (status & UART_RTSDISABLED) sbi(UART1_RTS_PORT, UART1_RTS_BIT); else if (status & UART_RTSENABLED) cbi(UART1_RTS_PORT, UART1_RTS_BIT);#endif#ifdef UART1_DTR_BIT if (status & UART_DTRDISABLED) sbi(UART1_DTR_PORT, UART1_DTR_BIT); else if (status & UART_DTRENABLED) cbi(UART1_DTR_PORT, UART1_DTR_BIT);#endif } else#endif /* __AVR_ENHANCED__ */ {#ifdef UART0_RTS_BIT if (status & UART_RTSDISABLED) sbi(UART0_RTS_PORT, UART0_RTS_BIT); else if (status & UART_RTSENABLED) cbi(UART0_RTS_PORT, UART0_RTS_BIT);#endif#ifdef UART0_DTR_BIT if (status & UART_DTRDISABLED) sbi(UART0_DTR_PORT, UART0_DTR_BIT); else if (status & UART_DTRENABLED) cbi(UART0_DTR_PORT, UART0_DTR_BIT);#endif } return 0;}/* * Carefully enable UART functions. */static void AhdlcAvrEnable(u_short base){ NutEnterCritical();#ifdef __AVR_ENHANCED__ if (base) {#ifdef UART1_CTS_BIT sbi(EIMSK, UART1_CTS_BIT);#endif outp(BV(RXCIE) | BV(RXEN) | BV(TXEN), UCSR1B); } else#endif /* __AVR_ENHANCED__ */ {#ifdef UART0_CTS_BIT sbi(EIMSK, UART0_CTS_BIT);#endif outp(BV(RXCIE) | BV(RXEN) | BV(TXEN), UCR); } NutExitCritical();}/* * Carefully disable UART functions. */static void AhdlcAvrDisable(u_short base){ /* * Disable UART interrupts. */ NutEnterCritical();#ifdef __AVR_ENHANCED__ if (base) {#ifdef UART1_CTS_BIT cbi(EIMSK, UART1_CTS_BIT);#endif outp(inp(UCSR1B) & ~(BV(RXCIE) | BV(UDRIE)), UCSR1B); } else#endif /* __AVR_ENHANCED__ */ {#ifdef UART0_CTS_BIT cbi(EIMSK, UART0_CTS_BIT);#endif outp(inp(UCR) & ~(BV(RXCIE) | BV(UDRIE)), UCR); } NutExitCritical(); /* * Allow incoming or outgoing character to finish. */ NutDelay(10); /* * Now disable UART functions. */#ifdef __AVR_ENHANCED__ if (base) outp(inp(UCSR1B) & ~(BV(RXEN) | BV(TXEN)), UCSR1B); else#endif /* __AVR_ENHANCED__ */ outp(inp(UCR) & ~(BV(RXEN) | BV(TXEN)), UCR);}/*! * \brief Perform on-chip UART control functions. * * \param dev Identifies the device that receives the device-control * function. * \param req Requested control function. May be set to one of the * following constants: * - UART_SETSPEED, conf points to an u_long value containing the baudrate. * - UART_GETSPEED, conf points to an u_long value receiving the current baudrate. * - UART_SETDATABITS, conf points to an u_long value containing the number of data bits, 5, 6, 7 or 8. * - UART_GETDATABITS, conf points to an u_long value receiving the number of data bits, 5, 6, 7 or 8. * - UART_SETPARITY, conf points to an u_long value containing the parity, 0 (no), 1 (odd) or 2 (even). * - UART_GETPARITY, conf points to an u_long value receiving the parity, 0 (no), 1 (odd) or 2 (even). * - UART_SETSTOPBITS, conf points to an u_long value containing the number of stop bits 1 or 2. * - UART_GETSTOPBITS, conf points to an u_long value receiving the number of stop bits 1 or 2. * - UART_SETSTATUS, conf points to an u_long value containing the changes for the control lines. * - UART_GETSTATUS, conf points to an u_long value receiving the state of the control lines and the device. * - UART_SETREADTIMEOUT, conf points to an u_long value containing the read timeout. * - UART_GETREADTIMEOUT, conf points to an u_long value receiving the read timeout. * - UART_SETWRITETIMEOUT, conf points to an u_long value containing the write timeout. * - UART_GETWRITETIMEOUT, conf points to an u_long value receiving the write timeout. * - UART_SETLOCALECHO, conf points to an u_long value containing 0 (off) or 1 (on). * - UART_GETLOCALECHO, conf points to an u_long value receiving 0 (off) or 1 (on). * - UART_SETFLOWCONTROL, conf points to an u_long value containing combined UART_FCTL_ values. * - UART_GETFLOWCONTROL, conf points to an u_long value containing receiving UART_FCTL_ values. * - UART_SETCOOKEDMODE, conf points to an u_long value containing 0 (off) or 1 (on). * - UART_GETCOOKEDMODE, conf points to an u_long value receiving 0 (off) or 1 (on). * - UART_SETRAWMODE, conf points to an u_long value containing 0 (off) or 1 (on). * - UART_GETRAWMODE, conf points to an u_long value receiving 0 (off) or 1 (on). * - HDLC_SETIFNET, conf points to a pointer containing the address of the network device's NUTDEVICE structure. * - HDLC_GETIFNET, conf points to a pointer receiving the address of the network device's NUTDEVICE structure. * * \param conf Points to a buffer that contains any data required for * the given control function or receives data from that * function. * \return 0 on success, -1 otherwise. * * \warning Timeout values are given in milliseconds and are limited to * the granularity of the system timer. * * \bug For ATmega103, only 8 data bits, 1 stop bit and no parity are allowed. * */int AhdlcAvrIOCtl(NUTDEVICE * dev, int req, void *conf){ int rc = 0; AHDLCDCB *dcb; void **ppv = (void **) conf; u_long *lvp = (u_long *) conf; u_char bv; u_short sv; u_char devnum; if (dev == 0) dev = &devUart0; devnum = dev->dev_base; dcb = dev->dev_dcb; switch (req) { case UART_SETSPEED: AhdlcAvrDisable(devnum); sv = (u_short) ((((2UL * NutGetCpuClock()) / (*lvp * 16UL)) + 1UL) / 2UL) - 1;#ifdef __AVR_ENHANCED__ if (devnum) { outp((u_char) sv, UBRR1L); outp((u_char) (sv >> 8), UBRR1H); } else { outp((u_char) sv, UBRR0L); outp((u_char) (sv >> 8), UBRR0H); }#else outp((u_char) sv, UBRR);#endif AhdlcAvrEnable(devnum); break; case UART_GETSPEED:#ifdef __AVR_ENHANCED__ if (devnum) sv = (u_short) inp(UBRR1H) << 8 | inp(UBRR1L); else sv = (u_short) inp(UBRR0H) << 8 | inp(UBRR0L);#else sv = inp(UBRR);#endif *lvp = NutGetCpuClock() / (16UL * (u_long) (sv + 1)); break; case UART_SETDATABITS: AhdlcAvrDisable(devnum); bv = (u_char)(*lvp);#ifdef __AVR_ENHANCED__ if (bv >= 5 && bv <= 8) { bv = (bv - 5) << 1; if (devnum) { outp((inp(UCSR1C) & 0xF9) | bv, UCSR1C); outp(inp(UCSR1B) & 0xFB, UCSR1B); } else { outp((inp(UCSR0C) & 0xF9) | bv, UCSR0C); outp(inp(UCSR0B) & 0xFB, UCSR0B); } } else rc = -1;#else if (bv != 8) rc = -1;#endif AhdlcAvrEnable(devnum); break; case UART_GETDATABITS:#ifdef __AVR_ENHANCED__ if (devnum) *lvp = ((inp(UCSR1C) & 0x06) >> 1) + 5; else *lvp = ((inp(UCSR0C) & 0x06) >> 1) + 5;#else *lvp = 8;#endif break; case UART_SETPARITY: AhdlcAvrDisable(devnum); bv = (u_char)(*lvp);#ifdef __AVR_ENHANCED__ if (bv <= 2) { if (bv == 1) bv = 3; bv <<= 4; if (devnum) outp((inp(UCSR1C) & 0xCF) | bv, UCSR1C); else outp((inp(UCSR0C) & 0xCF) | bv, UCSR0C); } else rc = -1;#endif if (bv) rc = -1; AhdlcAvrEnable(devnum); break; case UART_GETPARITY:#ifdef __AVR_ENHANCED__ if (devnum) bv = (inp(UCSR1C) & 0x30) >> 4; else bv = (inp(UCSR0C) & 0x30) >> 4; if (bv == 3) bv = 1;#else bv = 0;#endif *lvp = bv; break; case UART_SETSTOPBITS: AhdlcAvrDisable(devnum); bv = (u_char)(*lvp);#ifdef __AVR_ENHANCED__ if (bv == 1 || bv == 2) { bv = (bv - 1) << 3; if (devnum) outp((inp(UCSR1C) & 0xF7) | bv, UCSR1C); else outp((inp(UCSR0C) & 0xF7) | bv, UCSR0C); } else rc = -1;#else if (bv != 1) rc = -1;#endif AhdlcAvrEnable(devnum); break; case UART_GETSTOPBITS:#ifdef __AVR_ENHANCED__ if (devnum) *lvp = ((inp(UCSR1C) & 0x08) >> 3) + 1; else *lvp = ((inp(UCSR0C) & 0x08) >> 3) + 1;#else *lvp = 1;#endif break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -