Nut/OS  4.10.3
API Reference
usartsc16is752.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
00003  * Copyright (C) 2009 by Rittal GmbH & Co. KG. All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00022  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  *
00033  */
00034 
00035 /*
00036  * $Log$
00037  *
00038  * Revision 1.0  2009/04/13 ulrichprinz
00039  * First checkin, new twi driver for SC16IS752 dual usart chip
00040  * (currently SAM7X256 is tested only)
00041  *
00042  */
00043 
00044 
00045 // #define PRINT_DEBUG
00046 #if defined (PRINT_DEBUG)
00047 #include <stdio.h>
00048 
00049 /*
00050 
00051 #define MYPRINT(fmt, ...) printf ("%s:%s(%d)\t" fmt "\n", \
00052                                        __FILE__,__FUNCTION__,__LINE__, ##__VA_ARGS__);
00053 */
00054 #define MYPRINT(fmt, ...) printf ("%s(%d)\t" fmt "\n", \
00055                                        __FUNCTION__,__LINE__, ##__VA_ARGS__);
00056 
00057 
00058 #else
00059 #define MYPRINT(fmt, ...)
00060 #endif
00061 
00062 // #include <assert.h>
00063 #include <cfg/clock.h>
00064 
00065 #include <sys/atom.h>
00066 #include <sys/event.h>
00067 #include <sys/timer.h>
00068 
00069 #include <dev/irqreg.h>
00070 
00071 #include <dev/usartsc16is752.h>
00072 
00073 #include <dev/twif.h>
00074 
00079 
00080 #ifdef US_OVRE
00081 #undef US_OVRE
00082 #endif
00083 #define US_OVRE                 0x00000020      
00086 /* \brief ASCII code for software flow control, starts transmitter. */
00087 #define ASCII_XON   0x11
00088 /* \brief ASCII code for software flow control, stops transmitter. */
00089 #define ASCII_XOFF  0x13
00090 
00091 /* \brief XON transmit pending flag. */
00092 #define XON_PENDING     0x10
00093 /* \brief XOFF transmit pending flag. */
00094 #define XOFF_PENDING    0x20
00095 /* \brief XOFF sent flag. */
00096 #define XOFF_SENT       0x40
00097 /* \brief XOFF received flag. */
00098 #define XOFF_RCVD       0x80
00099 
00100 
00101 int Sc16is752RegWrite(uint8_t dev, uint8_t ch, uint8_t reg, uint8_t val);
00102 int Sc16is752RegRead(uint8_t dev, uint8_t ch, uint8_t reg, uint8_t *val);
00103 
00104 static int setBaudrate(uint8_t dev, uint8_t ch, int baud);
00105 int selectRegisterSet(uint8_t dev, uint8_t ch, uint8_t reg);
00106 static uint8_t selectSpecialRegisterSet(uint8_t dev, uint8_t ch);
00107 static uint8_t selectEnhancedRegisterSet(uint8_t dev, uint8_t ch);
00108 static uint8_t selectDefaultRegisterSet(uint8_t dev, uint8_t ch);
00109 static uint8_t switchEnhancedFunctions(uint8_t dev, uint8_t ch, uint8_t flag);
00110 static uint8_t switchTcrTlrSelect(uint8_t dev, uint8_t ch, uint8_t flag);
00111 static int Sc16is752RegRawRead(uint8_t dev, uint8_t ch, uint8_t reg, uint8_t *val);
00112 static int Sc16is752RegRawWrite(uint8_t dev, uint8_t ch, uint8_t reg, uint8_t val);
00113 
00114 
00118 static ureg_t rx_errors;
00119 
00123 static uint_fast8_t flow_control;
00124 
00128 //static uint_fast8_t tx_aframe;
00129 
00130 
00131 //#if defined(UART_RTS_BIT) || defined(US_MODE_HWHANDSHAKE)
00138 //static uint_fast8_t rts_control;
00139 //#endif
00140 
00141 //#if defined(UART_CTS_BIT) || defined(US_MODE_HWHANDSHAKE)
00148 //static uint_fast8_t cts_sense;
00149 //#endif
00150 
00152 static HANDLE irqEvents[DEV_MAX];
00153 static NUTDEVICE *deviceList[DEV_MAX][CH_MAX];
00154 
00155 /*
00156  * \brief USARTn transmitter ready interrupt handler.
00157  *
00158  * \param rbf Pointer to the transmitter ring buffer.
00159  */
00160 static void Sc16is752UsartTxReady(uint8_t dev, uint8_t ch, RINGBUF *rbf)
00161 {
00162     register uint8_t *cp = rbf->rbf_tail;
00163     uint8_t v;
00164 //
00165 //     /*
00166 //      * Process pending software flow controls first.
00167 //      */
00168 //     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00169 //         if (flow_control & XON_PENDING) {
00170 //             outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00171 //             flow_control |= XOFF_SENT;
00172 //         } else {
00173 //             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
00174 //             flow_control &= ~XOFF_SENT;
00175 //         }
00176 //         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00177 //         return;
00178 //     }
00179 //
00180 //     if (flow_control & XOFF_RCVD) {
00181 //         /*
00182 //          * If XOFF has been received, we disable the transmit interrupts
00183 //          * and return without sending anything.
00184 //          */
00185 //         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00186 //         return;
00187 //      }
00188 //
00189     if (rbf->rbf_cnt) {
00190 //
00191 // #ifdef UART_CTS_BIT
00192 //         /*
00193 //          * If CTS has been disabled, we disable the transmit interrupts
00194 //          * and return without sending anything.
00195 //          */
00196 //         if (cts_sense && bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00197 //             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00198 //             sbi(EIMSK, UART_CTS_BIT);
00199 //             return;
00200 //         }
00201 // #endif
00202         rbf->rbf_cnt--;
00203 
00204 //         /*
00205 //          * Send address in multidrop mode.
00206 //          */
00207 //         if (tx_aframe) {
00208 //             outr(USARTn_BASE + US_CR_OFF, US_SENDA);
00209 //         }
00210 //
00211         /*
00212          * Start transmission of the next character.
00213          */
00214                 Sc16is752RegWrite(dev, ch, THR, *cp);
00215                 MYPRINT("sended %c\n",*cp);
00216                 NutMicroDelay(500);
00217         /*
00218          * Wrap around the buffer pointer if we reached its end.
00219          */
00220         if (++cp == rbf->rbf_last) {
00221             cp = rbf->rbf_start;
00222         }
00223         rbf->rbf_tail = cp;
00224         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00225             NutEventPost(&rbf->rbf_que);
00226         }
00227     }
00228 
00229     /*
00230      * Nothing left to transmit, disable 'THR empty' interrupt.
00231      */
00232     else {
00233                 Sc16is752RegRead(dev, ch, IER, &v);
00234                 v &= ~(1<<1);
00235                 Sc16is752RegWrite(dev, ch, IER, v);
00236         rbf->rbf_cnt = 0;
00237         NutEventPost(&rbf->rbf_que);
00238     }
00239 }
00240 
00241 
00242 /*
00243  * \brief USARTn receiver ready interrupt handler.
00244  *
00245  *
00246  * \param rbf Pointer to the receiver ring buffer.
00247  */
00248 
00249 static void Sc16is752UsartRxReady(uint8_t dev, uint8_t ch, RINGBUF *rbf)
00250 {
00251     register size_t cnt;
00252     uint8_t c, e;
00253 
00254     /*
00255      * We read the received character as early as possible to avoid overflows
00256      * caused by interrupt latency.
00257      */
00258     Sc16is752RegRead(dev, ch, RHR, &c);
00259 //printf("r:%c\n", (char)c);
00260     /* Collect receiver errors. */
00261     Sc16is752RegRead(dev, ch, LSR, &e);
00262 
00263     rx_errors |= e & ((1<<3) | (1<<2) | (1<<1));  // Framing, parity, overrun error
00264 
00265 //     /*
00266 //      * Handle software handshake. We have to do this before checking the
00267 //      * buffer, because flow control must work in write-only mode, where
00268 //      * there is no receive buffer.
00269 //      */
00270 //     if (flow_control) {
00271 //         /* XOFF character disables transmit interrupts. */
00272 //         if (c == ASCII_XOFF) {
00273 //             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00274 //             flow_control |= XOFF_RCVD;
00275 //             return;
00276 //         }
00277 //         /* XON enables transmit interrupts. */
00278 //         else if (c == ASCII_XON) {
00279 //             outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00280 //             flow_control &= ~XOFF_RCVD;
00281 //             return;
00282 //         }
00283 //     }
00284 
00285     /*
00286      * Check buffer overflow.
00287      */
00288     cnt = rbf->rbf_cnt;
00289     if (cnt >= rbf->rbf_siz) {
00290         rx_errors |= US_OVRE;
00291         return;
00292     }
00293 
00294     /* Wake up waiting threads if this is the first byte in the buffer. */
00295     if (cnt++ == 0){
00296         NutEventPost(&rbf->rbf_que);
00297     }
00298 
00299 //     /*
00300 //      * Check the high watermark for software handshake. If the number of
00301 //      * buffered bytes is above this mark, then send XOFF.
00302 //      */
00303 //     else if (flow_control) {
00304 //         if(cnt >= rbf->rbf_hwm) {
00305 //             if((flow_control & XOFF_SENT) == 0) {
00306 //                 if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00307 //                     outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00308 //                     flow_control |= XOFF_SENT;
00309 //                     flow_control &= ~XOFF_PENDING;
00310 //                 } else {
00311 //                     flow_control |= XOFF_PENDING;
00312 //                 }
00313 //             }
00314 //         }
00315 //     }
00316 //
00317 // #ifdef UART_RTS_BIT
00318 //     /*
00319 //      * Check the high watermark for hardware handshake. If the number of
00320 //      * buffered bytes is above this mark, then disable RTS.
00321 //      */
00322 //     else if (rts_control && cnt >= rbf->rbf_hwm) {
00323 //         sbi(UART_RTS_PORT, UART_RTS_BIT);
00324 //     }
00325 // #endif
00326 
00327     /*
00328      * Store the character and increment and the ring buffer pointer.
00329      */
00330     *rbf->rbf_head++ = c;
00331     if (rbf->rbf_head == rbf->rbf_last) {
00332         rbf->rbf_head = rbf->rbf_start;
00333     }
00334 
00335     /* Update the ring buffer counter. */
00336     rbf->rbf_cnt = cnt;
00337 }
00338 
00339 
00340 
00341 void Sc16is752UsartProcessChannelInterrupt(uint8_t dev, uint8_t ch, uint8_t iir)
00342 {
00343     USARTDCB *dcb = deviceList[dev][ch]->dev_dcb;
00344     switch(iir)
00345     {
00346                 case 0x6:   // (0b00 0110) receiver line status Overrun Error (OE), Framing Error (FE), Parity Error
00347                                 // (PE), or Break Interrupt (BI) errors occur in characters in the RX FIFO
00348                         break;
00349                 case 0xc:   // (0b00 1100) RX time-out stale data in RX FIFO
00350                 //      break;
00351                 case 0x4:   // (0b00 0100) RHR interrupt receive data ready (FIFO disable) or
00352                                 // RX FIFO above trigger level (FIFO enable)
00353                         Sc16is752UsartRxReady(dev, ch, &dcb->dcb_rx_rbf);
00354                         break;
00355                 case 0x2:   // (0b00 0010) THR interrupt transmit FIFO empty (FIFO disable) or
00356                                 // TX FIFO passes above trigger level (FIFO enable)
00357                         Sc16is752UsartTxReady(dev, ch, &dcb->dcb_tx_rbf);
00358                         break;
00359                 case 0x0:   // (0b00 0000) modem status change of state of modem input pins
00360                         break;
00361                 case 0xe:   // (0b00 1110) I/O pins input pins change of state
00362                         break;
00363                 case 0x10:  // (0b01 0000) Xoff interrupt receive Xoff character(s)/special character
00364                         break;
00365                 case 0x20:  // (0b10 0000) CTS, RTS RTS pin or CTS pin change state from active (LOW)
00366                                 //to inactive (HIGH)
00367                         break;
00368     }
00369 }
00370 
00374 THREAD(Sc16is752UsartInterruptProcessing, arg)
00375 {
00376     uint8_t dev = (uint8_t)(((int)arg)&0xff);
00377     uint8_t iir;
00378     NutThreadSetPriority(50);
00379     for(;;)
00380     {
00381                 NutEventWait(&irqEvents[dev], NUT_WAIT_INFINITE);
00382                 MYPRINT("irq proccess\n");
00383                 Sc16is752RegRead(dev, 0, IIR, &iir);
00384                 MYPRINT("1\n");
00385                 if (!(iir&1))
00386                 {
00387                         MYPRINT("1\n");
00388                         Sc16is752UsartProcessChannelInterrupt(dev, 0, iir);
00389                 }
00390                 Sc16is752RegRead(dev, 1, IIR, &iir);
00391                 if (!(iir&1))
00392                 {
00393                         MYPRINT("1\n");
00394                         Sc16is752UsartProcessChannelInterrupt(dev, 1, iir);
00395                 }
00396     }
00397 }
00398 
00399 
00400 
00401 #if !defined(__linux__)
00402 
00407 static void Sc16is752UsartInterrupt(void *arg)
00408 {
00409      NUTDEVICE *nutDev= (NUTDEVICE *)arg;
00410      uint8_t dev = ((nutDev->dev_base)>>8) & 0xff;
00411         MYPRINT("irq\n");
00412      // Trigger interrupt processing thread (I2C access not allowed from ISR)
00413      NutEventPostFromIrq(&irqEvents[dev]);
00414 }
00415 #endif
00416 
00417 
00424 void Sc16is752UsartEnable(uint8_t dev, uint8_t ch)
00425 {
00426 #if defined(__linux__)
00427         printf("%s\n", __func__);
00428 #endif
00429 //     NutEnterCritical();
00430 //
00431 //     /* Enable UART receiver and transmitter. */
00432 //     outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
00433 //
00434 //     /* Enable UART receiver and transmitter interrupts. */
00435 //     outr(USARTn_BASE + US_IER_OFF, US_RXRDY | US_TXRDY);
00436 //     NutIrqEnable(&SIG_UART);
00437 //
00438 //     NutExitCritical();
00439 }
00440 
00441 
00445 void Sc16is752UsartDisable(uint8_t dev, uint8_t ch)
00446 {
00447 #if defined(__linux__)
00448         printf("%s\n", __func__);
00449 #endif
00450 //     /*
00451 //      * Disable USART interrupts.
00452 //      */
00453 //     NutEnterCritical();
00454 //     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
00455 //     NutExitCritical();
00456 //
00457 //     /*
00458 //      * Allow incoming or outgoing character to finish.
00459 //      */
00460 //     NutDelay(10);
00461 //
00462 //     /*
00463 //      * Disable USART transmit and receive.
00464 //      */
00465 //     outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
00466 }
00467 
00476 uint32_t Sc16is752UsartGetSpeed(uint8_t dev, uint8_t ch)
00477 {
00478 #if defined(__linux__)
00479         printf("%s\n", __func__);
00480 #endif
00481 //     ureg_t cs = inr(USARTn_BASE + US_MR_OFF);
00482 //     uint32_t clk;
00483 //
00484 //     clk = NutClockGet(NUT_HWCLK_PERIPHERAL);
00485 //     if ((cs & US_CLKS) == US_CLKS_MCK8) {
00486 //         clk /= 8;
00487 //     }
00488 //     else if ((cs & US_CLKS) != US_CLKS_MCK) {
00489 //         clk = 0;
00490 //     }
00491 //     return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
00492     return 0;
00493 }
00494 
00505 int Sc16is752UsartSetSpeed(uint32_t rate, uint8_t dev, uint8_t ch)
00506 {
00507 #if defined(__linux__)
00508         printf("%s\n", __func__);
00509 #endif
00510     Sc16is752UsartDisable(dev, ch);
00511 //     outr(USARTn_BASE + US_BRGR_OFF, (NutClockGet(NUT_HWCLK_PERIPHERAL) / (8 * (rate)) + 1) / 2);
00512     Sc16is752UsartEnable(dev, ch);
00513 
00514     return 0;
00515 }
00516 
00525 uint8_t Sc16is752UsartGetDataBits(uint8_t dev, uint8_t ch)
00526 {
00527 #if defined(__linux__)
00528         printf("%s\n", __func__);
00529 #endif
00530 //     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00531 //
00532 //     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00533 //         val = 9;
00534 //     }
00535 //     else {
00536 //         val &= US_CHRL;
00537 //         if (val == US_CHRL_5) {
00538 //             val = 5;
00539 //         }
00540 //         else if (val == US_CHRL_6) {
00541 //             val = 6;
00542 //         }
00543 //         else if (val == US_CHRL_7) {
00544 //             val = 7;
00545 //         }
00546 //         else {
00547 //             val = 8;
00548 //         }
00549 //     }
00550 //     return (uint8_t)val;
00551     return 0;
00552 }
00553 
00562 int Sc16is752UsartSetDataBits(uint8_t bits, uint8_t dev, uint8_t ch)
00563 {
00564 #if defined(__linux__)
00565         printf("%s\n", __func__);
00566 #endif
00567 //     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00568 //
00569 //     if (bits == 9) {
00570 //         val &= ~US_PAR;
00571 //         val |= US_PAR_MULTIDROP;
00572 //     }
00573 //     else {
00574 //         val &= ~US_CHRL;
00575 //         if (bits == 5) {
00576 //             val |= US_CHRL_5;
00577 //         }
00578 //         else if (bits == 6) {
00579 //             val |= US_CHRL_6;
00580 //         }
00581 //         else if (bits == 7) {
00582 //             val |= US_CHRL_7;
00583 //         }
00584 //         else if (bits == 8) {
00585 //             val |= US_CHRL_8;
00586 //         }
00587 //     }
00588 //
00589 //     At91UsartDisable();
00590 //     outr(USARTn_BASE + US_MR_OFF, val);
00591 //     At91UsartEnable();
00592 //
00593 //     /*
00594 //      * Verify the result.
00595 //      */
00596 //     if (At91UsartGetDataBits() != bits) {
00597 //         return -1;
00598 //     }
00599     return 0;
00600 }
00601 
00610 uint8_t Sc16is752UsartGetParity(uint8_t dev, uint8_t ch)
00611 {
00612 #if defined(__linux__)
00613         printf("%s\n", __func__);
00614 #endif
00615 //     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
00616 //
00617 //     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00618 //         val = 9;
00619 //     }
00620 //     else {
00621 //         if (val == US_PAR_ODD) {
00622 //             val = 1;
00623 //         }
00624 //         else if (val == US_PAR_EVEN) {
00625 //             val = 2;
00626 //         }
00627 //         else {
00628 //             val = 0;
00629 //         }
00630 //     }
00631 //     return (uint8_t)val;
00632     return 0;
00633 }
00634 
00645 int Sc16is752UsartSetParity(uint8_t mode, uint8_t dev, uint8_t ch)
00646 {
00647 #if defined(__linux__)
00648         printf("%s\n", __func__);
00649 #endif
00650 //     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
00651 //
00652 //     switch (mode) {
00653 //     case 0:
00654 //         val |= US_PAR_NO;
00655 //         break;
00656 //     case 1:
00657 //         val |= US_PAR_ODD;
00658 //         break;
00659 //     case 2:
00660 //         val |= US_PAR_EVEN;
00661 //         break;
00662 //     }
00663 //     At91UsartDisable();
00664 //     outr(USARTn_BASE + US_MR_OFF, val);
00665 //     At91UsartEnable();
00666 //
00667 //     /*
00668 //      * Verify the result.
00669 //      */
00670 //     if (At91UsartGetParity() != mode) {
00671 //         return -1;
00672 //     }
00673     return 0;
00674 }
00675 
00684 uint8_t Sc16is752UsartGetStopBits(uint8_t dev, uint8_t ch)
00685 {
00686 #if defined(__linux__)
00687         printf("%s\n", __func__);
00688 #endif
00689 //     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
00690 //     if (val == US_NBSTOP_1) {
00691 //         val = 1;
00692 //     }
00693 //     else if (val == US_NBSTOP_2) {
00694 //         val = 2;
00695 //     }
00696 //     else {
00697 //         val = 3;
00698 //     }
00699 //     return (uint8_t)val;
00700     return 0;
00701 }
00702 
00711 int Sc16is752UsartSetStopBits(uint8_t bits, uint8_t dev, uint8_t ch)
00712 {
00713 #if defined(__linux__)
00714         printf("%s\n", __func__);
00715 #endif
00716 //     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
00717 //
00718 //     switch(bits) {
00719 //     case 1:
00720 //         val |= US_NBSTOP_1;
00721 //         break;
00722 //     case 2:
00723 //         val |= US_NBSTOP_2;
00724 //         break;
00725 //     case 3:
00726 //         val |= US_NBSTOP_1_5;
00727 //         break;
00728 //     }
00729 //     At91UsartDisable();
00730 //     outr(USARTn_BASE + US_MR_OFF, val);
00731 //     At91UsartEnable();
00732 //
00733 //     /*
00734 //      * Verify the result.
00735 //      */
00736 //     if (At91UsartGetStopBits() != bits) {
00737 //         return -1;
00738 //     }
00739     return 0;
00740 }
00741 
00747 uint32_t Sc16is752UsartGetStatus(uint8_t dev, uint8_t ch)
00748 {
00749     uint32_t rc = 0;
00750 #if defined(__linux__)
00751         printf("%s\n", __func__);
00752 #endif
00753 //     /*
00754 //      * Set receiver error flags.
00755 //      */
00756 //     if ((rx_errors & US_FRAME) != 0) {
00757 //         rc |= UART_FRAMINGERROR;
00758 //     }
00759 //     if ((rx_errors & US_OVRE) != 0) {
00760 //         rc |= UART_OVERRUNERROR;
00761 //     }
00762 //     if ((rx_errors & US_PARE) != 0) {
00763 //         rc |= UART_PARITYERROR;
00764 //     }
00765 //
00766 //     /*
00767 //      * Determine software handshake status. The flow control status may
00768 //      * change during interrupt, but this doesn't really hurt us.
00769 //      */
00770 //     if (flow_control) {
00771 //         if (flow_control & XOFF_SENT) {
00772 //             rc |= UART_RXDISABLED;
00773 //         }
00774 //         if (flow_control & XOFF_RCVD) {
00775 //             rc |= UART_TXDISABLED;
00776 //         }
00777 //     }
00778 //
00779 //     /*
00780 //      * Determine hardware handshake control status.
00781 //      */
00782 //
00783 //     /*
00784 //      * Determine hardware handshake sense status.
00785 //      */
00786 //
00787 //     /*
00788 //      * Determine hardware modem sense status.
00789 //      */
00790 //
00791 //     /*
00792 //      * If transmitter and receiver haven't been detected disabled by any
00793 //      * of the checks above, then they are probably enabled.
00794 //      */
00795 //     if ((rc & UART_RXDISABLED) == 0) {
00796 //         rc |= UART_RXENABLED;
00797 //     }
00798 //     if ((rc & UART_TXDISABLED) == 0) {
00799 //         rc |= UART_TXENABLED;
00800 //     }
00801 //
00802 //     /*
00803 //      * Process multidrop setting.
00804 //      */
00805 //     if (tx_aframe) {
00806 //         rc |= UART_TXADDRFRAME;
00807 //     } else {
00808 //         rc |= UART_TXNORMFRAME;
00809 //     }
00810     return rc;
00811 }
00812 
00820 int Sc16is752UsartSetStatus(uint32_t flags, uint8_t dev, uint8_t ch)
00821 {
00822 #if defined(__linux__)
00823         printf("%s\n", __func__);
00824 #endif
00825 //     /*
00826 //      * Process software handshake control.
00827 //      */
00828 //     if (flow_control) {
00829 //
00830 //         /* Access to the flow control status must be atomic. */
00831 //         NutEnterCritical();
00832 //
00833 //         /*
00834 //          * Enabling or disabling the receiver means to behave like
00835 //          * having sent a XON or XOFF character resp.
00836 //          */
00837 //         if (flags & UART_RXENABLED) {
00838 //             flow_control &= ~XOFF_SENT;
00839 //         } else if (flags & UART_RXDISABLED) {
00840 //             flow_control |= XOFF_SENT;
00841 //         }
00842 //
00843 //         /*
00844 //          * Enabling or disabling the transmitter means to behave like
00845 //          * having received a XON or XOFF character resp.
00846 //          */
00847 //         if (flags & UART_TXENABLED) {
00848 //             flow_control &= ~XOFF_RCVD;
00849 //         } else if (flags & UART_TXDISABLED) {
00850 //             flow_control |= XOFF_RCVD;
00851 //         }
00852 //         NutExitCritical();
00853 //     }
00854 //
00855 //     /*
00856 //      * Process hardware handshake control.
00857 //      */
00858 //
00859 //     /*
00860 //      * Process hardware modem control.
00861 //      */
00862 //
00863 //     /*
00864 //      * Process multidrop setting.
00865 //      */
00866 //     if (flags & UART_TXADDRFRAME) {
00867 //         tx_aframe = 1;
00868 //     }
00869 //     if (flags & UART_TXNORMFRAME) {
00870 //         tx_aframe = 0;
00871 //     }
00872 //
00873 //     /*
00874 //      * Clear UART receive errors.
00875 //      */
00876 //     if (flags & UART_ERRORS) {
00877 //         outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
00878 //     }
00879 //
00880 //     /*
00881 //      * Verify the result.
00882 //      */
00883 //     if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
00884 //         return -1;
00885 //     }
00886     return 0;
00887 }
00888 
00898 uint8_t Sc16is752UsartGetClockMode(uint8_t dev, uint8_t ch)
00899 {
00900     uint8_t rc = 0;
00901 #if defined(__linux__)
00902         printf("%s\n", __func__);
00903 #endif
00904 
00905     return rc;
00906 }
00907 
00919 int Sc16is752UsartSetClockMode(uint8_t mode, uint8_t dev, uint8_t ch)
00920 {
00921 #if defined(__linux__)
00922         printf("%s\n", __func__);
00923 #endif
00924     /*
00925      * Verify the result.
00926      */
00927     if (Sc16is752UsartGetClockMode(dev, ch) != mode) {
00928         return -1;
00929     }
00930     return 0;
00931 }
00932 
00941 uint32_t Sc16is752UsartGetFlowControl(uint8_t dev, uint8_t ch)
00942 {
00943     uint32_t rc = 0;
00944 #if defined(__linux__)
00945         printf("%s\n", __func__);
00946 #endif
00947 
00948     if (flow_control) {
00949         rc |= USART_MF_XONXOFF;
00950     } else {
00951         rc &= ~USART_MF_XONXOFF;
00952     }
00953 
00954 
00955     return rc;
00956 }
00957 
00968 int Sc16is752UsartSetFlowControl(uint32_t flags, uint8_t dev, uint8_t ch)
00969 {
00970 #if defined(__linux__)
00971         printf("%s\n", __func__);
00972 #endif
00973     /*
00974      * Set software handshake mode.
00975      */
00976 
00977 
00978     /*
00979      * Verify the result.
00980      */
00981     if (Sc16is752UsartGetFlowControl(dev, ch) != flags) {
00982         return -1;
00983     }
00984     return 0;
00985 }
00986 
00987 
00988 
00989 
00991 
00999 void Sc16is752UsartTxStart(uint8_t dev, uint8_t ch)
01000 {
01001     uint8_t ier;
01002 #if defined(__linux__)
01003         printf("%s\n", __func__);
01004 #endif
01005     /* Enable transmit interrupts. */
01007     Sc16is752RegRead(dev, ch, IER, &ier);
01008     ier |= (1<<1);
01009     Sc16is752RegWrite(dev, ch, IER, ier);
01010 }
01011 
01012 
01021 void Sc16is752UsartRxStart(uint8_t dev, uint8_t ch)
01022 {
01023 #if defined(__linux__)
01024         printf("%s\n", __func__);
01025 #endif
01026     /*
01027      * Do any required software flow control.
01028      */
01029 //     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01030 //         NutEnterCritical();
01031 //         if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
01032 //             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
01033 //             flow_control &= ~XON_PENDING;
01034 //         } else {
01035 //             flow_control |= XON_PENDING;
01036 //         }
01037 //         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01038 //         NutExitCritical();
01039 //     }
01040 }
01041 
01042 
01043 
01052 int Sc16is752UsartInit(uint8_t dev, uint8_t ch, NUTDEVICE *nutDev, IRQ_HANDLER *irq)
01053 {
01054 
01055     deviceList[dev][ch] = nutDev; // needs to be stored here for interrupt processing
01056     uint8_t ier;
01057 
01058 #if defined(__linux__)
01059         printf("%s\n", __func__);
01060 #endif
01061         MYPRINT("1\n");
01062     /*
01063      * Register receive and transmit interrupts.
01064      */
01065 
01066     // Register IRQ1 for dev=0 and IRQ1 for dev=1 and ch=0
01067     // This requires to keep the init sequence: ch=0, then ch=1
01068     // Deinit must happen vice versa: first ch=1, then ch=0
01069     if (ch==0)
01070     {
01071                 /* Start Message Handler Thread. */
01072                 char threadname[]="usartirq0";
01073                 threadname[8] = '0'+dev;  // Create unique name
01074                 MYPRINT("1\n");
01075                 if (NutThreadCreate(threadname, Sc16is752UsartInterruptProcessing, (void *)(int)dev, 512)==0)
01076                         return -1;
01077                 MYPRINT("1\n");
01078 #if !defined(__linux__)
01079                 if (NutRegisterIrqHandler(irq, Sc16is752UsartInterrupt, nutDev))
01080                 return -1;
01081                 NutIrqSetMode(irq, NUT_IRQMODE_FALLINGEDGE);
01082                 MYPRINT("1\n");
01083                 NutIrqEnable(irq);
01084 #endif
01085     }
01086 #if 1
01087 MYPRINT("1\n");
01088     /* Reset UART. */
01089 //TOE  Sc16is752RegWrite(dev, ch, IOControl, (1<<3));  // SW Reset
01090     /* Enable receive interrupts. */
01092     Sc16is752RegRead(dev, ch, IER, &ier);
01093         MYPRINT("ier:%d\n",ier);
01094     ier |= (1<<0);  // Enable Rx interrupt
01095         MYPRINT("ier:%d\n",ier);
01096     Sc16is752RegWrite(dev, ch, IER, ier);
01097 MYPRINT("1\n");
01098     /* Set initial baudrate */
01099     setBaudrate(dev, ch, INIT_BAUDRATE);
01100 MYPRINT("1\n");
01101     /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
01102     Sc16is752RegWrite(dev, ch, LCR, 3);
01103         MYPRINT("1\n");
01104 #endif
01105 #if 0
01106 {
01107 uint8_t reg;
01108         uint8_t val;
01109 
01110         /* This register causes trubble */
01111     /* Reset UART. */
01112 //      buf[0] = ( IOControl << 3 );
01113 //      buf[1] = 0x08;                                                                                          // Software reset
01114 //      TwMasterTransact( sla, buf, 2, 0, 0, 50 );
01115 
01116         reg = LCR & 0x1F;
01117         val = 0x80;                                                                                             // eable special registers
01118         Sc16is752RegRawWrite( dev, ch, reg, val );
01119 
01120     /* Set initial baudrate */
01121         // div = 3; // XTAL / INIT_BAUDRATE / 16;
01122 
01123         reg = DLL & 0x1F;
01124         val = 3; // div & 0xff;
01125         Sc16is752RegRawWrite( dev, ch, reg, val );
01126         reg = DLH & 0x1F;
01127         val = 0; //div >> 8;                                                                                    // set baud rate
01128         Sc16is752RegRawWrite( dev, ch, reg, val );
01129 
01130         /* Set 8N1 */
01131         reg = LCR & 0x1F;
01132         val = 0x03;                                                                                             // 8N1
01133         Sc16is752RegRawWrite( dev, ch, reg, val );
01134     // ensure clock divisor is off
01135 
01136         reg = FCR & 0x1F;
01137         val = 0x01;                                                                                             // FIFO enable
01138         Sc16is752RegRawWrite( dev, ch, reg, val );
01139 
01140         reg = IER & 0x1F;
01141         val = 0x05;                                                                                             // FIFO enable
01142         Sc16is752RegRawWrite( dev, ch, reg, val );
01143         MYPRINT("val:%d\n",val);
01144 }
01145 #endif
01146 
01147 
01148 
01149     return 0;
01150 }
01151 
01160 int Sc16is752UsartDeinit(uint8_t dev, uint8_t ch, IRQ_HANDLER *irq)
01161 {
01162 #if defined(__linux__)
01163         printf("%s\n", __func__);
01164 #endif
01165     /* Reset UART (this implicitely disables all interrupts). */
01166 //TOE    Sc16is752RegWrite(dev, ch, IOControl, (1<<3));  // SW Reset
01167 
01168     /* Deregister receive and transmit interrupts. */
01169     // unregister interrupt,
01170     if (ch==0)
01171     {
01172 #if !defined(__linux__)
01173         NutRegisterIrqHandler(irq, 0, 0);
01174 #endif
01175     }
01176 
01177 
01178     return 0;
01179 }
01180 
01181 
01183 #if 1
01184 int setBaudrate(uint8_t dev, uint8_t ch, int baud)
01185 {
01186     uint8_t v;
01187 #if defined(__linux__)
01188         printf("%s\n", __func__);
01189 #endif
01190     // ensure clock divisor is off
01191     Sc16is752RegRead(dev, ch, MCR, &v);
01192     v &= ~(1<<8);
01193     Sc16is752RegWrite(dev, ch, MCR, v);
01194     // set baudrate
01195 
01196     int div = XTAL / baud / 16;
01197         Sc16is752RegRead(dev, ch, LCR, &v);
01198 
01199         Sc16is752RegWrite(dev, ch, LCR, 0x80);
01200     Sc16is752RegWrite(dev, ch, DLL, div & 0xff);
01201     Sc16is752RegWrite(dev, ch, DLH, div >> 8);
01202         Sc16is752RegWrite(dev, ch, LCR, v);
01203          return 0;
01204 }
01205 #endif
01206 
01207 /*
01208  * I2C register access wrapper
01209  */
01210 
01211 
01212 static regselstate_t regselState[DEV_MAX][CH_MAX] = { {{0,0}, {0,0}}, {{0,0}, {0,0}}};
01213 
01214 static uint8_t i2caddr[DEV_MAX] =
01215 {
01216     USART_DEVICE0_I2C_ADDR,
01217     USART_DEVICE1_I2C_ADDR
01218 };
01219 
01220 
01221 
01222 int Sc16is752RegWrite(uint8_t dev, uint8_t ch, uint8_t reg, uint8_t val)
01223 {
01224     // check valid range of arguments
01225 //     assert(dev<=DEV_MAX);
01226 //     assert(ch<=CH_MAX);
01227 
01228         //selectRegisterSet(dev, ch, reg);
01229     // Now, perform the register access
01230     return Sc16is752RegRawWrite(dev, ch, reg, val);
01231 }
01232 
01233 int Sc16is752RegRead(uint8_t dev, uint8_t ch, uint8_t reg, uint8_t *val)
01234 {
01235     // check valid range of arguments
01236 //     assert(dev<=DEV_MAX);
01237 //     assert(ch<=CH_MAX);
01238 
01239  //   selectRegisterSet(dev, ch, reg);
01240     // Now, perform the register access
01241     return Sc16is752RegRawRead(dev, ch, reg, val);
01242 }
01243 
01244 
01245 
01246 /*****
01247  * Some Utility functions to select the different register sets
01248  */
01249 
01250 
01256 int selectRegisterSet(uint8_t dev, uint8_t ch, uint8_t reg)
01257 {
01258         MYPRINT("selectRegSet");
01259     switch(reg&REGSEL_MASK)
01260     {
01261         case DEFSEL:
01262             if(((reg==MSR) || (reg==SPR)) && regselState[dev][ch].flags & TCRBIT)
01263             {
01264                         MYPRINT("switchTcrTlrSelect\n");
01265                         // turn off TCR/TLR register mode
01266                         switchTcrTlrSelect(dev, ch, 0);
01267             }
01268             else if(regselState[dev][ch].state != DEFSEL)
01269             {
01270                         MYPRINT("selectDefaultRegisterSet\n");
01271                         // select default register set
01272                         selectDefaultRegisterSet(dev, ch);
01273             }
01274         case TCRSEL:
01275                 MYPRINT("switchTcrTlrSelect\n");
01276             // select TCR/TLR registers
01277             switchTcrTlrSelect(dev, ch, 1);
01278             break;
01279         case SRSSEL:
01280                 MYPRINT("selectSpecialRegisterSet\n");
01281             // select Special Registers (DLL/DLH)
01282             selectSpecialRegisterSet(dev, ch);
01283             break;
01284         case ERSSEL:
01285                 MYPRINT("selectEnhancedRegisterSet\n");
01286             // select Enhanced Registers (EFR; XONx, XOFFx)
01287             selectEnhancedRegisterSet(dev, ch);
01288             break;
01289 
01290     }
01291     return 0;
01292 }
01293 
01294 
01301 static uint8_t selectSpecialRegisterSet(uint8_t dev, uint8_t ch)
01302 {
01303     uint8_t v;
01304     Sc16is752RegRawRead(dev, ch, LCR, &v);
01305     Sc16is752RegRawWrite(dev, ch, LCR, 0x80);
01306     regselState[dev][ch].state = SRSSEL;
01307     return v;
01308 }
01309 
01316 static uint8_t selectEnhancedRegisterSet(uint8_t dev, uint8_t ch)
01317 {
01318     uint8_t v=0;
01319     Sc16is752RegRawRead(dev, ch, LCR, &v);
01320     Sc16is752RegRawWrite(dev, ch, LCR, 0xbf);
01321     regselState[dev][ch].state = ERSSEL;
01322     return v;
01323 }
01324 
01330 static uint8_t selectDefaultRegisterSet(uint8_t dev, uint8_t ch)
01331 {
01332     uint8_t v=0;
01333     Sc16is752RegRawRead(dev, ch, LCR, &v);
01334     v &= 0x7f;   // turn off 'divisor latch enable' bit
01335     Sc16is752RegRawWrite(dev, ch, LCR, v);
01336     regselState[dev][ch].state = DEFSEL;
01337     return v;
01338 }
01339 
01346 static uint8_t switchEnhancedFunctions(uint8_t dev, uint8_t ch, uint8_t flag)
01347 {
01348     uint8_t oldLcr;
01349     uint8_t v=0;
01350     oldLcr = selectEnhancedRegisterSet(dev, ch);
01351     Sc16is752RegRawRead(dev, ch, EFR, &v);
01352     if(flag)
01353     {
01354                 v |= (1<<4);   // switch on enhanced functions bit
01355                 regselState[dev][ch].flags |= EEFBIT;
01356     }
01357     else
01358     {
01359                 v &= ~(1<<4);   // switch off enhanced functions bit
01360                 regselState[dev][ch].flags &= ~EEFBIT;
01361     }
01362     Sc16is752RegRawWrite(dev, ch, EFR, v);
01363     Sc16is752RegRawWrite(dev, ch, LCR, oldLcr);  // select original register set
01364     return 0;
01365 }
01366 
01367 
01368 static uint8_t switchTcrTlrSelect(uint8_t dev, uint8_t ch, uint8_t flag)
01369 {
01370     uint8_t v=0;
01371     switchEnhancedFunctions(dev, ch, 1);
01372     Sc16is752RegRawRead(dev, ch, MCR, &v);
01373     if(flag)
01374     {
01375                 v |= (1<<2);   // switch on TCR/TLR enable
01376                 regselState[dev][ch].flags |= TCRBIT;
01377     }
01378     else
01379     {
01380                 v &= ~(1<<2);   // switch off TCR/TLR enable
01381                 regselState[dev][ch].flags &= ~TCRBIT;
01382     }
01383     Sc16is752RegRawWrite(dev, ch, MCR, v);
01384     return 0;
01385 }
01386 
01387 
01388 static int Sc16is752RegRawWrite(uint8_t dev, uint8_t ch, uint8_t reg, uint8_t val)
01389 {
01390     uint8_t wbuf[2];
01391     wbuf[0] = REGADDR(reg & 0xf, ch);
01392     wbuf[1] = val;
01393 #if defined(__linux__)
01394     printf("%s(%d,%d,0x%02x,0x%02x) => slave addr:0x%02x data 0x%02x\n",
01395                  __func__, dev, ch, reg, val, i2caddr[dev], wbuf[0]);
01396         return 0;
01397 #else
01398          MYPRINT("%s(%d,%d,0x%02x,0x%02x) => slave addr:0x%02x data 0x%02x\n",
01399                  __func__, dev, ch, reg, val, i2caddr[dev], wbuf[0]);
01400 #endif
01401     return TwMasterTransact(i2caddr[dev], wbuf, 2, 0, 0, 0);
01402 }
01403 
01404 static int Sc16is752RegRawRead(uint8_t dev, uint8_t ch, uint8_t reg, uint8_t *val)
01405 {
01406     uint8_t wbuf, rc;
01407 
01408     wbuf = REGADDR(reg & 0xf, ch);
01409 #if defined(__linux__)
01410     printf("%s(%d,%d,0x%02x) => slave addr:0x%02x data 0x%02x\n",
01411                  __func__, dev, ch, reg, i2caddr[dev], wbuf);
01412         return 0;
01413 #else
01414   //  return TwMasterTransact(i2caddr[dev], wbuf, 1, val, 1, 0);
01415          rc = TwMasterRegRead (i2caddr[dev], wbuf, 1, val, 1, 0);
01416          MYPRINT("%s(%d,%d,0x%02x,0x%02x) => slave addr:0x%02x data 0x%02x\n",
01417                  __func__, dev, ch, reg, *val, i2caddr[dev], wbuf);
01418         return rc;
01419 #endif
01420 }
01421 
01422