ncv7410_driver.c
Go to the documentation of this file.
1 /**
2  * @file ncv7410_driver.c
3  * @brief Onsemi NCV7410 10Base-T1S Ethernet controller
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.2
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 NCV7410 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 NCV7410 controller initialization
67  * @param[in] interface Underlying network interface
68  * @return Error code
69  **/
70 
72 {
73  uint32_t value;
74 
75  //Debug message
76  TRACE_INFO("Initializing NCV7410 Ethernet controller...\r\n");
77 
78  //Initialize SPI interface
79  interface->spiDriver->init();
80 
81  //Initialize external interrupt line driver
82  if(interface->extIntDriver != NULL)
83  {
84  interface->extIntDriver->init();
85  }
86 
87  //Issue a device reset
89 
90  //Wait for the reset to complete
91  do
92  {
93  //Read reset control and status register
94  value = ncv7410ReadReg(interface, NCV7410_RESET);
95 
96  //The RESET self-clears when the reset finishes
97  } while((value & NCV7410_RESET_RESET) != 0);
98 
99  //Read the STATUS0 register and confirm that the RESETC field is 1
100  do
101  {
102  //Read the status register 0
103  value = ncv7410ReadReg(interface, NCV7410_STATUS0);
104 
105  //Check the value of the RESETC bit
106  } while((value & NCV7410_STATUS0_RESETC) == 0);
107 
108  //Write 1 to the RESETC field in the STATUS0 register to clear this field
110 
111  //Dump MMS0 registers for debugging purpose
112  TRACE_DEBUG("MMS0 registers:\r\n");
113  ncv7410DumpReg(interface, NCV7410_MMS_STD, 0, 16);
114 
115  //Configure DIO LEDs
116  ncv7410WriteReg(interface, NCV7410_DIOCFG,
120 
121  //Perform custom configuration
122  ncv7410InitHook(interface);
123 
124  //Configure the MAC for calculating and appending the FCS
125  value = ncv7410ReadReg(interface, NCV7410_MACCTRL0);
128 
129  //Use factory preprogrammed MAC address?
130  if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
131  {
132  //Read PHYID register
133  value = ncv7410ReadReg(interface, NCV7410_PHYID);
134  //The OUI field records the 22 MSB's of the OUI in reverse order
135  value = reverseInt32(value) << 2;
136 
137  //Save the OUI
138  interface->macAddr.b[0] = value & 0xFF;
139  interface->macAddr.b[1] = (value >> 8) & 0xFF;
140  interface->macAddr.b[2] = (value >> 16) & 0xFF;
141 
142  //Read MACID0 register
143  value = ncv7410ReadReg(interface, NCV7410_MACID0);
144 
145  //Save the lower 16 bits of the unique MAC address
146  interface->macAddr.b[5] = value & 0xFF;
147  interface->macAddr.b[4] = (value >> 8) & 0xFF;
148 
149  //Read MACID1 register
150  value = ncv7410ReadReg(interface, NCV7410_MACID1);
151 
152  //Save the upper 8 bits of the unique MAC address
153  interface->macAddr.b[3] = value & 0xFF;
154 
155  //Generate the 64-bit interface identifier
156  macAddrToEui64(&interface->macAddr, &interface->eui64);
157  }
158 
159  //Configure MAC address filtering
160  ncv7410UpdateMacAddrFilter(interface);
161 
162  //Configure the SPI protocol engine
166 
167  //When the MAC is configured, write 1 to the SYNC field in the CONFIG0
168  //register to indicate that the MAC configuration is complete
169  value = ncv7410ReadReg(interface, NCV7410_CONFIG0);
172 
173  //Enable TX and RX
174  value = ncv7410ReadReg(interface, NCV7410_MACCTRL0);
177 
178  //Enable the physical link
180 
181  //Accept any packets from the upper layer
182  osSetEvent(&interface->nicTxEvent);
183 
184  //Force the TCP/IP stack to poll the status at startup
185  interface->nicEvent = TRUE;
186  //Notify the TCP/IP stack of the event
188 
189  //Successful initialization
190  return NO_ERROR;
191 }
192 
193 
194 /**
195  * @brief NCV7410 custom configuration
196  * @param[in] interface Underlying network interface
197  **/
198 
199 __weak_func void ncv7410InitHook(NetInterface *interface)
200 {
201 #if (NCV7410_PLCA_SUPPORT == ENABLED)
202  //Set PLCA burst
205 
206  //Set PLCA node count and local ID
210 
211  //Enable PLCA
213 #else
214  //Disable PLCA
215  ncv7410WriteReg(interface, NCV7410_PLCACTRL0, 0);
216 #endif
217 }
218 
219 
220 /**
221  * @brief NCV7410 timer handler
222  * @param[in] interface Underlying network interface
223  **/
224 
225 void ncv7410Tick(NetInterface *interface)
226 {
227  uint32_t value;
228  bool_t linkState;
229 
230  //Read PHY status register
231  value = ncv7410ReadReg(interface, NCV7410_PHYSTATUS);
232  //Retrieve current link state
233  linkState = (value & NCV7410_PHYSTATUS_LKST) ? TRUE : FALSE;
234 
235  //Link up event?
236  if(linkState && !interface->linkState)
237  {
238  //The PHY is only able to operate in 10 Mbps mode
239  interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
240  interface->duplexMode = NIC_HALF_DUPLEX_MODE;
241 
242  //Update link state
243  interface->linkState = TRUE;
244 
245  //Process link state change event
246  nicNotifyLinkChange(interface);
247  }
248  //Link down event?
249  else if(!linkState && interface->linkState)
250  {
251  //Update link state
252  interface->linkState = FALSE;
253 
254  //Process link state change event
255  nicNotifyLinkChange(interface);
256  }
257 }
258 
259 
260 /**
261  * @brief Enable interrupts
262  * @param[in] interface Underlying network interface
263  **/
264 
266 {
267  //Enable interrupts
268  if(interface->extIntDriver != NULL)
269  {
270  interface->extIntDriver->enableIrq();
271  }
272 }
273 
274 
275 /**
276  * @brief Disable interrupts
277  * @param[in] interface Underlying network interface
278  **/
279 
281 {
282  //Disable interrupts
283  if(interface->extIntDriver != NULL)
284  {
285  interface->extIntDriver->disableIrq();
286  }
287 }
288 
289 
290 /**
291  * @brief NCV7410 interrupt service routine
292  * @param[in] interface Underlying network interface
293  * @return TRUE if a higher priority task must be woken. Else FALSE is returned
294  **/
295 
297 {
298  //When the SPI host detects an asserted IRQn from the MACPHY, it should
299  //initiate a data chunk transfer to obtain the current data footer
300  interface->nicEvent = TRUE;
301 
302  //Notify the TCP/IP stack of the event
303  return osSetEventFromIsr(&netEvent);
304 }
305 
306 
307 /**
308  * @brief NCV7410 event handler
309  * @param[in] interface Underlying network interface
310  **/
311 
313 {
314  uint32_t status;
315 
316  //Read buffer status register
317  status = ncv7410ReadReg(interface, NCV7410_BUFSTS);
318 
319  //Process all the data chunks currently available
320  while((status & NCV7410_BUFSTS_RCA) != 0)
321  {
322  //Read incoming packet
323  ncv7410ReceivePacket(interface);
324 
325  //Read buffer status register
326  status = ncv7410ReadReg(interface, NCV7410_BUFSTS);
327  }
328 }
329 
330 
331 /**
332  * @brief Send a packet
333  * @param[in] interface Underlying network interface
334  * @param[in] buffer Multi-part buffer containing the data to send
335  * @param[in] offset Offset to the first data byte
336  * @param[in] ancillary Additional options passed to the stack along with
337  * the packet
338  * @return Error code
339  **/
340 
342  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
343 {
344  static uint8_t chunk[NCV7410_CHUNK_PAYLOAD_SIZE + 4];
345  size_t i;
346  size_t j;
347  size_t n;
348  size_t length;
349  uint32_t status;
350  uint32_t header;
351  uint32_t footer;
352 
353  //Retrieve the length of the packet
354  length = netBufferGetLength(buffer) - offset;
355 
356  //Read buffer status register
357  status = ncv7410ReadReg(interface, NCV7410_BUFSTS);
358  //Get the number of data chunks available in the transmit buffer
359  n = (status & NCV7410_BUFSTS_TXC) >> 8;
360 
361  //Check the number of transmit credits available
363  {
364  //A data transaction consists of multiple chunks
365  for(i = 0; i < length; i += n)
366  {
367  //The default size of the data chunk payload is 64 bytes
369 
370  //Set up a data transfer
373 
374  //Start of packet?
375  if(i == 0)
376  {
377  //The SPI host shall set the SV bit when the beginning of an
378  //Ethernet frame is present in the current transmit data chunk
379  //payload
380  header |= NCV7410_TX_HEADER_SV;
381  }
382 
383  //End of packet?
384  if((i + n) == length)
385  {
386  //The SPI host shall set the EV bit when the end of an Ethernet
387  //frame is present in the current transmit data chunk payload
388  header |= NCV7410_TX_HEADER_EV;
389 
390  //When EV is 1, the EBO field shall contain the byte offset into
391  //the transmit data chunk payload that points to the last byte of
392  //the Ethernet frame to transmit
393  header |= ((n - 1) << 8) & NCV7410_TX_HEADER_EBO;
394  }
395 
396  //The parity bit is calculated over the transmit data header
397  if(ncv7410CalcParity(header) != 0)
398  {
399  header |= NCV7410_CTRL_HEADER_P;
400  }
401 
402  //A chunk is composed of 4 bytes of overhead plus the configured
403  //payload size
404  STORE32BE(header, chunk);
405 
406  //Copy data chunk payload
407  netBufferRead(chunk + 4, buffer, offset + i, n);
408 
409  //Pad frames shorter than the data chunk payload
411  {
412  osMemset(chunk + 4 + n, 0, NCV7410_CHUNK_PAYLOAD_SIZE - n);
413  }
414 
415  //Pull the CS pin low
416  interface->spiDriver->assertCs();
417 
418  //Perform data transfer
419  for(j = 0; j < (NCV7410_CHUNK_PAYLOAD_SIZE + 4); j++)
420  {
421  chunk[j] = interface->spiDriver->transfer(chunk[j]);
422  }
423 
424  //Terminate the operation by raising the CS pin
425  interface->spiDriver->deassertCs();
426 
427  //Receive data chunks consist of the receive data chunk payload followed
428  //by a 4-byte footer
429  footer = LOAD32BE(chunk + NCV7410_CHUNK_PAYLOAD_SIZE);
430 
431  //The RCA field indicates the number of receive data chunks available
432  if((footer & NCV7410_RX_FOOTER_RCA) != 0)
433  {
434  //Some data chunks are available for reading
435  interface->nicEvent = TRUE;
436  //Notify the TCP/IP stack of the event
438  }
439  }
440  }
441  else
442  {
443  //No sufficient credits available
444  }
445 
446  //The transmitter can accept another packet
447  osSetEvent(&interface->nicTxEvent);
448 
449  //Successful processing
450  return NO_ERROR;
451 }
452 
453 
454 /**
455  * @brief Receive a packet
456  * @param[in] interface Underlying network interface
457  * @return Error code
458  **/
459 
461 {
462  static uint8_t buffer[NCV7410_ETH_RX_BUFFER_SIZE];
463  static uint8_t chunk[NCV7410_CHUNK_PAYLOAD_SIZE + 4];
464  error_t error;
465  size_t i;
466  size_t n;
467  size_t length;
468  uint32_t header;
469  uint32_t footer;
470 
471  //Initialize variable
472  length = 0;
473 
474  //A data transaction consists of multiple chunks
475  while(1)
476  {
477  //Check the length of the received packet
479  {
480  error = ERROR_BUFFER_OVERFLOW;
481  break;
482  }
483 
484  //The SPI host sets NORX to 0 to indicate that it accepts and process
485  //any receive frame data within the current chunk
486  header = NCV7410_TX_HEADER_DNC;
487 
488  //The parity bit is calculated over the transmit data header
489  if(ncv7410CalcParity(header) != 0)
490  {
491  header |= NCV7410_CTRL_HEADER_P;
492  }
493 
494  //Transmit data chunks consist of a 4-byte header followed by the
495  //transmit data chunk payload,
496  STORE32BE(header, chunk);
497 
498  //Clear data chunk payload
499  osMemset(chunk + 4, 0, NCV7410_CHUNK_PAYLOAD_SIZE);
500 
501  //Pull the CS pin low
502  interface->spiDriver->assertCs();
503 
504  //Perform data transfer
505  for(i = 0; i < (NCV7410_CHUNK_PAYLOAD_SIZE + 4); i++)
506  {
507  chunk[i] = interface->spiDriver->transfer(chunk[i]);
508  }
509 
510  //Terminate the operation by raising the CS pin
511  interface->spiDriver->deassertCs();
512 
513  //Receive data chunks consist of the receive data chunk payload followed
514  //by a 4-byte footer
515  footer = LOAD32BE(chunk + NCV7410_CHUNK_PAYLOAD_SIZE);
516 
517  //When the DV bit is 0, the SPI host ignores the chunk payload
518  if((footer & NCV7410_RX_FOOTER_DV) == 0)
519  {
520  error = ERROR_BUFFER_EMPTY;
521  break;
522  }
523 
524  //When the SV bit is 1, the beginning of an Ethernet frame is present in
525  //the current transmit data chunk payload
526  if(length == 0)
527  {
528  if((footer & NCV7410_RX_FOOTER_SV) == 0)
529  {
530  error = ERROR_INVALID_PACKET;
531  break;
532  }
533  }
534  else
535  {
536  if((footer & NCV7410_RX_FOOTER_SV) != 0)
537  {
538  error = ERROR_INVALID_PACKET;
539  break;
540  }
541  }
542 
543  //When EV is 1, the EBO field contains the byte offset into the
544  //receive data chunk payload that points to the last byte of the
545  //received Ethernet frame
546  if((footer & NCV7410_RX_FOOTER_EV) != 0)
547  {
548  n = ((footer & NCV7410_RX_FOOTER_EBO) >> 8) + 1;
549  }
550  else
551  {
553  }
554 
555  //Copy data chunk payload
556  osMemcpy(buffer + length, chunk, n);
557  //Adjust the length of the packet
558  length += n;
559 
560  //When the EV bit is 1, the end of an Ethernet frame is present in the
561  //current receive data chunk payload
562  if((footer & NCV7410_RX_FOOTER_EV) != 0)
563  {
564  NetRxAncillary ancillary;
565 
566  //Additional options can be passed to the stack along with the packet
567  ancillary = NET_DEFAULT_RX_ANCILLARY;
568  //Pass the packet to the upper layer
569  nicProcessPacket(interface, buffer, length, &ancillary);
570 
571  //Successful processing
572  error = NO_ERROR;
573  break;
574  }
575  }
576 
577  //Return status code
578  return error;
579 }
580 
581 
582 /**
583  * @brief Configure MAC address filtering
584  * @param[in] interface Underlying network interface
585  * @return Error code
586  **/
587 
589 {
590  uint_t i;
591  uint_t j;
592  uint32_t value;
593  bool_t acceptMulticast;
594  MacAddr unicastMacAddr[3];
595  MacFilterEntry *entry;
596 
597  //Debug message
598  TRACE_DEBUG("Updating MAC filter...\r\n");
599 
600  //Set the lower 32 bits of the station MAC address
602  (interface->macAddr.b[2] << 24) | (interface->macAddr.b[3] << 16) |
603  (interface->macAddr.b[4] << 8) | interface->macAddr.b[5]);
604 
605  //Set the upper 16 bits of the station MAC address
607  (interface->macAddr.b[0] << 8) | interface->macAddr.b[1]);
608 
609  //The MAC supports 3 additional addresses for unicast perfect filtering
610  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
611  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
612  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
613 
614  //This flag will be set if multicast addresses should be accepted
615  acceptMulticast = FALSE;
616 
617  //The MAC address filter contains the list of MAC addresses to accept
618  //when receiving an Ethernet frame
619  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
620  {
621  //Point to the current entry
622  entry = &interface->macAddrFilter[i];
623 
624  //Valid entry?
625  if(entry->refCount > 0)
626  {
627  //Multicast address?
628  if(macIsMulticastAddr(&entry->addr))
629  {
630  //Accept multicast addresses
631  acceptMulticast = TRUE;
632  }
633  else
634  {
635  //Up to 3 additional MAC addresses can be specified
636  if(j < 3)
637  {
638  //Save the unicast address
639  unicastMacAddr[j++] = entry->addr;
640  }
641  }
642  }
643  }
644 
645  //Configure the first unicast address filter
646  if(j >= 1)
647  {
648  //Set the lower 32 bits of the MAC address
650  (unicastMacAddr[0].b[2] << 24) | (unicastMacAddr[0].b[3] << 16) |
651  (unicastMacAddr[0].b[4] << 8) | unicastMacAddr[0].b[5]);
652 
653  //Set the upper 16 bits of the MAC address
655  (unicastMacAddr[0].b[0] << 8) | unicastMacAddr[0].b[1]);
656  }
657  else
658  {
659  ncv7410WriteReg(interface, NCV7410_ADDRFILT1L, 0);
660  ncv7410WriteReg(interface, NCV7410_ADDRFILT1H, 0);
661  }
662 
663  //Configure the second unicast address filter
664  if(j >= 2)
665  {
666  //Set the lower 32 bits of the MAC address
668  (unicastMacAddr[1].b[2] << 24) | (unicastMacAddr[1].b[3] << 16) |
669  (unicastMacAddr[1].b[4] << 8) | unicastMacAddr[1].b[5]);
670 
671  //Set the upper 16 bits of the MAC address
673  (unicastMacAddr[1].b[0] << 8) | unicastMacAddr[1].b[1]);
674  }
675  else
676  {
677  ncv7410WriteReg(interface, NCV7410_ADDRFILT2L, 0);
678  ncv7410WriteReg(interface, NCV7410_ADDRFILT2H, 0);
679  }
680 
681  //Configure the third unicast address filter
682  if(j >= 3)
683  {
684  //Set the lower 32 bits of the MAC address
686  (unicastMacAddr[2].b[2] << 24) | (unicastMacAddr[2].b[3] << 16) |
687  (unicastMacAddr[2].b[4] << 8) | unicastMacAddr[2].b[5]);
688 
689  //Set the upper 16 bits of the MAC address
691  (unicastMacAddr[2].b[0] << 8) | unicastMacAddr[2].b[1]);
692  }
693  else
694  {
695  ncv7410WriteReg(interface, NCV7410_ADDRFILT3L, 0);
696  ncv7410WriteReg(interface, NCV7410_ADDRFILT3H, 0);
697  }
698 
699  //Read MACCTRL0 register
700  value = ncv7410ReadReg(interface, NCV7410_MACCTRL0);
701 
702  //Disable broadcast filter
704  //Enable destination address filter
706 
707  //Enable or disable the reception of multicast frames
708  if(acceptMulticast)
709  {
710  //Disable multicast filter
712  }
713  else
714  {
715  //Enable multicast filter
717  }
718 
719  //Update MACCTRL0 register
721 
722  //Successful processing
723  return NO_ERROR;
724 }
725 
726 
727 /**
728  * @brief Write register
729  * @param[in] interface Underlying network interface
730  * @param[in] mms Register memory map to access
731  * @param[in] address Register address
732  * @param[in] data Register value
733  **/
734 
735 void ncv7410WriteReg(NetInterface *interface, uint8_t mms, uint16_t address,
736  uint32_t data)
737 {
738  uint32_t header;
739 
740  //Set up a register write operation
742  //The MMS field selects the specific register memory map to access
743  header |= (mms << 24) & NCV7410_CTRL_HEADER_MMS;
744  //Address of the first register to access
745  header |= (address << 8) & NCV7410_CTRL_HEADER_ADDR;
746  //Specifies the number of registers to write
747  header |= (0 << 1) & NCV7410_CTRL_HEADER_LEN;
748 
749  //The parity bit is calculated over the control command header
750  if(ncv7410CalcParity(header) != 0)
751  {
752  header |= NCV7410_CTRL_HEADER_P;
753  }
754 
755  //Pull the CS pin low
756  interface->spiDriver->assertCs();
757 
758  //Write control command header
759  interface->spiDriver->transfer((header >> 24) & 0xFF);
760  interface->spiDriver->transfer((header >> 16) & 0xFF);
761  interface->spiDriver->transfer((header >> 8) & 0xFF);
762  interface->spiDriver->transfer(header & 0xFF);
763 
764  //Write data
765  interface->spiDriver->transfer((data >> 24) & 0xFF);
766  interface->spiDriver->transfer((data >> 16) & 0xFF);
767  interface->spiDriver->transfer((data >> 8) & 0xFF);
768  interface->spiDriver->transfer(data & 0xFF);
769 
770  //Send 32 bits of dummy data at the end of the control write command
771  interface->spiDriver->transfer(0x00);
772  interface->spiDriver->transfer(0x00);
773  interface->spiDriver->transfer(0x00);
774  interface->spiDriver->transfer(0x00);
775 
776  //Terminate the operation by raising the CS pin
777  interface->spiDriver->deassertCs();
778 }
779 
780 
781 /**
782  * @brief Read register
783  * @param[in] interface Underlying network interface
784  * @param[in] mms Register memory map to access
785  * @param[in] address Register address
786  * @return Register value
787  **/
788 
789 uint32_t ncv7410ReadReg(NetInterface *interface, uint8_t mms,
790  uint16_t address)
791 {
792  uint32_t data;
793  uint32_t header;
794 
795  //Set up a register read operation
796  header = NCV7410_CTRL_HEADER_AID;
797  //The MMS field selects the specific register memory map to access
798  header |= (mms << 24) & NCV7410_CTRL_HEADER_MMS;
799  //Address of the first register to access
800  header |= (address << 8) & NCV7410_CTRL_HEADER_ADDR;
801  //Specifies the number of registers to read
802  header |= (0 << 1) & NCV7410_CTRL_HEADER_LEN;
803 
804  //The parity bit is calculated over the control command header
805  if(ncv7410CalcParity(header) != 0)
806  {
807  header |= NCV7410_CTRL_HEADER_P;
808  }
809 
810  //Pull the CS pin low
811  interface->spiDriver->assertCs();
812 
813  //Write control command header
814  interface->spiDriver->transfer((header >> 24) & 0xFF);
815  interface->spiDriver->transfer((header >> 16) & 0xFF);
816  interface->spiDriver->transfer((header >> 8) & 0xFF);
817  interface->spiDriver->transfer(header & 0xFF);
818 
819  //Discard the echoed control header
820  interface->spiDriver->transfer(0x00);
821  interface->spiDriver->transfer(0x00);
822  interface->spiDriver->transfer(0x00);
823  interface->spiDriver->transfer(0x00);
824 
825  //Read data
826  data = interface->spiDriver->transfer(0x00) << 24;
827  data |= interface->spiDriver->transfer(0x00) << 16;
828  data |= interface->spiDriver->transfer(0x00) << 8;
829  data |= interface->spiDriver->transfer(0x00);
830 
831  //Terminate the operation by raising the CS pin
832  interface->spiDriver->deassertCs();
833 
834  //Return register value
835  return data;
836 }
837 
838 
839 /**
840  * @brief Dump registers for debugging purpose
841  * @param[in] interface Underlying network interface
842  * @param[in] mms Register memory map to access
843  * @param[in] address Start address
844  * @param[in] num Number of registers to dump
845  **/
846 
847 void ncv7410DumpReg(NetInterface *interface, uint8_t mms, uint16_t address,
848  uint_t num)
849 {
850  uint_t i;
851 
852  //Loop through registers
853  for(i = 0; i < num; i++)
854  {
855  //Display current register
856  TRACE_DEBUG("0x%02" PRIX16 ": 0x%08" PRIX32 "\r\n", address + i,
857  ncv7410ReadReg(interface, mms, address + i));
858  }
859 
860  //Terminate with a line feed
861  TRACE_DEBUG("\r\n");
862 }
863 
864 
865 /**
866  * @brief Calculate parity bit over a 32-bit data
867  * @param[in] data 32-bit bit stream
868  * @return Odd parity bit computed over the supplied data
869  **/
870 
871 uint32_t ncv7410CalcParity(uint32_t data)
872 {
873  //Calculate the odd parity bit computed over the supplied bit stream
874  data ^= data >> 1;
875  data ^= data >> 2;
876  data ^= data >> 4;
877  data ^= data >> 8;
878  data ^= data >> 16;
879 
880  //Return '1' when the number of bits set to one in the supplied bit
881  //stream is even (resulting in an odd number of ones when the parity is
882  //included), otherwise return '0'
883  return ~data & 0x01;
884 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:559
#define NCV7410_PLCACTRL0
#define NCV7410_TX_HEADER_EV
bool_t ncv7410IrqHandler(NetInterface *interface)
NCV7410 interrupt service routine.
void ncv7410Tick(NetInterface *interface)
NCV7410 timer handler.
#define NCV7410_PHYCTRL
int bool_t
Definition: compiler_port.h:61
uint8_t b
Definition: nbns_common.h:104
#define NCV7410_TX_HEADER_EBO
void ncv7410DisableIrq(NetInterface *interface)
Disable interrupts.
#define NCV7410_PLCABURST_BTMR_DEFAULT
#define netEvent
Definition: net_legacy.h:196
#define LOAD32BE(p)
Definition: cpu_endian.h:210
error_t ncv7410ReceivePacket(NetInterface *interface)
Receive a packet.
void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
Map a MAC address to the IPv6 modified EUI-64 identifier.
Definition: ethernet.c:946
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:143
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:690
uint32_t ncv7410ReadReg(NetInterface *interface, uint8_t mms, uint16_t address)
Read register.
#define NCV7410_MACID1
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define NCV7410_RX_FOOTER_DV
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
#define NCV7410_CONFIG0_ZARFE
#define NCV7410_BUFSTS_TXC
#define NCV7410_LOCAL_ID
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
error_t ncv7410SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define NCV7410_PHYSTATUS
#define NCV7410_STATUS0
#define NCV7410_CTRL_HEADER_ADDR
#define NCV7410_CONFIG0_TXCTHRESH_16_CREDITS
#define NCV7410_ADDRFILT1H
#define NCV7410_ADDRFILT3L
#define NCV7410_RESET
#define NCV7410_PLCACTRL0_EN
#define NCV7410_TX_HEADER_NORX
#define NCV7410_RX_FOOTER_SV
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:392
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define NCV7410_RESET_RESET
#define NCV7410_TX_HEADER_SV
#define NCV7410_RX_FOOTER_EV
#define NCV7410_PLCACTRL1_ID
#define NCV7410_CTRL_HEADER_P
#define NCV7410_MACCTRL0_BCSF
#define NCV7410_PHYID
#define NCV7410_MACCTRL0_MCSF
#define NCV7410_CTRL_HEADER_MMS
#define FALSE
Definition: os_port.h:46
void ncv7410WriteReg(NetInterface *interface, uint8_t mms, uint16_t address, uint32_t data)
Write register.
error_t ncv7410Init(NetInterface *interface)
NCV7410 controller initialization.
#define NCV7410_CHUNK_PAYLOAD_SIZE
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
#define NCV7410_RX_FOOTER_RCA
#define NCV7410_MACID0
#define NCV7410_MACCTRL0_TXEN
#define NCV7410_CTRL_HEADER_LEN
#define NCV7410_RX_FOOTER_EBO
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:105
#define NCV7410_PLCABURST_MAXBC_DEFAULT
#define NCV7410_ADDRFILT3H
#define NCV7410_CONFIG0
#define NCV7410_DIOCFG_VAL1
#define NetRxAncillary
Definition: net_misc.h:40
#define NCV7410_PLCACTRL1_NCNT
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:36
#define NCV7410_ETH_RX_BUFFER_SIZE
#define NCV7410_BUFSTS_RCA
MacAddr addr
MAC address.
Definition: ethernet.h:265
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define NCV7410_TX_HEADER_DV
#define NetTxAncillary
Definition: net_misc.h:36
#define NCV7410_ADDRFILT0H
const NicDriver ncv7410Driver
NCV7410 driver.
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
error_t ncv7410UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define NCV7410_PLCABURST
#define MIN(a, b)
Definition: os_port.h:63
#define NCV7410_CONFIG0_SYNC
MacAddr
Definition: ethernet.h:197
#define NCV7410_DIOCFG_FN0_LED_TX
#define TRACE_DEBUG(...)
Definition: debug.h:119
__weak_func void ncv7410InitHook(NetInterface *interface)
NCV7410 custom configuration.
#define NCV7410_STATUS0_RESETC
#define NCV7410_CTRL_HEADER_WNR
#define NCV7410_ADDRFILT1L
#define NCV7410_ADDRFILTnH_EN
void ncv7410EventHandler(NetInterface *interface)
NCV7410 event handler.
#define NCV7410_MACCTRL0_ADRF
#define NCV7410_BUFSTS
#define NCV7410_DIOCFG_FN1_LED_RX
#define NCV7410_CONFIG0_CSARFE
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
#define NCV7410_DIOCFG_SLR0
MAC filter table entry.
Definition: ethernet.h:264
Ipv6Addr address[]
Definition: ipv6.h:325
void ncv7410DumpReg(NetInterface *interface, uint8_t mms, uint16_t address, uint_t num)
Dump registers for debugging purpose.
#define NCV7410_TX_HEADER_DNC
#define NCV7410_DIOCFG
#define NCV7410_MACCTRL0_FCSA
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
uint8_t value[]
Definition: tcp.h:376
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
#define NCV7410_ADDRFILT2H
uint32_t reverseInt32(uint32_t value)
Reverse bit order in a 32-bit word.
Definition: cpu_endian.c:123
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define NCV7410_NODE_COUNT
#define NCV7410_MMS_STD
#define NCV7410_MACCTRL0
#define NCV7410_DIOCFG_VAL0
#define NCV7410_DIOCFG_SLR1
#define NCV7410_ADDRFILT2L
#define NCV7410_CTRL_HEADER_AID
#define NCV7410_PLCACTRL1
void ncv7410EnableIrq(NetInterface *interface)
Enable interrupts.
unsigned int uint_t
Definition: compiler_port.h:57
Onsemi NCV7410 10Base-T1S Ethernet controller.
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
uint32_t ncv7410CalcParity(uint32_t data)
Calculate parity bit over a 32-bit data.
#define NCV7410_ADDRFILT0L
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
#define NCV7410_PHYSTATUS_LKST
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
#define NCV7410_PHYCTRL_LCTL
#define NCV7410_CONFIG0_CPS_64_BYTES
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define NCV7410_MACCTRL0_RXEN
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83