/****************************************************************************** * Function: void MACReadRXBuffer(unsigned char* _buf, unsigned int _size) * * PreCondition: none * * Input: *_buf: buffer to write data read * _size: amount data to read * * Output: None * * Side Effects: Last packet is discarded if MACDiscardRx() hasn't already * been called. * * Overview: None * * Note: None *****************************************************************************/ void MACReadRXBuffer(unsigned char* _buf, unsigned int _size) { uint16_t rxstat; uint16_t len; // Set the read pointer to the start of the received packet enc28j60Write(ERDPTL, CurrentPacketLocation.Byte.LB); enc28j60Write(ERDPTH, CurrentPacketLocation.Byte.HB); // read the next packet pointer NextPacketLocation.Byte.LB = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); NextPacketLocation.Byte.HB = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); // read the packet length (see datasheet page 43) len = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; len-=4; //remove the CRC count // read the receive status (see datasheet page 43) rxstat = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; // limit retrieve length if (len > _size) len = _size; // copy the packet from the receive buffer enc28j60ReadBuffer(len, _buf); }
void MACWriteTXEndPt( unsigned int _size) { // calc end offset unsigned int offsetEnd = TXSTART_INIT + _size; // Set the TXND pointer to correspond to the packet size given enc28j60Write(ETXNDL, low(offsetEnd)); enc28j60Write(ETXNDH, high(offsetEnd)); }
/****************************************************************************** * Function: void SOCKETWriteBuffer(unsigned char* _buf, unsigned int _size, unsigned int _start) * * PreCondition: none * * Input: *_buf: buffer to write data * _size: amount data to write * _start: socket's buffer start address * * Output: None * * Side Effects: None * * Overview: Writes bytes to Socket RX/TX Buffer space * * Note: None *****************************************************************************/ void SOCKETWriteBuffer(unsigned char* _buf, unsigned int _size, unsigned int _start) { // Set the write pointer to start of socket buffer area enc28j60Write(EWRPTL, low(_start)); enc28j60Write(EWRPTH, high(_start)); // copy the packet into the socket buffer enc28j60WriteBuffer(_size, _buf); }
/****************************************************************************** * Function: void MACDiscardRx(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: Marks the last received packet (obtained using * MACGetHeader())as being processed and frees the buffer * memory associated with it * * Note: Is is safe to call this function multiple times between * MACGetHeader() calls. Extra packets won't be thrown away * until MACGetHeader() makes it available. *****************************************************************************/ void MACDiscardRx(void) { // Update Current pointer CurrentPacketLocation.Val = NextPacketLocation.Val; enc28j60Write(ERXRDPTL, NextPacketLocation.Byte.LB); enc28j60Write(ERXRDPTH, NextPacketLocation.Byte.HB); // decrement the packet counter indicate we are done with this packet enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); }
/****************************************************************************** * Function: void SOCKETReadBuffer(unsigned char* _buf, unsigned int _size, unsigned int _start) * * PreCondition: none * * Input: *_buf: buffer to write data read * _size: amount data to read * _start: socket's buffer start address * * Output: None * * Side Effects: interfere in ERDPT pointer * * Overview: Reads bytes from Socket RX/TX Buffer space * * Note: None *****************************************************************************/ void SOCKETReadBuffer(unsigned char* _buf, unsigned int _size, unsigned int _start) { // Set the read pointer to the start of the packet kept in the socket buffer enc28j60Write(ERDPTL, low(_start)); enc28j60Write(ERDPTH, high(_start)); //delay(1); // copy the packet from the socket buffer enc28j60ReadBuffer(_size, _buf); }
/****************************************************************************** * Function: void MACMemCopyAsync(FLOW flow, unsigned int destAddr, unsigned int len) * * PreCondition: SPI bus must be initialized (done in MACInit()). * * Input: destAddr: Destination address in the Ethernet memory to * copy to. If (PTR_BASE)-1 is specified, the * current EWRPT value will be used instead. * sourceAddr: Source address to read from. If (PTR_BASE)-1 is * specified, the current ERDPT value will be used * instead. * len: Number of bytes to copy * * Output: None * * Side Effects: Moves read and write pointers. DMA conflict with transmitting and receiving * * Overview: Bytes are asynchrnously transfered within the buffer. Call * MACIsMemCopyDone() to see when the transfer is complete. * * Note: If a prior transfer is already in progress prior to * calling this function, this function will block until it * can start this transfer. * * If (PTR_BASE)-1 is used for the sourceAddr or destAddr * parameters, then that pointer will get updated with the * next address after the read or write. *****************************************************************************/ void DMACopyFrom(FLOW flow, unsigned int sourceAddr, unsigned int len) { unsigned int destAddr = TXSTART_INIT; enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_DMAST); // Defining source address by read or write pointer if (flow == RX) { destAddr = NextPacketLocation.Val; } else if (flow == TX) { destAddr = TXSTART_INIT + 1; // write per-packet control byte (0x00 means use macon3 settings) enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00); } // Source Init Address enc28j60Write(EDMASTL, low(sourceAddr)); enc28j60Write(EDMASTH, high(sourceAddr)); // Source Stop Address enc28j60Write(EDMANDL, low((sourceAddr + len))); // + RXD_STATUS_VECTOR_SIZE)); enc28j60Write(EDMANDH, high((sourceAddr + len))); // + RXD_STATUS_VECTOR_SIZE)); // Destination Init Address enc28j60Write(EDMADSTL, low(destAddr)); enc28j60Write(EDMADSTH, high(destAddr)); // Clear flag enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_DMAIF); // Execute! enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); if (flow == TX) { // Set the write pointer to start of transmit buffer area enc28j60Write(EWRPTL, low((destAddr - 1))); enc28j60Write(EWRPTH, high((destAddr - 1))); // Set the TXND pointer to correspond to the packet size given enc28j60Write(ETXNDL, low(((destAddr - 1) + len))); enc28j60Write(ETXNDH, high(((destAddr - 1) + len))); } }
/****************************************************************************** * Function: void MACWriteTXBufferOffset(unsigned char* _buf, unsigned int _size, unsigned int offset_len) * * PreCondition: none * * Input: *_buf: buffer to write data * _size: amount data to write * offset:memory pointer to write data * * Output: None * * Side Effects: None * * Overview: Writes bytes to TX Buffer space and skips offset * * Note: None *****************************************************************************/ void MACWriteTXBufferOffset(unsigned char* _buf, unsigned int _size, unsigned int offset_len) { // calc offset unsigned int offsetStart = TXSTART_INIT + offset_len; unsigned int offsetEnd = offsetStart + _size; // Set the write pointer to start of transmit buffer area enc28j60Write(EWRPTL, low(offsetStart)); enc28j60Write(EWRPTH, high(offsetStart)); // Set the TXND pointer to correspond to the packet size given enc28j60Write(ETXNDL, low(offsetEnd)); enc28j60Write(ETXNDH, high(offsetEnd)); // write per-packet control byte (0x00 means use macon3 settings) enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00); // copy the packet into the transmit buffer enc28j60WriteBuffer(_size, _buf); }
/****************************************************************************** * Function: void MACMemCopyAsync(FLOW flow, unsigned int destAddr, unsigned int len) * * PreCondition: SPI bus must be initialized (done in MACInit()). * * Input: destAddr: Destination address in the Ethernet memory to * copy to. If (PTR_BASE)-1 is specified, the * current EWRPT value will be used instead. * sourceAddr: Source address to read from. If (PTR_BASE)-1 is * specified, the current ERDPT value will be used * instead. * len: Number of bytes to copy * * Output: None * * Side Effects: Moves read and write pointers. DMA conflict with transmitting and receiving * * Overview: Bytes are asynchrnously transfered within the buffer. Call * MACIsMemCopyDone() to see when the transfer is complete. * * Note: If a prior transfer is already in progress prior to * calling this function, this function will block until it * can start this transfer. * * If (PTR_BASE)-1 is used for the sourceAddr or destAddr * parameters, then that pointer will get updated with the * next address after the read or write. *****************************************************************************/ void DMACopyTo(FLOW flow, unsigned int destAddr, unsigned int len) { unsigned int sourceAddr = RXSTART_INIT; enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_DMAST); // Defining source address by read or write pointer if (flow == RX) { if ((CurrentPacketLocation.Val + RXD_STATUS_VECTOR_SIZE) <= RXSTOP_INIT) { sourceAddr = CurrentPacketLocation.Val + RXD_STATUS_VECTOR_SIZE; } else { unsigned int rest = (CurrentPacketLocation.Val + RXD_STATUS_VECTOR_SIZE) - RXSTOP_INIT; sourceAddr = rest - 1; } } else if (flow == TX) { sourceAddr = TXSTART_INIT; } // Source Init Address enc28j60Write(EDMASTL, low(sourceAddr)); enc28j60Write(EDMASTH, high(sourceAddr)); // Source Stop Address // Need compensate circular buffer WHEN RX COPY !!! unsigned int floatingEnd = (sourceAddr + len); if (flow == RX) { if (floatingEnd >= RXSTOP_INIT) { // Adjusting END for DMA copy // otherwise it will never reach end pointer // and never get it done unsigned int tempEnd = (floatingEnd - RXSTOP_INIT); if (tempEnd > 0) tempEnd--; floatingEnd = tempEnd; } } // Source Stop Address enc28j60Write(EDMANDL, low(floatingEnd)); enc28j60Write(EDMANDH, high(floatingEnd)); // Destination Init Address enc28j60Write(EDMADSTL, low(destAddr)); enc28j60Write(EDMADSTH, high(destAddr)); // Clear flag enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_DMAIF); // Execute! enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); }
void network_set_MAC(uint8_t* macaddr) { enc28j60Write(MAADR5, *macaddr++); enc28j60Write(MAADR4, *macaddr++); enc28j60Write(MAADR3, *macaddr++); enc28j60Write(MAADR2, *macaddr++); enc28j60Write(MAADR1, *macaddr++); enc28j60Write(MAADR0, *macaddr++); }
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); }
//********************************************************************************************************* // // Setzt die MAC-Adressse im Enc28j60 // //********************************************************************************************************* void nicSetMacAddress( char * MAC) { // write MAC address // NOTE: MAC address in ENC28J60 is byte-backward enc28j60Write(MAADR5, MAC[ 0 ] ); enc28j60Write(MAADR4, MAC[ 1 ] ); enc28j60Write(MAADR3, MAC[ 2 ] ); enc28j60Write(MAADR2, MAC[ 3 ] ); enc28j60Write(MAADR1, MAC[ 4 ] ); enc28j60Write(MAADR0, MAC[ 5 ] ); }
void nicSetMacAddress(uint8_t* macaddr) { // write MAC address // NOTE: MAC address in ENC28J60 is byte-backward enc28j60Write(MAADR5, *macaddr++); enc28j60Write(MAADR4, *macaddr++); enc28j60Write(MAADR3, *macaddr++); enc28j60Write(MAADR2, *macaddr++); enc28j60Write(MAADR1, *macaddr++); enc28j60Write(MAADR0, *macaddr++); }
void network_set_MAC(u08* macaddr) { // write MAC address // NOTE: MAC address in ENC28J60 is byte-backward enc28j60Write(MAADR5, *macaddr++); enc28j60Write(MAADR4, *macaddr++); enc28j60Write(MAADR3, *macaddr++); enc28j60Write(MAADR2, *macaddr++); enc28j60Write(MAADR1, *macaddr++); enc28j60Write(MAADR0, *macaddr++); }
/****************************************************************************** * Function: void MACInitMacAddr(unsigned char *_macadd) * * PreCondition: none * * Input: none * * Output: None * * Side Effects: none * * Overview: Init ENC28J60 hardware MAC address * * Note: None *****************************************************************************/ void MACInitMacAddr(unsigned char *_macadd) { // 2. // write MAC address // NOTE: MAC address in ENC28J60 is byte-backward enc28j60Write(MAADR5, _macadd[0]); enc28j60Write(MAADR4, _macadd[1]); enc28j60Write(MAADR3, _macadd[2]); enc28j60Write(MAADR2, _macadd[3]); enc28j60Write(MAADR1, _macadd[4]); enc28j60Write(MAADR0, _macadd[5]); }
/****************************************************************************** * Function: void MACInitMacAddr(unsigned char *_macadd) * * PreCondition: none * * Input: none * * Output: None * * Side Effects: none * * Overview: Init ENC28J60 hardware MAC address * * Note: None *****************************************************************************/ void MACInitMacAddr(unsigned char *macaddr) { // 2. m_macadd = macaddr; //*(&macaddr[0]); //m_macadd[3] = 192; // write MAC address // NOTE: MAC address in ENC28J60 is byte-backward enc28j60Write(MAADR5, m_macadd[0]); enc28j60Write(MAADR4, m_macadd[1]); enc28j60Write(MAADR3, m_macadd[2]); enc28j60Write(MAADR2, m_macadd[3]); enc28j60Write(MAADR1, m_macadd[4]); enc28j60Write(MAADR0, m_macadd[5]); }
int main(void) { led_conf(); network_init(); CLKPR = (1<<CLKPCE); //Change prescaler CLKPR = (1<<CLKPS0); //Use prescaler 2 //clock_prescale_set(2); enc28j60Write(ECOCON, 1 & 0x7); //Get a 25MHz signal from enc28j60 int i; uip_ipaddr_t ipaddr; struct timer periodic_timer, arp_timer; clock_init(); timer_set(&periodic_timer, CLOCK_SECOND / 2); timer_set(&arp_timer, CLOCK_SECOND * 10); uip_init(); struct uip_eth_addr mac = {UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5}; uip_setethaddr(mac); simple_httpd_init(); // httpd_init(); #ifdef __DHCPC_H__ dhcpc_init(&mac, 6); #else uip_ipaddr(ipaddr, 192,168,2,55); uip_sethostaddr(ipaddr); uip_ipaddr(ipaddr, 192,168,2,1); uip_setdraddr(ipaddr); uip_ipaddr(ipaddr, 255,255,255,0); uip_setnetmask(ipaddr); /* uip_ipaddr(ipaddr, 192,167,0,255); uip_sethostaddr(ipaddr); uip_ipaddr(ipaddr, 192,167,0,254); uip_setdraddr(ipaddr); uip_ipaddr(ipaddr, 255,255,0,0); uip_setnetmask(ipaddr); */ #endif /*__DHCPC_H__*/ while(1){ uip_len = network_read(); if(uip_len > 0) { if(BUF->type == htons(UIP_ETHTYPE_IP)){ uip_arp_ipin(); uip_input(); if(uip_len > 0) { uip_arp_out(); network_send(); } }else if(BUF->type == htons(UIP_ETHTYPE_ARP)){ uip_arp_arpin(); if(uip_len > 0){ network_send(); } } }else if(timer_expired(&periodic_timer)) { timer_reset(&periodic_timer); led_blink(); for(i = 0; i < UIP_CONNS; i++) { uip_periodic(i); if(uip_len > 0) { uip_arp_out(); network_send(); } } #if UIP_UDP for(i = 0; i < UIP_UDP_CONNS; i++) { uip_udp_periodic(i); if(uip_len > 0) { uip_arp_out(); network_send(); } } #endif /* UIP_UDP */ if(timer_expired(&arp_timer)) { timer_reset(&arp_timer); uip_arp_timer(); } } } return 0; }
int main(void) { network_init(); //CLKPR = (1<<CLKPCE); //Change prescaler //CLKPR = (1<<CLKPS0); //Use prescaler 2 //clock_prescale_set(clock_div_2); enc28j60Write(ECOCON, 1 & 0x7); //Get a 25MHz signal from enc28j60 uartInit(); uartSetBaudRate(9600); rprintfInit(uartSendByte); int i; uip_ipaddr_t ipaddr; struct timer periodic_timer, arp_timer; clock_init(); timer_set(&periodic_timer, CLOCK_SECOND / 2); timer_set(&arp_timer, CLOCK_SECOND * 10); uip_init(); struct uip_eth_addr mac = {UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5}; uip_setethaddr(mac); // set up the udp data stream // configure the target system ip and port uip_ipaddr_t target_ipaddr; uip_ipaddr(&target_ipaddr, 192,168,0,10); udpds_conf(&target_ipaddr, 1000, 1); #ifdef __DHCPC_H__ dhcpc_init(&mac, 6); #else uip_ipaddr(ipaddr, 192,168,0,1); uip_sethostaddr(ipaddr); uip_ipaddr(ipaddr, 192,168,0,1); uip_setdraddr(ipaddr); uip_ipaddr(ipaddr, 255,255,255,0); uip_setnetmask(ipaddr); #endif /*__DHCPC_H__*/ while(1){ uip_len = network_read(); if(uip_len > 0) { if(BUF->type == htons(UIP_ETHTYPE_IP)){ uip_arp_ipin(); uip_input(); if(uip_len > 0) { uip_arp_out(); network_send(); } }else if(BUF->type == htons(UIP_ETHTYPE_ARP)){ uip_arp_arpin(); if(uip_len > 0){ network_send(); } } }else if(timer_expired(&periodic_timer)) { timer_reset(&periodic_timer); for(i = 0; i < UIP_CONNS; i++) { uip_periodic(i); if(uip_len > 0) { uip_arp_out(); network_send(); } } #if UIP_UDP for(i = 0; i < UIP_UDP_CONNS; i++) { uip_udp_periodic(i); if(uip_len > 0) { uip_arp_out(); network_send(); } } #endif /* UIP_UDP */ if(timer_expired(&arp_timer)) { timer_reset(&arp_timer); uip_arp_timer(); } } } return 0; }
/****************************************************************************** * Function: void DMACopy(FLOW flow, unsigned int destAddr, unsigned int len) * * PreCondition: SPI bus must be initialized (done in MACInit()). * * Input: destAddr: Destination address in the Ethernet memory to * copy to. If (PTR_BASE)-1 is specified, the * current EWRPT value will be used instead. * sourceAddr: Source address to read from. If (PTR_BASE)-1 is * specified, the current ERDPT value will be used * instead. * len: Number of bytes to copy * * Output: None * * Side Effects: Moves read and write pointers. DMA conflict with transmitting and receiving * * Overview: Bytes are asynchrnously transfered within the buffer. Call * MACIsMemCopyDone() to see when the transfer is complete. * * Note: If a prior transfer is already in progress prior to * calling this function, this function will block until it * can start this transfer. * * If (PTR_BASE)-1 is used for the sourceAddr or destAddr * parameters, then that pointer will get updated with the * next address after the read or write. *****************************************************************************/ void DMACopy(FLOW flow, unsigned int destAddr, unsigned int len) { // finally using tx socket space, after 2 years developing this enc28's EEPROM approach // for documentation sake, I have made following organization // to enc28's 8k eeprom // 0H ~ 800H (2K) - RX FIFO (CYCLIC) // 802H ~ 1000H (2K-1byte) - TX FIFO (FLAT) // 1002H ~ 1401H - Socket RX Bank 0 (FLAT) // 1402H ~ 1801H - Socket RX Bank 1 (not used yet) (FLAT) // 1803H ~ 1C02H - Socket TX Bank 0 (FLAT) // 1C03H ~ 1FFEH - Socket TX Bank 1 (not used yet) (FLAT) -- Total 8K EEPROM used ONLY by this library! // Errata 7b has lots of issues about this addresses // I have made them by the book! // By Renato Aloi (May 2015) // While trying to remmember all rules to implement last and most important option: Write at TX Socket Buffer! unsigned int sourceAddr = RXSTART_INIT; // RX Copy From FIFO To Bank enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_DMAST); // Defining source address by read or write pointer if (flow == RX) { if ((CurrentPacketLocation.Val + RXD_STATUS_VECTOR_SIZE) <= RXSTOP_INIT) { sourceAddr = CurrentPacketLocation.Val + RXD_STATUS_VECTOR_SIZE; } else { unsigned int rest = (CurrentPacketLocation.Val + RXD_STATUS_VECTOR_SIZE) - RXSTOP_INIT; sourceAddr = rest - 1; } } else if (flow == TX) { sourceAddr = SOCKET_TX_START(0); // TX Copy From Bank To FIFO } // Source Init Address enc28j60Write(EDMASTL, low(sourceAddr)); enc28j60Write(EDMASTH, high(sourceAddr)); // Source Stop Address // Need compensate circular buffer WHEN RX COPY !!! unsigned int floatingEnd = (sourceAddr + len); if (flow == RX) { if (floatingEnd >= RXSTOP_INIT) { // Adjusting END for DMA copy // otherwise it will never reach end pointer // and never get it done unsigned int tempEnd = (floatingEnd - RXSTOP_INIT); if (tempEnd > 0) tempEnd--; floatingEnd = tempEnd; } } // Source Stop Address enc28j60Write(EDMANDL, low(floatingEnd)); enc28j60Write(EDMANDH, high(floatingEnd)); // Destination Init Address enc28j60Write(EDMADSTL, low(destAddr)); enc28j60Write(EDMADSTH, high(destAddr)); // Clear flag enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_DMAIF); // Execute! enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); }
int main(void) { network_init(); // network.c // enc28j60Init(); // enc28j60PhyWrite(PHLCON,0x476); //CLKPR = (1<<CLKPCE); //Change prescaler //CLKPR = (1<<CLKPS0); //Use prescaler 2 //clock_prescale_set(clock_div_2); enc28j60Write(ECOCON, 1 & 0x7); // enc28j60.c //Get a 25MHz signal from enc28j60 #ifdef MY_DEBUG uartInit(); uartSetBaudRate(9600); rprintfInit(uartSendByte); #endif int i; uip_ipaddr_t ipaddr; // uip.h // typedef u16_t uip_ip4addr_t[2]; // typedef uip_ip4addr_t uip_ipaddr_t; struct timer periodic_timer, arp_timer; clock_init(); timer_set(&periodic_timer, CLOCK_SECOND / 2); timer_set(&arp_timer, CLOCK_SECOND * 10); uip_init(); // uip.c //uip_arp_init(); // uip_arp.c // must be done or sometimes arp doesn't work struct uip_eth_addr mac = {UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5}; uip_setethaddr(mac); simple_httpd_init(); #ifdef __DHCPC_H__ dhcpc_init(&mac, 6); #else uip_ipaddr(ipaddr, 192,168,0,1); // uip.h uip_sethostaddr(ipaddr); // uip.h // #define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr)) uip_ipaddr(ipaddr, 192,168,0,1); uip_setdraddr(ipaddr); // #define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr)) uip_ipaddr(ipaddr, 255,255,255,0); uip_setnetmask(ipaddr); // #define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr)) #endif /*__DHCPC_H__*/ while(1){ uip_len = network_read(); // uip.c : u16_t uip_len; // network.c : return ((unt16_t) enc28j60PacketReceive(UIP_BUFSIZE, (uint8_t *)uip_buf)); // enc28j60.c : enc28j60PacketReceive // uip.c : uint8_t uip_buf[UIP_BUFSIZE+2]; // uipconf.h : UIP_BUFSIZE:300 if(uip_len > 0) { if(BUF->type == htons(UIP_ETHTYPE_IP)){ #ifdef MY_DEBUG //rprintf("eth in : uip_len = %d, proto = %d\n", uip_len, uip_buf[23]); //debugPrintHexTable(uip_len, uip_buf); #endif // struct uip_eth_hdr { // struct uip_eth_addr dest; // struct uip_eth_addr src; // u16_t type; // }; // struct uip_eth_addr { // Representation of a 48-bit Ethernet address // u8_t addr[6]; // }; // http://www.netmanias.com/ko/post/blog/5372/ethernet-ip-tcp-ip/packet-header-ethernet-ip-tcp-ip // UIP_ETHTYPE_IP(0x0800) : IPv4 Packet(ICMP, TCP, UDP) uip_arp_ipin(); #ifdef MY_DEBUG //rprintf("ip in : uip_len = %d, proto = %d\n", uip_len, uip_buf[23]); //debugPrintHexTable(uip_len, uip_buf+14); #endif // uip_arp.c // #define IPBUF ((struct ethip_hdr *)&uip_buf[0]) // struct ethip_hdr { // struct uip_eth_hdr ethhdr; // // IP header // u8_t vhl, // tos, // len[2], // ipid[2], // ipoffset[2], // ttl, // proto; // ICMP: 1, TCP: 6, UDP: 17 // u16_t ipchksum; // u16_t srcipaddr[2], // destipaddr[2]; // } // if ((IBUF->srcipaddr & uip_netmask) != uip_hostaddr & (uip_netmask)) return; // uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); uip_input(); #ifdef MY_DEBUG //rprintf("ip out : uip_len = %d, proto = %d\n", uip_len, uip_buf[23]); //debugPrintHexTable(uip_len, uip_buf+14); #endif // ip out packet // eg ICMP // uip_len : 84 // source ip <-> destination ip // type : 8 (Echo (ping) request) -> 0 (Echo (ping) reply) // uip.h // #define uip_input() uip_process(UIP_DATA) // UIP_DATA(1) : Tells uIP that there is incoming // uip_process : The actual uIP function which does all the work. if(uip_len > 0) { uip_arp_out(); #ifdef MY_DEBUG //rprintf("ip out : uip_len = %d, proto = %d\n", uip_len, uip_buf[23]); //debugPrintHexTable(uip_len, uip_buf); #endif // Destination MAC Address <=> Source MAC Address // w/o Ethernet CRC // uip_arp.c network_send(); // network.c // if(uip_len <= UIP_LLH_LEN + 40){ // UIP_LLH_LEN : 14 // enc28j60PacketSend(uip_len, (uint8_t *)uip_buf, 0, 0); // }else{ // enc28j60PacketSend(54, (uint8_t *)uip_buf , uip_len - UIP_LLH_LEN - 40, (uint8_t*)uip_appdata); // } } }else if(BUF->type == htons(UIP_ETHTYPE_ARP)){ // UIP_ETHYPE_ARP(0x0806) #ifdef MY_DEBUG //rprintf("arp in : uip_len = %d\n", uip_len); //debugPrintHexTable(uip_len, uip_buf); #endif // arp in : 64 bytes uip_arp_arpin(); if(uip_len > 0){ // always uip_len > 0 #ifdef MY_DEBUG //rprintf("ip in : uip_len = %d\n", uip_len); //debugPrintHexTable(uip_len, uip_buf); #endif // arp out : 42 bytes // 64 - Ethernet_padding(18) - Ethernet_CRC(4) // Send MAC address <--> Target MAC address // Send IP address <--> Target IP address // uip_arp.c network_send(); } } }else if(timer_expired(&periodic_timer)) { timer_reset(&periodic_timer); for(i = 0; i < UIP_CONNS; i++) { uip_periodic(i); // uip.h // #define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ // uip_process(UIP_UDP_TIMER); } while (0) // UIP_UDP_TIMER : 5 // uip.c; uip_process // if(flag == UIP_UDP_TIMER) { // if(uip_udp_conn->lport != 0) { // uip_conn = NULL; // uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; // uip_len = uip_slen = 0; // uip_flags = UIP_POLL; // UIP_UDP_APPCALL(); // goto udp_send; // } // } else { // goto drop; // } if(uip_len > 0) { uip_arp_out(); network_send(); } } #if UIP_UDP for(i = 0; i < UIP_UDP_CONNS; i++) { uip_udp_periodic(i); if(uip_len > 0) { uip_arp_out(); network_send(); } } #endif /* UIP_UDP */ if(timer_expired(&arp_timer)) { timer_reset(&arp_timer); uip_arp_timer(); } } } return 0; }
/****************************************************************************** * Function: void SOCKETSetTxPointer(unsigned int addr) * * PreCondition: none * * Input: addr = Address to set TX pointer to. * * Output: None * * Side Effects: None * * Overview: Sets TX pointer location * * Note: None *****************************************************************************/ void SOCKETSetTxPointer(unsigned int addr) { enc28j60Write(EWRPTL, low(addr)); enc28j60Write(EWRPTH, high(addr)); }
/****************************************************************************** * Function: void MACInit(void) * * PreCondition: none * * Input: none * * Output: None * * Side Effects: none * * Overview: Init. ENC28J60 hardware * * Note: None *****************************************************************************/ void MACInit(void) { // 1. NextPacketLocation.Val = 0; CurrentPacketLocation.Val = 0; // RESET the entire ENC28J60, clearing all registers MACSendSystemReset(); // Start up in Bank 0 and configure the receive buffer boundary pointers // and the buffer write protect pointer (receive buffer read pointer) NextPacketLocation.Val = RXSTART_INIT; CurrentPacketLocation.Val = RXSTART_INIT; enc28j60Write(ERXSTL, low(RXSTART_INIT)); enc28j60Write(ERXSTH, high(RXSTART_INIT)); enc28j60Write(ERXRDPTL, low(RXSTART_INIT)); // Write low byte first enc28j60Write(ERXRDPTH, high(RXSTART_INIT)); // Write high byte last enc28j60Write(ERXNDL, low(RXSTOP_INIT)); enc28j60Write(ERXNDH, high(RXSTOP_INIT)); enc28j60Write(ETXSTL, low(TXSTART_INIT)); enc28j60Write(ETXSTH, high(TXSTART_INIT)); // Enter Bank 1 and configure Receive Filters // For broadcast packets we allow only ARP packtets // All other packets should be unicast only for our mac (MAADR) // // The pattern to match on is therefore // Type ETH.DST // ARP BROADCAST // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 // in binary these poitions are:11 0000 0011 1111 // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 enc28j60Write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN); enc28j60Write(EPMM0, 0x3F); enc28j60Write(EPMM1, 0x30); enc28j60Write(EPMCSL, 0xF9); enc28j60Write(EPMCSH, 0xF7); // promiscuous mode //enc28j60Write(ERXFCON, ERXFCON_CRCEN); // Disable the CLKOUT output to reduce EMI generation enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECOCON, 0x00); // Output off (0V) //enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECOCON, 0x01); // 25.000MHz //enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECOCON, 0x03); // 8.3333MHz (*4 with PLL is 33.3333MHz) // Enable the receive portion of the MAC // full duplex //enc28j60Write(MACON1, (MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS)); // half duplex enc28j60Write(MACON1, MACON1_MARXEN); // bring MAC out of reset enc28j60Write(MACON2, 0x00); // Pad packets to 60 bytes, add CRC, and check Type/Length field. // full duplex //enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, // MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX); // half duplex enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN); // Allow infinite deferals if the medium is continuously busy // (do not time out a transmission if the half duplex medium is // completely saturated with other people's data) enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON4, MACON4_DEFER); // Clear because we are in full duplex mode //enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, MACON4, MACON4_DEFER); // Set the maximum packet size which the controller will accept unsigned int limit = 1518; // 6+6+2+1500+4 // 1518 is the IEEE 802.3 specified limit enc28j60Write(MAMXFLL, low(limit)); enc28j60Write(MAMXFLH, high(limit)); // set inter-frame gap (back-to-back) // half duplex enc28j60Write(MABBIPG, 0x12); // full duplex //enc28j60Write(MABBIPG, 0x15); // set inter-frame gap (non-back-to-back) enc28j60Write(MAIPGL, 0x12); // half duplex enc28j60Write(MAIPGH, 0x00); // full duplex //enc28j60Write(MAIPGH, 0x0C); // Late collisions occur beyond 63+8 bytes (8 bytes for preamble/start of frame delimiter) // 55 is all that is needed for IEEE 802.3, but ENC28J60 B5 errata for improper link pulse // collisions will occur less often with a larger number. enc28j60Write(MACLCON2, 63); }