Sunday 17 February 2019

beaglebone black - Linux enc28j60 driver always times out on transmit


I've wired up an ENC28J60 module with an SPI interface to a Beaglebone Black development board running Linux 3.8, but I cannot get the device to TX (or RX) anything. Every attempt to TX times out and increments the TX errors.



Originally, the driver that shipped with the Linux kernel would not allow me to bring the link up. After a bunch of debugging, I found that if I waited some amount of time during board initialization, that I could get the link to come up. The patch to the driver was in the enc28j60_check_link_status function and was more or less the following.


  unsigned long timeout = jiffies + 1*HZ;                                                                                                                                                             
while ((enc28j60_phy_read(priv, PHSTAT2) & PHSTAT2_LSTAT) == 0) {
if (time_after(jiffies, timeout)) {
if (netif_msg_drv(priv))
dev_dbg(&priv->spi->dev,
"reg %02x ready timeout!\n", reg);
break;
}
schedule();

}

Now, I can reliably load the driver and configure the interface like so.


ifconfig rename3 down
ethtool -s rename3 msglvl 0xffff
ethtool -s rename3 speed 10 duplex full
ifconfig rename3 up

I've customized the ENC28J60's driver to do a bunch of additional printk while I've been searching for the root of the problem. I get the following after bringing the interface up.


Feb  1 00:22:48 arm kernel: [  100.001942] enc28j60: HELLO WORLD

Feb 1 00:22:48 arm kernel: [ 100.002092] enc28j60: enc28j60_net_open() enter
Feb 1 00:22:48 arm kernel: [ 100.002119] enc28j60: enc28j60_hw_disable() enter
Feb 1 00:22:48 arm kernel: [ 100.002315] enc28j60: enc28j60_hw_init() enter
Feb 1 00:22:48 arm kernel: [ 100.002342] enc28j60: enc28j60_hw_init() - FullDuplex
Feb 1 00:22:48 arm kernel: [ 100.002366] enc28j60: enc28j60_soft_reset() enter
Feb 1 00:22:48 arm kernel: [ 100.006957] enc28j60: nolock_rxfifo_init() enter
Feb 1 00:22:48 arm kernel: [ 100.007117] enc28j60: erxrdpt_workaround() enter
Feb 1 00:22:48 arm kernel: [ 100.007373] enc28j60: nolock_txfifo_init() enter
Feb 1 00:22:48 arm kernel: [ 100.007807] enc28j60: chip RevID: 0x06
Feb 1 00:22:48 arm kernel: [ 100.009680] enc28j60: enc28j60_phy_write() enter

Feb 1 00:22:48 arm kernel: [ 100.010950] enc28j60: enc28j60_phy_write() enter
Feb 1 00:22:48 arm kernel: [ 100.011335] enc28j60: enc28j60_phy_write() enter
Feb 1 00:22:48 arm kernel: [ 100.014973] enc28j60 Hw initialized.
Feb 1 00:22:48 arm kernel: [ 100.014973] HwRevID: 0x06
Feb 1 00:22:48 arm kernel: [ 100.014973] Cntrl: ECON1 ECON2 ESTAT EIR EIE
Feb 1 00:22:48 arm kernel: [ 100.014973] 0x03 0x80 0x01 0x00 0x00
Feb 1 00:22:48 arm kernel: [ 100.014973] MAC : MACON1 MACON3 MACON4
Feb 1 00:22:48 arm kernel: [ 100.014973] 0x0d 0x33 0x00
Feb 1 00:22:48 arm kernel: [ 100.014973] Rx : ERXST ERXND ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL
Feb 1 00:22:48 arm kernel: [ 100.014973] 0x0000 0x19ff 0x0000 0x19ff 0xa1 0x00 0x05ee

Feb 1 00:22:48 arm kernel: [ 100.014973] Tx : ETXST ETXND MACLCON1 MACLCON2 MAPHSUP
Feb 1 00:22:48 arm kernel: [ 100.014973] 0x1a00 0x1fff 0x0f 0x37 0x10
Feb 1 00:22:48 arm kernel: [ 100.015073] enc28j60: enc28j60_set_hw_macaddr() enter
Feb 1 00:22:48 arm kernel: [ 100.015105] enc28j60: rename3: Setting MAC address to ee:31:66:60:5a:52
Feb 1 00:22:48 arm kernel: [ 100.015530] enc28j60: enc28j60_hw_enable() enter
Feb 1 00:22:48 arm kernel: [ 100.015556] enc28j60: enc28j60_hw_enable() enabling interrupts.
Feb 1 00:22:48 arm kernel: [ 100.015578] enc28j60: enc28j60_phy_write() enter
Feb 1 00:22:48 arm kernel: [ 100.017800] enc28j60: enc28j60_check_link_status() enter
Feb 1 00:22:48 arm kernel: [ 100.020726] enc28j60: enc28j60_check_link_status() PHSTAT1: 1800, PHSTAT2: 0200
Feb 1 00:22:48 arm kernel: [ 100.020760] enc28j60:enc28j60_check_link_status() polling PHSTAT2_LSTAT != 0

Feb 1 00:22:48 arm kernel: [ 100.069286] enc28j60:enc28j60_check_link_status() reg/link now 1536/1024
Feb 1 00:22:48 arm kernel: [ 100.069319] enc28j60:enc28j60_check_link_status() have link! setting carrier on
Feb 1 00:22:48 arm kernel: [ 100.069362] net rename3: link up - Full duplex
Feb 1 00:22:58 arm kernel: [ 109.989281] enc28j60: enc28j60_send_packet() enter
Feb 1 00:22:58 arm kernel: [ 109.989329] enc28j60: enc28j60_send_packet() enter
Feb 1 00:22:58 arm kernel: [ 109.989411] enc28j60: enc28j60_tx_work_handler() enter
Feb 1 00:22:58 arm kernel: [ 109.989437] enc28j60: enc28j60_hw_tx() enter
Feb 1 00:22:58 arm kernel: [ 109.989459] enc28j60: Tx Packet Len:70
Feb 1 00:22:58 arm kernel: [ 109.989481] enc28j60: enc28j60_hw_tx - packet len:70
Feb 1 00:22:58 arm kernel: [ 109.989517] pk data: 00000000: 33 33 00 00 00 02 ee 31 66 60 5a 52 86 dd 60 00 33.....1f`ZR..`.

Feb 1 00:22:58 arm kernel: [ 109.989548] pk data: 00000010: 00 00 00 10 3a ff fe 80 00 00 00 00 00 00 ec 31 ....:..........1
Feb 1 00:22:58 arm kernel: [ 109.989576] pk data: 00000020: 66 ff fe 60 5a 52 ff 02 00 00 00 00 00 00 00 00 f..`ZR..........
Feb 1 00:22:58 arm kernel: [ 109.989605] pk data: 00000030: 00 00 00 00 00 02 85 00 21 65 00 00 00 00 01 01 ........!e......
Feb 1 00:22:58 arm kernel: [ 109.989633] pk data: 00000040: ee 31 66 60 5a 52 .1f`ZR
Feb 1 00:22:58 arm kernel: [ 109.989655] enc28j60: enc28j60_packet_write() enter
Feb 1 00:22:58 arm kernel: [ 109.990379] enc28j60: enc28j60_packet_write() after control byte ERWPT:0x1a01
Feb 1 00:22:58 arm kernel: [ 109.990406] enc28j60: spi_write_buf() enter
Feb 1 00:22:58 arm kernel: [ 109.990571] enc28j60: enc28j60_packet_write() spi_write returns 0
Feb 1 00:22:58 arm kernel: [ 109.990761] enc28j60: enc28j60_packet_write() after write packet ERWPT:0x1a47, len=70
Feb 1 00:23:18 arm kernel: [ 129.979247] enc28j60: enc28j60_tx_timeout() enter

Feb 1 00:23:18 arm kernel: [ 129.979313] net rename3: enc28j60 tx timeout

I've narrowed it down with additional print statements to a call to spi_sync in spi_read_buf. Does anyone with knowledge of Linux network drivers or Microchip's ENC28J60 know what I should be looking into to resolve this problem?




No comments:

Post a Comment

arduino - Can I use TI's cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...