📄 emac.c
字号:
#include "at91rm9200.h"
#include "emac.h"
#include "routine.h"
#include "uart.h"
static rbd_list rbdl[LISTLENGTH]; //receive buffer descriptor list
static unsigned int recv_buf[LISTLENGTH][MAXFRAME]; //receive buffer
static unsigned char send_buf[MAXFRAME]; //buffer for packet to be sent
static unsigned char local_mac[6]; //local mac
static unsigned char local_ip[4]; //local ip
static unsigned char server_mac[6]; //server mac
static unsigned char server_ip[4]; //server ip
static unsigned char target_mac[6]; //target mac
static unsigned char target_ip[4]; //target ip
static void set_local_mac( emac_reg_p emac ) {
local_mac[0] = 0x00;
local_mac[1] = 0x11;
local_mac[2] = 0xd8;
local_mac[3] = 0xe8;
local_mac[4] = 0x34;
local_mac[5] = 0x2c;
emac->eth_sa1l = local_mac[5] | (local_mac[4]<<8) | (local_mac[3]<<16) | (local_mac[2]<<24);
emac->eth_sa1h = local_mac[1] | (local_mac[0]<<8);
}
static void set_local_ip( ) {
local_ip[0] = 0xac;
local_ip[1] = 0x10;
local_ip[2] = 0x64;
local_ip[3] = 0xf1;
}
static void set_server_ip( ){
server_ip[0] = 0xac;
server_ip[1] = 0x10;
server_ip[2] = 0x64;
server_ip[3] = 0xe9;
}
static unsigned mii_readPhy(emac_reg_p emac, unsigned char reg){
unsigned value = 0x60020000 | (reg<<18);
emac->eth_ctl |= EMAC_MPE;
emac->eth_man = value;
while( !(emac->eth_sr&EMAC_IDLE) );
emac->eth_ctl &= ~EMAC_MPE;
return (unsigned)(emac->eth_man&0xffff);
}
static void get_link_speed( emac_reg_p emac ){
unsigned short value;
unsigned int update;
value = mii_readPhy(emac, MII_STATUS2);
if( !( value & 0x400 ) )
return;
if( value & 0x4000 )
update |= EMAC_SPD;
if( value & 0x200 )
update |= EMAC_FD;
emac->eth_cfg = emac->eth_cfg & ~( EMAC_SPD | EMAC_FD ) | update;
}
static void emac_configure() {
int i;
emac_reg_p emac = (emac_reg_s *)EMAC_BASE;
for(i=0; i<LISTLENGTH; i++){ //setup recv buf pointers
rbdl[i].address = (unsigned) ( recv_buf[i] );
rbdl[i].size = 0;
}
rbdl[i-1].address |= 0x2;
emac->eth_ctl = 0;
if( !(emac->eth_sr & EMAC_LINK) )
get_link_speed( emac );
set_local_mac( emac );
set_local_ip();
set_server_ip();
emac->eth_rbqp = (unsigned) rbdl;
emac->eth_rsr |= (EMAC_BNA | EMAC_REC | EMAC_OVR);
emac->eth_cfg |= EMAC_CAF;
emac->eth_cfg = ( emac->eth_cfg & ~(EMAC_CLK) ) | EMAC_CLK_32;
emac->eth_ctl |= (EMAC_TE | EMAC_RE);
emac->eth_tar = (unsigned)send_buf;
}
void emac_init() {
unsigned temp;
arp_packet * arp = (arp_packet *) send_buf;
pio_reg_p pioa = (pio_reg_s *)PIOA_BASE;
pio_reg_p piob = (pio_reg_s *)PIOB_BASE;
pmc_reg_p pmc = (pmc_reg_s *)PMC_BASE;
pmc->pmc_pcer = ( (unsigned) 0x1<<ID_EMAC);
temp = 0x1ff80;
pioa->pio_asr |= temp;
pioa->pio_bsr &= ~temp;
pioa->pio_pdr = temp;
temp = 0xff000;
pioa->pio_asr &= ~temp;
pioa->pio_bsr |= temp;
pioa->pio_pdr = temp;
p_memset( (char*)arp->stuff, 0, 6 );
emac_configure();
}
void arp_frame( int op ) {
arp_packet * arp = (arp_packet *) send_buf;
emac_reg_p emac = (emac_reg_s *)EMAC_BASE;
p_memcpy( (char*)local_mac, (char*)arp->srcAddr, 6 );
arp->frameLen = SWAP16( TYPE_ARP );
arp->hardware = SWAP16(1);
arp->protocol = SWAP16(TYPE_IP);
arp->hlen = 6;
arp->plen = 4;
p_memcpy( (char *)local_mac, (char *)(arp->sendHA), 6);
p_memcpy( (char *)local_ip, (char *)arp->sendIP, 4);
if( op == REQUEST ) {
p_memset( (char*)arp->dstAddr, 0xff, 6);
arp->operation = SWAP16(1);
p_memset( (char *)arp->targetHA, 0, 6);
p_memcpy( (char *)server_ip, (char *)arp->targetIP, 4);
}
else if( op == REPLY ) {
p_memcpy( (char*)target_mac, (char*)arp->dstAddr, 6 );
arp->operation = SWAP16(2);
p_memcpy( (char*)target_mac, (char*)arp->targetHA, 6 );
p_memcpy( (char*)target_ip, (char*)arp->targetIP, 4 );
}
}
void send_packet( ) {
emac_reg_p emac = (emac_reg_s *)EMAC_BASE;
while( !(emac->eth_tsr & EMAC_BNQ) );
emac->eth_tsr |= EMAC_COMP;
emac->eth_tar = (unsigned)send_buf;
emac->eth_tcr = 0x40;
}
static void delay_millis( ) {
int i, max;
for( i=0; i<FCOUNT; i++ );
}
static void format_string( char *str, char* mac ) {
int i, j;
for( i=0; i<6; i++ ) {
*str = ASCII_HI( mac[i] );
str++;
*str = ASCII_LO( mac[i] );
str++;
if( i==5 )
*str = '\0';
else {
*str = '.';
str++;
}
}
}
void emac_test() {
int i, frame;
emac_reg_p emac = (emac_reg_s *)EMAC_BASE;
arp_packet * arp;
char mac[18];
put_s( "arp test begin.\r\n" );
arp_frame( REQUEST );
send_packet();
while(1) {
// put_s( "." );
delay_millis( 1 );
for(frame=-1, i=0; i<LISTLENGTH; i++) {
if( rbdl[i].address & 0x1 ) {
frame = i;
emac->eth_rsr |= 0x2;
break;
}
}
if( frame<0 )
continue;
put_s( "got a frame.\r\n" );
arp = (arp_packet*) ( rbdl[frame].address & 0xfffffffc );
if( arp->frameLen == SWAP16( TYPE_ARP ) ) {
if( p_memcmp( (char*)arp->targetIP, (char*)local_ip, 4 ) ) {
if( arp->operation == SWAP16( REQUEST ) ) {
p_memcpy( (char*)arp->sendHA, target_mac, 6 );
p_memcpy( (char*)arp->sendIP, target_ip, 6 );
put_s( "mac:\t" );
format_string( (char*) mac, (char*)target_mac );
put_s( "\r\n" );
arp_frame( REPLY );
send_packet();
}
if( arp->operation == SWAP16( REPLY ) ) {
p_memcpy( (char*)arp->sendHA, server_mac, 6 );
format_string( (char*)mac, (char*)server_mac );
break;
}
}
}
}
put_s( "The MAC for AC.10.64.E9 is:\t" );
put_s( (char*) mac );
put_s( "emac test end.\r\n" );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -