enc624j600_driver.c
Go to the documentation of this file.
1 /**
2  * @file enc624j600_driver.c
3  * @brief ENC624J600 Ethernet controller
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
37 #include "debug.h"
38 
39 
40 /**
41  * @brief ENC624J600 driver
42  **/
43 
45 {
47  ETH_MTU,
55  NULL,
56  NULL,
57  NULL,
58  TRUE,
59  TRUE,
60  TRUE,
61  FALSE
62 };
63 
64 
65 /**
66  * @brief ENC624J600 controller initialization
67  * @param[in] interface Underlying network interface
68  * @return Error code
69  **/
70 
72 {
73  uint16_t temp;
74  Enc624j600Context *context;
75 
76  //Debug message
77  TRACE_INFO("Initializing ENC624J600 Ethernet controller...\r\n");
78 
79  //Initialize SPI interface
80  interface->spiDriver->init();
81 
82  //Initialize external interrupt line driver
83  if(interface->extIntDriver != NULL)
84  {
85  interface->extIntDriver->init();
86  }
87 
88  //Point to the driver context
89  context = (Enc624j600Context *) interface->nicContext;
90 
91  //Initialize driver specific variables
93 
94  //Issue a system reset
95  enc624j600SoftReset(interface);
96 
97  //Disable CLKOUT output
100 
101  //Optionally set the station MAC address
102  if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
103  {
104  //Use the factory preprogrammed station address
105  temp = enc624j600ReadReg(interface, ENC624J600_MAADR1);
106  interface->macAddr.w[0] = letoh16(temp);
107  temp = enc624j600ReadReg(interface, ENC624J600_MAADR2);
108  interface->macAddr.w[1] = letoh16(temp);
109  temp = enc624j600ReadReg(interface, ENC624J600_MAADR3);
110  interface->macAddr.w[2] = letoh16(temp);
111 
112  //Generate the 64-bit interface identifier
113  macAddrToEui64(&interface->macAddr, &interface->eui64);
114  }
115  else
116  {
117  //Override the factory preprogrammed address
118  temp = htole16(interface->macAddr.w[0]);
119  enc624j600WriteReg(interface, ENC624J600_MAADR1, temp);
120  temp = htole16(interface->macAddr.w[1]);
121  enc624j600WriteReg(interface, ENC624J600_MAADR2, temp);
122  temp = htole16(interface->macAddr.w[2]);
123  enc624j600WriteReg(interface, ENC624J600_MAADR3, temp);
124  }
125 
126  //Set receive buffer location
128  //Program the tail pointer ERXTAIL to the last even address of the buffer
130 
131  //Configure the receive filters
135 
136  //Initialize the hash table
137  enc624j600WriteReg(interface, ENC624J600_EHT1, 0x0000);
138  enc624j600WriteReg(interface, ENC624J600_EHT2, 0x0000);
139  enc624j600WriteReg(interface, ENC624J600_EHT3, 0x0000);
140  enc624j600WriteReg(interface, ENC624J600_EHT4, 0x0000);
141 
142  //All short frames will be zero-padded to 60 bytes and a valid CRC is then
143  //appended
147 
148  //Program the MAMXFL register with the maximum frame length to be accepted
151 
152  //PHY initialization
156 
157  //Clear interrupt flags
158  enc624j600WriteReg(interface, ENC624J600_EIR, 0x0000);
159 
160  //Configure interrupts as desired
164 
165  //Set RXEN to enable reception
167 
168  //Perform custom configuration
169  enc624j600InitHook(interface);
170 
171  //Dump registers for debugging purpose
172  enc624j600DumpReg(interface);
173  enc624j600DumpPhyReg(interface);
174 
175  //Accept any packets from the upper layer
176  osSetEvent(&interface->nicTxEvent);
177 
178  //Force the TCP/IP stack to poll the link state at startup
179  interface->nicEvent = TRUE;
180  //Notify the TCP/IP stack of the event
182 
183  //Successful initialization
184  return NO_ERROR;
185 }
186 
187 
188 /**
189  * @brief ENC624J600 custom configuration
190  * @param[in] interface Underlying network interface
191  **/
192 
193 __weak_func void enc624j600InitHook(NetInterface *interface)
194 {
195 }
196 
197 
198 /**
199  * @brief ENC624J600 timer handler
200  * @param[in] interface Underlying network interface
201  **/
202 
203 void enc624j600Tick(NetInterface *interface)
204 {
205 }
206 
207 
208 /**
209  * @brief Enable interrupts
210  * @param[in] interface Underlying network interface
211  **/
212 
214 {
215  //Enable interrupts
216  if(interface->extIntDriver != NULL)
217  {
218  interface->extIntDriver->enableIrq();
219  }
220 }
221 
222 
223 /**
224  * @brief Disable interrupts
225  * @param[in] interface Underlying network interface
226  **/
227 
229 {
230  //Disable interrupts
231  if(interface->extIntDriver != NULL)
232  {
233  interface->extIntDriver->disableIrq();
234  }
235 }
236 
237 
238 /**
239  * @brief ENC624J600 interrupt service routine
240  * @param[in] interface Underlying network interface
241  * @return TRUE if a higher priority task must be woken. Else FALSE is returned
242  **/
243 
245 {
246  bool_t flag;
247  uint16_t status;
248 
249  //This flag will be set if a higher priority task must be woken
250  flag = FALSE;
251 
252  //Clear the INTIE bit, immediately after an interrupt event
254 
255  //Read interrupt status register
256  status = enc624j600ReadReg(interface, ENC624J600_EIR);
257 
258  //Link status change?
259  if((status & ENC624J600_EIR_LINKIF) != 0)
260  {
261  //Disable LINKIE interrupt
263 
264  //Set event flag
265  interface->nicEvent = TRUE;
266  //Notify the TCP/IP stack of the event
267  flag |= osSetEventFromIsr(&netEvent);
268  }
269 
270  //Packet received?
271  if((status & ENC624J600_EIR_PKTIF) != 0)
272  {
273  //Disable PKTIE interrupt
275 
276  //Set event flag
277  interface->nicEvent = TRUE;
278  //Notify the TCP/IP stack of the event
279  flag |= osSetEventFromIsr(&netEvent);
280  }
281 
282  //Packet transmission complete?
283  if((status & (ENC624J600_EIR_TXIF | ENC624J600_EIR_TXABTIF)) != 0)
284  {
285  //Clear interrupt flags
288 
289  //Notify the TCP/IP stack that the transmitter is ready to send
290  flag |= osSetEventFromIsr(&interface->nicTxEvent);
291  }
292 
293  //Once the interrupt has been serviced, the INTIE bit is set again to
294  //re-enable interrupts
296 
297  //A higher priority task must be woken?
298  return flag;
299 }
300 
301 
302 /**
303  * @brief ENC624J600 event handler
304  * @param[in] interface Underlying network interface
305  **/
306 
308 {
309  error_t error;
310  uint16_t status;
311  uint16_t value;
312 
313  //Read interrupt status register
314  status = enc624j600ReadReg(interface, ENC624J600_EIR);
315 
316  //Check whether the link state has changed
317  if((status & ENC624J600_EIR_LINKIF) != 0)
318  {
319  //Clear interrupt flag
321  //Read Ethernet status register
323 
324  //Check link state
325  if((value & ENC624J600_ESTAT_PHYLNK) != 0)
326  {
327  //Read PHY status register 3
329 
330  //Get current speed
331  if((value & ENC624J600_PHSTAT3_SPDDPX1) != 0)
332  {
333  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
334  }
335  else
336  {
337  interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
338  }
339 
340  //Determine the new duplex mode
341  if((value & ENC624J600_PHSTAT3_SPDDPX2) != 0)
342  {
343  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
344  }
345  else
346  {
347  interface->duplexMode = NIC_HALF_DUPLEX_MODE;
348  }
349 
350  //Link is up
351  interface->linkState = TRUE;
352 
353  //Update MAC configuration parameters for proper operation
354  enc624j600UpdateMacConfig(interface);
355  }
356  else
357  {
358  //Link is down
359  interface->linkState = FALSE;
360  }
361 
362  //Process link state change event
363  nicNotifyLinkChange(interface);
364  }
365 
366  //Check whether a packet has been received?
367  if((status & ENC624J600_EIR_PKTIF) != 0)
368  {
369  //Clear interrupt flag
371 
372  //Process all pending packets
373  do
374  {
375  //Read incoming packet
376  error = enc624j600ReceivePacket(interface);
377 
378  //No more data in the receive buffer?
379  } while(error != ERROR_BUFFER_EMPTY);
380  }
381 
382  //Re-enable LINKIE and PKTIE interrupts
385 }
386 
387 
388 /**
389  * @brief Send a packet
390  * @param[in] interface Underlying network interface
391  * @param[in] buffer Multi-part buffer containing the data to send
392  * @param[in] offset Offset to the first data byte
393  * @param[in] ancillary Additional options passed to the stack along with
394  * the packet
395  * @return Error code
396  **/
397 
399  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
400 {
401  size_t length;
402 
403  //Retrieve the length of the packet
404  length = netBufferGetLength(buffer) - offset;
405 
406  //Check the frame length
407  if(length > 1536)
408  {
409  //The transmitter can accept another packet
410  osSetEvent(&interface->nicTxEvent);
411  //Report an error
412  return ERROR_INVALID_LENGTH;
413  }
414 
415  //Make sure the link is up before transmitting the frame
416  if(!interface->linkState)
417  {
418  //The transmitter can accept another packet
419  osSetEvent(&interface->nicTxEvent);
420  //Drop current packet
421  return NO_ERROR;
422  }
423 
424  //Ensure that the transmitter is ready to send
426  {
427  return ERROR_FAILURE;
428  }
429 
430  //Point to the SRAM buffer
432  //Copy the packet to the SRAM buffer
433  enc624j600WriteBuffer(interface, ENC624J600_CMD_WGPDATA, buffer, offset);
434 
435  //Program ETXST to the start address of the packet
437  //Program ETXLEN with the length of data copied to the memory
439 
440  //Clear TXIF and TXABTIF interrupt flags
443 
444  //Set the TXRTS bit to initiate transmission
446 
447  //Successful processing
448  return NO_ERROR;
449 }
450 
451 
452 /**
453  * @brief Receive a packet
454  * @param[in] interface Underlying network interface
455  * @return Error code
456  **/
457 
459 {
460  static uint8_t temp[ENC624J600_ETH_RX_BUFFER_SIZE];
461  error_t error;
462  uint16_t length;
463  uint32_t status;
464  uint8_t header[8];
465  Enc624j600Context *context;
466 
467  //Point to the driver context
468  context = (Enc624j600Context *) interface->nicContext;
469 
470  //Verify that a packet is waiting by ensuring that PKTCNT is non-zero
472  {
473  //Point to the next packet
474  enc624j600WriteReg(interface, ENC624J600_ERXRDPT, context->nextPacket);
475 
476  //The packet is preceded by a 8-byte header
477  enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA, header,
478  sizeof(header));
479 
480  //The first two bytes are the address of the next packet
481  context->nextPacket = LOAD16LE(header);
482  //Get the length of the received packet
483  length = LOAD16LE(header + 2);
484  //Get the receive status vector (RSV)
485  status = LOAD32LE(header + 4);
486 
487  //Make sure no error occurred
488  if((status & ENC624J600_RSV_RECEIVED_OK) != 0)
489  {
490  //Limit the number of data to read
492  //Read packet data
494 
495  //Valid packet received
496  error = NO_ERROR;
497  }
498  else
499  {
500  //The received packet contains an error
501  error = ERROR_INVALID_PACKET;
502  }
503 
504  //Update the ERXTAIL pointer value to the point where the packet has
505  //been processed, taking care to wrap back at the end of the received
506  //memory buffer
507  if(context->nextPacket == ENC624J600_RX_BUFFER_START)
508  {
511  }
512  else
513  {
515  context->nextPacket - 2);
516  }
517 
518  //Set PKTDEC to decrement the PKTCNT bits
520  }
521  else
522  {
523  //No more data in the receive buffer
524  error = ERROR_BUFFER_EMPTY;
525  }
526 
527  //Check whether a valid packet has been received
528  if(!error)
529  {
530  NetRxAncillary ancillary;
531 
532  //Additional options can be passed to the stack along with the packet
533  ancillary = NET_DEFAULT_RX_ANCILLARY;
534 
535  //Pass the packet to the upper layer
536  nicProcessPacket(interface, temp, length, &ancillary);
537  }
538 
539  //Return status code
540  return error;
541 }
542 
543 
544 /**
545  * @brief Configure MAC address filtering
546  * @param[in] interface Underlying network interface
547  * @return Error code
548  **/
549 
551 {
552  uint_t i;
553  uint_t k;
554  uint32_t crc;
555  uint16_t hashTable[4];
556  MacFilterEntry *entry;
557 
558  //Debug message
559  TRACE_DEBUG("Updating MAC filter...\r\n");
560 
561  //Clear hash table
562  osMemset(hashTable, 0, sizeof(hashTable));
563 
564  //The MAC address filter contains the list of MAC addresses to accept
565  //when receiving an Ethernet frame
566  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
567  {
568  //Point to the current entry
569  entry = &interface->macAddrFilter[i];
570 
571  //Valid entry?
572  if(entry->refCount > 0)
573  {
574  //Compute CRC over the current MAC address
575  crc = enc624j600CalcCrc(&entry->addr, sizeof(MacAddr));
576  //Calculate the corresponding index in the table
577  k = (crc >> 23) & 0x3F;
578  //Update hash table contents
579  hashTable[k / 16] |= (1 << (k % 16));
580  }
581  }
582 
583  //Write the hash table to the ENC624J600 controller
584  enc624j600WriteReg(interface, ENC624J600_EHT1, hashTable[0]);
585  enc624j600WriteReg(interface, ENC624J600_EHT2, hashTable[1]);
586  enc624j600WriteReg(interface, ENC624J600_EHT3, hashTable[2]);
587  enc624j600WriteReg(interface, ENC624J600_EHT4, hashTable[3]);
588 
589  //Debug message
590  TRACE_DEBUG(" EHT1 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_EHT1));
591  TRACE_DEBUG(" EHT2 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_EHT2));
592  TRACE_DEBUG(" EHT3 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_EHT3));
593  TRACE_DEBUG(" EHT4 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_EHT4));
594 
595  //Successful processing
596  return NO_ERROR;
597 }
598 
599 
600 /**
601  * @brief Adjust MAC configuration parameters for proper operation
602  * @param[in] interface Underlying network interface
603  **/
604 
606 {
607  uint16_t duplexMode;
608 
609  //Determine the new duplex mode by reading the PHYDPX bit
611 
612  //Full-duplex mode?
613  if(duplexMode)
614  {
615  //Configure the FULDPX bit to match the current duplex mode
619 
620  //Configure the Back-to-Back Inter-Packet Gap register
623  }
624  //Half-duplex mode?
625  else
626  {
627  //Configure the FULDPX bit to match the current duplex mode
631 
632  //Configure the Back-to-Back Inter-Packet Gap register
635  }
636 }
637 
638 
639 /**
640  * @brief Reset ENC624J600 controller
641  * @param[in] interface Underlying network interface
642  * @return Error code
643  **/
644 
646 {
647  //Wait for the SPI interface to be ready
648  do
649  {
650  //Write 0x1234 to EUDAST
651  enc624j600WriteReg(interface, ENC624J600_EUDAST, 0x1234);
652  //Read back register and check contents
653  } while(enc624j600ReadReg(interface, ENC624J600_EUDAST) != 0x1234);
654 
655  //Poll CLKRDY and wait for it to become set
657  {
658  }
659 
660  //Issue a system reset command by setting ETHRST
662  //Wait at least 25us for the reset to take place
663  sleep(1);
664 
665  //Read EUDAST to confirm that the system reset took place. EUDAST should
666  //have reverted back to its reset default
667  if(enc624j600ReadReg(interface, ENC624J600_EUDAST) != 0x0000)
668  {
669  return ERROR_FAILURE;
670  }
671 
672  //Wait at least 256us for the PHY registers and PHY status bits to become
673  //available
674  sleep(1);
675 
676  //The controller is now ready to accept further commands
677  return NO_ERROR;
678 }
679 
680 
681 /**
682  * @brief Write ENC624J600 register
683  * @param[in] interface Underlying network interface
684  * @param[in] address Register address
685  * @param[in] data Register value
686  **/
687 
688 void enc624j600WriteReg(NetInterface *interface, uint8_t address,
689  uint16_t data)
690 {
691  //Pull the CS pin low
692  interface->spiDriver->assertCs();
693 
694  //Write opcode
695  interface->spiDriver->transfer(ENC624J600_CMD_WCRU);
696  //Write register address
697  interface->spiDriver->transfer(address);
698  //Write register value
699  interface->spiDriver->transfer(LSB(data));
700  interface->spiDriver->transfer(MSB(data));
701 
702  //Terminate the operation by raising the CS pin
703  interface->spiDriver->deassertCs();
704 }
705 
706 
707 /**
708  * @brief Read ENC624J600 register
709  * @param[in] interface Underlying network interface
710  * @param[in] address Register address
711  * @return Register value
712  **/
713 
714 uint16_t enc624j600ReadReg(NetInterface *interface, uint8_t address)
715 {
716  uint16_t data;
717 
718  //Pull the CS pin low
719  interface->spiDriver->assertCs();
720 
721  //Write opcode
722  interface->spiDriver->transfer(ENC624J600_CMD_RCRU);
723  //Write register address
724  interface->spiDriver->transfer(address);
725  //Read the lower 8 bits of data
726  data = interface->spiDriver->transfer(0x00);
727  //Read the upper 8 bits of data
728  data |= interface->spiDriver->transfer(0x00) << 8;
729 
730  //Terminate the operation by raising the CS pin
731  interface->spiDriver->deassertCs();
732 
733  //Return register contents
734  return data;
735 }
736 
737 
738 /**
739  * @brief Write PHY register
740  * @param[in] interface Underlying network interface
741  * @param[in] address PHY register address
742  * @param[in] data Register value
743  **/
744 
745 void enc624j600WritePhyReg(NetInterface *interface, uint8_t address,
746  uint16_t data)
747 {
748  uint16_t status;
749 
750  //Write the address of the PHY register to write to
753 
754  //Write the 16 bits of data into the MIWR register
756 
757  //Wait until the PHY register has been written
758  do
759  {
760  //Read MII Management Status register
761  status = enc624j600ReadReg(interface, ENC624J600_MISTAT);
762  //Check the value of the busy status bit
763  } while((status & ENC624J600_MISTAT_BUSY) != 0);
764 }
765 
766 
767 /**
768  * @brief Read PHY register
769  * @param[in] interface Underlying network interface
770  * @param[in] address PHY register address
771  * @return Register value
772  **/
773 
774 uint16_t enc624j600ReadPhyReg(NetInterface *interface, uint8_t address)
775 {
776  uint16_t status;
777 
778  //Write the address of the PHY register to read from
781 
782  //Start read operation
784 
785  //Wait at least 25.6us before polling the BUSY bit
786  usleep(100);
787 
788  //Wait for the read operation to complete
789  do
790  {
791  //Read MII Management Status register
792  status = enc624j600ReadReg(interface, ENC624J600_MISTAT);
793  //Check the value of the busy status bit
794  } while((status & ENC624J600_MISTAT_BUSY) != 0);
795 
796  //Clear command register
797  enc624j600WriteReg(interface, ENC624J600_MICMD, 0x00);
798 
799  //Return register contents
800  return enc624j600ReadReg(interface, ENC624J600_MIRD);
801 }
802 
803 
804 /**
805  * @brief Write SRAM buffer
806  * @param[in] interface Underlying network interface
807  * @param[in] opcode SRAM buffer operation
808  * @param[in] buffer Multi-part buffer containing the data to be written
809  * @param[in] offset Offset to the first data byte
810  **/
811 
813  uint8_t opcode, const NetBuffer *buffer, size_t offset)
814 {
815  uint_t i;
816  size_t j;
817  size_t n;
818  uint8_t *p;
819 
820  //Pull the CS pin low
821  interface->spiDriver->assertCs();
822 
823  //Write opcode
824  interface->spiDriver->transfer(opcode);
825 
826  //Loop through data chunks
827  for(i = 0; i < buffer->chunkCount; i++)
828  {
829  //Is there any data to copy from the current chunk?
830  if(offset < buffer->chunk[i].length)
831  {
832  //Point to the first byte to be read
833  p = (uint8_t *) buffer->chunk[i].address + offset;
834  //Compute the number of bytes to copy at a time
835  n = buffer->chunk[i].length - offset;
836 
837  //Copy data to SRAM buffer
838  for(j = 0; j < n; j++)
839  {
840  interface->spiDriver->transfer(p[j]);
841  }
842 
843  //Process the next block from the start
844  offset = 0;
845  }
846  else
847  {
848  //Skip the current chunk
849  offset -= buffer->chunk[i].length;
850  }
851  }
852 
853  //Terminate the operation by raising the CS pin
854  interface->spiDriver->deassertCs();
855 }
856 
857 
858 /**
859  * @brief Read SRAM buffer
860  * @param[in] interface Underlying network interface
861  * @param[in] opcode SRAM buffer operation
862  * @param[out] data Buffer where to store the incoming data
863  * @param[in] length Number of data to read
864  **/
865 
867  uint8_t opcode, uint8_t *data, size_t length)
868 {
869  size_t i;
870 
871  //Pull the CS pin low
872  interface->spiDriver->assertCs();
873 
874  //Write opcode
875  interface->spiDriver->transfer(opcode);
876 
877  //Copy data from SRAM buffer
878  for(i = 0; i < length; i++)
879  {
880  data[i] = interface->spiDriver->transfer(0x00);
881  }
882 
883  //Terminate the operation by raising the CS pin
884  interface->spiDriver->deassertCs();
885 }
886 
887 
888 /**
889  * @brief Set bit field
890  * @param[in] interface Underlying network interface
891  * @param[in] address Register address
892  * @param[in] mask Bits to set in the target register
893  **/
894 
895 void enc624j600SetBit(NetInterface *interface, uint8_t address,
896  uint16_t mask)
897 {
898  //Pull the CS pin low
899  interface->spiDriver->assertCs();
900 
901  //Write opcode
902  interface->spiDriver->transfer(ENC624J600_CMD_BFSU);
903  //Write register address
904  interface->spiDriver->transfer(address);
905  //Write bit mask
906  interface->spiDriver->transfer(LSB(mask));
907  interface->spiDriver->transfer(MSB(mask));
908 
909  //Terminate the operation by raising the CS pin
910  interface->spiDriver->deassertCs();
911 }
912 
913 
914 /**
915  * @brief Clear bit field
916  * @param[in] interface Underlying network interface
917  * @param[in] address Register address
918  * @param[in] mask Bits to clear in the target register
919  **/
920 
921 void enc624j600ClearBit(NetInterface *interface, uint8_t address,
922  uint16_t mask)
923 {
924  //Pull the CS pin low
925  interface->spiDriver->assertCs();
926 
927  //Write opcode
928  interface->spiDriver->transfer(ENC624J600_CMD_BFCU);
929  //Write register address
930  interface->spiDriver->transfer(address);
931  //Write bit mask
932  interface->spiDriver->transfer(LSB(mask));
933  interface->spiDriver->transfer(MSB(mask));
934 
935  //Terminate the operation by raising the CS pin
936  interface->spiDriver->deassertCs();
937 }
938 
939 
940 /**
941  * @brief CRC calculation using the polynomial 0x4C11DB7
942  * @param[in] data Pointer to the data over which to calculate the CRC
943  * @param[in] length Number of bytes to process
944  * @return Resulting CRC value
945  **/
946 
947 uint32_t enc624j600CalcCrc(const void *data, size_t length)
948 {
949  uint_t i;
950  uint_t j;
951  uint32_t crc;
952  const uint8_t *p;
953 
954  //Point to the data over which to calculate the CRC
955  p = (uint8_t *) data;
956  //CRC preset value
957  crc = 0xFFFFFFFF;
958 
959  //Loop through data
960  for(i = 0; i < length; i++)
961  {
962  //The message is processed bit by bit
963  for(j = 0; j < 8; j++)
964  {
965  //Update CRC value
966  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
967  {
968  crc = (crc << 1) ^ 0x04C11DB7;
969  }
970  else
971  {
972  crc = crc << 1;
973  }
974  }
975  }
976 
977  //Return CRC value
978  return crc;
979 }
980 
981 
982 /**
983  * @brief Dump registers for debugging purpose
984  * @param[in] interface Underlying network interface
985  **/
986 
988 {
989 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
990  uint8_t i;
991  uint8_t bank;
992  uint16_t address;
993 
994  //Display header
995  TRACE_DEBUG(" Bank 0 Bank 1 Bank 2 Bank 3 Unbanked\r\n");
996 
997  //Loop through register addresses
998  for(i = 0; i < 32; i += 2)
999  {
1000  //Display register address
1001  TRACE_DEBUG("%02" PRIX8 ": ", i);
1002 
1003  //Loop through bank numbers
1004  for(bank = 0; bank < 5; bank++)
1005  {
1006  //Format register address
1007  address = 0x7E00 | (bank << 5) | i;
1008  //Display register contents
1009  TRACE_DEBUG("0x%04" PRIX16 " ", enc624j600ReadReg(interface, address));
1010  }
1011 
1012  //Jump to the following line
1013  TRACE_DEBUG("\r\n");
1014  }
1015 
1016  //Terminate with a line feed
1017  TRACE_DEBUG("\r\n");
1018 #endif
1019 }
1020 
1021 
1022 /**
1023  * @brief Dump PHY registers for debugging purpose
1024  * @param[in] interface Underlying network interface
1025  **/
1026 
1028 {
1029 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
1030  uint8_t i;
1031 
1032  //Loop through PHY registers
1033  for(i = 0; i < 32; i++)
1034  {
1035  //Display current PHY register
1036  TRACE_DEBUG("%02" PRIX8 ": 0x%04" PRIX16 "\r\n", i, enc624j600ReadPhyReg(interface, i));
1037  }
1038 
1039  //Terminate with a line feed
1040  TRACE_DEBUG("\r\n");
1041 #endif
1042 }
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
#define LOAD16LE(p)
Definition: cpu_endian.h:181
#define LOAD32LE(p)
Definition: cpu_endian.h:203
#define letoh16(value)
Definition: cpu_endian.h:437
#define htole16(value)
Definition: cpu_endian.h:429
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint8_t opcode
Definition: dns_common.h:188
void enc624j600WriteBuffer(NetInterface *interface, uint8_t opcode, const NetBuffer *buffer, size_t offset)
Write SRAM buffer.
void enc624j600EventHandler(NetInterface *interface)
ENC624J600 event handler.
void enc624j600DisableIrq(NetInterface *interface)
Disable interrupts.
void enc624j600ClearBit(NetInterface *interface, uint8_t address, uint16_t mask)
Clear bit field.
const NicDriver enc624j600Driver
ENC624J600 driver.
__weak_func void enc624j600InitHook(NetInterface *interface)
ENC624J600 custom configuration.
void enc624j600WriteReg(NetInterface *interface, uint8_t address, uint16_t data)
Write ENC624J600 register.
error_t enc624j600UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void enc624j600Tick(NetInterface *interface)
ENC624J600 timer handler.
error_t enc624j600ReceivePacket(NetInterface *interface)
Receive a packet.
bool_t enc624j600IrqHandler(NetInterface *interface)
ENC624J600 interrupt service routine.
uint16_t enc624j600ReadReg(NetInterface *interface, uint8_t address)
Read ENC624J600 register.
void enc624j600UpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void enc624j600DumpReg(NetInterface *interface)
Dump registers for debugging purpose.
error_t enc624j600Init(NetInterface *interface)
ENC624J600 controller initialization.
error_t enc624j600SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
void enc624j600SetBit(NetInterface *interface, uint8_t address, uint16_t mask)
Set bit field.
void enc624j600DumpPhyReg(NetInterface *interface)
Dump PHY registers for debugging purpose.
void enc624j600ReadBuffer(NetInterface *interface, uint8_t opcode, uint8_t *data, size_t length)
Read SRAM buffer.
void enc624j600WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data)
Write PHY register.
error_t enc624j600SoftReset(NetInterface *interface)
Reset ENC624J600 controller.
uint32_t enc624j600CalcCrc(const void *data, size_t length)
CRC calculation using the polynomial 0x4C11DB7.
void enc624j600EnableIrq(NetInterface *interface)
Enable interrupts.
uint16_t enc624j600ReadPhyReg(NetInterface *interface, uint8_t address)
Read PHY register.
ENC624J600 Ethernet controller.
#define ENC624J600_MIREGADR
#define ENC624J600_CMD_BFCU
#define ENC624J600_EGPWRPT
#define ENC624J600_ECON2
#define ENC624J600_RX_BUFFER_START
#define ENC624J600_MABBIPG_BBIPG_DEFAULT_HD
#define ENC624J600_ESTAT_PHYLNK
#define ENC624J600_ERXFCON_HTEN
#define ENC624J600_PHANA_AD100
#define ENC624J600_ERXST
#define ENC624J600_MACON2_R1_DEFAULT
#define ENC624J600_ERXFCON_CRCEN
#define ENC624J600_ECON1
#define ENC624J600_ERXFCON_BCEN
#define ENC624J600_CMD_BFSU
#define ENC624J600_MIRD
#define ENC624J600_TX_BUFFER_START
#define ENC624J600_MABBIPG_BBIPG_DEFAULT_FD
#define ENC624J600_EIE_TXIE
#define ENC624J600_PHANA_AD10FD
#define ENC624J600_MACON2_PADCFG_AUTO
#define ENC624J600_ECON1_TXRTS
#define ENC624J600_EHT4
#define ENC624J600_ECON2_ETHEN
#define ENC624J600_EIE_INTIE
#define ENC624J600_EIR_TXABTIF
#define ENC624J600_CMD_WGPDATA
#define ENC624J600_ERXTAIL
#define ENC624J600_EHT2
#define ENC624J600_ETXST
#define ENC624J600_MACON2_DEFER
#define ENC624J600_MAADR1
#define ENC624J600_MISTAT_BUSY
#define ENC624J600_MACON2
#define ENC624J600_MIWR
#define ENC624J600_PHSTAT3_SPDDPX2
#define ENC624J600_CMD_RCRU
#define ENC624J600_ETXLEN
#define ENC624J600_PHANA_AD100FD
#define ENC624J600_EIE_PKTIE
#define ENC624J600_ECON1_RXEN
#define ENC624J600_EHT3
#define ENC624J600_ERXFCON
#define ENC624J600_ERXFCON_UCEN
#define ENC624J600_ETH_RX_BUFFER_SIZE
#define ENC624J600_EUDAST
#define ENC624J600_ERXFCON_RUNTEN
#define ENC624J600_MABBIPG
#define ENC624J600_MIREGADR_R12_8_DEFAULT
#define ENC624J600_MACON2_FULDPX
#define ENC624J600_PHANA_ADPAUS0
#define ENC624J600_MICMD
#define ENC624J600_ESTAT_PHYDPX
#define ENC624J600_PHANA
#define ENC624J600_EIE_LINKIE
#define ENC624J600_MAMXFL
#define ENC624J600_MACON2_TXCRCEN
#define ENC624J600_ECON2_STRCH
#define ENC624J600_ERXRDPT
#define ENC624J600_EIR_PKTIF
#define ENC624J600_CMD_WCRU
#define ENC624J600_RX_BUFFER_STOP
#define ENC624J600_CMD_RRXDATA
#define ENC624J600_PHANA_AD10
#define ENC624J600_PHSTAT3
#define ENC624J600_EIR_TXIF
#define ENC624J600_EIE_TXABTIE
#define ENC624J600_MISTAT
#define ENC624J600_EHT1
#define ENC624J600_RSV_RECEIVED_OK
#define ENC624J600_ECON2_ETHRST
#define ENC624J600_MAADR2
#define ENC624J600_ECON1_PKTDEC
#define ENC624J600_ESTAT_CLKRDY
#define ENC624J600_ESTAT
#define ENC624J600_ESTAT_PKTCNT
#define ENC624J600_EIR_LINKIF
#define ENC624J600_MICMD_MIIRD
#define ENC624J600_EIR
#define ENC624J600_EIE
#define ENC624J600_MAADR3
#define ENC624J600_PHANA_ADIEEE_DEFAULT
#define ENC624J600_PHSTAT3_SPDDPX1
error_t
Error codes.
Definition: error.h:43
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PACKET
Definition: error.h:140
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
Map a MAC address to the IPv6 modified EUI-64 identifier.
Definition: ethernet.c:944
#define ETH_MTU
Definition: ethernet.h:116
uint8_t data[]
Definition: ethernet.h:222
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
MacAddr
Definition: ethernet.h:195
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
Ipv6Addr address[]
Definition: ipv6.h:316
uint8_t p
Definition: ndp.h:300
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:101
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:391
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:548
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
#define osMemset(p, value, length)
Definition: os_port.h:135
#define LSB(x)
Definition: os_port.h:55
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define usleep(delay)
Definition: os_port.h:297
#define MSB(x)
Definition: os_port.h:59
#define sleep(delay)
Definition: os_port.h:301
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
uint16_t length
Definition: net_mem.h:79
void * address
Definition: net_mem.h:78
ENC424J600 driver context.
uint16_t nextPacket
Next packet in the receive buffer.
MAC filter table entry.
Definition: ethernet.h:262
MacAddr addr
MAC address.
Definition: ethernet.h:263
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint_t chunkCount
Definition: net_mem.h:90
ChunkDesc chunk[]
Definition: net_mem.h:92
NIC driver.
Definition: nic.h:283
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369
uint8_t mask
Definition: web_socket.h:319