📄 ahdlcavr.c
字号:
case UART_GETSTATUS: AhdlcAvrGetStatus(dev, lvp); break; case UART_SETSTATUS: AhdlcAvrSetStatus(dev, *lvp); break; case UART_SETREADTIMEOUT: dcb->dcb_rtimeout = *lvp; break; case UART_GETREADTIMEOUT: *lvp = dcb->dcb_rtimeout; break; case UART_SETWRITETIMEOUT: dcb->dcb_wtimeout = *lvp; break; case UART_GETWRITETIMEOUT: *lvp = dcb->dcb_wtimeout; break; case UART_SETLOCALECHO: bv = (u_char)(*lvp); if (bv) dcb->dcb_modeflags |= UART_MF_LOCALECHO; else dcb->dcb_modeflags &= ~UART_MF_LOCALECHO; break; case UART_GETLOCALECHO: if (dcb->dcb_modeflags & UART_MF_LOCALECHO) *lvp = 1; else *lvp = 0; break; case UART_SETFLOWCONTROL: bv = (u_char)(*lvp); if (bv) dcb->dcb_modeflags |= UART_MF_LOCALECHO; else dcb->dcb_modeflags &= ~UART_MF_LOCALECHO; break; case UART_GETFLOWCONTROL: break; case UART_SETRAWMODE: bv = (u_char)(*lvp); if (bv) dcb->dcb_modeflags |= UART_MF_RAWMODE; else dcb->dcb_modeflags &= ~UART_MF_RAWMODE; break; case UART_GETRAWMODE: if (dcb->dcb_modeflags & UART_MF_RAWMODE) *lvp = 1; else *lvp = 0; break; case HDLC_SETIFNET: if (ppv && (*ppv != 0)) { dev->dev_icb = *ppv; dev->dev_type = IFTYP_NET; NutEventPost(&dcb->dcb_mf_evt); } else { dev->dev_type = IFTYP_CHAR; if (dev->dev_icb != 0) { dev->dev_icb = 0; /* * Signal AHDLC Thread, so it can change it's state instantly */ NutEventPost(&dcb->dcb_rx_rdy); } } break; case HDLC_GETIFNET: *ppv = dev->dev_icb; break; default: rc = -1; break; } return rc;}/*! * \brief Initialize asynchronous HDLC device. * * This function will be called during device registration. It * initializes the hardware, registers all required interrupt * handlers and initializes all internal data structures used by * this driver. * * \param dev Identifies the device to initialize. * * \return 0 on success, -1 otherwise. */int AhdlcAvrInit(NUTDEVICE * dev){ int rc = 0; AHDLCDCB *dcb; u_long baudrate = 9600; /* Disable UART. */ AhdlcAvrDisable(dev->dev_base); /* Initialize driver control block. */ dcb = dev->dev_dcb; memset(dcb, 0, sizeof(AHDLCDCB)); dcb->dcb_base = dev->dev_base; dcb->dcb_rx_buf = NutHeapAlloc(256); dcb->dcb_tx_buf = NutHeapAlloc(256); dcb->dcb_rx_mru = 1500; dcb->dcb_tx_mru = 1500; dcb->dcb_tx_accm = 0xFFFFFFFF; /* * Initialize UART handshake hardware and register interrupt handlers. */ if (dev->dev_base) {#ifdef __AVR_ENHANCED__#ifdef UART1_CTS_BIT sbi(UART1_CTS_PORT, UART1_CTS_BIT); cbi(UART1_CTS_DDR, UART1_CTS_BIT); /* Falling edge will generate interrupts. */#if UART1_CTS_BIT == 4 sbi(EICR, 1);#elif UART1_CTS_BIT == 5 sbi(EICR, 3);#elif UART1_CTS_BIT == 6 sbi(EICR, 5);#elif UART1_CTS_BIT == 7 sbi(EICR, 7);#endif#endif#ifdef UART1_RTS_BIT sbi(UART1_RTS_PORT, UART1_RTS_BIT); sbi(UART1_RTS_DDR, UART1_RTS_BIT);#endif#ifdef UART1_DTR_BIT sbi(UART1_DTR_PORT, UART1_DTR_BIT); sbi(UART1_DTR_DDR, UART1_DTR_BIT);#endif if (NutRegisterIrqHandler(&sig_UART1_RECV, Rx1Complete, dcb)) rc = -1; else if (NutRegisterIrqHandler(&sig_UART1_DATA, Tx1Complete, dcb))#ifdef UART1_CTS_BIT rc = -1; else if (NutRegisterIrqHandler(&UART1_CTS_SIGNAL, Cts1Interrupt, dev))#endif#endif /* __AVR_ENHANCED__ */ rc = -1; } else {#ifdef UART0_CTS_BIT sbi(UART0_CTS_PORT, UART0_CTS_BIT); cbi(UART0_CTS_DDR, UART0_CTS_BIT);#if UART0_CTS_BIT == 4 sbi(EICR, 1);#elif UART0_CTS_BIT == 5 sbi(EICR, 3);#elif UART0_CTS_BIT == 6 sbi(EICR, 5);#elif UART0_CTS_BIT == 7 sbi(EICR, 7);#endif#endif#ifdef UART0_RTS_BIT sbi(UART0_RTS_PORT, UART0_RTS_BIT); sbi(UART0_RTS_DDR, UART0_RTS_BIT);#endif#ifdef UART0_DTR_BIT sbi(UART0_DTR_PORT, UART0_DTR_BIT); sbi(UART0_DTR_DDR, UART0_DTR_BIT);#endif if (NutRegisterIrqHandler(&sig_UART0_RECV, Rx0Complete, dcb)) rc = -1; else if (NutRegisterIrqHandler(&sig_UART0_DATA, Tx0Complete, dcb)) rc = -1;#ifdef UART0_CTS_BIT else if (NutRegisterIrqHandler(&UART0_CTS_SIGNAL, Cts0Interrupt, dev)) rc = -1;#endif } /* * If we have been successful so far, start the HDLC receiver thread, * set the initial baudrate and enable the UART. */ if (rc == 0 && NutThreadCreate("ahdlcrx", AhdlcRx, dev, NUT_THREAD_AHDLCRXSTACK)) { AhdlcAvrIOCtl(dev, UART_SETSPEED, &baudrate); return 0; } /* We failed, clean up. */ if (dcb->dcb_rx_buf) NutHeapFree((void *) dcb->dcb_rx_buf); if (dcb->dcb_tx_buf) NutHeapFree((void *) dcb->dcb_tx_buf); return -1;}/*! * \brief Read from the asynchronous HDLC device. * * This function is called by the low level input routines of the * \ref xrCrtLowio "C runtime library", using the _NUTDEVICE::dev_read * entry. * * The function may block the calling thread until at least one * character has been received or a timeout occurs. * * It is recommended to set a proper read timeout with software handshake. * In this case a timeout may occur, if the communication peer lost our * last XON character. The application may then use ioctl() to disable the * receiver and do the read again. This will send out another XON. * * \param fp Pointer to a \ref _NUTFILE structure, obtained by a * previous call to AhdlcOpen(). * \param buffer Pointer to the buffer that receives the data. If zero, * then all characters in the input buffer will be * removed. * \param size Maximum number of bytes to read. * * \return The number of bytes read, which may be less than the number * of bytes specified. A return value of -1 indicates an error, * while zero is returned in case of a timeout. */int AhdlcAvrRead(NUTFILE * fp, void *buffer, int size){ int rc = 0; AHDLCDCB *dcb = fp->nf_dev->dev_dcb; u_char *cp = buffer; /* * Get characters from receive buffer. */ if (buffer) { while (rc < size) { if (dcb->dcb_rd_idx != dcb->dcb_rx_idx) { *cp++ = dcb->dcb_rx_buf[dcb->dcb_rd_idx++]; rc++; } else if (rc || NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout)) break; } } /* * Call without data buffer discards receive buffer. */ else dcb->dcb_rd_idx = dcb->dcb_rx_idx; return rc;}/*! * \brief Write to the asynchronous HDLC device. * * \param dev Pointer to a previously registered NUTDEVICE structure. * \param buffer Pointer the data to write. * \param len Number of data bytes to write. * \param pflg If this flag is set, then the buffer is located in program * space. * * \return The number of bytes written. In case of a write timeout, this * may be less than the specified length. */int AhdlcAvrPut(NUTDEVICE * dev, CONST void *buffer, int len, int pflg){ int rc = 0; AHDLCDCB *dcb = dev->dev_dcb; CONST u_char *cp = buffer; /* * Put characters in transmit buffer. */ if (buffer) { while (rc < len) { if (SendRawByte(dcb, pflg ? PRG_RDB(cp) : *cp, 0)) break; cp++; rc++; } } /* * Call without data pointer starts transmission. */ else { /* * TODO: Check handshake. */#ifdef __AVR_ENHANCED__ if (dev->dev_base) sbi(UCSR1B, UDRIE); else#endif sbi(UCR, UDRIE); } return rc;}/*! * \brief Write to the asynchronous HDLC device. * * This function is called by the low level output routines of the * \ref xrCrtLowio "C runtime library", using the * \ref _NUTDEVICE::dev_write entry. * * The function may block the calling thread. * * \param fp Pointer to a _NUTFILE structure, obtained by a previous * call to AhldcOpen(). * \param buffer Pointer to the data to be written. If zero, then the * output buffer will be flushed. * \param len Number of bytes to write. * * \return The number of bytes written, which may be less than the number * of bytes specified if a timeout occured. A return value of -1 * indicates an error. */int AhdlcAvrWrite(NUTFILE * fp, CONST void *buffer, int len){ return AhdlcAvrPut(fp->nf_dev, buffer, len, 0);}/*! * \brief Write to the asynchronous HDLC device. * * Similar to AhdlcWrite() except that the data is located in program * memory. * * This function is called by the low level output routines of the * \ref xrCrtLowio "C runtime library", using the _NUTDEVICE::dev_write_P * entry. * * The function may block the calling thread. * * \param fp Pointer to a NUTFILE structure, obtained by a previous * call to AhdlcOpen(). * \param buffer Pointer to the data in program space to be written. * \param len Number of bytes to write. * * \return The number of bytes written, which may be less than the number * of bytes specified if a timeout occured. A return value of -1 * indicates an error. */int AhdlcAvrWrite_P(NUTFILE * fp, PGM_P buffer, int len){ return AhdlcAvrPut(fp->nf_dev, (CONST char *) buffer, len, 1);}/*! * \brief Open the asynchronous HDLC device. * * This function is called by the low level open routine of the C runtime * library, using the _NUTDEVICE::dev_open entry. * * \param dev Pointer to the NUTDEVICE structure. * \param name Ignored, should point to an empty string. * \param mode Operation mode. Any of the following values may be or-ed: * - \ref _O_BINARY * - \ref _O_RDONLY * - \ref _O_WRONLY * \param acc Ignored, should be zero. * * \return Pointer to a NUTFILE structure if successful or NUTFILE_EOF otherwise. */NUTFILE *AhdlcAvrOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc){ NUTFILE *fp; if ((fp = NutHeapAlloc(sizeof(NUTFILE))) == 0) return NUTFILE_EOF; fp->nf_next = 0; fp->nf_dev = dev; fp->nf_fcb = 0; /* Enable handshake outputs. */#ifdef __AVR_ENHANCED__ if (dev->dev_base) {#ifdef UART1_RTS_BIT cbi(UART1_RTS_PORT, UART1_RTS_BIT);#endif#ifdef UART1_DTR_BIT cbi(UART1_DTR_PORT, UART1_DTR_BIT);#endif } else#endif /* __AVR_ENHANCED__ */ {#ifdef UART0_RTS_BIT cbi(UART0_RTS_PORT, UART0_RTS_BIT);#endif#ifdef UART0_DTR_BIT cbi(UART0_DTR_PORT, UART0_DTR_BIT);#endif } return fp;}/*! * \brief Close the asynchronous HDLC device. * * This function is called by the low level close routine of the C runtime * library, using the _NUTDEVICE::dev_close entry. * * \param fp Pointer to a _NUTFILE structure, obtained by a previous call * to UsartOpen(). * * \return 0 on success or -1 otherwise. * * \todo We may support shared open and use dev_irq as an open counter. */int AhdlcAvrClose(NUTFILE * fp){ if (fp && fp != NUTFILE_EOF) { /* Disable handshake outputs. */#ifdef __AVR_ENHANCED__ if (fp->nf_dev->dev_base) {#ifdef UART1_RTS_BIT sbi(UART1_RTS_PORT, UART1_RTS_BIT);#endif#ifdef UART1_DTR_BIT sbi(UART1_DTR_PORT, UART1_DTR_BIT);#endif } else#endif /* __AVR_ENHANCED__ */ {#ifdef UART0_RTS_BIT sbi(UART0_RTS_PORT, UART0_RTS_BIT);#endif#ifdef UART0_DTR_BIT sbi(UART0_DTR_PORT, UART0_DTR_BIT);#endif } NutHeapFree(fp); return 0; } return -1;}/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -