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

📄 ethernet.c

📁 ATmega103、ATmega128做的开发板web server源码
💻 C
字号:
/******************************************************************
* ethernet.c: Low level Ethernet interface routines
* 
* Copyright (c) 2001 Atmel Corporation.
* All Rights Reserved.
*
* You are autorized to use, copy and distribute this software only at 
* a single site (the term "site" meaning a single company location). 
* This copyright notice must be included in any copy, modification 
* or portion of this software merged into another program.
* 
* This software is licenced solely for use with Atmel AVR micro 
* controller family. The software may not be modified to execute on 
* any other microcontroller architectures
*
* This software is provided "as is"; Without warranties either express
* or implied, including any warranty regarding merchantability, 
* fitness for a particular purpose or noninfringement. 
*
* In no event shall Atmel or its suppliers be liable for any special, 
* indirect,incidential or concequential damages resulting from the 
* use or inability to use this software.
*
* Revision history:
*
* January 17, 2001:   Version 1.0   Created by JB
* July 13, 2001		  Version 1.2     JB
* 					- Changed to IAR compiler V2.25
*					- Renamed flash file functions to avoid conflict with 
*					  standard file I/O names	
*					- Bug fixes in HTTP
*					- Speed optimization in TCP 
*
*
*******************************************************************/

#include <iom103.h>
#include "ethernet.h"
#include "ip.h"
#include "arp.h"
#include "main.h"
#include <stdio.h>
#include <string.h>

typedef struct
{
  unsigned int hisMAC0, hisMAC1, hisMAC2; 
  unsigned int hisIP0, hisIP1;
}ARP;                                             

config_type ID;
ARP MACtable[ETH_MAC_TABLE_SIZE+1];   

extern unsigned int frame[FRAME_SIZE];

/*sendFrame sends the frame positioned in the global array frame and is called by
  ARP and IP. Sendframe adds a ethernet header to the frame before it is sent.
  length denotes the framelength in bytes. The frame starts at frame[14] to give
  sendFrame space to append the ethernet header.*/
char sendFrame(unsigned int length, unsigned int type, unsigned int hisIP0, unsigned int hisIP1)
{
  unsigned int i=0;    
  unsigned char j = 3;                    
  unsigned char arpNr;
  unsigned int *pframe, *pTxFrame;
  unsigned int temp;
  
  length += ETH_HEADER_LENGTH;                  //Add ethernet frame length
  arpNr=getMAC(hisIP0, hisIP1);                 //Check if ethernet address is in the ARP table.
  
  /*add ethernet address*/
  pTxFrame = (unsigned int *) &ID.MAC0;
  pframe = &frame[ETH_SENDER_MAC];
  j = 3;
  do
  {
    *pframe++ = *pTxFrame++;
  } while(--j);
  
  if (arpNr != 0xfe)                            //If the address is found, arpNr != 0.
  {                                             
    if (arpNr!= 0xff)                           //Broadcast returns arpNr == 0xff
    {
      pTxFrame = (unsigned int *) &MACtable[arpNr];
      pframe = &frame[ETH_TARGET_MAC];
      j = 3;

      /*Add receivers ethernet address*/
      do
      {
        *pframe++ = *pTxFrame++;
      } while(--j);

    }
    else                                        //This is a broadcast
    {
      /*add broadcast address*/
      pframe = &frame[ETH_SENDER_MAC];
      j = 3;
      do
      {
        *pframe++ = 0xffff;
      } while(--j);
    }    
    frame[ETH_TYPE] = type;                     //Add protocol type given by caller (of function)
    *ppTxCMD = 0x00c0;                          //Inform ethernet controller to prepare for transmission
    *ppTxLength = length;                       //Inform ethernet controller of length of frame
//    while ( (*ppBusST & 0x0100) == 0)           //Wait for ethernet controller to be ready
    while ( (ppBusST & 0x0100) == 0)           //Wait for ethernet controller to be ready
    {
    }   
    
    pframe = frame;
    pTxFrame = ppTxFrame;
     
    /*send frame, change byte ordering*/
    for (i=0; i < length; i+=2)                 
    {
//      *pTxFrame++ = (((*pframe & 0x00ff) << 8) | ((*pframe++ & 0xff00 ) >> 8));
		temp = *pframe++;						// Use temp variable to avoid reading twice
    	*pTxFrame++ = ((LO(temp))<<8 | (HI(temp)));
    }
    return 1;
  }
  return 0;
}

/*receiveEvent is called everytime a packet is received. (Upon irq4)*/
void receiveEvent( void ) 
{
  
	static unsigned char macNr = 0;
	unsigned char lmacnr;						// Local temp storage of macNr
  	unsigned int *pframe = frame;
  	unsigned int *pRxFrame = ppRxFrame;
  	unsigned int length,i;
	ARP *MACtableptr;    
	unsigned int temp;
      
  i = *ppRxStatus;                              //Read receive status. The value is not used, but it must be read.
  length = *ppRxLength;                         //Read packet length.
  
  /*Copy the packet into frame[], changing byte order*/
  for (i=0;i<length;i+= 2) 
  {
//    ptr[i+1] = ptr2[i]; 
//    ptr[i] = ptr2[i+1];
	temp = *pRxFrame++;
	*pframe++ = ((LO(temp)<<8) | (HI(temp)));
  }
  lmacnr = macNr+1;
  if (lmacnr > (ETH_MAC_TABLE_SIZE-1) )
  {
	  lmacnr = 0;
  }
  pframe = frame;
  if (pframe[ETH_TYPE] == 0x0806)        //Check if frame is ARP or IP
  {
    if ( (pframe[ARP_OPCODE] == 0x0002) || (pframe[ARP_TARGET_IP0] == ID.IP0) || (pframe[ARP_TARGET_IP1] == ID.IP1) )
    {
      macNr = lmacnr;
      MACtableptr = &MACtable[lmacnr];
      MACtableptr->hisMAC0 = pframe[ETH_SENDER_MAC0];
      MACtableptr->hisMAC1 = pframe[ETH_SENDER_MAC1];
      MACtableptr->hisMAC2 = pframe[ETH_SENDER_MAC2];
      MACtableptr->hisIP0 = pframe[ARP_SENDER_IP0];
      MACtableptr->hisIP1 = pframe[ARP_SENDER_IP1];
    }
    receiveARP();
  }
 if (pframe[ETH_TYPE] == 0x0800)   // if this is an IP frame....
  {
    /*Copy ethernet address into ARPtable, this may be unneccecary 
      since the address may already exist in the table*/
    macNr = lmacnr;
    MACtableptr = &MACtable[lmacnr];
    MACtableptr->hisMAC0 = pframe[ETH_SENDER_MAC0];
    MACtableptr->hisMAC1 = pframe[ETH_SENDER_MAC1];
    MACtableptr->hisMAC2 = pframe[ETH_SENDER_MAC2];
    MACtableptr->hisIP0 = pframe[IP_SENDER_IP0];
    MACtableptr->hisIP1 = pframe[IP_SENDER_IP1];
    receiveIP(length-ETH_HEADER_LENGTH);
  }
}

/*getMAC check if the ethernet address to the given ip address exists in ARP table.
  If the address exists, 1 is returned. If it is an broadcast, 2 is returned, else 0 is returned.*/
char getMAC(unsigned int hisIP0, unsigned int hisIP1)
{
  unsigned char arpNr=0;
  
  if ( (hisIP0 == 0xffff) && (hisIP1 == 0xffff) ) //broadcast address, return 0xff
  {
    return (0xff); 
  }
  else 
  {
    do
    {
      if ((hisIP0 == MACtable[arpNr].hisIP0) && (hisIP1 == MACtable[arpNr].hisIP1))
      {
        return arpNr;    
      }    
    } while (++arpNr<ETH_MAC_TABLE_SIZE+1);
    sendARP(hisIP0, hisIP1);                                    //not found, send ARP-request and return 0xfe
    return (0xfe);
  }
}

/*dhcpMAC is called by dhcp to store the ethernet address of the DHCP server.
  This is because the dhcp server is rarely called, but it is nececcary that the
  packet arrives. MACtable[ARP_TABLE_LENGTH] can only be overwritten by dhcpMAC...*/
void dhcpMAC(unsigned int hisIP0, unsigned int hisIP1)
{
  unsigned int *MACtableptr;    
  unsigned int *frameptr;
  unsigned char j;

  MACtableptr = (unsigned int *) &MACtable[ETH_MAC_TABLE_SIZE];
  frameptr = &frame[ETH_SENDER_MAC];
  j = 3;
  do
  {
    *MACtableptr++ = *frameptr++;               //add sender MAC to MAC-table
  } while(--j);
  *MACtableptr++ = hisIP0;
  *MACtableptr++ = hisIP1;
}

/* This is actually more like pseudo-milli-seconds.. Only used during
  initialization of ethernet controller*/
#pragma optimize=z 3
void waitMS(unsigned int MS)
{
  unsigned int z;
  
  do
  {
    z = 0x733;
    do
    {
    } while (--z);
  } while (--MS);
}  

/*Initialize ethernet controller.Enable receive interrupt and memory mode*/
void initEthernet( void )
{
  config_type *IDptr = &ID;
  
  waitMS(20);
  DDRD |= 0x01;                         // set PORTD bit 0 as output,no pullup
  PORTD |= 0x01;                        // reset ethernet controller
  waitMS(20);
  PORTD &= ~(0x01);                     // release reset
  waitMS(20);
  *PPptr = (unsigned int)ppSelfCTL - MEMBASE;  // Set PP pointer to selfCTL.
  
  /*Wait for reset bit to be cleared*/
//  while (*PPdata0 & 0x40)                      
  while (PPdata0 & 0x40)                      
  {
  }
  
  waitMS(10);
  *PPptr = (unsigned int)ppSelfST - MEMBASE;  // Set PP pointer to SelfS
  
  /*Wait for init done bit*/
//  while ( !((temp = *PPdata0) & 0x80 ) ) 
  while ( !(PPdata0 & 0x80 ) ) 
  {
  }  
	
  *PPptr = (unsigned int)ppLineCTL - MEMBASE;
  PPdata0 = 0xd3;
  *PPptr = (unsigned int)ppTestCTL - MEMBASE;
  PPdata0 = 0x4000;
  *PPptr = (unsigned int)ppRxCFG - MEMBASE;
  PPdata0 = 0x0100;
  *PPptr = (unsigned int)ppRxCTL - MEMBASE;
  PPdata0 = 0x0100 | 0x0400 | 0x0800 | 0x2000;
  *PPptr = (unsigned int)ppTxCFG - MEMBASE;
  PPdata0 = 0x107;
  *PPptr = (unsigned int)ppIA0 - MEMBASE;     // Write ethernet address.
  PPdata0 = (((IDptr->MAC0>>8)&0xff)|((IDptr->MAC0<<8)&0xff00));
  *PPptr = (unsigned int)ppIA1 - MEMBASE;
  PPdata0 = (((IDptr->MAC1>>8)&0xff)|((IDptr->MAC1<<8)&0xff00));
  *PPptr = (unsigned int)ppIA2 - MEMBASE;
  PPdata0 = (((IDptr->MAC2>>8)&0xff)|((IDptr->MAC2<<8)&0xff00));
  *PPptr = (unsigned int)ppIntNum - MEMBASE;  // Choose interrupt number
  PPdata0 = 0x0;
  *PPptr = (unsigned int)ppMEMbase - MEMBASE; // Set memory mapped base address.
  PPdata0 = (MEMBASE & 0x1fff);
  *PPptr = (unsigned int)ppBusCTL - MEMBASE;
  PPdata0 |= 0x8400;
}



⌨️ 快捷键说明

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