00001 /* 00002 * Copyright (C) 2002-2003 by Call Direct Cellular Solutions Pty. Ltd. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. All advertising materials mentioning features or use of this 00014 * software must display the following acknowledgement: 00015 * 00016 * This product includes software developed by Call Direct Cellular Solutions Pty. Ltd. 00017 * and its contributors. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY CALL DIRECT CELLULAR SOLUTIONS AND CONTRIBUTORS 00020 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00021 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00022 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CALL DIRECT 00023 * CELLULAR SOLUTIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00024 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00025 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00026 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00027 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00028 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00029 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00030 * SUCH DAMAGE. 00031 * 00032 * For additional information see http://www.calldirect.com.au/ 00033 * 00034 * - 00035 * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved. 00036 * 00037 * Redistribution and use in source and binary forms, with or without 00038 * modification, are permitted provided that the following conditions 00039 * are met: 00040 * 00041 * 1. Redistributions of source code must retain the above copyright 00042 * notice, this list of conditions and the following disclaimer. 00043 * 2. Redistributions in binary form must reproduce the above copyright 00044 * notice, this list of conditions and the following disclaimer in the 00045 * documentation and/or other materials provided with the distribution. 00046 * 3. All advertising materials mentioning features or use of this 00047 * software must display the following acknowledgement: 00048 * 00049 * This product includes software developed by egnite Software GmbH 00050 * and its contributors. 00051 * 00052 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00053 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00054 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00055 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00056 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00057 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00058 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00059 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00060 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00061 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00062 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00063 * SUCH DAMAGE. 00064 * 00065 * For additional information see http://www.ethernut.de/ 00066 * 00067 * - 00068 * Portions Copyright (C) 2000 David J. Hudson <dave@humbug.demon.co.uk> 00069 * 00070 * This file is distributed in the hope that it will be useful, but WITHOUT 00071 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00072 * FITNESS FOR A PARTICULAR PURPOSE. 00073 * 00074 * You can redistribute this file and/or modify it under the terms of the GNU 00075 * General Public License (GPL) as published by the Free Software Foundation; 00076 * either version 2 of the License, or (at your discretion) any later version. 00077 * See the accompanying file "copying-gpl.txt" for more details. 00078 * 00079 * As a special exception to the GPL, permission is granted for additional 00080 * uses of the text contained in this file. See the accompanying file 00081 * "copying-liquorice.txt" for details. 00082 * - 00083 * Portions Copyright (c) 1983, 1993 by 00084 * The Regents of the University of California. All rights reserved. 00085 * 00086 * Redistribution and use in source and binary forms, with or without 00087 * modification, are permitted provided that the following conditions 00088 * are met: 00089 * 1. Redistributions of source code must retain the above copyright 00090 * notice, this list of conditions and the following disclaimer. 00091 * 2. Redistributions in binary form must reproduce the above copyright 00092 * notice, this list of conditions and the following disclaimer in the 00093 * documentation and/or other materials provided with the distribution. 00094 * 3. All advertising materials mentioning features or use of this software 00095 * must display the following acknowledgement: 00096 * This product includes software developed by the University of 00097 * California, Berkeley and its contributors. 00098 * 4. Neither the name of the University nor the names of its contributors 00099 * may be used to endorse or promote products derived from this software 00100 * without specific prior written permission. 00101 * 00102 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00103 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00104 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00105 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00106 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00107 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00108 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00109 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00110 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00111 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00112 * SUCH DAMAGE. 00113 * - 00114 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 00115 * 00116 * Permission to use, copy, modify, and distribute this software for any 00117 * purpose with or without fee is hereby granted, provided that the above 00118 * copyright notice and this permission notice appear in all copies, and that 00119 * the name of Digital Equipment Corporation not be used in advertising or 00120 * publicity pertaining to distribution of the document or software without 00121 * specific, written prior permission. 00122 * 00123 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 00124 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 00125 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 00126 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 00127 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 00128 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 00129 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00130 * SOFTWARE. 00131 */ 00132 00133 /* 00134 * $Log: cs8900.c,v $ 00135 * Revision 1.3 2008/08/11 06:59:14 haraldkipp 00136 * BSD types replaced by stdint types (feature request #1282721). 00137 * 00138 * Revision 1.2 2006/10/08 16:48:07 haraldkipp 00139 * Documentation fixed 00140 * 00141 * Revision 1.1 2005/07/26 18:02:27 haraldkipp 00142 * Moved from dev. 00143 * 00144 * Revision 1.9 2005/04/30 16:42:41 chaac 00145 * Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If NUTDEBUG 00146 * is defined in NutConf, it will make effect where it is used. 00147 * 00148 * Revision 1.8 2004/05/26 09:40:30 olereinhardt 00149 * Changed reading of packet length / receive status to be compatible with 00150 * newer AVRGCC versions. (Need to read high byte first!) 00151 * 00152 * Added software reset / wakeup routine to init code. (only avalilable in new code) 00153 * 00154 * Revision 1.7 2004/05/25 11:39:47 olereinhardt 00155 * Define NUT_CS8900_OLD to get the old functionality back again 00156 * 00157 * Revision 1.6 2004/05/24 17:09:17 olereinhardt 00158 * Changed base address handling in cs8900.c and moved cs8900.h to /include/dev 00159 * Base address can now be passed to the nic driver by NutRegisterDevice. 00160 * Removed some Assembler code in cs8900.c 00161 * 00162 * Added some databus waitstate settings for the upper half of the address space in os/arch/avr_nutinit.c. Now three waitstates are default for 0x8000-0xFFFF 00163 * 00164 * Added terminal device driver for hd44780 compatible LCD displays directly 00165 * connected to the memory bus (memory mapped). See hd44780.c for more information. 00166 * Therefore some minor changed in include/dev/term.h and dev/term.c are needet to 00167 * pass a base address to the lcd driver. 00168 * 00169 * Revision 1.5 2004/03/18 14:06:52 haraldkipp 00170 * Deprecated header file replaced 00171 * 00172 * Revision 1.4 2003/10/13 10:13:49 haraldkipp 00173 * First release 00174 * 00175 * Revision 1.3 2003/08/05 20:11:30 haraldkipp 00176 * Removed from ICCAVR compilation 00177 * 00178 * Revision 1.2 2003/07/20 20:07:38 haraldkipp 00179 * Conflicting Ethernet driver routine names solved. 00180 * 00181 * Revision 1.1 2003/07/20 16:37:21 haraldkipp 00182 * CrystalTek 8900A driver added. 00183 * 00184 * 00185 * Revision 1.0 2002/03/28 MJC CDCS 00186 * Created 00187 * 00188 * Revision 1.1 2003/03/25 MJC CDCS 00189 * Modified behaviour when transmit buffer space unavailable 00190 * 00191 */ 00192 00193 /* Not ported. */ 00194 #ifdef __GNUC__ 00195 00196 #include <cfg/os.h> 00197 #include <string.h> 00198 #include <avr/interrupt.h> 00199 00200 #include <sys/heap.h> 00201 #include <sys/thread.h> 00202 #include <sys/event.h> 00203 #include <sys/timer.h> 00204 #include <sys/confnet.h> 00205 00206 #include <dev/nicrtl.h> 00207 #include <netinet/if_ether.h> 00208 #include <net/ether.h> 00209 #include <net/if_var.h> 00210 #include <netinet/ip.h> 00211 00212 #include <dev/irqreg.h> 00213 #include "cs8900.h" 00214 00215 #ifdef NUTDEBUG 00216 #include <sys/osdebug.h> 00217 #include <net/netdebug.h> 00218 #endif 00219 00224 00225 00226 // Ethernet flags byte 00227 // Bit 0 = transmit byte flag 00228 uint8_t cs_flags; 00229 volatile uint16_t cs_base = 0x0000; 00230 00231 00232 void CSWrite16(uint16_t addr, uint16_t data) 00233 { 00234 uint16_t *p; 00235 00236 p = (uint16_t *) addr; 00237 cli(); 00238 *p = data; 00239 sei(); 00240 } 00241 00242 void CSWritePP16(uint16_t addr, uint16_t data) 00243 { 00244 uint16_t *p; 00245 00246 cli(); 00247 p = (uint16_t *) CS_PP_PTR; 00248 *p = addr; 00249 00250 CSWrite16(CS_PP_DATA0, data); 00251 00252 return; 00253 } 00254 00255 uint16_t CSRead16(uint16_t addr) 00256 { 00257 uint16_t *p; 00258 uint16_t d; 00259 00260 cli(); 00261 p = (uint16_t *) addr; 00262 d = *p; 00263 sei(); 00264 00265 return d; 00266 } 00267 00268 uint16_t CSReadPP16(uint16_t addr) 00269 { 00270 uint16_t *p; 00271 00272 cli(); 00273 p = (uint16_t *) CS_PP_PTR; 00274 *p = addr; 00275 00276 return CSRead16(CS_PP_DATA0); 00277 } 00278 00279 uint32_t CSReadPP32(u_int addr) 00280 { 00281 uint32_t l; 00282 uint32_t *p; 00283 00284 cli(); 00285 p = (uint32_t *) CS_PP_PTR; 00286 *p = addr; 00287 p = (uint32_t *) CS_PP_DATA0; 00288 l = *p; 00289 sei(); 00290 00291 return l; 00292 } 00293 00294 00295 00296 void CSBeginFrame(void) 00297 { 00298 cs_flags &= ~1; 00299 } 00300 00301 void CSEndFrame(void) 00302 { 00303 uint8_t *p; 00304 00305 cli(); 00306 p = (uint8_t *) CS_DATA_P0 + 1; 00307 sei(); 00308 00309 // If odd number of bytes in packet pad it out 00310 if (cs_flags & 1) 00311 p = 0; 00312 } 00313 00314 void CSWriteFrameByte(uint8_t data) 00315 { 00316 uint8_t *p; 00317 00318 if (cs_flags & 1) 00319 p = (uint8_t *) CS_DATA_P0 + 1; 00320 else 00321 p = (uint8_t *) CS_DATA_P0; 00322 00323 *p = data; 00324 cs_flags ^= 1; 00325 } 00326 00327 static int CSEthPutPacket(NUTDEVICE * dev, NETBUF * nb) 00328 { 00329 uint16_t i; 00330 uint16_t sz; 00331 uint8_t *p; 00332 NICINFO *ni; 00333 00334 ni = (NICINFO *) dev->dev_dcb; 00335 00336 // 00337 // Calculate the number of bytes to be send. Do not 00338 // send packets larger than 1536 bytes. 00339 // 00340 sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz; 00341 if (sz >= 0x600) { 00342 NutNetBufFree(nb); 00343 return -1; 00344 } 00345 #if 0 00346 if (tcp_trace) { 00347 NutPrintFormat_P(dev_debug, PSTR("[ETHTX-%u]\r\n"), sz); 00348 NutPrintFlush(dev_debug); 00349 } 00350 #endif 00351 00352 // Start transmission after entire frame is loaded into CS8900 00353 CSWrite16(CS_TX_CMD_I, 0xC0); 00354 // Set frame size 00355 CSWrite16(CS_TX_LEN_I, sz); 00356 00357 // Wait for buffer space, but only for a while (200ms) 00358 // If the cable is disconnected this will never become true 00359 // If we don't get the go ahead within 200ms return 0 (Sucess) 00360 // And let the upper layers deal with re-transmission 00361 // If we return failure TCP sockets will close straight away which probably 00362 // isn't the correct behaviour 00363 i = 0; 00364 while ((CSReadPP16(CS_BUS_STAT) & 0x0100) == 0) { 00365 i++; 00366 if (i > 20) 00367 return 0; 00368 NutSleep(10); 00369 } 00370 00371 // 00372 // Transfer ethernet physical header. 00373 // 00374 CSBeginFrame(); 00375 00376 p = nb->nb_dl.vp; 00377 for (i = 0; i < nb->nb_dl.sz; i++) { 00378 CSWriteFrameByte(*p++); 00379 } 00380 00381 00382 p = nb->nb_nw.vp; 00383 for (i = 0; i < nb->nb_nw.sz; i++) { 00384 CSWriteFrameByte(*p++); 00385 } 00386 00387 p = nb->nb_tp.vp; 00388 for (i = 0; i < nb->nb_tp.sz; i++) { 00389 CSWriteFrameByte(*p++); 00390 } 00391 00392 p = nb->nb_ap.vp; 00393 for (i = 0; i < nb->nb_ap.sz; i++) { 00394 CSWriteFrameByte(*p++); 00395 } 00396 00397 CSEndFrame(); 00398 00399 return 0; 00400 } 00401 00416 int CSNicOutput(NUTDEVICE * dev, NETBUF * nb) 00417 { 00418 int rc = -1; 00419 NICINFO *ni; 00420 00421 ni = (NICINFO *) dev->dev_dcb; 00422 00423 #if 0 00424 if (tcp_trace) { 00425 NutPrintFormat_P(dev_debug, PSTR("Enter EthOutput\r\n")); 00426 NutPrintFlush(dev_debug); 00427 } 00428 #endif 00429 00430 if ((rc = CSEthPutPacket(dev, nb)) == 0) 00431 ni->ni_tx_packets++; 00432 00433 return rc; 00434 } 00435 00436 00437 00438 00439 00447 THREAD(CSNICrx, arg) 00448 { 00449 NUTDEVICE *dev; 00450 IFNET *ifn; 00451 NICINFO *ni; 00452 NETBUF *nb; 00453 uint8_t *p; 00454 uint8_t *q; 00455 uint16_t i, m; 00456 volatile uint16_t l; 00457 00458 dev = arg; 00459 ifn = (IFNET *) dev->dev_icb; 00460 ni = (NICINFO *) dev->dev_dcb; 00461 00462 #if 0 00463 if (tcp_trace) { 00464 NutPrintFormat_P(dev_debug, PSTR("Enter ETHReceive\r\n")); 00465 NutPrintFlush(dev_debug); 00466 } 00467 #endif 00468 00469 l = 0; 00470 00471 NutThreadSetPriority(8); 00472 for (;;) { 00473 while ((CSReadPP16(CS_RX_EVENT) & 0x0100) == 0) { 00474 NutSleep(10); 00475 } 00476 00477 #ifdef NUT_CS8900_OLD 00478 // Get the RxStatus But don't let the compiler do any optomisation 00479 asm volatile ("lds __tmp_reg__, %3" "\n\t" 00480 "mov %B0, __tmp_reg__" "\n\t" "lds __tmp_reg__, %2" "\n\t" "mov %A0, __tmp_reg__" "\n\t":"=r" (l) 00481 :"0"(l), "n"((unsigned short) (CS_DATA_P0)), "n"((unsigned short) (CS_DATA_P0 + 1)) 00482 ); 00483 00484 // Get the Packet Length But don't let the compiler do any optomisation 00485 asm volatile ("lds __tmp_reg__, %3" "\n\t" 00486 "mov %B0, __tmp_reg__" "\n\t" "lds __tmp_reg__, %2" "\n\t" "mov %A0, __tmp_reg__" "\n\t":"=r" (l) 00487 :"0"(l), "n"((unsigned short) (CS_DATA_P0)), "n"((unsigned short) (CS_DATA_P0 + 1)) 00488 ); 00489 #else 00490 00491 l = *(uint8_t *) (CS_DATA_P0 + 1) << 8 | *(uint8_t *) (CS_DATA_P0); 00492 l = *(uint8_t *) (CS_DATA_P0 + 1) << 8 | *(uint8_t *) (CS_DATA_P0); 00493 #endif 00494 //NutPrintFormat_P(dev_debug,PSTR("RxLength = %x \r\n"), l); 00495 //NutPrintFlush(dev_debug); 00496 00497 // Account for odd length packets 00498 if (l & 1) 00499 m = l - 1; 00500 else 00501 m = l; 00502 00503 00504 nb = NutNetBufAlloc(0, NBAF_DATALINK, l); 00505 if (nb) { 00506 q = nb->nb_dl.vp; 00507 for (i = 0; i < m; i += 2) { 00508 p = (uint8_t *) CS_DATA_P0; 00509 *q++ = *p; 00510 p = (uint8_t *) CS_DATA_P0 + 1; 00511 *q++ = *p; 00512 } 00513 00514 // Odd length packets 00515 if (m != l) { 00516 p = (uint8_t *) CS_DATA_P0; 00517 *q++ = *p; 00518 00519 p = (uint8_t *) CS_DATA_P0 + 1; 00520 m = *p; 00521 } 00522 ni->ni_rx_packets++; 00523 (*ifn->if_recv) (dev, nb); 00524 } 00525 } 00526 } 00527 00528 void CSSoftwareWakeup(void) 00529 { 00530 volatile uint16_t *p; 00531 00532 p = (uint16_t *) CS_PP_PTR; 00533 *p = CS_SELF_CTRL; 00534 00535 NutDelay(10); 00536 } 00537 00538 00539 void CSSoftwareReset(void) 00540 { 00541 volatile uint16_t *p; 00542 00543 p = (uint16_t *) CS_PP_PTR; 00544 *p = CS_SELF_CTRL; 00545 p = (uint16_t *) CS_DATA_P0; 00546 *p = 0x0040; 00547 } 00548 00549 00560 int CSNicInit(NUTDEVICE * dev) 00561 { 00562 uint16_t i; 00563 uint16_t j; 00564 IFNET *ifn; 00565 NICINFO *ni; 00566 00567 #if 0 00568 if (tcp_trace) { 00569 NutPrintFormat_P(dev_debug, PSTR("Enter NicInit \r\n")); 00570 NutPrintFlush(dev_debug); 00571 } 00572 #endif 00573 cs_base = dev->dev_base; 00574 00575 if (confnet.cd_size == 0) 00576 NutNetLoadConfig(dev->dev_name); 00577 00578 ifn = dev->dev_icb; 00579 memcpy(ifn->if_mac, confnet.cdn_mac, 6); 00580 memset(dev->dev_dcb, 0, sizeof(NICINFO)); 00581 ni = (NICINFO *) dev->dev_dcb; 00582 00583 // Take CS8900 out of reset and wait for internal reset to complete 00584 #ifdef NUT_CS8900_OLD 00585 outp(inp(PORTD) & ~RESETE, PORTD); 00586 #else 00587 CSSoftwareWakeup(); 00588 CSSoftwareReset(); 00589 #endif 00590 00591 NutDelay(100); 00592 00593 // Check for presence 00594 if (CSReadPP16(CS_PROD_ID) != 0x630E) 00595 return -1; 00596 00597 // 00598 // Copy our MAC address to the NIC 00599 // 00600 for (i = 0; i < 6; i += 2) { 00601 j = ifn->if_mac[i] << 8; 00602 j |= ifn->if_mac[i + 1]; 00603 CSWritePP16(CS_IEEE_ADDR + i, j); 00604 j = CSReadPP16(CS_IEEE_ADDR + i); 00605 #if 0 00606 if (tcp_trace) { 00607 NutPrintFormat_P(dev_debug, PSTR("ADDR = %x\r\n"), j); 00608 NutPrintFlush(dev_debug); 00609 } 00610 #endif 00611 } 00612 00613 // 00614 // Enable the Transmitter and Receiver 00615 // 00616 CSWritePP16(CS_LINE_CTRL, 0x00C0); 00617 //i = CSReadPP16(CS_LINE_CTRL); 00618 //NutPrintFormat_P(dev_debug,PSTR("CS_LINE_CTRL = %x\r\n"), i); 00619 00620 CSWritePP16(CS_RX_CTL, 0x0F40); 00621 //i = CSReadPP16(CS_RX_CTL); 00622 //NutPrintFormat_P(dev_debug,PSTR("CS_RX_CTL = %x\r\n"), i); 00623 00624 // 00625 // Start receiver thread 00626 // 00627 NutThreadCreate("csnicrx", CSNICrx, dev, 500); 00628 00629 return 0; 00630 } 00631 00633 #else 00634 void keep_icc_happy(void) 00635 { 00636 } 00637 00638 #endif