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

📄 rtl8019.c

📁 该工程源码是基于EasyARM2200开发平台开发的嵌入式TCP/IP协议栈
💻 C
字号:
/*
*********************************************************************************************************
*                                              ModbusTCP
*                                   programmable human machine interface
*
*                         (c) Copyright 2007, 浙大中自集成控制股份有限公司开发二部
*                                          All Rights Reserved
*
* File : LcdDriver.c
* By   : lb
*********************************************************************************************************
*/
/***********************************************
8019的驱动,但是不会用它的查询去做,这样会影响实时性,中断的
处理机制我传给了ethernetif.c去做了。
************************************************/
#define __RTL8019__SLF__

#include "RTL8019.h"
#include "ucos_ii.h"
#include "def.h"

unsigned char  txd_buffer_select=0;   		//选择网卡的发送缓冲区  
static unsigned char next_page;
unsigned char My_hwaddr[6];

#define Rtl8019ResetLow 	IO0CLR |= 0x40; 
#define Rtl8019ResetHigh 	IO0SET |= 0x40;
#define P06DirOut			IO0DIR |= 0x40;

extern void ENT2_ISR(void);


void page(unsigned char pagenumber)
{
	unsigned char  temp;

	temp = Read8019Reg(0x00);
	temp=temp&0x3B ;
	pagenumber=pagenumber <<6;
	temp=temp | pagenumber;
	Write8019Reg(0x00, temp);
}


void Init8019GPIO(void)
{
	unsigned char i;
	PINSEL0 = 0xC000;
	i=100;
	while(i--);
	P06DirOut;
}


void InitINT(void)
{
	EXTMODE = 0x0f;					// 设置EINT1中断为边沿触发模式
  	EXTPOLAR = 0x0f;				// 设置EINT1中断为下降沿触发
	VICIntSelect = 0x00000000;		// 设置所有中断分配为IRQ中断
   	VICVectCntl6 = 0x20|16;			// 分配EINT1中断到向量中断0
   	VICVectAddr6 = (int)ENT2_ISR; 	// 设置中断服务程序地址
   	EXTINT = 0x04;					// 清除EINT1中断标志	
   	VICIntEnable |= 1<<16;			// 使能EINT1中断	*/
}

static void Rtl8019AS_Reset() //复位网卡
{
	Rtl8019ResetHigh;
	OSTimeDly(10);
	Rtl8019ResetLow;
	OSTimeDly(10);
}

static void WriteRtl8019NodeID(void)
{
	page(1);
	Write8019Reg(0x01, My_hwaddr[0]);
	Write8019Reg(0x02, My_hwaddr[1]);
	Write8019Reg(0x03, My_hwaddr[2]);
	Write8019Reg(0x04, My_hwaddr[3]);
	Write8019Reg(0x05, My_hwaddr[4]);
	Write8019Reg(0x06, My_hwaddr[5]);
	page(0);
}

void init_8019(void)
{
	unsigned char i;
	while(1)
	{
		Rtl8019AS_Reset();			//复位8019
		OSTimeDly(8);	
		Write8019Reg(0x00, 0x21);	//使芯片处于停止模式,这时进行寄存器设置 停止模式下,将不会发送和接收数据包
		OSTimeDly(8);				//延时10毫秒,确保芯片进入停止模式
		i = Read8019Reg(0x00);
		if(i == 0x21)
			break;
	}
	page(0);
	Write8019Reg(0x0a, 0x00);
	Write8019Reg(0x0b, 0x00);
	Write8019Reg(0x0c, 0xe0);	//monitor mode (no packet receive)
	Write8019Reg(0x0d, 0xe2);	//loop back mode 使芯片处于mon和loopback模式,跟外部网络断开

	Write8019Reg(0x01, 0x4c);
	Write8019Reg(0x02, 0x80);
	Write8019Reg(0x03, 0x4c);
	Write8019Reg(0x04, 0x40);

	Write8019Reg(0x07, 0xff);	//清除所有中断标志位
	Write8019Reg(0x0f, 0x11);	//disable all interrupt

	Write8019Reg(0x0e, 0xc8);	//byte dma 8位dma方式
	page(1);
	Write8019Reg(0x07, 0x4d);
	Write8019Reg(0x08, 0x00);
	Write8019Reg(0x09, 0x00);
	Write8019Reg(0x0a, 0x00);
	Write8019Reg(0x0b, 0x00);

	Write8019Reg(0x0c, 0x00);
	Write8019Reg(0x0d, 0x00);
	Write8019Reg(0x0e, 0x00);
	Write8019Reg(0x0f, 0x00);

	Write8019Reg(0x00, 0x22);	//这时让芯片开始工作
	//ReadRtl8019NodeID();		//读出网卡的物理地址48位  
	WriteRtl8019NodeID();		//将网卡地址写入到mar寄存器  
	page(0);

	Write8019Reg(0x0c, 0xcc);	//将网卡设置成正常的模式,跟外部网络连接
	Write8019Reg(0x0d, 0xe0);
	Write8019Reg(0x00, 0x22);	//这时让芯片开始工作
	Write8019Reg(0x07, 0xff);	//清除所有中断标志位
}

void send_frame(unsigned char * outbuf, unsigned short len)/*发送一个数据包的命令,长度最小为60字节,最大1514字节*/
{
	unsigned char i;
	unsigned short ii;
	unsigned char temp;
	
	page(0);
	if(len<60)len=60;
	txd_buffer_select=!txd_buffer_select;
  	if(txd_buffer_select)
		Write8019Reg(0x09, 0x40);		//txdwrite highaddress将远程DMA地址分为两个,40-45,46-4b。前面用于发送包。
	else
		Write8019Reg(0x09, 0x46);		//txdwrite highaddress后面用于构造端的包

	Write8019Reg(0x08, 0x00);				//read page address low
	Write8019Reg(0x0b, (unsigned char)(len>>8));	//read count high
	Write8019Reg(0x0a, (unsigned char)(len&0xff));	//read count low
	Write8019Reg(0x00, 0x12);				//write dma, page0从远端DMA写到8019RAM中数据
	for(ii=0; ii<len; ii++)	//for(ii=4;ii<len+4;ii++)  //是否加4有待验证
	{
		Write8019Reg(0x10, *(outbuf+ii));
	}

	/* 以下3句为中止dma的操作,可以不要            */
//	reg0b=0x00;		//read count high   中止DMA操作
//	reg0a=0x00;		//read count low;
//	reg00=0x22;		//complete dma page 0

	for(i=0;i<16;i++)	//最多重发16次
	{
		for(ii=0;ii<1000;ii++)	//检查txp为是否为低
		{
			temp = Read8019Reg(0x00);
			if((temp&0x04)==0) break;
		}

		temp = Read8019Reg(0x04);
		if((temp&0x01)!=0) break;	//表示发送成功,如果不成功,则执行reg00=3e,继续发送。
		
		Write8019Reg(0x00, 0x3e);
	}

	Write8019Reg(0x07, 0xff);	//清除所有中断标志位
	if(txd_buffer_select)
		
		Write8019Reg(0x04, 0x40);	//txd packet start; //设置发送开始页的地址
	else 
		Write8019Reg(0x04, 0x46);	//txd packet start;
	Write8019Reg(0x06, (unsigned char)(len>>8));	//high byte counter要发送的包的字节数(长度)
	Write8019Reg(0x05, (unsigned char)(len&0xff));	//low byte counter

	Write8019Reg(0x07, 0xff);		//清除所有中断
	Write8019Reg(0x00, 0x3e);		//to sendpacket;  从本地DMA中发送包

}

char query_8019(void)
{   
	unsigned char my_bnry=0;
	unsigned char my_curr=0;
	
	page(0);
	my_bnry = Read8019Reg(0x03);	//bnry page have read 读页指针
	
	page(1);
	my_curr = Read8019Reg(0x07);	//curr writepoint 8019写页指针
	
	page(0);
	if ((my_curr==0))	return 0;
	my_bnry++;
	if (my_bnry>0x7f)	my_bnry=0x4c;
	if (my_bnry!=my_curr)		//此时表示有新的数据包在缓冲区里
	{
		Write8019Reg(0x0b, 0x00);	//complete dma page 0			//
		Write8019Reg(0x0a, 0x00);									//	
		Write8019Reg(0x00, 0x22);
		return 1;
	}
	Write8019Reg(0x0b, 0x00);	//complete dma page 0			//
	Write8019Reg(0x0a, 0x00);									//	
	Write8019Reg(0x00, 0x22);
	return 0;
	//Write8019Reg(0x0b, 0x00);	//complete dma page 0
	//Write8019Reg(0x0a, 0x00);
	//Write8019Reg(0x00, 0x22);
}

unsigned short GetPackedLen(void)
{
	unsigned char bnry,curr;

	unsigned short len=0x0000;
	unsigned char temp;

	page(0); 	//bnry page have read 读页指针
	bnry = Read8019Reg(0x03);
	
	page(1);	//curr writepoint 8019写页指针
	curr = Read8019Reg(0x07);
	
	page(0);
	if ((curr==0))	return 0;	//读的过程出错
	next_page=bnry;
	bnry++;
	if (bnry>0x7f)	bnry=0x4c;
	if (bnry!=curr)	//此时表示有新的数据包在缓冲区里
	{
		//读取一包的前4个字节:4字节的8019头部
		page(0);
		//read page address high
		Write8019Reg(0x09, bnry);
		//read page address low
		Write8019Reg(0x08, 0x00);
		//read count high
		Write8019Reg(0x0b, 0x00);
		//read count low;
		Write8019Reg(0x0a, 0x04);
		//read dma
		Write8019Reg(0x00, 0x0a);

		temp = Read8019Reg(0x10);
		temp = Read8019Reg(0x10);
		
		next_page = temp-1;		//next page start-1

		len = Read8019Reg(0x10);
		temp = Read8019Reg(0x10);
		len += temp<<8;

	 	Write8019Reg(0x0b, 0x00);	//complete dma page 0
	 	Write8019Reg(0x0a, 0x00);
	 	Write8019Reg(0x00, 0x22);
	 	return len;
	}
	return 0;	
}


void rcve_frame(unsigned char * inbuf, unsigned short len)
{
	unsigned char bnry,curr;

	unsigned short ii;
	
	if (inbuf == NULL)
	{
		//out of RAM
		//Tell 8019 to skip the frame
		page(1);	//page1
		curr = Read8019Reg(0x07);
		page(0);		//切换回page0
        bnry = curr -1;
        if(bnry < 0x4c) bnry =0x7f;	//write to bnry   
		Write8019Reg(0x03, bnry);	//清除中断状态可以不用
		Write8019Reg(0x07, 0xff);
		return;
	}
	
	page(0); 	//bnry page have read 读页指针
	bnry = Read8019Reg(0x03);
	
	page(1);	//curr writepoint 8019写页指针
	curr = Read8019Reg(0x07);
		
	//This flag keeps track of allocated rcve memory
	//rcve_buf_allocated = TRUE;
	//Call the assembler function to get the incoming frame
	//read page address high
	Write8019Reg(0x09, bnry);	//read page address low
	Write8019Reg(0x08, 0x04);	//read count high
	Write8019Reg(0x0b, (unsigned char)(len>>8));	//read count low;
	Write8019Reg(0x0a, (unsigned char)(len&0xff));	//read dma
	Write8019Reg(0x00, 0x0a);
    for(ii=0;ii<len;ii++)
    {
    	inbuf[ii] = Read8019Reg(0x10);
    }
	//dma complete  page0     
   	Write8019Reg(0x0b, 0x00);
   	Write8019Reg(0x0a, 0x00);
   	Write8019Reg(0x00, 0x22);
   	//Return pointer to start of buffer
	bnry=next_page;
	if (bnry<0x4c)  bnry=0x7f;	//write to bnry
	Write8019Reg(0x03, bnry);
    Write8019Reg(0x07, 0xff);
	return;	
}

⌨️ 快捷键说明

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