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

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/