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