📄 dm9000.c
字号:
#define __DM9000
#include "uCOS_II/SOURCE/API/os_api.h"
#include "uCOS_II/include/ucos_ii.h"
#include "uCOS_II/include/OS_CPU.h"
#include "dm9000.h"
#undef __DM9000
#define rTCNTO4 (*(volatile unsigned *)0x51000040)
#define IPaddr_t unsigned long
#define NSR_TX2END (1<<3)
#define NSR_TX1END (1<<2)
unsigned long timestamp;
unsigned long lastdec; // 上次所得计数值. 用于换算CPU运行时间.
int timer_load_val ; // 定时器装载值
//********************** Global Variable **********************
// 网络数据缓冲区
volatile u_char * NetTxPacket; // 发送包 /* THE transmit packet */
volatile u_char * NetRxPackets[PKTBUFSRX]; // 接收包 /* Receive packets */
// 网卡参数
char MACAddr[] = {8, 1, 62, 38, 10, 91}; // MAC地址
IPaddr_t IPAddr = 0x0A0A0A76; // 自身IP地址: 10.10.10.118
IPaddr_t GateAddr = 0x0a0a0afe; // 网关: 10.10.10.254
IPaddr_t MaskAddr = 0xffffff00; // 子网掩码: 255.255.255.0
IPaddr_t ServerAddr = 0x0A0A0A1A; // 服务器地址: 10.10.10.26
//*************************************************************
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 取DM9000ID.
// 描述: packet page register access functions.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
u32_t GetDM9000ID (void)
{
u32_t id_val;
DM9000_PPTR = DM9000_PID_H;
id_val = (DM9000_PDATA & 0xff) << 8;
DM9000_PPTR = DM9000_PID_L;
id_val+= (DM9000_PDATA & 0xff);
id_val = id_val << 16;
DM9000_PPTR = DM9000_VID_H;
id_val += (DM9000_PDATA & 0xff) << 8;
DM9000_PPTR = DM9000_VID_L;
id_val += (DM9000_PDATA & 0xff);
return id_val;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网卡I/O写.
//
// [参数表]
// reg: 寄存器号.
// value: 写入值.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static void dm9000_iow(int reg, u8_t value)
{
DM9000_PPTR = reg;
DM9000_PDATA = value & 0xff; //value & 0xff = value ;00001110&11111111=00001110
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网卡I/O读.
//
// [参数表]
// reg: 寄存器号.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static unsigned char dm9000_ior(int reg)
{
DM9000_PPTR = reg;
return DM9000_PDATA & 0xff;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网卡复位.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static void eth_reset (void)
{
int IoMode,i;
dm9000_iow(0, 1); /* register 0 set 1 in order to reset, auto clean after 10us*/
for( i=0; i<1000; i++ ); // 延时
IoMode = dm9000_ior(0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */
dm9000_iow(0x1e, 0x01); /* Let GPIO0 output */
dm9000_iow(0x1f, 0x00); /* Enable PHY , Let GPIO0 output value = 0*/
dm9000_iow(0xff, 0x80); /* disable interrupt and sram read/write point auto return*/
dm9000_iow(0x01, 0xc); /* clear TX status */
dm9000_iow(0x05, 0x33); /* enable rx fuction, note: must set promiscuous mode */
dm9000_ior(0x06);
dm9000_iow(0x02, 1); /* enable tx fuction */
IoMode = dm9000_ior(0x01);
}
//Eint9中断服务程序
//__irq void Eint9_ISR(void)
void irqDM9000ISR(void)
{
//extern HANDLER hEthernetInput;
U16 ulIntStatus, ulReceiveStatus;
U32 len,i, tx_status;
OSPrintf("\nEnter interrupt\n");
OSIntEnter();
{
//U16 ulIntStatus, ulReceiveStatus;
//* 获取中断状态
ulIntStatus = dm9000_ior(0xfe);
//*清除中断
dm9000_iow(0xfe, ulIntStatus);
if (ulIntStatus & 0x01) {
OSPrintf("\nEnter rx interrupt\n");
//OSAPISemSend(hEthernetInput);
}
//ulReceiveStatus = dm9000_ior(0x06);
if (ulIntStatus & 0x02) {
OSPrintf("\nEnter tx interrupt\n");
tx_status = dm9000_ior(0x01);/* Got TX status */
//if(tx_status & (NSR_TX2END | NSR_TX1END))
//{
//}
}
//len = eth_rx();
//len = receivepacket(Buffer);
//OSPrintf("接收数据长度:%d <--->",len);
//OSPrintf("\r\n数据接收\r\n");
//ClearPending(BIT_EINT4_7);
rSRCPND |= 0x1<<5;
rINTPND |= 0x1<<5 ;
rEINTPEND |= 1<<9;
}
OSIntExit();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 初始化网卡.
// 描述: 初始化DM9000.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void DM9k_init(void)
{
//extern HANDLER hEthernetInput;
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr = 0;
#endif
int i=0, oft;
UBYTE ubDelaySeconds = 0;
u32_t ID = 0;
//ID = GetDM9000ID(); // 取网卡ID号
//if ( ID != DM9000_ID) // 若ID验证失败, 则跳出
// return;
OSPrintf("Intialize dm9000!\r\n");
while ((ID != DM9000_ID)&&(i++<3)) {
// 若ID验证失败, 则反复读取
eth_reset (); // 网卡重置
ID = GetDM9000ID(); // 取网卡ID号
OSTimeDlyHMSM(0, 0, ubDelaySeconds, 0);
}
OSPrintf("Success to read dm9000 id which is %x\n", ID);
//eth_reset (); // 网卡重置
//hEthernetInput = OSAPISemNew(0);
for( i=0, oft=0x10; i<6; i++, oft++) {
// 写入MAC地址
dm9000_iow(oft, MACAddr[i]);
}
// 设置dm9000中断
OS_ENTER_CRITICAL()
{
//GPG1设置为EINT9,DM9000的INT连接EINIT9 [3:2]=10
rGPGCON = (rGPGCON & (~(0x03<<2))) | (0x02<<2);
//rEXTINT0 = (rEXTINT0 & (~(0x07<<28))) | (0x01<<28);
rEXTINT1 = (rEXTINT1 & (~(0x07<<4))) | (0x01<<4);
//EINIT9中断使能
rEINTMASK = rEINTMASK & (~(0x01<<9));
//rINTMOD |= 0x01<<5;
//ChearPending()清除SCRPND和INTPND对应的位,rSRCPND = bit;rINTPND = bit;rINTPND;
//ClearPending(BIT_EINT4_7); //BIT_EINT4_7 (0x1<<4)
rSRCPND |= 0x1<<5;
rINTPND |= 0x1<<5 ;
//pISR_EINT8_23 = (U32)Eint9_ISR;
pISR_EINT8_23 = (U32)irqDM9000ISR;
rINTMSK = rINTMSK & (~(BIT_EINT4_7));
}
OS_EXIT_CRITICAL()
// dm9000中断使能
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网络接收一个数据包.
// 描述: Get a data block via Ethernet.
//
// 返回: 数据包长度.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int eth_rx (void)
{
int i;
unsigned short rxlen;
unsigned short *addr;
unsigned short status;
u8_t RxRead;
RxRead = dm9000_ior(0xf1);
RxRead = dm9000_ior(0xf0);
RxRead = (DM9000_PDATA) & 0xff;
RxRead = (DM9000_PDATA) & 0xff;
if (RxRead != 1) /* no data */
return 0;
DM9000_PPTR = 0xf2; /* set read ptr ++ */
status = DM9000_PDATA; /* get status */
rxlen = DM9000_PDATA; /* get len */
// 数据包长度溢出, 返回
if (rxlen > PKTSIZE_ALIGN + PKTALIGN)
return 0;
// 接收数据包
for( addr=(unsigned short *)NetRxPackets[0], i=rxlen>>1; i>0; i--)
*addr++ = DM9000_PDATA;
if (rxlen & 1) {
*addr = DM9000_PDATA;
}
//NetReceiveProcess (NetRxPackets[0], rxlen); // 网络接收数据包处理
rGPFDAT ^= (0x01 << 4);
return rxlen; // 返回数据包长度
}//eth_rx()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//函数:函数拷贝缓冲池里的数据,传给low_level_input函数使用.
//描述:for the function low_level_input ,need to know ,if it is not usefull
//[参数表]:
//len :数据包长度.间接从eth_rx()函数里读取
//返回:数据包首地址
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
u8_t *revc_frame(u16_t len)
{
u8_t *ptr ;
//ptr = pbuf_alloc(PBUF_RAW,len,PBUF_POOL) ;
memcpy(ptr,NetRxPackets,len) ;
return ptr ;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网络发送一个数据包.
// 描述: Send a data block via Ethernet.
//
// [参数表]
// packet: 数据包地址.
// length: 数据包长度.
//
// 返回: 数据包长度.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int eth_send (volatile void *packet, int length)
{
volatile unsigned short *addr;
int tmo;
u8_t TxStatus;
int length1 = length;
int IoMode, TryTimes=0, TryTimes1=0;
while (1) {
TryTimes++;
if (TryTimes > 5) { // 试5次
break;
}
TxStatus = dm9000_ior( 0x01);
TxStatus = TxStatus & 0xc;
/*if(!TxStatus) // 发送完成置零,要判是否连接OK
{
TryTimes1 = 0;
for( tmo = get_timer(0)+CFG_HZ; get_timer(0)< tmo; )
{
TryTimes1++;
if( TryTimes1>5000 )
{
eth_reset ();
return 1;
}
}
IoMode = dm9000_ior( 0x01);
if(IoMode & 0x40) // 没有连接, 重新复位再试
eth_reset ();
}
else
break;*/
if (TxStatus) {
break;
}
TryTimes1 = 0;
for (tmo = get_timer(0)+CFG_HZ; get_timer(0)< tmo; ) {
TryTimes1++;
if (TryTimes1>5000) {
eth_reset ();
return 1;
}
}
IoMode = dm9000_ior( 0x01);
if (IoMode & 0x40) { // 没有连接, 重新复位再试
eth_reset ();
}
}
DM9000_PPTR = 0xf8; /* data copy ready set */
/* copy data */
for (addr = packet; length > 0; length -= 2)
DM9000_PDATA = *addr++;
dm9000_iow(0xfd, (length1 >> 8) & 0xff); /*set transmit leng */
dm9000_iow(0xfc, length1 & 0xff);
/* start transmit */
dm9000_iow(0x02, 1);
rGPFDAT ^= (0x01 << 5);
return 0;
}//eth_send()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//自己添加一个函数.函数get_timer
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
u_long get_timer(int t)
{
unsigned long now;
now = rTCNTO4; // 读出当前定时器计数值
if (lastdec >= now) // 根据上次所得计数值与本次所得计数值之间的大小关系换算出CPU运行时间
{
// normal mode
timestamp += lastdec - now;
}
else
{
// we have an overflow ...
timestamp += lastdec + timer_load_val - now;
}
lastdec = now; // 用本次采用的定时器计数值更新上次所得计数值
return timestamp-t;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -