Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
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
00104
00105
00106 #ifndef _IOFBF
00107 #define _IOFBF 0x00
00108 #define _IOLBF 0x01
00109 #define _IONBF 0x02
00110 #endif
00111
00116
00117
00118
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
00143
00144
00145
00146
00147
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
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
00197
00198
00199
00200
00201
00202
00203
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
00267
00268 if (UartAvrOutput(dev))
00269 return -1;
00270
00271
00272
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
00285
00286
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
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
00329
00330 static void UartAvrDisable(uint16_t base)
00331 {
00332
00333
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
00346
00347 NutDelay(10);
00348
00349
00350
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
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
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
00665
00666 dcb = dev->dev_dcb;
00667 memset(dcb, 0, sizeof(UARTDCB));
00668 dcb->dcb_modeflags = UART_MF_NOBUFFER;
00669
00670
00671
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
00689
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
00720
00721 if (buffer == 0) {
00722 ifs->if_rd_idx = ifs->if_rx_idx;
00723 return 0;
00724 }
00725
00726
00727
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
00783
00784 if (buffer == 0) {
00785 rc = UartAvrFlush(dev);
00786 return rc;
00787 }
00788
00789
00790
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