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

📄 dm9000.c

📁 dm9000ad驱动程序
💻 C
字号:
/*
********************************************************************************
*                        MARM7-01 for InterNiche TCP/IP
*
* File : bsp_8019.c
* By   : X.T.HUANG
*
* Notes:
*       1. 按照RTL8019AS芯片说明书,寄存器中的保留位应设为1
*       2. 该芯片内部的SRAM页面地址范围:40H ~ 7FH
*       3. 16位总线宽,小端模式
********************************************************************************
*/

#include "uCOS_II.h"
#include "os_cfg_r.h"
#include "intrDefine.h"
#include <stdio.h>
 
#include "ipport.h"
#include "netbuf.h"
#include "net.h"
#include "dm9000.h"

#include "../tcpip_init.h"
//#include "includes.h"

#include "dal_arm_gpio.h"
#include "dal_arm_mpuio.h"

OS_EVENT *DM9000T_Q; 
OS_EVENT *DM9000R_Q; 
#define  TASK_STK_SIZE                  1024
OS_STK        TaskStk[TASK_STK_SIZE];
OS_STK        TaskStartStk[TASK_STK_SIZE];
OS_STK        TaskTEMP[TASK_STK_SIZE];
OS_STK        TaskTEMP1[TASK_STK_SIZE];
 
 


/*=============================================================================
  DM9000A 接收函数设置宏
  =============================================================================*/


/*=============================================================================
  DM9000A 传送函数设置宏
  =============================================================================*/

/*=============================================================================
  系统全域的设置宏
  =============================================================================*/
 

// for ST5105
//#define   NET_BASE_ADDR			0x45000000
//#define   NET_CMD					(1 << 2)
//#define   NET_REG_ADDR			(*((volatile unsigned char *) NET_BASE_ADDR))
//#define   NET_REG_DATA			(*((volatile unsigned short *) (NET_BASE_ADDR + NET_CMD)))
//#define   NET_REG_DATA_byte		(*((volatile unsigned char *) (NET_BASE_ADDR + NET_CMD)))
//#define   NET_REG_DATA_word		(*((volatile unsigned short *) (NET_BASE_ADDR + NET_CMD)))

// for ST551X
#define   NET_BASE_ADDR			0x4000000
#define   NET_CMD				0x04
#define   NET_CMDB				0x02

#pragma   ST_device (unsigned char )
#pragma   ST_device (unsigned short )
 
#define   NET_REG_ADDR (*((unsigned char *) NET_BASE_ADDR))
#define   NET_REG_DATA (*((unsigned short *) (NET_BASE_ADDR + NET_CMD)))
#define   NET_REG_DATA_byte (*((unsigned char *) (NET_BASE_ADDR + NET_CMD)))
#define   NET_REG_DATA_word (*((unsigned short *) (NET_BASE_ADDR + NET_CMD)))

/*=============================================================================
  系统全域的变量
  =============================================================================*/
unsigned char  MyHardware[6] = { 0x00 , 0x80 , 0xe1 , 0x11 , 0x8d , 0x44};/*{0xF0 ,0xF1, 0xF2 , 0xF3 , 0xF4 ,0xF5};*/
unsigned char  Myip[4] = { 202, 195, 114, 23};
unsigned char  Receive_data[Max_Ethernet_Lenth]; 
unsigned char  Receive_datat[Max_Ethernet_Lenth+2]; 
void *DM9000_Rx_Pk[Max_Ethernet_Lenth];

//unsigned char  Receive_data[Max_Ethernet_Lenth]; 
unsigned char  Send_data[Max_Ethernet_Lenth] = 
       {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x08, 0x06, 
        0x00, 0x01, 
        0x08, 0x00,
        0x06,
        0x04,
        0x00, 0x01,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00
		};
		
/*  R-ARP
      0   1  2  3  4  5  6  7   8  9 10 11 12 13 14 15
0000  ff ff ff ff ff ff 00 00  00 00 00 00 08 06 00 01   
0010  08 00 06 04 00 01 00 00  00 00 00 00 00 00 00 00   
0020  00 00 00 00 00 00 00 00  00 00
*/
	
	
		
unsigned short ReceiveLength = 0;
/*-----------------------------------------------------------------------------
  读寄 DM9000A 寄存器
  reg          却读取寄存器的位置
  -----------------------------------------------------------------------------
  返回         读出寄存器的值 
  -----------------------------------------------------------------------------*/
unsigned char ior(unsigned char reg)
{
	NET_REG_ADDR = reg;
	return(NET_REG_DATA_byte);
}

/*-----------------------------------------------------------------------------
  写入 DM9000A 寄存器
  reg          却写入寄存器的位置
  writedata    却写入寄存器的值
  -----------------------------------------------------------------------------
  返回         无
  -----------------------------------------------------------------------------*/
void iow(unsigned char reg, unsigned char writedata)
{  
	NET_REG_ADDR = reg;
	NET_REG_DATA_byte = writedata;
} 
/*=============================================================================
  基本操作函数
  =============================================================================*/
/*-----------------------------------------------------------------------------
  等待操作函数
  -----------------------------------------------------------------------------
  返回         无
  -----------------------------------------------------------------------------*/
 

unsigned char device_ck(void)
{
	unsigned char i = 0x30;
	while(i-- && (ior(DM9000_REG_VID_L) != 0x46)) 
	 OSTaskDelay(1);
	
	return i;
}


/*-----------------------------------------------------------------------------
  设置 DM9000A MAC 、 广播 、 多播 寄存器
  -----------------------------------------------------------------------------
  返回         无
  -----------------------------------------------------------------------------*/
void dm9k_hash_table(void)
{
	unsigned char i;
	
#ifdef Fix_Note_Address
	MyHardware[0] = 0x00;
	MyHardware[1] = 0x60;
	MyHardware[2] = 0x6e;
	MyHardware[3] = 0x90;
	MyHardware[4] = 0x00;
	MyHardware[5] = 0xae;
#endif
	
	/* 设置 网卡 MAC 位置,来自於 MyHardware */
	for(i = 0; i < 6; i++)
		iow(DM9000_REG_PAR + i, MyHardware[i]);
	
	for(i = 0; i < 8; i++) 								/* 清除 网卡多播设置 */
		iow(DM9000_REG_MAR + i, 0x00);
	iow(DM9000_REG_MAR + 7, 0x80);  					/* 速设置 广播包 设置 */
}
/*-----------------------------------------------------------------------------
  写入 DM9000A PHY 寄存器
  phy_reg      却写入 PHY 寄存器的位置
  writedata    却写入 PHY 寄存器的值
  -----------------------------------------------------------------------------
  返回         无
  -----------------------------------------------------------------------------*/
void dm9k_phy_write(unsigned char phy_reg, unsigned short writedata)
{
	/* 设置写入 PHY 寄存器的位置 */
	iow(DM9000_REG_EPAR, phy_reg | DM9000_PHY);
	
	/* 设置写入 PHY 寄存器的值 */
	iow(DM9000_REG_EPDRH, ( writedata >> 8 ) & 0xff);
	iow(DM9000_REG_EPDRL, writedata & 0xff);
	
	iow(DM9000_REG_EPCR, 0x0a); 						/* 将资料写入 PHY 寄存器 */
	while(ior(DM9000_REG_EPCR) & 0x01);					/* 查是否执薪崾?*/
	iow(DM9000_REG_EPCR, 0x08); 						/* 清除写入命令 */
}

/*-----------------------------------------------------------------------------
  网卡 软件重置 函数
  -----------------------------------------------------------------------------
  返回         无
  -----------------------------------------------------------------------------*/
void dm9k_reset(void) 
{  
	//NIC_ENTER_CRITICAL();
	iow(DM9000_REG_NCR, DM9000_REG_RESET);			/* 对 DM9000A 进行软件重置 */
	OSTaskDelay(10);								/* delay 10us */	
	iow(DM9000_REG_NCR, DM9000_REG_RESET);			/* 对 DM9000A 进行软件重置 */
	OSTaskDelay(10);								/* delay 10us */	
	
	/* 基本记存器相关设置 */
	iow(DM9000_REG_IMR, DM9000_IMR_OFF); 			/* 开启内存自环模式 */
	iow(DM9000_REG_TCR2, DM9000_TCR2_SET);			/* 设置 LED 显示模式 */
	
	/* 清除多馀资讯 */
	iow(DM9000_REG_NSR, 0x2c);
	iow(DM9000_REG_TCR, 0x00);
	iow(DM9000_REG_ISR, 0x3f);
	
#ifdef DM9000A_FLOW_CONTROL
	iow(DM9000_REG_BPTR, DM9000_BPTR_SET);			/* 半双工流控设置 */
	iow(DM9000_REG_FCTR, DM9000_FCTR_SET);			/* 全双工流控设置 */
	iow(DM9000_REG_FCR, DM9000_FCR_SET);			/* 开启流控设置 */
#endif

#ifdef  Rx_Int_enable
	iow(DM9000_REG_IMR, DM9000_IMR_SET);			/* 开启 中断模式 */
#else
	iow(DM9000_REG_IMR, DM9000_IMR_OFF);			/* 关闭 中断模式 */
#endif
	
	iow(DM9000_REG_RCR, DM9000_RCR_SET);			/* 开启 接收工能 */
	//NIC_EXIT_CRITICAL();
}
/*=============================================================================
  初始化 及 软件重置 操作函数
  =============================================================================*/
/*-----------------------------------------------------------------------------
  网卡 初始化 函数
  -----------------------------------------------------------------------------
  返回         无
  -----------------------------------------------------------------------------*/
unsigned char InitNic(void)	 
{
	unsigned long device_id = 0;
	unsigned char device_check = 0;
	unsigned char device_ver = 0;
	
/*	
	U32 st7100emiaddr=0xba100000;

	*(volatile unsigned int*)(st7100emiaddr+0x0180)=0x002426d1;
	*(volatile unsigned int*)(st7100emiaddr+0x0188)=0x0a444444;
	*(volatile unsigned int*)(st7100emiaddr+0x0190)=0x0a444444;
	*(volatile unsigned int*)(st7100emiaddr+0x0198)=0x00000000;	
*/	
	
	iow(DM9000_REG_NCR, DM9000_REG_RESET);			/* 对 DM9000A 进行软件重置 */
	while(ior(DM9000_REG_NCR) & DM9000_REG_RESET)
	{
		OSTaskDelay(10);								/* delay 10us */	
	}
	
	iow(DM9000_REG_BUSCR, 0x61);
	
	device_id  = ior(DM9000_REG_VID_L);
	device_id |= ior(DM9000_REG_VID_H) << 8;
	device_id |= ior(DM9000_REG_PID_L) << 16;
	device_id |= ior(DM9000_REG_PID_H) << 24;
	
	device_check = ior(0x43) & 0x20;
	device_ver = ior(0x2c);
	
	if(device_ver <=  0x19)
	{
		device_check = 0x20;
		iow(DM9000_REG_BUSCR, 0x21);
	}
	
	if((device_id != 0x90000A46) || (device_check != 0x20))
	{
		myprintf("DM9K_DEBUG ==> DEIVCE NOT FOUND, SYSTEM ERR !!\n");
		myprintf("DM9K_DEBUG ==> id 0x%x check 0x%x !!\n", device_id, device_check);
		return 0;
	}
	
	iow(DM9000_REG_NCR, DM9000_REG_RESET);			/* 对 DM9000A 进行软件重置 */
	while(ior(DM9000_REG_NCR) & DM9000_REG_RESET)
	{
		OSTaskDelay(10);								/* delay 10us */	
	}
	
	dm9k_reset();									/* 进行 DM9000A 软件设置 */
	
	dm9k_hash_table();								/* 设置 DM9000A MAC 及 多播*/
	
	iow(DM9000_REG_GPR, DM9000_PHY_OFF);			/* 关闭 PHY ,进行 PHY 设置*/
	device_ck();
	dm9k_phy_write(0x00, 0x8000);					/* 重置 PHY 的寄存器 */
#ifdef DM9000A_FLOW_CONTROL
	dm9k_phy_write(0x04, 0x01e1 | 0x0400);			/* 设置 自适应模式相容表 */
#else
	dm9k_phy_write(0x04, 0x01e1);					/* 设置 自适应模式相容表 */
#endif
	dm9k_phy_write(0x00, 0x1200);					/* 设置 基本连接模式 */
	iow(DM9000_REG_GPR, DM9000_PHY_ON);				/* 结束 PHY 设置, 开启 PHY */
	device_ck();
 	
	return 1;
}




 
/*-----------------------------------------------------------------------------
  接收封包涵数
  -----------------------------------------------------------------------------
  返回         无
  -----------------------------------------------------------------------------*/


unsigned short Rec_Packet(void)  
{
	unsigned short *rx_packet = (unsigned short *) Receive_data;
	unsigned char  rx_checkbyte;
	unsigned short rx_status, rx_length;
	unsigned char  jump_packet;
	unsigned short i;
	unsigned short calc_len, calc_MRR;
	
	while(1)
	{
		jump_packet = 0;								/* 清除跳包动作 */
		ior(DM9000_REG_MRCMDX);							/* 更新读取指针内容 */
		/* 暂存目前的读取指针 */
		calc_MRR = (ior(DM9000_REG_MRRH) << 8) + ior(DM9000_REG_MRRL);
		rx_checkbyte = ior(DM9000_REG_MRCMDX);			/* 取回读取指针内容 */
		
		if(rx_checkbyte == DM9000_PKT_RDY)				/* 内存有封包需要读取 */
		{
			/* 读取封包相关资讯 及 长度 */
			NET_REG_ADDR = DM9000_REG_MRCMD;
			rx_status = NET_REG_DATA_word;
			rx_length = NET_REG_DATA_word;
			
			/* 若收到超过系统可承受的封包,此包跳过 */
			if(rx_length > Max_Ethernet_Lenth)
				jump_packet = 1;
			
#ifdef Broadcast_Jump
			/* 若收到的广播或多播包超过特定长度,此包跳过 */
			if(rx_status & 0x4000)
			{
				if(rx_length > Max_Broadcast_Lenth)
					jump_packet = 1;
			}
#endif
			/* 计算下一个包的指针位 , 若接收长度为奇数,需加一对齐偶字节。*/
			/* 若是超过 0x3fff ,则需回归绕到 0x0c00 起始位置 */
			calc_MRR += (rx_length + 4);
			if(rx_length & 0x01) calc_MRR++;
			if(calc_MRR > 0x3fff) calc_MRR -= 0x3400;
			
			if(jump_packet == 0x01)
			{
				/* 将指针移到下一个包的包头位置 */
				iow (DM9000_REG_MRRH, (calc_MRR >> 8) & 0xff);
				iow (DM9000_REG_MRRL, calc_MRR & 0xff );
				continue;
			}
			
			/* 开始将内存的资料搬到到系统中,每次移动一个 word */
			calc_len = (rx_length + 1) >> 1;
			for(i = 0 ; i < calc_len ; i++)
				rx_packet[i] = NET_REG_DATA_word;
			
#ifdef Fifo_Point_Check
			if(calc_MRR != ((ior(DM9000_REG_MRRH) << 8) + ior(DM9000_REG_MRRL)))
			{
#ifdef Point_Error_Reset
				dm9k_reset();								/* 若是指针出错,重置 */
#else
				/*若是指针出错,将指针移到下一霭

⌨️ 快捷键说明

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