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

📄 ethernet.c

📁 阿根廷教授编写的嵌入式internet的实验教程的高质量代码
💻 C
字号:
/******************************************************************************************
   Ethernet.c (v1.0)
-------------------------------------------------------------------------------------
This code is from the book:
"Embedded Internet: TCP/IP Basics, Implementation and Applications" by Sergio Scaglia
[Pearson Education, 2006 - ISBN: 0-32-130638-4]

This code is copyright (c) 2006 by Sergio Scaglia, and it may only be used for educational
purposes.  For commercial use, please contact me at sscaglia@intramarket.com.ar
For more information and updates, please visit www.embeddedinternet.org
******************************************************************************************/

#include "stack.h"
#include "Ethernet.h"
#include "arp.h"
#include <iolpc2129.h>
#include <string.h>
#include <stdio.h>	


/* CS8900 PacketPage I/O Port Definitions  */
#define pp_RxTxData	0x00	// Receive/Transmit data Port 0
#define pp_TxCmd	0x04	// Transmit Command
#define pp_TxLen	0x06	// Transmit Length
#define pp_Ptr	        0x0A	// PacketPage Pointer
#define pp_Data0	0x0C	// PacketPage Data Port 0


/* CS8900 PacketPage Internal Registers  */
#define pp_RxCFG	 0x0102		// Receiver Configuration
#define pp_RxCTL	 0x0104		// Receiver Control
#define pp_LineCTL	 0x0112		// Line Control
#define pp_SelfCTL       0x0114		// Self Control
#define pp_TestCTL	 0x0118		// Test Control
#define pp_RxEvent	 0x0124		// Receiver Event
#define pp_SelfStatus    0x0136		// Self Status
#define pp_BusStatus	 0x0138 	// Bus Status
#define pp_IndividualA   0x0158		// Individual Address


char rx_buf[PACKET_BUF_SIZE];
char tx_buf[PACKET_BUF_SIZE];
char MyMAC[6] = MyMACAddress;
char MyIP[4]  = MyIPAddress;	        // device IPv4 address	
char Gateway[4] = GatewayAddress;
char SubNetMask[4] = SubNetMaskAddress;


/***************************************/
/* CS8900 Ethernet Private Functions  */
/***************************************/

char CS8900_read_port(char port_address) {
  char port_data;

  IO0CLR = SAB;					// Clear Address lines		
  IO0SET = (port_address<<4) & SAB;		// Set Address lines
  IO0CLR = IOR;				        // IOR=0 - Enable Read 		
  port_data = ((IO0PIN & SDB)>>16);		// Read Data from CS8900
  IO0SET = IOR;				        // IOR=1 - Disable Read
  return port_data;				// Return Data
}


void CS8900_write_port(char port_address, char port_data) {

  IO0DIR |= SDB;			        // SD7-SD0 as Outputs - Data lines
  IO0CLR = SDB;		                        // Clear Data lines		
  IO0SET = (port_data<<16);			// Set Data lines
  IO0CLR = SAB;					// Clear Address lines
  IO0SET = (port_address<<4) & SAB;		// Set Address lines
  IO0CLR = IOW;			                // IOW=0 - Enable Write
  IO0SET = IOW;			                // IOW=1 - Disable Write
  IO0DIR &= (~SDB);      	                // SD7-SD0 as Inputs - Data lines
}


unsigned short CS8900_read_reg(unsigned short reg_address) {

  CS8900_write_port(pp_Ptr, (reg_address & 0x0FF)); 						// Write Packet Page pointer - Lower byte
  CS8900_write_port(pp_Ptr+1, ((reg_address>>8) & 0x0FF));					// Write Packet Page pointer - Higher byte
  return ((CS8900_read_port(pp_Data0+1)<<8) + CS8900_read_port(pp_Data0));  // Read Data Port 0 and return
}


void CS8900_write_reg(unsigned short reg_address, unsigned short reg_data)
{
  CS8900_write_port(pp_Ptr, (reg_address & 0x0FF)); 	      // Write Packet Page pointer - Lower byte
  CS8900_write_port(pp_Ptr+1, ((reg_address>>8) & 0x0FF));    // Write Packet Page pointer - Higher byte
  CS8900_write_port(pp_Data0, (reg_data & 0x0FF));	      // Write Packet Page Data Port 0 - Lower byte
  CS8900_write_port(pp_Data0+1, ((reg_data>>8) & 0x0FF));     // Write Packet Page Data Port 0 - Higher byte
}


void frame_send(unsigned short len) {
  unsigned short i, j=0xFFFF;

  if (len > PACKET_BUF_SIZE) {		//len exceeds maximum ethernet frame length
    printf("Ethernet: maximum frame length exceeded\n");
    return;
  }
  CS8900_write_port(pp_TxCmd, 0xC0);
  CS8900_write_port(pp_TxCmd+1, 0x00);
  CS8900_write_port(pp_TxLen, (len & 0xFF));
  CS8900_write_port(pp_TxLen+1, ((len>>8) & 0xFF));			
  do {
    j--;
  } while(!((CS8900_read_reg(pp_BusStatus) & 0x0100)) && j>0);
  if (j == 0) {
    printf("Ethernet: CS8900 not ready to accept a frame!\n");
    return;
  }
  for(i=0; i<len; i+=2) {
    CS8900_write_port(pp_RxTxData, tx_buf[i]);
    CS8900_write_port(pp_RxTxData+1, tx_buf[i+1]);
   }
}


#if debug_ethernet
void frame_display(unsigned short len) {
  unsigned short i, j;

  printf("Frame Received - Length: %d bytes\r\n", len);
  printf("Destination:    %02x-%02x-%02x-%02x-%02x-%02x\r\n", FRAMEr->destination[0], FRAMEr->destination[1],
					  FRAMEr->destination[2], FRAMEr->destination[3],
					  FRAMEr->destination[4], FRAMEr->destination[5]);
	
  printf("Source:         %02x-%02x-%02x-%02x-%02x-%02x\r\n", FRAMEr->source[0], FRAMEr->source[1],
	                                  FRAMEr->source[2], FRAMEr->source[3],
					  FRAMEr->source[4], FRAMEr->source[5]);

  printf("Type:           %04x\r\n", HTONS(FRAMEr->protocol));
  printf("Data:\r\n     ");
  j=0;
  for(i=14; i<len; i++) {
    printf("%02x ", rx_buf[i]);
    j++;
    if (j==16) {
      j=0;
      printf("\r\n     ");
    }
  }
  printf("\r\n----------------------------------------------------\r\n");
}
#endif //debug_ethernet


unsigned short frame_get(void) {
  char header[4];
  unsigned short RxLength;
  unsigned short i;

  header[0] = CS8900_read_port(pp_RxTxData + 1);
  header[1] = CS8900_read_port(pp_RxTxData);
  header[2] = CS8900_read_port(pp_RxTxData + 1);
  header[3] = CS8900_read_port(pp_RxTxData);
  RxLength = (header[2]<<8) + header[3];
  if (RxLength > PACKET_BUF_SIZE) {			// Skip Frame
    CS8900_write_reg(pp_RxCFG, (CS8900_read_reg(pp_RxCFG) | 0x0040));	   // Set Skip bit in RxCFG register
    return 0;
  }
  for(i=0; i<RxLength; i+=2) {
    rx_buf[i]   = CS8900_read_port(pp_RxTxData);
    rx_buf[i+1] = CS8900_read_port(pp_RxTxData + 1);
  }
#if debug_ethernet
  frame_display(RxLength);	
#endif  // debug_ethernet
  return RxLength;
}


void frame_process(void) {

  if (frame_get() == 0)
    return;
  switch (HTONS(FRAMEr->protocol)) {
    case ARP_PROTOCOL:
      arp_process();
      break;
    case IP_PROTOCOL:
      //  ip_process();
      break;
  }
}


/***************************************/
/*   Ethernet Public Functions         */
/***************************************/
void ethernet_init(void) {
  unsigned short ret;

  /* Define pin directions */
  IO0DIR |= (SAB | IOR |IOW);	// SA3-SA0, IOR, and IOW as Outputs
  IO0DIR &= (~SDB);      	// SD7-SD0 as Inputs
  IO0SET = IOW | IOR;		// Set IOR=IOW=1

  /* Reset the CS8900A */
  CS8900_write_reg(pp_SelfCTL, 0x0040);

  while(!(CS8900_read_reg(pp_SelfStatus) & 0x0080));  // wait for INITD=1 indicating CS8900 Reset Ok

  /* Load parameters */
  CS8900_write_reg(pp_LineCTL, 0x0000);	    // Clear all bits for 10Base-T
  CS8900_write_reg(pp_TestCTL, 0x4000);	    // Set Full-Duplex bit
  CS8900_write_reg(pp_RxCTL, 0x0D00);	    // Set RXOkA, IndividualA, BroadcastA bits
  CS8900_write_reg(pp_RxCFG, 0x0000);	    // Clear BufferCRC bit

  /* Load MAC Address */
  CS8900_write_reg(pp_IndividualA,   (MyMAC[1]<<8) + MyMAC[0]);
  CS8900_write_reg(pp_IndividualA+2, (MyMAC[3]<<8) + MyMAC[2]);
  CS8900_write_reg(pp_IndividualA+4, (MyMAC[5]<<8) + MyMAC[4]);

  /* Enable Transmitter and Receiver  */
  ret = CS8900_read_reg(pp_LineCTL) | 0x00C0;	// Set TxOn and RxOn bits
  CS8900_write_reg(pp_LineCTL, ret);		// in Line Control Register
}


void ethernet_poll(void) {

  if ((CS8900_read_reg(pp_RxEvent) & 0x0100)) {  // if RxOK bit set, there is a frame
    frame_process();
  }
}


void ethernet_send(unsigned short protocol, unsigned short len) {
  char IPdest[4] = pcIP;
			
  if (protocol == ARP_PROTOCOL) {
    if (HTONS(ARPt->opcode) == 0x0001) {
      memset(FRAMEt->destination,0xFF,6);
    }else {
      memcpy(FRAMEt->destination,ARPt->tarhwaddr,6);
    }
  }else {	
    if (arp_resolve(IPdest, FRAMEt->destination) == ARP_ENTRY_NOT_FOUND) {
      return;
    }
  }	
  memcpy(FRAMEt->source, MyMAC, 6);
  FRAMEt->protocol = HTONS(protocol);
  frame_send(len + (sizeof(struct ethernet_hdr)));	
}

⌨️ 快捷键说明

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