⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nicrtl.c

📁 avr上的RTOS
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of *    contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * For additional information see http://www.ethernut.de/ * *//* * $Log: nicrtl.c,v $ * Revision 1.1  2005/07/26 18:02:40  haraldkipp * Moved from dev. * * Revision 1.15  2005/04/30 16:42:41  chaac * Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If NUTDEBUG * is defined in NutConf, it will make effect where it is used. * * Revision 1.14  2005/02/10 07:06:18  hwmaier * Changes to incorporate support for AT90CAN128 CPU * * Revision 1.13  2005/02/05 20:42:38  haraldkipp * Force compiler error for leftover debug prints. * * Revision 1.12  2005/01/24 21:11:50  freckle * renamed NutEventPostFromIRQ into NutEventPostFromIrq * * Revision 1.11  2005/01/22 19:24:46  haraldkipp * Changed AVR port configuration names from PORTx to AVRPORTx. * * Revision 1.10  2005/01/21 16:49:46  freckle * Seperated calls to NutEventPostAsync between Threads and IRQs * * Revision 1.9  2004/12/17 15:31:28  haraldkipp * Support of rising edge interrupts for hardware w/o inverter gate. * Fixed compilation issue for hardware with RTL reset port. * Thanks to FOCUS Software Engineering Pty Ltd. * * Revision 1.8  2004/09/10 10:36:01  haraldkipp * ICCAVR compile problems fixed * * Revision 1.7  2004/08/25 10:41:00  haraldkipp * Hardware dependent definitions are configurable. For performance reasons the * base address is not kept in a variable any longer. It is now a preprocessor * macro and the parameters during device registration are ignored. The speed * improvements provided by Kolja Waschk for the LAN91C111 had been implemented * here too. The driver will not touch a port anymore unless a reset port bit * had been configured. For Ethernut 1.1 bit 4 PORTE must be specified in the * configuration. Finally, an EEPROM emulation had been added, which can use * address bus bits instead of wasting additional port pins. The required * hardware has been implemented on Rev.-G Ethernut 1.3 boards. This fixes the * Realtek full duplex problem. * * Revision 1.6  2004/05/17 19:14:53  haraldkipp * Added Bengt Florin's RTL8019 driver mods * * Revision 1.5  2004/03/16 16:48:27  haraldkipp * Added Jan Dubiec's H8/300 port. * * Revision 1.4  2003/08/05 20:05:59  haraldkipp * Bugfix. Empty MAC address is FF, not 00 * * Revision 1.3  2003/07/17 09:39:56  haraldkipp * Optimized controller feeding. * Ignore LSB of packet status. * * Revision 1.2  2003/05/15 14:09:16  haraldkipp * Much better performance under heavy traffic. * * Revision 1.1.1.1  2003/05/09 14:40:48  haraldkipp * Initial using 3.2.1 * */#include <cfg/os.h>#include <cfg/arch/avr.h>#include <string.h>#include <sys/atom.h>#include <sys/heap.h>#include <sys/thread.h>#include <sys/event.h>#include <sys/timer.h>#include <sys/confnet.h>#include <net/ether.h>#include <net/if_var.h>#include <dev/irqreg.h>#include <dev/nicrtl.h>#include "rtlregs.h"#ifdef NUTDEBUG#include <sys/osdebug.h>#include <net/netdebug.h>#endif/* * Determine ports, which had not been explicitely configured. */#if (RTL_EESK_AVRPORT == AVRPORTB)#define RTL_EESK_PIN    PINB#define RTL_EESK_DDR    DDRB#elif (RTL_EESK_AVRPORT == AVRPORTC)#define RTL_EE_MEMBUS#define RTL_EESK_PIN    PINC#define RTL_EESK_DDR    DDRC#elif (RTL_EESK_AVRPORT == AVRPORTD)#define RTL_EESK_PIN    PIND#define RTL_EESK_DDR    DDRD#elif (RTL_EESK_AVRPORT == AVRPORTE)#define RTL_EESK_PIN    PINE#define RTL_EESK_DDR    DDRE#elif (RTL_EESK_AVRPORT == AVRPORTF)#define RTL_EESK_PIN    PINF#define RTL_EESK_DDR    DDRF#endif /* RTL_EESK_AVRPORT */#if (RTL_EEDO_AVRPORT == AVRPORTB)#define RTL_EEDO_PORT   PORTB#define RTL_EEDO_DDR    DDRB#elif (RTL_EEDO_AVRPORT == AVRPORTC)#define RTL_EE_MEMBUS#define RTL_EEDO_PORT   PORTC#define RTL_EEDO_DDR    DDRC#elif (RTL_EEDO_AVRPORT == AVRPORTD)#define RTL_EEDO_PORT   PORTD#define RTL_EEDO_DDR    DDRD#elif (RTL_EEDO_AVRPORT == AVRPORTE)#define RTL_EEDO_PORT   PORTE#define RTL_EEDO_DDR    DDRE#elif (RTL_EEDO_AVRPORT == AVRPORTF)#define RTL_EEDO_PORT   PORTF#define RTL_EEDO_DDR    DDRF#endif /* RTL_EEDO_AVRPORT */#if (RTL_EEMU_AVRPORT == AVRPORTB)#define RTL_EEMU_PORT   PORTB#define RTL_EEMU_DDR    DDRB#elif (RTL_EEMU_AVRPORT == AVRPORTC)#define RTL_EE_MEMBUS#define RTL_EEMU_PORT   PORTC#define RTL_EEMU_DDR    DDRC#elif (RTL_EEMU_AVRPORT == AVRPORTD)#define RTL_EEMU_PORT   PORTD#define RTL_EEMU_DDR    DDRD#elif (RTL_EEMU_AVRPORT == AVRPORTE)#define RTL_EEMU_PORT   PORTE#define RTL_EEMU_DDR    DDRE#elif (RTL_EEMU_AVRPORT == AVRPORTF)#define RTL_EEMU_PORT   PORTF#define RTL_EEMU_DDR    DDRF#endif /* RTL_EEMU_AVRPORT */#if (RTL_RESET_AVRPORT == AVRPORTB)#define RTL_RESET_PORT   PORTB#define RTL_RESET_DDR    DDRB#elif (RTL_RESET_AVRPORT == AVRPORTD)#define RTL_RESET_PORT   PORTD#define RTL_RESET_DDR    DDRD#elif (RTL_RESET_AVRPORT == AVRPORTE)#define RTL_RESET_PORT   PORTE#define RTL_RESET_DDR    DDRE#elif (RTL_RESET_AVRPORT == AVRPORTF)#define RTL_RESET_PORT   PORTF#define RTL_RESET_DDR    DDRF#endif /* RTL_RESET_AVRPORT *//*! * \brief Interrupt used. */#if (RTL_SIGNAL_IRQ == INT0)#define RTL_SIGNAL sig_INTERRUPT0#ifdef __AVR_ENHANCED__#define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC00); sbi(EICRA, ISC01)#endif#elif (RTL_SIGNAL_IRQ == INT1)#define RTL_SIGNAL sig_INTERRUPT1#ifdef __AVR_ENHANCED__#define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC10); sbi(EICRA, ISC11)#endif#elif (RTL_SIGNAL_IRQ == INT2)#define RTL_SIGNAL sig_INTERRUPT2#ifdef __AVR_ENHANCED__#define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC20); sbi(EICRA, ISC21)#endif#elif (RTL_SIGNAL_IRQ == INT3)#define RTL_SIGNAL sig_INTERRUPT3#ifdef __AVR_ENHANCED__#define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC30); sbi(EICRA, ISC31)#endif#elif (RTL_SIGNAL_IRQ == INT4)#define RTL_SIGNAL sig_INTERRUPT4#ifdef __AVR_ENHANCED__#define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC40); sbi(EICRB, ISC41)#endif#elif (RTL_SIGNAL_IRQ == INT6)#define RTL_SIGNAL sig_INTERRUPT6#ifdef __AVR_ENHANCED__#define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC60); sbi(EICRB, ISC61)#endif#elif (RTL_SIGNAL_IRQ == INT7)#define RTL_SIGNAL sig_INTERRUPT7#ifdef __AVR_ENHANCED__#define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC70); sbi(EICRB, ISC71)#endif#else#define RTL_SIGNAL sig_INTERRUPT5#ifdef __AVR_ENHANCED__#define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC50); sbi(EICRB, ISC51)#endif#endif /* RTL_SIGNAL_IRQ *//*! * \brief Size of a single ring buffer page. */#define NIC_PAGE_SIZE   0x100/*! * \brief First ring buffer page address. */#define NIC_START_PAGE  0x40/*! * \brief Last ring buffer page address plus 1. */#define NIC_STOP_PAGE   0x60/*! * \brief Number of pages in a single transmit buffer. * * This should be at least the MTU size. */#define NIC_TX_PAGES    6/*! * \brief Number of transmit buffers. * * The initial value had been 2. The idea was to use two alternating * buffers. However, this had never been implemented and we took over * Bengt Florin's change, defining 1 transmit buffer only and give * more buffer space to the receiver. * * The controller memory layout is now * * - 0x4000..0x45ff  1.5K bytes transmit buffer * - 0x4600..0x5fff  6.5K bytes receive buffer * * The routines are still not using the buffers in an optimal way, * as transmission is limited to 1 packet at a time. In fact several * smaller packets would fit into the 1.5 kByte buffer. On the other * hand, filling the buffer with more than one transmission packet * may result in other bad effects, like pulling the IORDY line more * often. */#define NIC_TX_BUFFERS      1#define NIC_FIRST_TX_PAGE   NIC_START_PAGE#define NIC_FIRST_RX_PAGE   (NIC_FIRST_TX_PAGE + NIC_TX_PAGES * NIC_TX_BUFFERS)#define NIC_CR_PAGE0 (0)#define NIC_CR_PAGE1 (NIC_CR_PS0)#define NIC_CR_PAGE2 (NIC_CR_PS1)#define NIC_CR_PAGE3 (NIC_CR_PS1 | NIC_CR_PS0)/* * This delay has been added by Bengt Florin and is used to minimize * the effect of the IORDY line during reads. Bengt contributed a * more versatile loop, which unfortunately wasn't portable to the * ImageCraft compiler. * * Both versions depend on the CPU clock and had been tested with * 14.7456 MHz. */static INLINE void Delay16Cycles(void){    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();    _NOP();}/*! * \addtogroup xgNicRtl *//*@{*//*! * Realtek packet header. */struct nic_pkt_header {    u_char ph_status;           /*!< \brief Status, contents of RSR register */    u_char ph_nextpg;           /*!< \brief Page for next packet */    u_short ph_size;            /*!< \brief Size of header and packet in octets */};#define NICINB(reg)         (*((volatile u_char *)RTL_BASE_ADDR + reg))#define NICOUTB(reg, val)   (*((volatile u_char *)RTL_BASE_ADDR + reg) = val)/*! * \brief Reset the Ethernet controller. * */static int NicReset(void){    u_char i;    u_char j;/* * Toggle the hardware reset line. Since Ethernut version 1.3 the * hardware reset pin of the nic is no longer connected to bit 4 * on port E, but wired to the board reset line. */#ifdef RTL_RESET_BIT    sbi(RTL_RESET_DDR, RTL_RESET_BIT);    sbi(RTL_RESET_PORT, RTL_RESET_BIT);    NutDelay(WAIT100);    cbi(RTL_RESET_PORT, RTL_RESET_BIT);    NutDelay(WAIT250);    NutDelay(WAIT250);#endif    /*     * Do the software reset by reading from the reset register followed     * by writing to the reset register. Wait until the controller enters     * the reset state.     */    for (j = 0; j < 20; j++) {        i = NICINB(NIC_RESET);        NutDelay(WAIT5);        NICOUTB(NIC_RESET, i);        for (i = 0; i < 20; i++) {            NutDelay(WAIT50);            /*             * We got the reset bit. However, Ethernut 1.1 may             * still fail because the NIC hasn't got it's hardware             * reset and the data lines remain in tristate. So we             * read noise instead of the register. To solve this             * problem, we will verify the NIC's id.             */            if ((NICINB(NIC_PG0_ISR) & NIC_ISR_RST) != 0 &&     /* */                NICINB(NIC_PG0_RBCR0) == 0x50 &&        /* */                NICINB(NIC_PG0_RBCR1) == 0x70)                return 0;        }    }    return -1;}static int DetectNicEeprom(void){#ifdef RTL_EESK_BIT    register u_int cnt = 0;    NutEnterCritical();    /*     * Prepare the EEPROM emulation port bits. Configure the EEDO     * and the EEMU lines as outputs and set both lines to high.     */    sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);    sbi(RTL_EEDO_DDR, RTL_EEDO_BIT);#ifdef RTL_EEMU_BIT    sbi(RTL_EEMU_PORT, RTL_EEMU_BIT);    sbi(RTL_EEMU_DDR, RTL_EEMU_BIT);#endif    NutDelay(20);    /*     * Force the chip to re-read the EEPROM contents.     */    NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);    NICOUTB(NIC_PG3_EECR, NIC_EECR_EEM0);    /*     * No external memory access beyond this point.     */#ifdef RTL_EE_MEMBUS    /*     * No external memory access beyond this point.     */#ifdef __AVR_ENHANCED__    /* On the ATmega 128 we release bits 5-7 as normal port pins. */    outb(XMCRB, inb(XMCRB) | _BV(XMM0) | _BV(XMM1));#else    /* On the ATmega 103 we have to disable the external memory interface. */    cbi(MCUCR, SRE);#endif#endif    /*     * Check, if the chip toggles our EESK input. If not, we do not     * have EEPROM emulation hardware.     */    if (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT)) {        while (++cnt && bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -