Forum Discussion
DE2 Ethernet Primitive Solution
With the DE2 board, the Ethernet controller does not seem to work in Quartus II 8.0 or 8.1. There are several problems with the DE2_NET demonstration; it was built pre-7.1, the software driver does not work, the support is for crap, nobody seems to post anything useful on this topic etc. So here is the answer I would have killed for a month ago; in the DM9000A ISR, re-initialize the DM9000A and set a flag. In the main program loop, register the ISR again and clear the flag.
Sample code: //--------------------------------------------------------------# include "basic_io.h"# include "test.h"# include "LCD.h"# include "DM9000A.C" # define DE2_8_7Segs_BASE 0x01901028 unsigned int aaa,rx_len,i,packet_num; unsigned char RXT[68]; unsigned int EnetReceive; void ethernet_interrupts() { packet_num++; aaa=ReceivePacket (RXT,&rx_len); //Do your processing here. //Reinitialize the DM9000A and set the flag to setup the //ISR pointer. DM9000_init(); EnetReceive = TRUE; } int main(void) { unsigned int Success; unsigned char TXT[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x01,0x60,0x6E,0x11,0x02,0x0F, 0x08,0x00,0x11,0x22,0x33,0x44, 0x55,0x66,0x77,0x88,0x99,0xAA, 0x55,0x66,0x77,0x88,0x99,0xAA, 0x55,0x66,0x77,0x88,0x99,0xAA, 0x55,0x66,0x77,0x88,0x99,0xAA, 0x55,0x66,0x77,0x88,0x99,0xAA, 0x55,0x66,0x77,0x88,0x99,0xAA, 0x55,0x66,0x77,0x88,0x99,0xAA, 0x00,0x00,0x00,0x20 }; //Initialize the LCD. LCD_Init(); //Test the LCD. Success = DM9000_init(); LCD_Show_Text(""); if (Success == DMFE_SUCCESS) { //Tell the user if the DM9000A initialize or failed. LCD_Show_Text("DM9000A"); LCD_Line2(); LCD_Show_Text("Initialized."); alt_irq_register( DM9000A_IRQ, NULL, (void*)ethernet_interrupts ); } else { LCD_Show_Text("DM9000 Failed."); } packet_num=0; EnetReceive = FALSE; //Main loop. while (Success == 0) { //Register the ISR again after the ISR has fired and the device has been //re-initialized. if (EnetReceive == TRUE) { alt_irq_register( DM9000A_IRQ, NULL, (void*)ethernet_interrupts ); EnetReceive = FALSE; } Success = TransmitPacket(TXT,0x40); msleep(500); outport(DE2_8_7SEGS_BASE ,packet_num); } LCD_Show_Text("TX Failed."); return 0; } //------------------------------------------------------------------------- /* To get a full grasp of why this works read ·http://www.altera.com/literature/hb/nios2/n2sw_nii52006.pdf If you are doing this as a continuing project, become very familiar with the ISO-OSI 7 model and device networking. Note: Currently this code is very sloppy and needs revision. The true event in the init function needs to be determined. The only reason I posted this "as-is" was because of the crazy ammount of time I spent on this problem and the elation which comes with success. */21 Replies
- Altera_Forum
Honored Contributor
Hi Adam.
I don´t think that is a solution for the problem. One, because you get a very slow transfer data rate after that. And another curious thing, is that I get the DE2_NET working fine with a loop pack (like the DE2 manual example), without re initializing the DM9000. Although is correct that initializing the DM9000 you can get it working, it is not very usefull, should be something missing more, to avoid the init() routine each time to recieve a packet. Just a thought. - Altera_Forum
Honored Contributor
I agree fully; the central reason I posted the code was it worked. With Quartus 8 and 8.1 web, I could not get packet reception, even at a very slow rate, without the system crashing.
Re-initializing is sloppy and is probably the equivalent of killing a fly with an RPG. I will post a later revision, probably toward the end of this month, or early April, which will contain the the proper sequence for packet reception. For some reason, I could not get the loop-back functionality to work for packet reception; I'll have to play around with it. The primary reasoning for this thread is to get someone off the ground who is having the same problem. My current thought is the drive is not entirely functional for reception; the interrupt mask may not be cleared or the memory does not flush, indicative of an issue with the DE2_NET demo. Thank you for taking the time to go through this; if you find a solution before me, I would love to see it. I'm really only interested in the primitives. Thank You, Adam F. - Altera_Forum
Honored Contributor
I am trying to use ur code for DM9000A, but without LCD.h and test.h.
but the driver could not initialize the DM9000A and prompts "DM9000A failed" what may be the problem? can u help - Altera_Forum
Honored Contributor
Hello,
I am having different problem. I send one packet to board, ISR executes, ReceivePacket function executes but then even though I don't send any packet, the ISR keeps running. When I set a breakpoint in ReceivePacket, I see rx_READY = IORD(DM9000A_BASE,IO_data)&0x03; rxReady is 0. But the algorithm doesn't care for this status. So I changed it like this: rx_READY = IORD(DM9000A_BASE,IO_data); if ((rx_READY & 0x01) == 1 ) { ... receive packet... } else //---UNCOMMENTED rest-- if ((rx_READY & 0x02) != 0 )//rx_READY) /* status check first byte: rx_READY Bit[1:0] must be "00"b or "01"b */ { //same code } but this is still not a good solution since ISR enters once more to reset the device. So how can I tell ISR not to enter ISR again after receiving the packet I already sent. What should I do? Clear ISR status/stop int request etc.. after receiving packet? According to datasheet, ISR Status Register-Packet Received bit is a RW/C1 so one has to write 1 to correspond bit. So I did a iow to ISR in ReceivePacket function. This solved the problem but I still don't think this as a good solution. Many thanks, Luisa - Altera_Forum
Honored Contributor
:confused:
--- Quote Start --- I am trying to use ur code for DM9000A, but without LCD.h and test.h. but the driver could not initialize the DM9000A and prompts "DM9000A failed" what may be the problem? can u help --- Quote End --- Are you using the DE2_NET example? It shipped with the board on a disk; without it, the code I wrote is pretty useless. Also, an e-mail address will help. I'm usually against doing other people's work, but I can hand over what I developed if everything is on a university chain. This is pretty involved, I also need to know a bit about which HW modules you are using. The problem I ran into was I would receive one packet and never get another. - Altera_Forum
Honored Contributor
TO_BE_DONE
- Altera_Forum
Honored Contributor
hi,
I found there are some problem with the ReceivePacket function: I post my code: unsigned int ReceivePacket (unsigned char *data_ptr,unsigned int *rx_len) { unsigned char rx_READY,GoodPacket; unsigned char Tmp, RxStatus; unsigned int high_b,low_b; unsigned int i; RxStatus = rx_len[0] = 0; GoodPacket=FALSE; /* mask NIC interrupts IMR: PAR only */ iow(IMR, PAR_set); /* dummy read a byte from MRCMDX REG. F0H */ rx_READY = ior(MRCMDX); /* got most updated byte: rx_READY */ rx_READY = IORD(DM9000A_BASE,IO_data)&0x03; usleep(STD_DELAY); /* reset the read pointer*/ Tmp = ior(0xF5); printf("RD_P:0x%02X",Tmp); Tmp = ior(0xF4); printf("%02X\n",Tmp); Tmp = ior(0x25); printf("WR_P:0x%02X",Tmp); Tmp = ior(0x24); printf("%02X\n",Tmp); /* check if (rx_READY == 0x01): Received Packet READY? */ if (rx_READY == DM9000_PKT_READY) { /* got RX_Status & RX_Length from RX SRAM */ IOWR(DM9000A_BASE, IO_addr, MRCMD); /* set MRCMD REG. F2H RX I/O port ready */ usleep(STD_DELAY); IORD(DM9000A_BASE,IO_data); /*move pointer to status address*/ RxStatus = IORD(DM9000A_BASE,IO_data); usleep(STD_DELAY); low_b = IORD(DM9000A_BASE,IO_data); high_b = IORD(DM9000A_BASE,IO_data); rx_len[0] = high_b<<8; rx_len[0] = rx_len[0]+low_b - 4; /* Check this packet_status GOOD or BAD? */ if ( !(RxStatus & 0xBF) && (rx_len[0] < MAX_PACKET_SIZE) ) { /* read 1 received packet from RX SRAM into RX buffer */ for (i = 0; i < rx_len[0]; i += 1) { usleep(STD_DELAY); data_ptr[i] = IORD(DM9000A_BASE, IO_data); } /* dump the 4 BYTE FCS */ IORD(DM9000A_BASE, IO_data); IORD(DM9000A_BASE, IO_data); IORD(DM9000A_BASE, IO_data); IORD(DM9000A_BASE, IO_data); GoodPacket=TRUE; } /* end if (GoodPacket) */ else { /* this packet is bad, dump it from RX SRAM */ for (i = 0; i < rx_len[0]; i += 1) { usleep(STD_DELAY); Tmp = IORD(DM9000A_BASE, IO_data); } /* dump the 4 BYTE FCS */ IORD(DM9000A_BASE, IO_data); IORD(DM9000A_BASE, IO_data); IORD(DM9000A_BASE, IO_data); IORD(DM9000A_BASE, IO_data); printf("\nError\n"); rx_len[0] = 0; } /* end if (!GoodPacket) */ } /* end if (rx_READY == DM9000_PKT_READY) ok */ else if(!rx_READY) /* status check first byte: rx_READY Bit[1:0] must be "00"b or "01"b */ { /* software-RESET NIC */ iow(NCR, 0x03); /* NCR REG. 00 RST Bit [0] = 1 reset on, and LBK Bit [2:1] = 01b MAC loopback on */ usleep(20); /* wait > 10us for a software-RESET ok */ iow(NCR, 0x00); /* normalize */ iow(NCR, 0x03); usleep(20); iow(NCR, 0x00); /* program operating registers~ */ iow(NCR, NCR_set); /* NCR REG. 00 enable the chip functions (and disable this MAC loopback mode back to normal) */ iow(0x08, BPTR_set); /* BPTR REG.08 (if necessary) RX Back Pressure Threshold in Half duplex moe only: High Water 3KB, 600 us */ iow(0x09, FCTR_set); /* FCTR REG.09 (if necessary) Flow Control Threshold setting High/ Low Water Overflow 5KB/ 10KB */ iow(0x0A, RTFCR_set); /* RTFCR REG.0AH (if necessary) RX/TX Flow Control Register enable TXPEN, BKPM (TX_Half), FLCE (RX) */ iow(0x0F, 0x00); /* Clear the all Event */ iow(0x2D, 0x80); /* Switch LED to mode 1 */ /* set other registers depending on applications */ iow(ETXCSR, ETXCSR_set); /* Early Transmit 75% */ /* enable interrupts to activate DM9000 ~on */ iow(IMR, INTR_set); /* IMR REG. FFH PAR=1 only, or + PTM=1& PRM=1 enable RxTx interrupts */ /* enable RX (Broadcast/ ALL_MULTICAST) ~go */ iow(RCR , RCR_set | RX_ENABLE | PASS_MULTICAST); /* RCR REG. 05 RXEN Bit [0] = 1 to enable the RX machine/ filter */ } /* end NIC H/W system Data-Bus error */ iow(ISR, 0x01); iow(IMR, INTR_set); // iow(0x0F, 0x00); //iow(IMR, INTR_set); return GoodPacket ? DMFE_SUCCESS : DMFE_FAIL; } I added the code(red), the problem you mentioned is solved. the reason is MII added 4 byte FCS, When you read the packet, you should discard them, otherwise when you read the packet next time,you SRAM read pointer will point to the address less 4 byte than the right address,so it doesn't work. I also find the receive packet function doesn't clear the interrupt and re enable the receive packet interrupt again, so I added the code for it. Now ,you can try it , good luck - Altera_Forum
Honored Contributor
That's fantastic!
I chewed through that example so many times it drove me nuts. Plus the DM900A thing was about 1/8th of my project. Thanks, Adam F. - Altera_Forum
Honored Contributor
You are welcome!
:) - Altera_Forum
Honored Contributor
huwenmin :cool:
thanks a lot