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

📄 ethernet.c

📁 keilc pic的版本 才搞到的 希望对大家有帮助
💻 C
字号:
#include <reg167.h>
#include <CS8900.h>
#include <string.h>
#include <intrins.h>

/* hw & ip addresses */
#define ETH_ALEN	6
#define IP_LEN		4
BYTE own_hw_addr[ETH_ALEN] = { 00, 0x00, 0x00, 0x12, 0x34, 0x56 };
BYTE own_ip_addr[IP_LEN]   = { 192, 168, 100, 210 };

/* extract the low or high byte out of a word16 */
#define HIGHBYTE(w)		((BYTE)(w>>8))
#define LOWBYTE(w)		((BYTE)(w&0x00ff))


// 48 bit IEEE OUI (Organizationally Unique Identifier)
#define MAC1    0x00
#define MAC2    0x00
#define MAC3    0x00
#define MAC4    0x12
#define MAC5    0x34
#define MAC6    0x56


BOOL CheckIOInterface(void) {
  WORD pic, rev, iobadr;
  
// check product identification code and revision number
  Ether.IO.PPP = cProductIdentificationCode | cAutoIncrement;
  pic = Ether.IO.PPD;
  rev = Ether.IO.PPD;
  if (pic != 0x630E) return(FALSE);     // chip not accessible
//if (rev != 0x0900) return(FALSE);     // chip version may vary

  Ether.IO.PPP = cIOBaseAddress;
  iobadr = Ether.IO.PPD;
  if (iobadr != 0x0300) return (FALSE); // must be 0x0300

// switch on the LINK LED
//Ether.IO.PPP = cSelfCTL;
//Ether.IO.PPD |= 0x5000;

  return(TRUE);
}

BOOL EnableMemInterface(void) {
//DWORD volatile pic;
  WORD  volatile v1, v2;

  Ether.IO.PPP = cMemBaseAddress | cAutoIncrement;
  v1 = Ether.IO.PPP;    // load low word of address
  Ether.IO.PPD = 0x0000;    // load low word of address
  Ether.IO.PPD = 0x0000;    // load high word of address

  v1 = Ether.IO.PPP;    // load low word of address
  Ether.IO.PPP = cMemBaseAddress | cAutoIncrement;
  v1 = Ether.IO.PPD;    // load low word of address
  v2 = Ether.IO.PPD;    // load high word of address

  Ether.IO.PPP = cBusCTL;   // Select Bus Contol Register Reg17
  Ether.IO.PPD |= 0x0400;   // Set MemoryE Bit
  Ether.IO.PPP = cMemBaseAddress | cAutoIncrement;
  v1 = Ether.IO.PPD;    // load low word of address
  v2 = Ether.IO.PPD;    // load high word of address
//if ((pic & 0x0000ffff) != 0x0000630E)  // Read Product Ident Code (chip version may vary)
//  return (FALSE);

  return (TRUE);             // Return successful
}

BOOL ResetChip(void) { 
  WORD i, rev, pic;

  Ether.IO.PPP = cSelfCTL;
  Ether.IO.PPD = SELF_CTL_RESET; //issue a reset to the chip
  i = 0;
  while(Ether.IO.PPD & SELF_CTL_RESET) i++;      // wait until reset done
  i = 0;
  Ether.IO.PPP = cSelfST;
  while(!(Ether.IO.PPD & SELF_ST_INIT_DONE)) i++; // wait until INITD bit set
  Ether.IO.PPP = cProductIdentificationCode | cAutoIncrement;
  pic = Ether.IO.PPD;
  rev = Ether.IO.PPD;
  if (pic != 0x630E) return(FALSE);     // chip not accessible
//if (rev != 0x0900) return(FALSE);     // chip version may vary

  return(TRUE);
}



// Initializes the chip 

BOOL InitChip(void) {

  Ether.LineCTL = LINE_CTL_10BASET;  // set to 10BaseT
  Ether.TestCTL = TEST_CTL_FDX;      // set to full duplex
  Ether.RxCFG   = RX_CFG_RX_OK_IE;   // enable RxOK interrupt
  Ether.RxCTL   = (RX_CTL_RX_OK_A | RX_CTL_IND_A | RX_CTL_BCAST_A | RX_CTL_RUNT_A | RX_CTL_PROM_A);
  Ether.TxCFG   = TX_CFG_ALL_IE;

// Important: The IA needs to be byte reversed IA=aa:bb:cc:dd:ee:ff

  Ether.IndividualAddress[0] = MAC1;
  Ether.IndividualAddress[1] = MAC2;
  Ether.IndividualAddress[2] = MAC3;
  Ether.IndividualAddress[3] = MAC4;
  Ether.IndividualAddress[4] = MAC5;
  Ether.IndividualAddress[5] = MAC6;

  Ether.InterruptNumber = 0x00;              //INT is on INTRQ0

  Ether.BusCTL  |= BUS_CTL_INT_ENBL;         // enable interrupt
  Ether.LineCTL |= LINE_CTL_RX_ON | LINE_CTL_TX_ON; // set SerRxOn and SerTxOn

  return(TRUE);
}


void error(void) {

  while(1);
}

typedef union mac_a {
  BYTE b[6];
  WORD w[3];
} MAC_A;

typedef union ip_a {
  BYTE  b[4];
  WORD  w[2];
  DWORD d;
} IP_A;

typedef struct ethernet_header {
  MAC_A  Dest;
  MAC_A  Sender;
  WORD   Protocol;
  WORD   Data[1];      // 46 - 1500 bytes of data
} ETHERNET_HEADER;

typedef struct arp_header {
  WORD   HardwAdrSpace;      // usually 0x0001
  WORD   ProtocolAdrSpace;   // usually 0x0800
  BYTE   HwLen;              // usually 6 (MAC address len)
  BYTE   ProtLen;            // usually 4 (IP addresws len)
  WORD   Opcode;             // 1 request / 2 reply
  MAC_A  SenderHwAdr;
  IP_A   SenderProtAdr;
  MAC_A  DestHwAdr;
  IP_A   DestProtAdr;  
} ARP_HEADER;

void SendARPReply(ARP_HEADER huge *pARP) {
  ETHERNET_HEADER huge *pETH;
  ARP_HEADER huge *pARPDest;

  Ether.TxCMD2 = 0x00C9;	/* start xmit after entire frame is in CS8900 */
  Ether.TxLength = 42;

	/* wait until ready for xmit */
  while ((Ether.BusST & BUS_ST_RDY4TXNOW) == 0);

  pETH = (ETHERNET_HEADER huge *)&Ether.TransmitFrameLocation[0];
  /* copy the 6 byte dest hardware address */
  xmemcpy(&pETH->Dest, &pARP->SenderHwAdr, ETH_ALEN);
  /* copy the 6 byte source hardware address */
  xmemcpy(&pETH->Sender, &own_hw_addr[0], ETH_ALEN);
  /* copy the protocol 2 bytes, network order */
  pETH->Protocol = 0x0608;
  pARPDest = (ARP_HEADER huge *)pETH->Data;
  pARPDest->HardwAdrSpace    = 0x0100;
  pARPDest->ProtocolAdrSpace = 0x0008;
  pARPDest->HwLen            = 0x0006;
  pARPDest->ProtLen          = 0x0004;
  pARPDest->Opcode           = 0x0200;  //reply
  xmemcpy(&pARPDest->SenderHwAdr,   &own_hw_addr[0],     ETH_ALEN);
  xmemcpy(&pARPDest->SenderProtAdr, &own_ip_addr[0],     IP_LEN);
  xmemcpy(&pARPDest->DestHwAdr,     &pARP->SenderHwAdr,  ETH_ALEN);
  xmemcpy(&pARPDest->DestProtAdr,   &pARP->SenderProtAdr,IP_LEN);
}


void ProceedARP(ARP_HEADER huge *pARP) {

// check if ARP header is correct
  if (pARP->HardwAdrSpace    != 0x0100) return;
  if (pARP->ProtocolAdrSpace != 0x0008) return;
  if (pARP->HwLen            != 0x0006) return;
  if (pARP->ProtLen          != 0x0004) return;
  switch (pARP->Opcode) {
    case 0x0100: //ToDo enter addresses into ARP table // ARP request
                 if (xmemcmp(own_ip_addr, &pARP->DestProtAdr, IP_LEN)) return; // is it me?
                 SendARPReply(pARP);
                 break;
    case 0x0200: //ToDo enter addresses into ARP table // ARP reply
                 break;
    default:     // Ignore all other commands
                 break;
  }
}


void AnalyzeEthernetHeader(ETHERNET_HEADER huge *pETH) {
  
  switch (pETH->Protocol) {            // Protocol in revers byte order
    case 0x0008:                       // IP 
                 break;
    case 0x0608: ProceedARP((ARP_HEADER huge *)pETH->Data);   // ARP
                 break;
    case 0x3580:         // RARP
                 break;
    default:             // Ignore all other protocols
                 break;
  }
}



void EtherInt(void) interrupt 0x1F {
	WORD IRQSource;

	while ((IRQSource = Ether.ISQ) != 0)    /* Read Interrupt Service Queue */
		{
		switch(IRQSource & 0x003F) {
	    case 0x04:              // Receive Interrupt occured
// IRQSource contains the RxEvent Register contents
          AnalyzeEthernetHeader((ETHERNET_HEADER huge *)&Ether.ReceiveFrameLocation[0]);
	      break;

	    case 0x08:              // Transmit Interrupt occured
// IRQSource contains the TxEvent Register contents
	      break;

	    case 0x0C:              // Buffer Interrupt occured
// IRQSource contains the BufEvent Register contents
	      break;

	    case 0x10:              // Receive Buffer Miss Interrupt occured
// IRQSource contains the RxMISS Register contents
	      break;

	    case 0x12:              // Transmit Collision Counter Interrupt occured
// IRQSource contains the TxCOLL Register contents
	      break;

	    default:
// This should never occur
	      break;
		}
	}
}


/******************************************************************************/
/***************************      MAIN PROGRAM      ***************************/
/******************************************************************************/
void main ( void )  {                          /* main entry for program      */

	BYTE test_pkt[] = {"Hello, World\0"};

  if (CheckIOInterface() == FALSE) error();

  if (ResetChip() == FALSE) error();

  if (EnableMemInterface() == FALSE) error();

  if (InitChip() == FALSE) error();

  P2 |= 0x8000;               // Initialize external interrupt for ethernet controller
  DP2 &= 0x7FFF;
  CCM3 = 0x1000;
  CC15IC = 0x44;              // IE = 1, ILVL = 1, GLVL = 0
  IEN = 1;                    // enable all interrupts

  while(1)	{
	_nop_();
  }
}


 

⌨️ 快捷键说明

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