Nut/OS  4.10.3
API Reference
uartavr.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 /*
00035  * $Log$
00036  * Revision 1.5  2008/08/11 06:59:17  haraldkipp
00037  * BSD types replaced by stdint types (feature request #1282721).
00038  *
00039  * Revision 1.4  2006/10/08 16:48:08  haraldkipp
00040  * Documentation fixed
00041  *
00042  * Revision 1.3  2005/10/16 23:21:33  hwmaier
00043  * Fixed compilation issue regards U2X macro with Imagecraft
00044  *
00045  * Revision 1.2  2005/10/07 22:01:27  hwmaier
00046  * Obsolete dcb_baudSelect removed. Support for double speed (U2X) added (using same method as in usartavr.c).
00047  *
00048  * Revision 1.1  2005/07/26 18:02:40  haraldkipp
00049  * Moved from dev.
00050  *
00051  * Revision 1.9  2005/07/14 09:12:20  freckle
00052  * Rewrote CS in UartAvrInput
00053  *
00054  * Revision 1.8  2005/01/24 21:12:05  freckle
00055  * renamed NutEventPostFromIRQ into NutEventPostFromIrq
00056  *
00057  * Revision 1.7  2005/01/21 16:49:46  freckle
00058  * Seperated calls to NutEventPostAsync between Threads and IRQs
00059  *
00060  * Revision 1.6  2004/12/16 08:40:35  haraldkipp
00061  * Late increment fixes ICCAVR bug.
00062  *
00063  * Revision 1.5  2004/05/24 20:15:50  drsung
00064  * Added function UartAvrSize to return number of chars in input buffer.
00065  *
00066  * Revision 1.4  2004/03/18 14:01:07  haraldkipp
00067  * Deprecated header file replaced
00068  *
00069  * Revision 1.3  2004/03/18 10:09:27  haraldkipp
00070  * Removed deprecated raw I/O
00071  *
00072  * Revision 1.2  2003/07/20 18:28:10  haraldkipp
00073  * Explain how to disable timeout.
00074  *
00075  * Revision 1.1.1.1  2003/05/09 14:40:55  haraldkipp
00076  * Initial using 3.2.1
00077  *
00078  * Revision 1.21  2003/05/06 18:35:06  harald
00079  * Avoid duplicate initialization
00080  *
00081  * Revision 1.20  2003/04/21 16:26:01  harald
00082  * Use predefined eof
00083  *
00084  * Revision 1.19  2003/03/31 14:53:08  harald
00085  * Prepare release 3.1
00086  *
00087  */
00088 
00089 #include <string.h>
00090 
00091 #include <sys/atom.h>
00092 #include <sys/heap.h>
00093 #include <sys/event.h>
00094 #include <sys/timer.h>
00095 #include <sys/device.h>
00096 
00097 #include <dev/irqreg.h>
00098 #include <dev/uartavr.h>
00099 
00100 #include <fcntl.h>
00101 
00102 /*
00103  * Not nice because stdio already defined them. But in order to save memory,
00104  * we do the whole buffering and including stdio here would be more weird.
00105  */
00106 #ifndef _IOFBF
00107 #define _IOFBF      0x00
00108 #define _IOLBF      0x01
00109 #define _IONBF      0x02
00110 #endif
00111 
00116 
00117 /*
00118  * Handle AVR UART transmit complete.
00119  */
00120 static void TxComplete(void *arg)
00121 {
00122     NUTDEVICE *dev = (NUTDEVICE *) arg;
00123     IFSTREAM *ifs = dev->dev_icb;
00124     UARTDCB *dcb;
00125 
00126     if (ifs->if_tx_idx != ifs->if_wr_idx) {
00127 #ifdef UDR1
00128         if (dev->dev_base)
00129             UDR1 = ifs->if_tx_buf[ifs->if_tx_idx];
00130         else
00131 #endif
00132             outb(UDR, ifs->if_tx_buf[ifs->if_tx_idx]);
00133         ifs->if_tx_idx++;
00134     } else {
00135         ifs->if_tx_act = 0;
00136         dcb = dev->dev_dcb;
00137         NutEventPostFromIrq(&dcb->dcb_tx_rdy);
00138     }
00139 }
00140 
00141 /*
00142  * Handle AVR UART receive complete.
00143  *
00144  * Note, that this function modifies the receive index in
00145  * interrupt context. This requires, that any non atomic
00146  * access of this index requires interrupts being disabled.
00147  * Thanks to Mike Cornelius, who pointed this out.
00148  */
00149 static void RxComplete(void *arg)
00150 {
00151     NUTDEVICE *dev = (NUTDEVICE *) arg;
00152     IFSTREAM *ifs = dev->dev_icb;
00153     UARTDCB *dcb;
00154 
00155 #ifdef UDR1
00156     if (dev->dev_base)
00157         ifs->if_rx_buf[ifs->if_rx_idx] = inb(UDR1);
00158     else
00159 #endif
00160         ifs->if_rx_buf[ifs->if_rx_idx] = inb(UDR);
00161 
00162     if (ifs->if_rd_idx == ifs->if_rx_idx) {
00163         dcb = dev->dev_dcb;
00164         NutEventPostFromIrq(&dcb->dcb_rx_rdy);
00165     }
00166     /* Late increment fixes ICCAVR bug on volatile variables. */
00167     ifs->if_rx_idx++;
00168 }
00169 
00182 int UartAvrInput(NUTDEVICE * dev)
00183 {
00184     int rc = 0;
00185     int empty;
00186     IFSTREAM *ifs = dev->dev_icb;
00187     UARTDCB *dcb =  dev->dev_dcb;
00188 
00189     NutEnterCritical();
00190     empty = ifs->if_rd_idx == ifs->if_rx_idx;
00191     NutExitCritical();
00192 
00193     if (empty) {
00194 
00195         /*
00196          * Changing if into a while loop fixes a serious bug:
00197          * Previous receiver events without any waiting thread
00198          * set the event handle to the signaled state. So the
00199          * wait returns immediately. Unfortunately the calling
00200          * routines rely on a filled buffer when we return 0.
00201          * Thanks to Mike Cornelius, who found this bug.
00202          *
00203          * MR (2005-07-14): Reduced critical sections
00204          */
00205         do {
00206 
00207             rc = NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout);
00208 
00209             NutEnterCritical();
00210             empty = ifs->if_rd_idx == ifs->if_rx_idx;
00211             NutExitCritical();
00212 
00213         } while (rc == 0 && empty);
00214     }
00215 
00216     return rc;
00217 }
00218 
00233 int UartAvrOutput(NUTDEVICE * dev)
00234 {
00235     IFSTREAM *ifs = dev->dev_icb;
00236 
00237     if (ifs->if_tx_act == 0 && ifs->if_tx_idx != ifs->if_wr_idx) {
00238         ifs->if_tx_act = 1;
00239 #ifdef UDR1
00240         if (dev->dev_base)
00241             UDR1 = ifs->if_tx_buf[ifs->if_tx_idx];
00242         else
00243 #endif
00244             outb(UDR, ifs->if_tx_buf[ifs->if_tx_idx]);
00245         ifs->if_tx_idx++;
00246     }
00247     return 0;
00248 }
00249 
00260 int UartAvrFlush(NUTDEVICE * dev)
00261 {
00262     IFSTREAM *ifs = dev->dev_icb;
00263     UARTDCB *dcb = dev->dev_dcb;
00264 
00265     /*
00266      * Start any pending output.
00267      */
00268     if (UartAvrOutput(dev))
00269         return -1;
00270 
00271     /*
00272      * Wait until output buffer empty.
00273      */
00274     NutEnterCritical();
00275     while (ifs->if_tx_idx != ifs->if_wr_idx)
00276         NutEventWait(&dcb->dcb_tx_rdy, 100);
00277     NutExitCritical();
00278 
00279     return 0;
00280 }
00281 
00282 /*
00283  *
00284  * \param dev Indicates the UART device.
00285  *
00286  * \return 0 on success, -1 otherwise.
00287  */
00288 static int UartAvrGetStatus(NUTDEVICE * dev, uint32_t * status)
00289 {
00290     IFSTREAM *ifs = dev->dev_icb;
00291     uint8_t us;
00292 
00293     *status = 0;
00294 
00295 #ifdef UDR1
00296     if (dev->dev_base)
00297         us = inb(UCSR1A);
00298     else
00299 #endif
00300         us = inb(USR);
00301     if (us & FE)
00302         *status |= UART_FRAMINGERROR;
00303     if (us & DOR)
00304         *status |= UART_OVERRUNERROR;
00305     if (ifs->if_tx_idx == ifs->if_wr_idx)
00306         *status |= UART_TXBUFFEREMPTY;
00307     if (ifs->if_rd_idx == ifs->if_rx_idx)
00308         *status |= UART_RXBUFFEREMPTY;
00309     return 0;
00310 }
00311 
00312 /*
00313  * Carefully enable UART functions.
00314  */
00315 static void UartAvrEnable(uint16_t base)
00316 {
00317     NutEnterCritical();
00318 #ifdef UCSR1B
00319     if (base)
00320         UCSR1B = BV(RXCIE) | BV(TXCIE) | BV(RXEN) | BV(TXEN);
00321     else
00322 #endif
00323         UCR = BV(RXCIE) | BV(TXCIE) | BV(RXEN) | BV(TXEN);
00324     NutExitCritical();
00325 }
00326 
00327 /*
00328  * Carefully disable UART functions.
00329  */
00330 static void UartAvrDisable(uint16_t base)
00331 {
00332     /*
00333      * Disable UART interrupts.
00334      */
00335     NutEnterCritical();
00336 #ifdef UCSR1B
00337     if (base)
00338         UCSR1B &= ~(BV(RXCIE) | BV(TXCIE));
00339     else
00340 #endif
00341         UCR &= ~(BV(RXCIE) | BV(TXCIE));
00342     NutExitCritical();
00343 
00344     /*
00345      * Allow incoming or outgoing character to finish.
00346      */
00347     NutDelay(10);
00348 
00349     /*
00350      * Now disable UART functions.
00351      */
00352 #ifdef UCSR1B
00353     if (base)
00354         UCSR1B &= ~(BV(RXEN) | BV(TXEN));
00355     else
00356 #endif
00357         UCR &= ~(BV(RXEN) | BV(TXEN));
00358 }
00359 
00400 int UartAvrIOCtl(NUTDEVICE * dev, int req, void *conf)
00401 {
00402     int rc = 0;
00403     UARTDCB *dcb;
00404     uint32_t *lvp = (uint32_t *) conf;
00405     uint32_t lv = *lvp;
00406     uint8_t bv = (uint8_t) lv;
00407     uint16_t sv;
00408     uint8_t devnum;
00409 
00410     if (dev == 0)
00411         dev = &devUart0;
00412 
00413     devnum = dev->dev_base;
00414     dcb = dev->dev_dcb;
00415 
00416     switch (req) {
00417     case UART_SETSPEED:
00418         UartAvrDisable(devnum);
00419 #ifdef __AVR_ENHANCED__
00420         if (devnum) {
00421             if (bit_is_set(UCSR1A, U2X1)) {
00422                 lv <<= 2;
00423             } else {
00424                 lv <<= 3;
00425             }
00426         } else {
00427             if (bit_is_set(UCSR0A, U2X0)) {
00428                 lv <<= 2;
00429             } else {
00430                 lv <<= 3;
00431             }
00432         }
00433 #else
00434         lv <<= 3;
00435 #endif
00436         sv = (uint16_t) ((NutGetCpuClock() / lv + 1UL) / 2UL) - 1;
00437 #ifdef UBRR1H
00438         if (devnum) {
00439             UBRR1L = (uint8_t) sv;
00440             UBRR1H = (uint8_t) (sv >> 8);
00441         } else {
00442             UBRR0L = (uint8_t) sv;
00443             UBRR0H = (uint8_t) (sv >> 8);
00444         }
00445 #else
00446         UBRR = (uint8_t) sv;
00447 #endif
00448         UartAvrEnable(devnum);
00449         break;
00450 
00451     case UART_GETSPEED:
00452 #ifdef UBRR1H
00453         if (devnum) {
00454             if (bit_is_set(UCSR1A, U2X1))
00455                 lv = 8UL;
00456             else
00457                 lv = 16UL;
00458             sv = (uint16_t) (UBRR1H) << 8 | UBRR1L;
00459         }
00460         else
00461         {
00462             if (bit_is_set(UCSR0A, U2X0))
00463                 lv = 8UL;
00464             else
00465                 lv = 16UL;
00466             sv = (uint16_t) (UBRR0H) << 8 | UBRR0L;
00467         }
00468 #else
00469         sv = UBRR;
00470         lv = 16UL;
00471 #endif
00472         *lvp = NutGetCpuClock() / (lv * (uint32_t) (sv + 1));
00473         break;
00474 
00475     case UART_SETDATABITS:
00476         UartAvrDisable(devnum);
00477 #ifdef UCSR1C
00478         if (bv >= 5 && bv <= 8) {
00479             bv = (bv - 5) << 1;
00480             if (devnum) {
00481                 UCSR1C = (UCSR1C & 0xF9) | bv;
00482                 UCSR1B &= 0xFB;
00483             } else {
00484                 UCSR0C = (UCSR0C & 0xF9) | bv;
00485                 UCSR0B &= 0xFB;
00486             }
00487         } else
00488             rc = -1;
00489 #else
00490         if (bv != 8)
00491             rc = -1;
00492 #endif
00493         UartAvrEnable(devnum);
00494         break;
00495 
00496     case UART_GETDATABITS:
00497 #ifdef UCSR1C
00498         if (devnum)
00499             *lvp = ((UCSR1C & 0x06) >> 1) + 5;
00500         else
00501             *lvp = ((UCSR0C & 0x06) >> 1) + 5;
00502 #else
00503         *lvp = 8;
00504 #endif
00505         break;
00506 
00507     case UART_SETPARITY:
00508         UartAvrDisable(devnum);
00509 #ifdef UCSR1C
00510         if (bv <= 2) {
00511             if (bv == 1)
00512                 bv = 3;
00513             bv <<= 4;
00514             if (devnum)
00515                 UCSR1C = (UCSR1C & 0xCF) | bv;
00516             else
00517                 UCSR0C = (UCSR0C & 0xCF) | bv;
00518         } else
00519             rc = -1;
00520 #endif
00521         if (bv)
00522             rc = -1;
00523         UartAvrEnable(devnum);
00524         break;
00525 
00526     case UART_GETPARITY:
00527 #ifdef UCSR1C
00528         if (devnum)
00529             bv = (UCSR1C & 0x30) >> 4;
00530         else
00531             bv = (UCSR0C & 0x30) >> 4;
00532         if (bv == 3)
00533             bv = 1;
00534 #else
00535         bv = 0;
00536 #endif
00537         break;
00538 
00539     case UART_SETSTOPBITS:
00540         UartAvrDisable(devnum);
00541 #ifdef UCSR1C
00542         if (bv == 1 || bv == 2) {
00543             bv = (bv - 1) << 3;
00544             if (devnum)
00545                 UCSR1C = (UCSR1C & 0xF7) | bv;
00546             else
00547                 UCSR0C = (UCSR0C & 0xF7) | bv;
00548         } else
00549             rc = -1;
00550 #else
00551         if (bv != 1)
00552             rc = -1;
00553 #endif
00554         UartAvrEnable(devnum);
00555         break;
00556 
00557     case UART_GETSTOPBITS:
00558 #ifdef UCSR1C
00559         if (devnum)
00560             *lvp = ((UCSR1C & 0x08) >> 3) + 1;
00561         else
00562             *lvp = ((UCSR0C & 0x08) >> 3) + 1;
00563 #else
00564         *lvp = 1;
00565 #endif
00566         break;
00567 
00568     case UART_GETSTATUS:
00569         UartAvrGetStatus(dev, lvp);
00570         break;
00571     case UART_SETSTATUS:
00572         rc = -1;
00573         break;
00574 
00575     case UART_SETREADTIMEOUT:
00576         dcb->dcb_rtimeout = lv;
00577         break;
00578     case UART_GETREADTIMEOUT:
00579         *lvp = dcb->dcb_rtimeout;
00580         break;
00581 
00582     case UART_SETWRITETIMEOUT:
00583         dcb->dcb_wtimeout = lv;
00584         break;
00585     case UART_GETWRITETIMEOUT:
00586         *lvp = dcb->dcb_wtimeout;
00587         break;
00588 
00589     case UART_SETLOCALECHO:
00590         if (bv)
00591             dcb->dcb_modeflags |= UART_MF_LOCALECHO;
00592         else
00593             dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
00594         break;
00595     case UART_GETLOCALECHO:
00596         if (dcb->dcb_modeflags & UART_MF_LOCALECHO)
00597             *lvp = 1;
00598         else
00599             *lvp = 0;
00600         break;
00601 
00602     case UART_SETFLOWCONTROL:
00603         if (bv)
00604             dcb->dcb_modeflags |= UART_MF_LOCALECHO;
00605         else
00606             dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
00607         break;
00608     case UART_GETFLOWCONTROL:
00609         break;
00610 
00611     case UART_SETCOOKEDMODE:
00612         if (bv)
00613             dcb->dcb_modeflags |= UART_MF_COOKEDMODE;
00614         else
00615             dcb->dcb_modeflags &= ~UART_MF_COOKEDMODE;
00616         break;
00617     case UART_GETCOOKEDMODE:
00618         if (dcb->dcb_modeflags & UART_MF_COOKEDMODE)
00619             *lvp = 1;
00620         else
00621             *lvp = 0;
00622         break;
00623 
00624     default:
00625         rc = -1;
00626         break;
00627     }
00628     return rc;
00629 }
00630 
00641 int UartAvrInit(NUTDEVICE * dev)
00642 {
00643     IFSTREAM *ifs;
00644     UARTDCB *dcb;
00645     uint32_t baudrate = 9600;
00646 
00647     /*
00648      * We only support character devices for on-chip UARTs.
00649      */
00650     if (dev->dev_type != IFTYP_STREAM || dev->dev_irq != 0 ||
00651         (dev->dev_base != 0 && dev->dev_base != 1))
00652         return -1;
00653 
00654     /*
00655      * Initialize interface control block.
00656      */
00657     ifs = dev->dev_icb;
00658     memset(ifs, 0, sizeof(IFSTREAM));
00659     ifs->if_input = UartAvrInput;
00660     ifs->if_output = UartAvrOutput;
00661     ifs->if_flush = UartAvrFlush;
00662 
00663     /*
00664      * Initialize driver control block.
00665      */
00666     dcb = dev->dev_dcb;
00667     memset(dcb, 0, sizeof(UARTDCB));
00668     dcb->dcb_modeflags = UART_MF_NOBUFFER;
00669 
00670     /*
00671      * Register interrupt handler.
00672      */
00673     if (dev->dev_base) {
00674 #ifdef UDR1
00675         if (NutRegisterIrqHandler(&sig_UART1_RECV, RxComplete, dev))
00676             return -1;
00677         if (NutRegisterIrqHandler(&sig_UART1_TRANS, TxComplete, dev))
00678 #endif
00679             return -1;
00680     } else {
00681         if (NutRegisterIrqHandler(&sig_UART0_RECV, RxComplete, dev))
00682             return -1;
00683         if (NutRegisterIrqHandler(&sig_UART0_TRANS, TxComplete, dev))
00684             return -1;
00685     }
00686 
00687     /*
00688      * Set baudrate and handshake default. This will also
00689      * enable the UART functions.
00690      */
00691     UartAvrIOCtl(dev, UART_SETSPEED, &baudrate);
00692 
00693     return 0;
00694 }
00695 
00699 int UartAvrRead(NUTFILE * fp, void *buffer, int size)
00700 {
00701     int rc;
00702     NUTDEVICE *dev;
00703     IFSTREAM *ifs;
00704     UARTDCB *dcb;
00705     uint8_t elmode;
00706     uint8_t ch;
00707     uint8_t *cp = buffer;
00708 
00709     dev = fp->nf_dev;
00710     ifs = (IFSTREAM *) dev->dev_icb;
00711     dcb = dev->dev_dcb;
00712 
00713     if (dcb->dcb_modeflags & UART_MF_COOKEDMODE)
00714         elmode = 1;
00715     else
00716         elmode = 0;
00717 
00718     /*
00719      * Call without data pointer discards receive buffer.
00720      */
00721     if (buffer == 0) {
00722         ifs->if_rd_idx = ifs->if_rx_idx;
00723         return 0;
00724     }
00725 
00726     /*
00727      * Get characters from receive buffer.
00728      */
00729     for (rc = 0; rc < size;) {
00730         if (ifs->if_rd_idx == ifs->if_rx_idx) {
00731             if (rc)
00732                 break;
00733             while (ifs->if_rd_idx == ifs->if_rx_idx) {
00734                 if (UartAvrInput(dev)) {
00735                     return 0;
00736                 }
00737             }
00738         }
00739         ch = ifs->if_rx_buf[ifs->if_rd_idx++];
00740         if (elmode && (ch == '\r' || ch == '\n')) {
00741             if (ifs->if_last_eol == 0 || ifs->if_last_eol == ch) {
00742                 ifs->if_last_eol = ch;
00743                 *cp++ = '\n';
00744                 rc++;
00745             }
00746         } else {
00747             ifs->if_last_eol = 0;
00748             *cp++ = ch;
00749             rc++;
00750         }
00751     }
00752     return rc;
00753 }
00754 
00758 int UartAvrPut(NUTDEVICE * dev, CONST void *buffer, int len, int pflg)
00759 {
00760     int rc;
00761     IFSTREAM *ifs;
00762     UARTDCB *dcb;
00763     CONST uint8_t *cp;
00764     uint8_t lbmode;
00765     uint8_t elmode;
00766     uint8_t ch;
00767 
00768     ifs = dev->dev_icb;
00769     dcb = dev->dev_dcb;
00770 
00771     if (dcb->dcb_modeflags & UART_MF_LINEBUFFER)
00772         lbmode = 1;
00773     else
00774         lbmode = 0;
00775 
00776     if (dcb->dcb_modeflags & UART_MF_COOKEDMODE)
00777         elmode = 1;
00778     else
00779         elmode = 0;
00780 
00781     /*
00782      * Call without data pointer starts transmission.
00783      */
00784     if (buffer == 0) {
00785         rc = UartAvrFlush(dev);
00786         return rc;
00787     }
00788 
00789     /*
00790      * Put characters in transmit buffer.
00791      */
00792     cp = buffer;
00793     for (rc = 0; rc < len;) {
00794         if ((uint8_t) (ifs->if_wr_idx + 1) == ifs->if_tx_idx) {
00795             if (UartAvrFlush(dev)) {
00796                 return -1;
00797             }
00798         }
00799         ch = pflg ? PRG_RDB(cp) : *cp;
00800         if (elmode == 1 && ch == '\n') {
00801             elmode = 2;
00802             if (lbmode == 1)
00803                 lbmode = 2;
00804             ch = '\r';
00805         } else {
00806             if (elmode == 2)
00807                 elmode = 1;
00808             cp++;
00809             rc++;
00810         }
00811         ifs->if_tx_buf[ifs->if_wr_idx++] = ch;
00812     }
00813 
00814     if (lbmode > 1 || (dcb->dcb_modeflags & UART_MF_NOBUFFER) != 0) {
00815         if (UartAvrFlush(dev))
00816             rc = -1;
00817     }
00818     return rc;
00819 }
00820 
00821 int UartAvrWrite(NUTFILE * fp, CONST void *buffer, int len)
00822 {
00823     return UartAvrPut(fp->nf_dev, buffer, len, 0);
00824 }
00825 
00826 int UartAvrWrite_P(NUTFILE * fp, PGM_P buffer, int len)
00827 {
00828     return UartAvrPut(fp->nf_dev, (CONST char *) buffer, len, 1);
00829 }
00830 
00831 
00835 NUTFILE *UartAvrOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00836 {
00837     NUTFILE *fp = NutHeapAlloc(sizeof(NUTFILE));
00838     UARTDCB *dcb;
00839 
00840     if (fp == 0)
00841         return NUTFILE_EOF;
00842 
00843     dcb = dev->dev_dcb;
00844     if (mode & _O_BINARY)
00845         dcb->dcb_modeflags &= ~UART_MF_COOKEDMODE;
00846     else
00847         dcb->dcb_modeflags |= UART_MF_COOKEDMODE;
00848 
00849     fp->nf_next = 0;
00850     fp->nf_dev = dev;
00851     fp->nf_fcb = 0;
00852 
00853     return fp;
00854 }
00855 
00859 int UartAvrClose(NUTFILE * fp)
00860 {
00861     NutHeapFree(fp);
00862 
00863     return 0;
00864 }
00865 
00869 long UartAvrSize(NUTFILE * fp)
00870 {
00871     NUTDEVICE *dev;
00872     IFSTREAM *ifs;
00873 
00874     dev = fp->nf_dev;
00875     ifs = (IFSTREAM *) dev->dev_icb;
00876     return ((uint8_t)(ifs->if_rx_idx - ifs->if_rd_idx));
00877 }
00878 
00879