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 #include <cfg/ahdlc.h>
00057
00058 #include <string.h>
00059 #include <stdlib.h>
00060 #include <fcntl.h>
00061
00062 #include <sys/nutconfig.h>
00063 #include <sys/atom.h>
00064 #include <sys/heap.h>
00065 #include <sys/event.h>
00066 #include <sys/timer.h>
00067 #include <sys/thread.h>
00068
00069 #include <dev/irqreg.h>
00070 #include <dev/ppp.h>
00071
00072 #include <netinet/if_ppp.h>
00073 #include <net/ppp.h>
00074 #include <net/if_var.h>
00075
00076 #include <dev/usartat91.h>
00077 #include <dev/at91_ahdlc.h>
00078
00079
00080 #ifndef NUT_AHDLC_RECV_DMA_SIZE
00081 #define NUT_AHDLC_RECV_DMA_SIZE 64
00082 #endif
00083
00084
00085 static unsigned char DMA_RxBuf0[NUT_AHDLC_RECV_DMA_SIZE];
00086
00087 #define UART_RECEIVER_TIMEOUT 32
00088
00089 #define SIG_UART sig_UART1
00090 #define US_ID US1_ID
00091 #define US_GPIO_PINS 0x00000360
00092
00093
00094
00099
00100 static AHDLCDCB dcb_ahdlc;
00101
00108 NUTDEVICE devAhdlc1 = {
00109 0,
00110 {'u', 'a', 'r', 't', '1', 0, 0, 0, 0},
00111 IFTYP_CHAR,
00112 1,
00113 0,
00114 0,
00115 &dcb_ahdlc,
00116 AhdlcAt91Init,
00117 AhdlcAt91IOCtl,
00118 AhdlcAt91Read,
00119 AhdlcAt91Write,
00120 AhdlcAt91Open,
00121 AhdlcAt91Close,
00122 0
00123 };
00124
00125
00126
00127
00128
00129 static prog_char fcstab[512] = {
00130 0x00, 0x00, 0x11, 0x89, 0x23, 0x12, 0x32, 0x9b, 0x46, 0x24, 0x57, 0xad, 0x65, 0x36, 0x74, 0xbf,
00131 0x8c, 0x48, 0x9d, 0xc1, 0xaf, 0x5a, 0xbe, 0xd3, 0xca, 0x6c, 0xdb, 0xe5, 0xe9, 0x7e, 0xf8, 0xf7,
00132 0x10, 0x81, 0x01, 0x08, 0x33, 0x93, 0x22, 0x1a, 0x56, 0xa5, 0x47, 0x2c, 0x75, 0xb7, 0x64, 0x3e,
00133 0x9c, 0xc9, 0x8d, 0x40, 0xbf, 0xdb, 0xae, 0x52, 0xda, 0xed, 0xcb, 0x64, 0xf9, 0xff, 0xe8, 0x76,
00134 0x21, 0x02, 0x30, 0x8b, 0x02, 0x10, 0x13, 0x99, 0x67, 0x26, 0x76, 0xaf, 0x44, 0x34, 0x55, 0xbd,
00135 0xad, 0x4a, 0xbc, 0xc3, 0x8e, 0x58, 0x9f, 0xd1, 0xeb, 0x6e, 0xfa, 0xe7, 0xc8, 0x7c, 0xd9, 0xf5,
00136 0x31, 0x83, 0x20, 0x0a, 0x12, 0x91, 0x03, 0x18, 0x77, 0xa7, 0x66, 0x2e, 0x54, 0xb5, 0x45, 0x3c,
00137 0xbd, 0xcb, 0xac, 0x42, 0x9e, 0xd9, 0x8f, 0x50, 0xfb, 0xef, 0xea, 0x66, 0xd8, 0xfd, 0xc9, 0x74,
00138
00139 0x42, 0x04, 0x53, 0x8d, 0x61, 0x16, 0x70, 0x9f, 0x04, 0x20, 0x15, 0xa9, 0x27, 0x32, 0x36, 0xbb,
00140 0xce, 0x4c, 0xdf, 0xc5, 0xed, 0x5e, 0xfc, 0xd7, 0x88, 0x68, 0x99, 0xe1, 0xab, 0x7a, 0xba, 0xf3,
00141 0x52, 0x85, 0x43, 0x0c, 0x71, 0x97, 0x60, 0x1e, 0x14, 0xa1, 0x05, 0x28, 0x37, 0xb3, 0x26, 0x3a,
00142 0xde, 0xcd, 0xcf, 0x44, 0xfd, 0xdf, 0xec, 0x56, 0x98, 0xe9, 0x89, 0x60, 0xbb, 0xfb, 0xaa, 0x72,
00143 0x63, 0x06, 0x72, 0x8f, 0x40, 0x14, 0x51, 0x9d, 0x25, 0x22, 0x34, 0xab, 0x06, 0x30, 0x17, 0xb9,
00144 0xef, 0x4e, 0xfe, 0xc7, 0xcc, 0x5c, 0xdd, 0xd5, 0xa9, 0x6a, 0xb8, 0xe3, 0x8a, 0x78, 0x9b, 0xf1,
00145 0x73, 0x87, 0x62, 0x0e, 0x50, 0x95, 0x41, 0x1c, 0x35, 0xa3, 0x24, 0x2a, 0x16, 0xb1, 0x07, 0x38,
00146 0xff, 0xcf, 0xee, 0x46, 0xdc, 0xdd, 0xcd, 0x54, 0xb9, 0xeb, 0xa8, 0x62, 0x9a, 0xf9, 0x8b, 0x70,
00147
00148 0x84, 0x08, 0x95, 0x81, 0xa7, 0x1a, 0xb6, 0x93, 0xc2, 0x2c, 0xd3, 0xa5, 0xe1, 0x3e, 0xf0, 0xb7,
00149 0x08, 0x40, 0x19, 0xc9, 0x2b, 0x52, 0x3a, 0xdb, 0x4e, 0x64, 0x5f, 0xed, 0x6d, 0x76, 0x7c, 0xff,
00150 0x94, 0x89, 0x85, 0x00, 0xb7, 0x9b, 0xa6, 0x12, 0xd2, 0xad, 0xc3, 0x24, 0xf1, 0xbf, 0xe0, 0x36,
00151 0x18, 0xc1, 0x09, 0x48, 0x3b, 0xd3, 0x2a, 0x5a, 0x5e, 0xe5, 0x4f, 0x6c, 0x7d, 0xf7, 0x6c, 0x7e,
00152 0xa5, 0x0a, 0xb4, 0x83, 0x86, 0x18, 0x97, 0x91, 0xe3, 0x2e, 0xf2, 0xa7, 0xc0, 0x3c, 0xd1, 0xb5,
00153 0x29, 0x42, 0x38, 0xcb, 0x0a, 0x50, 0x1b, 0xd9, 0x6f, 0x66, 0x7e, 0xef, 0x4c, 0x74, 0x5d, 0xfd,
00154 0xb5, 0x8b, 0xa4, 0x02, 0x96, 0x99, 0x87, 0x10, 0xf3, 0xaf, 0xe2, 0x26, 0xd0, 0xbd, 0xc1, 0x34,
00155 0x39, 0xc3, 0x28, 0x4a, 0x1a, 0xd1, 0x0b, 0x58, 0x7f, 0xe7, 0x6e, 0x6e, 0x5c, 0xf5, 0x4d, 0x7c,
00156
00157 0xc6, 0x0c, 0xd7, 0x85, 0xe5, 0x1e, 0xf4, 0x97, 0x80, 0x28, 0x91, 0xa1, 0xa3, 0x3a, 0xb2, 0xb3,
00158 0x4a, 0x44, 0x5b, 0xcd, 0x69, 0x56, 0x78, 0xdf, 0x0c, 0x60, 0x1d, 0xe9, 0x2f, 0x72, 0x3e, 0xfb,
00159 0xd6, 0x8d, 0xc7, 0x04, 0xf5, 0x9f, 0xe4, 0x16, 0x90, 0xa9, 0x81, 0x20, 0xb3, 0xbb, 0xa2, 0x32,
00160 0x5a, 0xc5, 0x4b, 0x4c, 0x79, 0xd7, 0x68, 0x5e, 0x1c, 0xe1, 0x0d, 0x68, 0x3f, 0xf3, 0x2e, 0x7a,
00161 0xe7, 0x0e, 0xf6, 0x87, 0xc4, 0x1c, 0xd5, 0x95, 0xa1, 0x2a, 0xb0, 0xa3, 0x82, 0x38, 0x93, 0xb1,
00162 0x6b, 0x46, 0x7a, 0xcf, 0x48, 0x54, 0x59, 0xdd, 0x2d, 0x62, 0x3c, 0xeb, 0x0e, 0x70, 0x1f, 0xf9,
00163 0xf7, 0x8f, 0xe6, 0x06, 0xd4, 0x9d, 0xc5, 0x14, 0xb1, 0xab, 0xa0, 0x22, 0x92, 0xb9, 0x83, 0x30,
00164 0x7b, 0xc7, 0x6a, 0x4e, 0x58, 0xd5, 0x49, 0x5c, 0x3d, 0xe3, 0x2c, 0x6a, 0x1e, 0xf1, 0x0f, 0x78
00165 };
00166
00170 #define IN_ACC_MAP(c, m) (( ((uint8_t) (c)) < 0x20) && ((m) & (1UL << (c))) != 0)
00171
00172 #ifndef NUT_THREAD_AHDLCRXSTACK
00173 #define NUT_THREAD_AHDLCRXSTACK 2048
00174 #endif
00175
00176
00177
00183 static void At91UsartInterrupt(void *arg)
00184 {
00185 AHDLCDCB *dcb = arg;
00186 uint16_t count, i;
00187 ureg_t csr = inr(US1_CSR);
00188
00189 if (csr & (US_ENDRX | US_RXBUFF | US_TIMEOUT)) {
00190
00191
00192 if (csr & US_TIMEOUT) {
00193 count = NUT_AHDLC_RECV_DMA_SIZE - inr(USART1_BASE + PERIPH_RCR_OFF);
00194 } else {
00195 count = NUT_AHDLC_RECV_DMA_SIZE;
00196 }
00197
00198 for (i = 0; i < count; i++) {
00199 dcb->dcb_rx_buf[dcb->dcb_rx_idx] = DMA_RxBuf0[i];
00200 dcb->dcb_rx_idx++;
00201 }
00202
00203 outr(USART1_BASE + PERIPH_RPR_OFF, (unsigned int) DMA_RxBuf0);
00204 outr(USART1_BASE + PERIPH_RCR_OFF, NUT_AHDLC_RECV_DMA_SIZE);
00205 outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTEN);
00206 outr(US1_CR, inr(US1_CR) | US_STTTO);
00207 NutEventPostFromIrq(&dcb->dcb_rx_rdy);
00208 }
00209
00210 if (csr & US_TXRDY) {
00211 if (dcb->dcb_tx_idx != dcb->dcb_wr_idx) {
00212 outr(US1_THR, dcb->dcb_tx_buf[dcb->dcb_tx_idx]);
00213 dcb->dcb_tx_idx++;
00214 } else {
00215 outr(US1_IDR, US_TXRDY);
00216 NutEventPostFromIrq(&dcb->dcb_tx_rdy);
00217 }
00218 }
00219
00220 }
00221
00222
00223
00224
00225
00226
00227 static int SendRawByte(AHDLCDCB * dcb, uint8_t ch, uint8_t flush)
00228 {
00229
00230
00231
00232
00233 while ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00234 if (NutEventWait(&dcb->dcb_tx_rdy, dcb->dcb_wtimeout))
00235 break;
00236 }
00237
00238
00239
00240
00241 if ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00242 return -1;
00243 }
00244
00245
00246
00247
00248
00249 dcb->dcb_tx_buf[dcb->dcb_wr_idx] = ch;
00250 dcb->dcb_wr_idx++;
00251
00252
00253
00254
00255
00256 if (flush || (uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00257
00258 NutEnterCritical();
00259
00260 outr(US1_IER, US_TXRDY);
00261
00262 NutExitCritical();
00263 }
00264 return 0;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273 static int SendHdlcData(AHDLCDCB * dcb, CONST uint8_t * data, uint16_t len, uint16_t * txfcs)
00274 {
00275 uint16_t tbx;
00276 uint16_t fcs;
00277
00278 if (txfcs)
00279 fcs = *txfcs;
00280 else
00281 fcs = 0;
00282
00283 while (len) {
00284 tbx = (uint16_t) ((uint8_t) fcs ^ *data) << 1;
00285 fcs >>= 8;
00286 fcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00287
00288 if (IN_ACC_MAP(*data, dcb->dcb_tx_accm) || *data == AHDLC_FLAG || *data == AHDLC_ESCAPE) {
00289 if (SendRawByte(dcb, AHDLC_ESCAPE, 0)) {
00290 return -1;
00291 }
00292 if (SendRawByte(dcb, *data ^ AHDLC_TRANS, 0)) {
00293 return -1;
00294 }
00295 } else if (SendRawByte(dcb, *data, 0)) {
00296 return -1;
00297 }
00298 data++;
00299 len--;
00300 }
00301 if (txfcs)
00302 *txfcs = fcs;
00303
00304 return 0;
00305 }
00306
00317 int AhdlcOutput(NUTDEVICE * dev, NETBUF * nb)
00318 {
00319 uint16_t txfcs;
00320 AHDLCDCB *dcb = dev->dev_dcb;
00321 uint16_t sz;
00322
00323
00324
00325
00326
00327 if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00328 return 0;
00329 }
00330
00331
00332
00333
00334
00335 sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
00336
00337 if (sz > dcb->dcb_tx_mru) {
00338 return -1;
00339 }
00340
00341
00342
00343
00344 SendRawByte(dcb, AHDLC_FLAG, 0);
00345
00346
00347 txfcs = AHDLC_INITFCS;
00348 if (SendHdlcData(dcb, nb->nb_dl.vp, nb->nb_dl.sz, &txfcs))
00349 return -1;
00350 if (SendHdlcData(dcb, nb->nb_nw.vp, nb->nb_nw.sz, &txfcs))
00351 return -1;
00352 if (SendHdlcData(dcb, nb->nb_tp.vp, nb->nb_tp.sz, &txfcs))
00353 return -1;
00354 if (SendHdlcData(dcb, nb->nb_ap.vp, nb->nb_ap.sz, &txfcs))
00355 return -1;
00356
00357
00358 txfcs ^= 0xffff;
00359 if (SendHdlcData(dcb, (uint8_t *) & txfcs, 2, 0))
00360 return -1;
00361
00362 SendRawByte(dcb, AHDLC_FLAG, 1);
00363
00364 return 0;
00365 }
00366
00373 THREAD(AhdlcRx, arg)
00374 {
00375 NUTDEVICE *dev = arg;
00376 NUTDEVICE *netdev;
00377 AHDLCDCB *dcb = dev->dev_dcb;
00378 IFNET *ifn;
00379 NETBUF *nb;
00380 uint8_t *rxbuf;
00381 uint8_t *rxptr;
00382 uint16_t rxcnt;
00383 uint8_t ch;
00384 uint16_t tbx;
00385 uint8_t inframe;
00386 uint8_t escaped;
00387 uint16_t rxfcs;
00388
00389 NutThreadSetPriority(9);
00390 for (;;) {
00391
00392
00393
00394 rxptr = 0;
00395 rxcnt = 0;
00396 escaped = 0;
00397 rxfcs = AHDLC_INITFCS;
00398 inframe = 0;
00399
00400 for (;;) {
00401
00402
00403
00404
00405
00406
00407
00408 while ((netdev = dev->dev_icb) == 0) {
00409 if (NutEventWait(&dcb->dcb_mf_evt, 1000) == 0) {
00410 NutSleep(100);
00411 }
00412 }
00413 ifn = netdev->dev_icb;
00414 dcb->dcb_rtimeout = 1000;
00415 inframe = 0;
00416
00417
00418
00419
00420
00421
00422 if ((rxbuf = NutHeapAlloc(dcb->dcb_rx_mru)) != 0) {
00423 break;
00424 }
00425 NutSleep(1000);
00426 }
00427
00428
00429
00430
00431 ifn->if_send = AhdlcOutput;
00432 netdev->dev_ioctl(netdev, LCP_LOWERUP, 0);
00433
00434 for (;;) {
00435
00436
00437
00438
00439 while (dcb->dcb_rd_idx == dcb->dcb_rx_idx) {
00440 if (dev->dev_icb == 0)
00441 break;
00442
00443 if (NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout)) {
00444 continue;
00445 }
00446 }
00447
00448
00449
00450
00451 if (dev->dev_icb == 0)
00452 break;
00453
00454
00455
00456
00457
00458 if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00459
00460
00461
00462
00463
00464 NutSleep(100);
00465 continue;
00466 }
00467
00468
00469
00470
00471 ch = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
00472
00473 if (inframe) {
00474 if (ch != AHDLC_FLAG) {
00475 if (ch == AHDLC_ESCAPE) {
00476 escaped = 1;
00477 continue;
00478 }
00479 if (escaped) {
00480 ch ^= AHDLC_TRANS;
00481 escaped = 0;
00482 }
00483
00484
00485
00486
00487
00488
00489 if (rxcnt++ < dcb->dcb_rx_mru) {
00490
00491 tbx = (uint16_t) ((uint8_t) rxfcs ^ ch) << 1;
00492 rxfcs >>= 8;
00493 rxfcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00494 *rxptr++ = ch;
00495 } else
00496 inframe = 0;
00497 continue;
00498 }
00499
00500 if (rxcnt > 6 && rxfcs == AHDLC_GOODFCS) {
00501
00502
00503
00504
00505 rxcnt -= 2;
00506 if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, rxcnt)) != 0) {
00507 memcpy(nb->nb_dl.vp, rxbuf, rxcnt);
00508 (*ifn->if_recv) (netdev, nb);
00509 }
00510 }
00511 }
00512
00513
00514
00515
00516 if (ch == AHDLC_FLAG) {
00517 inframe = 1;
00518 escaped = 0;
00519 rxptr = rxbuf;
00520 rxcnt = 0;
00521 rxfcs = AHDLC_INITFCS;
00522 }
00523 }
00524
00525
00526
00527 netdev->dev_ioctl(netdev, LCP_LOWERDOWN, 0);
00528
00529
00530 if (rxbuf) {
00531 NutHeapFree(rxbuf);
00532 rxbuf = 0;
00533 }
00534 }
00535 }
00536
00537
00538
00539
00540
00541
00542 static int AhdlcAt91GetStatus(NUTDEVICE * dev, uint32_t * status)
00543 {
00544 AHDLCDCB *dcb = dev->dev_dcb;
00545
00546
00547 *status = 0;
00548
00549 #ifdef __AVR_ENHANCED__
00550 if (dev->dev_base) {
00551 #ifdef UART1_CTS_BIT
00552 if (bit_is_set(UART1_CTS_PIN, UART1_CTS_BIT))
00553 *status |= UART_CTSDISABLED;
00554 else
00555 *status |= UART_CTSENABLED;
00556 #endif
00557 #ifdef UART1_RTS_BIT
00558 if (bit_is_set(UART1_RTS_PORT, UART1_RTS_BIT))
00559 *status |= UART_RTSDISABLED;
00560 else
00561 *status |= UART_RTSENABLED;
00562 #endif
00563 #ifdef UART1_DTR_BIT
00564 if (bit_is_set(UART1_DTR_PORT, UART1_DTR_BIT))
00565 *status |= UART_DTRDISABLED;
00566 else
00567 *status |= UART_DTRENABLED;
00568 #endif
00569 us = inp(UCSR1A);
00570 } else
00571 #endif
00572 {
00573 #ifdef UART0_CTS_BIT
00574 if (bit_is_set(UART0_CTS_PIN, UART0_CTS_BIT))
00575 *status |= UART_CTSDISABLED;
00576 else
00577 *status |= UART_CTSENABLED;
00578 #endif
00579 #ifdef UART0_RTS_BIT
00580 if (bit_is_set(UART0_RTS_PORT, UART0_RTS_BIT))
00581 *status |= UART_RTSDISABLED;
00582 else
00583 *status |= UART_RTSENABLED;
00584 #endif
00585 #ifdef UART0_DTR_BIT
00586 if (bit_is_set(UART0_DTR_PORT, UART0_DTR_BIT))
00587 *status |= UART_DTRDISABLED;
00588 else
00589 *status |= UART_DTRENABLED;
00590 #endif
00591
00592 }
00593
00594
00595
00596
00597 if (dcb->dcb_tx_idx == dcb->dcb_wr_idx)
00598 *status |= UART_TXBUFFEREMPTY;
00599 if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00600 *status |= UART_RXBUFFEREMPTY;
00601
00602 return 0;
00603 }
00604
00605
00606
00607
00608
00609
00610 static int AhdlcAt91SetStatus(NUTDEVICE * dev, uint32_t status)
00611 {
00612
00613 #ifdef __AVR_ENHANCED__
00614 if (dev->dev_base) {
00615 #ifdef UART1_RTS_BIT
00616 if (status & UART_RTSDISABLED)
00617 sbi(UART1_RTS_PORT, UART1_RTS_BIT);
00618 else if (status & UART_RTSENABLED)
00619 cbi(UART1_RTS_PORT, UART1_RTS_BIT);
00620 #endif
00621 #ifdef UART1_DTR_BIT
00622 if (status & UART_DTRDISABLED)
00623 sbi(UART1_DTR_PORT, UART1_DTR_BIT);
00624 else if (status & UART_DTRENABLED)
00625 cbi(UART1_DTR_PORT, UART1_DTR_BIT);
00626 #endif
00627 } else
00628 #endif
00629 {
00630 #ifdef UART0_RTS_BIT
00631 if (status & UART_RTSDISABLED)
00632 sbi(UART0_RTS_PORT, UART0_RTS_BIT);
00633 else if (status & UART_RTSENABLED)
00634 cbi(UART0_RTS_PORT, UART0_RTS_BIT);
00635 #endif
00636 #ifdef UART0_DTR_BIT
00637 if (status & UART_DTRDISABLED)
00638 sbi(UART0_DTR_PORT, UART0_DTR_BIT);
00639 else if (status & UART_DTRENABLED)
00640 cbi(UART0_DTR_PORT, UART0_DTR_BIT);
00641 #endif
00642 }
00643 return 0;
00644 }
00645
00646
00647
00648
00649 static void AhdlcAt91Enable(uint16_t base)
00650 {
00651
00652 NutEnterCritical();
00653
00654 outr(US1_RTOR, UART_RECEIVER_TIMEOUT);
00655 outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTEN);
00656 outr(US1_CR, US_TXEN | US_RXEN | US_STTTO);
00657
00658
00659 outr(US1_IER, US_ENDRX | US_RXBUFF | US_TIMEOUT);
00660
00661 NutIrqEnable(&SIG_UART);
00662
00663 NutExitCritical();
00664 }
00665
00666
00667
00668
00669
00670 static void AhdlcAt91Disable(uint16_t base)
00671 {
00672
00673 NutEnterCritical();
00674
00675 NutIrqDisable(&SIG_UART);
00676
00677 outr(US1_IDR, -1);
00678 outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTDIS);
00679
00680 NutExitCritical();
00681
00682
00683
00684 NutDelay(10);
00685
00686
00687
00688
00689 outr(US1_CR, US_RXDIS | US_TXDIS);
00690 }
00691
00729 int AhdlcAt91IOCtl(NUTDEVICE * dev, int req, void *conf)
00730 {
00731 int rc = 0;
00732 AHDLCDCB *dcb;
00733 void **ppv = (void **) conf;
00734 uint32_t *lvp = (uint32_t *) conf;
00735 uint8_t bv;
00736 uint8_t devnum;
00737 ureg_t cs;
00738
00739 if (dev == 0) {
00740 dev = &devUsartAt910;
00741 }
00742
00743 devnum = dev->dev_base;
00744 dcb = dev->dev_dcb;
00745
00746 switch (req) {
00747
00748 case UART_SETSPEED:
00749
00750 AhdlcAt91Disable(dcb->dcb_base);
00751 #if defined(AT91_PLL_MAINCK)
00752 outr(USART1_BASE + US_BRGR_OFF, (At91GetMasterClock() / (8 * (*lvp)) + 1) / 2);
00753 #else
00754 outr(USART1_BASE + US_BRGR_OFF, (NutGetCpuClock() / (8 * (*lvp)) + 1) / 2);
00755 #endif
00756 AhdlcAt91Enable(dcb->dcb_base);
00757 break;
00758
00759 case UART_GETSPEED:
00760 cs = inr(USART1_BASE + US_MR_OFF);
00761 uint32_t clk;
00762 #if defined(AT91_PLL_MAINCK)
00763 clk = At91GetMasterClock();
00764 #else
00765 clk = NutGetCpuClock();
00766 #endif
00767 if ((cs & US_CLKS) == US_CLKS_MCK8) {
00768 clk /= 8;
00769 } else if ((cs & US_CLKS) != US_CLKS_MCK) {
00770 clk = 0;
00771 }
00772 *lvp = (clk / (16UL * (inr(USART1_BASE + US_BRGR_OFF) & 0xFFFF)));
00773 break;
00774
00775 case UART_GETSTATUS:
00776 AhdlcAt91GetStatus(dev, lvp);
00777 break;
00778 case UART_SETSTATUS:
00779 AhdlcAt91SetStatus(dev, *lvp);
00780 break;
00781
00782 case UART_SETREADTIMEOUT:
00783 dcb->dcb_rtimeout = *lvp;
00784 break;
00785 case UART_GETREADTIMEOUT:
00786 *lvp = dcb->dcb_rtimeout;
00787 break;
00788
00789 case UART_SETWRITETIMEOUT:
00790 dcb->dcb_wtimeout = *lvp;
00791 break;
00792 case UART_GETWRITETIMEOUT:
00793 *lvp = dcb->dcb_wtimeout;
00794 break;
00795
00796 case UART_SETLOCALECHO:
00797 bv = (uint8_t) (*lvp);
00798 if (bv)
00799 dcb->dcb_modeflags |= UART_MF_LOCALECHO;
00800 else
00801 dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
00802 break;
00803 case UART_GETLOCALECHO:
00804 if (dcb->dcb_modeflags & UART_MF_LOCALECHO)
00805 *lvp = 1;
00806 else
00807 *lvp = 0;
00808 break;
00809
00810 case UART_SETFLOWCONTROL:
00811 bv = (uint8_t) (*lvp);
00812 if (bv)
00813 dcb->dcb_modeflags |= UART_MF_LOCALECHO;
00814 else
00815 dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
00816 break;
00817 case UART_GETFLOWCONTROL:
00818 break;
00819
00820 case UART_SETRAWMODE:
00821 bv = (uint8_t) (*lvp);
00822 if (bv)
00823 dcb->dcb_modeflags |= UART_MF_RAWMODE;
00824 else
00825 dcb->dcb_modeflags &= ~UART_MF_RAWMODE;
00826 break;
00827
00828 case UART_GETRAWMODE:
00829 if (dcb->dcb_modeflags & UART_MF_RAWMODE)
00830 *lvp = 1;
00831 else
00832 *lvp = 0;
00833 break;
00834
00835 case HDLC_SETIFNET:
00836 if (ppv && (*ppv != 0)) {
00837 dev->dev_icb = *ppv;
00838 dev->dev_type = IFTYP_NET;
00839 NutEventPost(&dcb->dcb_mf_evt);
00840 } else {
00841
00842 dev->dev_type = IFTYP_CHAR;
00843
00844 if (dev->dev_icb != 0) {
00845 dev->dev_icb = 0;
00846
00847
00848
00849
00850 NutEventPost(&dcb->dcb_rx_rdy);
00851 }
00852 }
00853 break;
00854
00855 case HDLC_GETIFNET:
00856 *ppv = dev->dev_icb;
00857 break;
00858
00859 default:
00860 rc = -1;
00861 break;
00862 }
00863 return rc;
00864 }
00865
00866
00879 int AhdlcAt91Init(NUTDEVICE * dev)
00880 {
00881 int rc = 0;
00882 AHDLCDCB *dcb;
00883
00884
00885
00886 AhdlcAt91Disable(dev->dev_base);
00887
00888
00889 dcb = dev->dev_dcb;
00890 memset(dcb, 0, sizeof(AHDLCDCB));
00891 dcb->dcb_base = dev->dev_base;
00892 dcb->dcb_rx_buf = NutHeapAlloc(256);
00893 dcb->dcb_tx_buf = NutHeapAlloc(256);
00894 dcb->dcb_rx_mru = 1500;
00895 dcb->dcb_tx_mru = 1500;
00896 dcb->dcb_tx_accm = 0xFFFFFFFF;
00897
00898
00899 if (NutRegisterIrqHandler(&SIG_UART, At91UsartInterrupt, dcb)) {
00900 return -1;
00901 }
00902
00903 outr(PMC_PCER, _BV(US1_ID));
00904
00905 outr(PIOA_PDR, US_GPIO_PINS);
00906
00907
00908 outr(US1_CR, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
00909
00910 outr(US1_IDR, 0xFFFFFFFF);
00911
00912 #if defined (US_RCR_OFF)
00913 outr(US1_RCR, 0);
00914 #endif
00915 #if defined (US_TCR_OFF)
00916 outr(US1_TCR, 0);
00917 #endif
00918
00919 #if defined(AT91_PLL_MAINCK)
00920 outr(US1_BRGR, (At91GetMasterClock() / (8 * (115200)) + 1) / 2);
00921 #else
00922 outr(US1_BRGR, (NutGetCpuClock() / (8 * (115200)) + 1) / 2);
00923 #endif
00924
00925 outr(US1_MR, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1 | US_MODE_HWHANDSHAKE);
00926
00927
00928 outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTDIS);
00929 outr(USART1_BASE + PERIPH_RPR_OFF, (unsigned int) DMA_RxBuf0);
00930 outr(USART1_BASE + PERIPH_RCR_OFF, NUT_AHDLC_RECV_DMA_SIZE);
00931 outr(USART1_BASE + PERIPH_RNPR_OFF, 0);
00932 outr(USART1_BASE + PERIPH_RNCR_OFF, 0);
00933
00934
00935
00936
00937
00938 if (rc == 0 && NutThreadCreate("ahdlcrx", AhdlcRx, dev,
00939 (NUT_THREAD_AHDLCRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD)) {
00940
00941 return 0;
00942 }
00943
00944
00945 if (dcb->dcb_rx_buf)
00946 NutHeapFree((void *) dcb->dcb_rx_buf);
00947 if (dcb->dcb_tx_buf)
00948 NutHeapFree((void *) dcb->dcb_tx_buf);
00949
00950 return -1;
00951 }
00952
00953
00954
00955
00982 int AhdlcAt91Read(NUTFILE * fp, void *buffer, int size)
00983 {
00984 int rc = 0;
00985 AHDLCDCB *dcb = fp->nf_dev->dev_dcb;
00986 uint8_t *cp = buffer;
00987
00988
00989
00990
00991 if (buffer) {
00992 while (rc < size) {
00993 if (dcb->dcb_rd_idx != dcb->dcb_rx_idx) {
00994 *cp++ = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
00995 rc++;
00996 } else if (rc || NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout))
00997 break;
00998 }
00999 }
01000
01001
01002
01003
01004 else
01005 dcb->dcb_rd_idx = dcb->dcb_rx_idx;
01006
01007 return rc;
01008 }
01009
01022 int AhdlcAt91Put(NUTDEVICE * dev, CONST void *buffer, int len, int pflg)
01023 {
01024 int rc = 0;
01025 AHDLCDCB *dcb = dev->dev_dcb;
01026 CONST uint8_t *cp = buffer;
01027
01028
01029
01030
01031 if (buffer) {
01032 while (rc < len) {
01033 if (SendRawByte(dcb, pflg ? PRG_RDB(cp) : *cp, 0))
01034 break;
01035 cp++;
01036 rc++;
01037 }
01038 }
01039
01040
01041
01042
01043 else {
01044
01045 NutEnterCritical();
01046
01047 outr(US1_IER, US_TXRDY);
01048
01049 NutExitCritical();
01050 }
01051 return rc;
01052 }
01053
01073 int AhdlcAt91Write(NUTFILE * fp, CONST void *buffer, int len)
01074 {
01075 return AhdlcAt91Put(fp->nf_dev, buffer, len, 0);
01076 }
01077
01099 int AhdlcAt91Write_P(NUTFILE * fp, PGM_P buffer, int len)
01100 {
01101 return AhdlcAt91Put(fp->nf_dev, (CONST char *) buffer, len, 1);
01102 }
01103
01120 NUTFILE *AhdlcAt91Open(NUTDEVICE * dev, CONST char *name, int mode, int acc)
01121 {
01122 NUTFILE *fp;
01123
01124 if ((fp = NutHeapAlloc(sizeof(NUTFILE))) == 0)
01125 return NUTFILE_EOF;
01126
01127 fp->nf_next = 0;
01128 fp->nf_dev = dev;
01129 fp->nf_fcb = 0;
01130
01131 outr(US1_RTOR, UART_RECEIVER_TIMEOUT);
01132 outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTEN);
01133 outr(US1_CR, US_TXEN | US_RXEN | US_STTTO);
01134
01135
01136 outr(US1_IER, US_ENDRX | US_RXBUFF | US_TIMEOUT);
01137
01138 NutEnterCritical();
01139
01140 NutIrqEnable(&SIG_UART);
01141
01142 NutExitCritical();
01143
01144 return fp;
01145 }
01146
01160 int AhdlcAt91Close(NUTFILE * fp)
01161 {
01162 if (fp && fp != NUTFILE_EOF) {
01163 NutHeapFree(fp);
01164 return 0;
01165 }
01166 return -1;
01167 }
01168