📄 dm9000.c.bak
字号:
/*
********************************************************************************
* 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 + -