He conectado un módulo ENC28J60 con una interfaz SPI a una placa de desarrollo Beaglebone Black que ejecuta Linux 3.8, pero no puedo llevar el dispositivo a TX (o RX). Cada intento de TX expira e incrementa los errores de TX.
Originalmente, el controlador que venía con el kernel de Linux no me permitía abrir el enlace. Después de un montón de depuración, descubrí que si esperaba un poco de tiempo durante la inicialización de la placa, podría hacer que se abriera el enlace. El parche para el controlador estaba en la función enc28j60_check_link_status
y era más o menos el siguiente.
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();
}
Ahora, puedo cargar de manera confiable el controlador y configurar la interfaz como tal.
ifconfig rename3 down
ethtool -s rename3 msglvl 0xffff
ethtool -s rename3 speed 10 duplex full
ifconfig rename3 up
Personalicé el controlador del ENC28J60 para hacer un montón de printk
adicional mientras buscaba la raíz del problema. Obtengo lo siguiente después de activar la interfaz.
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
Lo he reducido con declaraciones de impresión adicionales a una llamada a spi_sync
en spi_read_buf
. ¿Alguien que tenga conocimiento de los controladores de red de Linux o del ENC28J60 de Microchip sabe qué debo investigar para resolver este problema?