static void network_init(void) { struct uip_eth_addr macaddr; net_event = process_alloc_event(); #if CONFIG_DRIVERS_ENC28J60 // Set our MAC address memcpy_P(&macaddr, &mac, sizeof(mac)); // Set up ethernet enc28j60Init(&macaddr); enc28j60Write(ECOCON, 0 & 0x7); // Disable clock output _delay_ms(10); /* Magjack leds configuration, see enc28j60 datasheet, page 11 */ // LEDA=green LEDB=yellow // // 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit enc28j60PhyWrite(PHLCON, 0x476); _delay_ms(100); #endif #if CONFIG_DRIVERS_ENC424J600 // Initialise the hardware enc424j600Init(); // Disable clock output and set up LED stretch uint16_t econ2 = enc424j600ReadReg(ECON2); econ2 |= ECON2_STRCH; // stretch LED duration econ2 &= ~(ECON2_COCON3 | ECON2_COCON2 | ECON2_COCON1 | ECON2_COCON0); enc424j600WriteReg(ECON2, econ2); // Set up LEDs uint16_t eidled = enc424j600ReadReg(EIDLED); eidled &= 0x00ff; // and-out the high byte (LED config) eidled |= EIDLED_LACFG1 | EIDLED_LBCFG2 | EIDLED_LBCFG1; enc424j600WriteReg(EIDLED, eidled); // Get the MAC address enc424j600GetMACAddr(macaddr.addr); #endif #if !CONFIG_LIB_CONTIKI_IPV6 // Set up timers timer_set(&arp_timer, CLOCK_SECOND * 10); #endif uip_setethaddr(macaddr); }
/** * Reads MAC address of device * */ void enc424j600ReadMacAddr(u08 * macAddr) { // Get MAC adress u16 regValue; regValue = enc424j600ReadReg(MAADR1); *macAddr++ = ((u08*) & regValue)[0]; *macAddr++ = ((u08*) & regValue)[1]; regValue = enc424j600ReadReg(MAADR2); *macAddr++ = ((u08*) & regValue)[0]; *macAddr++ = ((u08*) & regValue)[1]; regValue = enc424j600ReadReg(MAADR3); *macAddr++ = ((u08*) & regValue)[0]; *macAddr++ = ((u08*) & regValue)[1]; u16 w = enc424j600ReadReg(MACON2); printf("MACON2 0x%04X\n", w); }
static void enc424j600WritePHYReg(u08 address, u16 Data) { // Write the register address enc424j600WriteReg(MIREGADR, 0x0100 | address); // Write the data enc424j600WriteReg(MIWR, Data); // Wait until the PHY register has been written while (enc424j600ReadReg(MISTAT) & MISTAT_BUSY); }
static u16 enc424j600ReadPHYReg(u08 address) { u16 returnValue; // Set the right address and start the register read operation enc424j600WriteReg(MIREGADR, 0x0100 | address); enc424j600WriteReg(MICMD, MICMD_MIIRD); // Loop to wait until the PHY register has been read through the MII // This requires 25.6us while (enc424j600ReadReg(MISTAT) & MISTAT_BUSY); // Stop reading enc424j600WriteReg(MICMD, 0x0000); // Obtain results and return returnValue = enc424j600ReadReg(MIRD); return returnValue; }
/** * Enables powersave mode * */ void enc424j600PowerSaveEnable(void) { //Turn off modular exponentiation and AES engine enc424j600BFCReg(EIR, EIR_CRYPTEN); //Turn off packet reception enc424j600BFCReg(ECON1, ECON1_RXEN); //Wait for any in-progress receptions to complete while (enc424j600ReadReg(ESTAT) & ESTAT_RXBUSY) { _delay_us(100); } //Wait for any current transmisions to complete while (enc424j600ReadReg(ECON1) & ECON1_TXRTS) { _delay_us(100); } //Power-down PHY u16 state; state = enc424j600ReadPHYReg(PHCON1); enc424j600WritePHYReg(PHCON1, state | PHCON1_PSLEEP); //Power-down eth interface enc424j600BFCReg(ECON2, ECON2_ETHEN); enc424j600BFCReg(ECON2, ECON2_STRCH); }
/* urusan paket LWIP */ int pastikan_paket() { /* TODO, ini saat awal2 perlu diatasi, karena sering bukan PTIF */ u16 dd = enc424j600ReadReg(EIR); //if (!(enc424j600ReadReg(EIR) & EIR_PKTIF)) if (!(dd & EIR_PKTIF)) { //printf("ZZ%XZZ:", dd); //printf("v"); /* ini sering error 0x80 >> entah kenapa */ return FALSE; } else return TRUE; }
static void enc424j600SendSystemReset(void) { debug_entry; int try = 0; int try2 = 0; unsigned int s; // Perform a reset via the SPI/PSP interface do { // Set and clear a few bits that clears themselves upon reset. // If EUDAST cannot be written to and your code gets stuck in this // loop, you have a hardware problem of some sort (SPI or PMP not // initialized correctly, I/O pins aren't connected or are // shorted to something, power isn't available, etc.) // sbi(PORTE, PE7); do { enc424j600WriteReg(EUDAST, 0x1234); try++; if (try > 15) break; } while ( (enc424j600ReadReg(EUDAST) != 0x1234)); s = enc424j600ReadReg(EUDAST); printf("Try : %d, EUDAST 0x%X\r\n", try, s); try = 0; // Issue a reset and wait for it to complete enc424j600BFSReg(ECON2, ECON2_ETHRST); currentBank = 0; while ((enc424j600ReadReg(ESTAT) & (ESTAT_CLKRDY | ESTAT_RSTDONE | ESTAT_PHYRDY)) != (ESTAT_CLKRDY | ESTAT_RSTDONE | ESTAT_PHYRDY)); delay_loop_us(300); // Check to see if the reset operation was successful by // checking if EUDAST went back to its reset default. This test // should always pass, but certain special conditions might make // this test fail, such as a PSP pin shorted to logic high. try2 ++; if (try2 > 25) break; } while (enc424j600ReadReg(EUDAST) != 0x0000u); s = enc424j600ReadReg(EUDAST); printf("Try2 : %d, 0x%X\r\n", try2, s); // Really ensure reset is done and give some time for power to be stable _delay_us(1000); debug_leave; } void enc424j600MACFlush_ku(void) { // Check to see if the duplex status has changed. This can // change if the user unplugs the cable and plugs it into a // different node. Auto-negotiation will automatically set // the duplex in the PHY, but we must also update the MAC // inter-packet gap timing and duplex state to match. if (enc424j600ReadReg(EIR) & EIR_LINKIF) { enc424j600BFCReg(EIR, EIR_LINKIF); u16 w; // Update MAC duplex settings to match PHY duplex setting w = enc424j600ReadReg(MACON2); if (enc424j600ReadReg(ESTAT) & ESTAT_PHYDPX) { // Switching to full duplex enc424j600WriteReg(MABBIPG, 0x15); w |= MACON2_FULDPX; } else { // Switching to half duplex enc424j600WriteReg(MABBIPG, 0x12); w &= ~MACON2_FULDPX; } enc424j600WriteReg(MACON2, w); } } /** * Is transmission active? * @return <bool> */ static bool enc424j600MACIsTxReady(void) { return !(enc424j600ReadReg(ECON1) & ECON1_TXRTS); } //static void enc424j600MACFlush(void) { void enc424j600MACFlush(void) { // Check to see if the duplex status has changed. This can // change if the user unplugs the cable and plugs it into a // different node. Auto-negotiation will automatically set // the duplex in the PHY, but we must also update the MAC // inter-packet gap timing and duplex state to match. if (enc424j600ReadReg(EIR) & EIR_LINKIF) { enc424j600BFCReg(EIR, EIR_LINKIF); u16 w; // Update MAC duplex settings to match PHY duplex setting w = enc424j600ReadReg(MACON2); if (enc424j600ReadReg(ESTAT) & ESTAT_PHYDPX) { // Switching to full duplex enc424j600WriteReg(MABBIPG, 0x15); w |= MACON2_FULDPX; } else { // Switching to half duplex enc424j600WriteReg(MABBIPG, 0x12); w &= ~MACON2_FULDPX; } enc424j600WriteReg(MACON2, w); } // Start the transmission, but only if we are linked. if (enc424j600ReadReg(ESTAT) & ESTAT_PHYLNK) enc424j600BFSReg(ECON1, ECON1_TXRTS); } /** * Calculates IP checksum value * * */ static u16 enc424j600ChecksumCalculation(u16 position, u16 length, u16 seed) { // Wait until module is idle while (enc424j600ReadReg(ECON1) & ECON1_DMAST) { } // Clear DMACPY to prevent a copy operation enc424j600BFCReg(ECON1, ECON1_DMACPY); // Clear DMANOCS to select a checksum operation enc424j600BFCReg(ECON1, ECON1_DMANOCS); // Clear DMACSSD to use the default seed of 0000h enc424j600BFCReg(ECON1, ECON1_DMACSSD); // Set EDMAST to source address enc424j600WriteReg(EDMAST, position); // Set EDMALEN to length enc424j600WriteReg(EDMALEN, length); //If we have a seed, now it's time if (seed) { enc424j600BFSReg(ECON1, ECON1_DMACSSD); enc424j600WriteReg(EDMACS, seed); } // Initiate operation enc424j600BFSReg(ECON1, ECON1_DMAST); // Wait until done while (enc424j600ReadReg(ECON1) & ECON1_DMAST) { } return enc424j600ReadReg(EDMACS); } /******************************************************************** * READERS AND WRITERS * ******************************************************************/ static void enc424j600WriteMemoryWindow(u08 window, u08 *data, u16 length) { u08 op = WBMUDA; if (window & GP_WINDOW) op = WBMGP; if (window & RX_WINDOW) op = WBMRX; enc424j600WriteN(op, data, length); }
/** * Is link connected? * @return <bool> */ bool enc424j600IsLinked(void) { return (enc424j600ReadReg(ESTAT) & ESTAT_PHYLNK) != 0u; }
/** * Recieves packet * */ u16 enc424j600PacketReceive(u16 len, u08* packet) { u16 newRXTail; RXSTATUS statusVector; if (!(enc424j600ReadReg(EIR) & EIR_PKTIF)) { return FALSE; } #ifdef AUTO_ICMP_ECHO //Check if packet is ICMP echo packet and answer to it automaticaly kkjk //Set buffer for packet data u08 packetData[2]; // Set the RX Read Pointer to the beginning of the next unprocessed packet + statusVektor + nextPacketPointer + position where paket type is saved enc424j600WriteReg(ERXRDPT, nextPacketPointer + sizeof (statusVector) + ETH_HEADER); //Read type of paket first, if it's IP enc424j600ReadMemoryWindow(RX_WINDOW, packetData, sizeof (packetData)); if (packetData[0] == IP_PROTOCOL1 && packetData[1] == IP_PROTOCOL2) { //Ok, it's ip packet, check if it's icmp packet enc424j600WriteReg(ERXRDPT, nextPacketPointer + 2 + sizeof (statusVector) + IP_PROTOCOL_POS); enc424j600ReadMemoryWindow(RX_WINDOW, packetData, 1); if (packetData[0] == ICMP_PROTOCOL) { //It's icmp packet, read lenght and do DMA copy operation from recieve buffer to transmit buffer enc424j600WriteReg(ERXRDPT, nextPacketPointer + 2); enc424j600ReadMemoryWindow(RX_WINDOW, packetData, 2); if (*(u16*) packetData < 1522) { //Now do DMA copy, first read length from IP packet u16 ipPacketLen; u08 ipHeaderLen; enc424j600WriteReg(ERXRDPT, nextPacketPointer + 2 + sizeof (statusVector) + 14); enc424j600ReadMemoryWindow(RX_WINDOW, (u08*) & ipHeaderLen, 1); ipHeaderLen = (ipHeaderLen & 15)*4; enc424j600WriteReg(ERXRDPT, nextPacketPointer + 2 + sizeof (statusVector) + 16); enc424j600ReadMemoryWindow(RX_WINDOW, (u08*) & ipPacketLen, 2); ipPacketLen = HTONS(ipPacketLen); //Wait until controler is ready while (enc424j600ReadReg(ECON1) & ECON1_DMAST) { } //Set DMA copy and no checksum while copying (checksum computing at the end will be faster) //Switch MAC addr enc424j600BFSReg(ECON1, ECON1_DMACPY); enc424j600BFSReg(ECON1, ECON1_DMANOCS); enc424j600WriteReg(EDMAST, nextPacketPointer + 2 + sizeof (statusVector) + 6); //Switch MAC addr in packet enc424j600WriteReg(EDMADST, TXSTART); enc424j600WriteReg(EDMALEN, 6); enc424j600BFSReg(ECON1, ECON1_DMAST); // Wait until done while (enc424j600ReadReg(ECON1) & ECON1_DMAST) { } enc424j600WriteReg(EDMAST, nextPacketPointer + 2 + sizeof (statusVector)); //Switch MAC addr in packet enc424j600WriteReg(EDMADST, TXSTART + 6); enc424j600WriteReg(EDMALEN, 6); enc424j600BFSReg(ECON1, ECON1_DMAST); // Wait until done while (enc424j600ReadReg(ECON1) & ECON1_DMAST) { } enc424j600WriteReg(EDMAST, nextPacketPointer + 2 + sizeof (statusVector) + 12); //Copy packet enc424j600WriteReg(EDMADST, TXSTART + 12); enc424j600WriteReg(EDMALEN, ipPacketLen + 2); enc424j600BFSReg(ECON1, ECON1_DMAST); // Wait until done while (enc424j600ReadReg(ECON1) & ECON1_DMAST) { } //Switch IP addr enc424j600WriteReg(EDMAST, nextPacketPointer + 2 + sizeof (statusVector) + 26); //Switch IP addr in packet enc424j600WriteReg(EDMADST, TXSTART + 30); enc424j600WriteReg(EDMALEN, 4); enc424j600BFSReg(ECON1, ECON1_DMAST); // Wait until done while (enc424j600ReadReg(ECON1) & ECON1_DMAST) { } enc424j600WriteReg(EDMAST, nextPacketPointer + 2 + sizeof (statusVector) + 30); //Switch IP addr in packet enc424j600WriteReg(EDMADST, TXSTART + 26); enc424j600WriteReg(EDMALEN, 4); enc424j600BFSReg(ECON1, ECON1_DMAST); // Wait until done while (enc424j600ReadReg(ECON1) & ECON1_DMAST) { } //Change echo request to echo reply packetData[0] = 0; packetData[1] = 0; enc424j600WriteReg(EGPWRPT, 34); enc424j600WriteMemoryWindow(GP_WINDOW, packetData, 1); enc424j600WriteReg(EGPWRPT, 36); enc424j600WriteMemoryWindow(GP_WINDOW, packetData, 2); //Compute checksum (use packetData for mem saving) *(u16*) packetData = enc424j600ChecksumCalculation(ETH_HEADER + ipHeaderLen, ipPacketLen - ipHeaderLen, 0x0000); //Write it to the packet enc424j600WriteReg(EGPWRPT, 36); enc424j600WriteMemoryWindow(GP_WINDOW, packetData, 2); //Flush packet out enc424j600WriteReg(ETXLEN, ipPacketLen + ETH_HEADER); enc424j600MACFlush(); } enc424j600WriteReg(ERXRDPT, nextPacketPointer); enc424j600ReadMemoryWindow(RX_WINDOW, (u08*) & nextPacketPointer, sizeof (nextPacketPointer)); newRXTail = nextPacketPointer - 2; //Special situation if nextPacketPointer is exactly RXSTART if (nextPacketPointer == RXSTART) newRXTail = RAMSIZE - 2; //Packet decrement enc424j600BFSReg(ECON1, ECON1_PKTDEC); //Write new RX tail enc424j600WriteReg(ERXTAIL, newRXTail); // return 0; } } #endif // Set the RX Read Pointer to the beginning of the next unprocessed packet enc424j600WriteReg(ERXRDPT, nextPacketPointer); //printf("next %X, size %d\n", nextPacketPointer, sizeof (nextPacketPointer)); enc424j600ReadMemoryWindow(RX_WINDOW, (u08*) & nextPacketPointer, sizeof (nextPacketPointer)); enc424j600ReadMemoryWindow(RX_WINDOW, (u08*) & statusVector, sizeof (statusVector)); len = (statusVector.bits.ByteCount <= len+4) ? statusVector.bits.ByteCount-4 : 0; enc424j600ReadMemoryWindow(RX_WINDOW, packet, len); newRXTail = nextPacketPointer - 2; //Special situation if nextPacketPointer is exactly RXSTART if (nextPacketPointer == RXSTART) newRXTail = RAMSIZE - 2; //Packet decrement enc424j600BFSReg(ECON1, ECON1_PKTDEC); //Write new RX tail enc424j600WriteReg(ERXTAIL, newRXTail); return len; }