MOD-ENC28J60 and Linux (Debian/GNU)

Started by leo, December 03, 2012, 05:43:03 PM

Previous topic - Next topic

lorenzo

Hi Mouha,

here is a link (https://dl.dropbox.com/u/96533863/enc28j60.zip) to a file which contains:
- script.bin
- uImage
- a folder named "3.0.52+" which must be put in your /lib/modules folder of rootfs

Yes you must connect #INT pin of enc28j60 to your PB04 (PIN8) of your GPIO connector.

BR
Lorenzo

leo

Hi Lorenzo,

these are good news after vacation. :)
I tried both ways (your guide/dropbox files) to get the interface working but without much success. The failure is the same with both.
I think I wired everything correct. GPIO PIN 13 on GPIO-2 40pin connector ( PIN 8 ) with Ext 5 on enc28j60 ( #INT ). Without the wire the driver do not show the message: ==ENC28J60_CLEAR_IRQ_NO=

Here are some infos.

kernel spi config:

[    0.170000] [spi]: sw spi init !!
[    0.170000] [spi]: sw spi init fetch spi0 uning configuration failed
[    0.180000] [spi]: Found 1 spi devices in config files
[    0.180000] [spi]: boards num modalias         max_spd_hz       bus_num  cs   mode
[    0.190000] [spi]: 0          enc28j60         20000000         2        0    0x0   
[    0.200000] [spi]: bus num = 2, spi used = 3
[    0.200000] [spi]: source = sdram_pll_p, src_clk = 408000000, mclk 102000000
[    0.210000] [spi]: allwinners SoC SPI Driver loaded for Bus SPI-2 with 1 Slaves attached
[    0.220000] [spi]: [spi-2]: driver probe succeed, base dc8aa000, irq 12, dma_id 2!


on enc28j60 module load:

[    3.700000] enc28j60 spi2.0: enc28j60 Ethernet driver 1.01 loaded
[    3.800000] enc28j60 spi2.0: enc28j60 enc28j60 spi_irq param load successfully.
[    3.800000] enc28j60 spi2.0: enc28j60 enc28j60_probe, gpio_addr = 0xdc8c4800.
[    3.880000] enc28j60 spi2.0: enc28j60 enc28j60_probe, 1670: gpio_int_info, port = 2, port_num = 4.
[    3.890000] enc28j60 spi2.0: enc28j60 ENC28J60 interrupt configuration
[    3.890000] enc28j60 spi2.0: enc28j60==ENC28J60_CLEAR_IRQ_NO=
[    4.000000] net eth0: enc28j60 driver registered


on network initialization:

[   12.350000] enc28j60 spi2.0: enc28j60 ==========------ENC28J60 Interrupt-----============
[   12.350000] enc28j60 spi2.0: enc28j60 ==ENC28J60 IRQ OK=
[   12.360000] net eth0: link up - Half duplex
[   12.550000] enc28j60 spi2.0: enc28j60 ==========------ENC28J60 Interrupt-----============
[   12.550000] enc28j60 spi2.0: enc28j60 ==ENC28J60 IRQ OK=
[   12.860000] enc28j60 spi2.0: enc28j60 ==========------ENC28J60 Interrupt-----============
[   12.860000] enc28j60 spi2.0: enc28j60 ==ENC28J60 IRQ OK=
[   13.070000] enc28j60 spi2.0: enc28j60 ==========------ENC28J60 Interrupt-----============
[   13.070000] enc28j60 spi2.0: enc28j60 ==ENC28J60 IRQ OK=
[   13.190000] enc28j60 spi2.0: enc28j60 ==========------ENC28J60 Interrupt-----============
[   13.190000] enc28j60 spi2.0: enc28j60 ==ENC28J60 IRQ OK=
[   13.250000] enc28j60 spi2.0: enc28j60 ==========------ENC28J60 Interrupt-----============
[   13.250000] enc28j60 spi2.0: enc28j60 ==ENC28J60 IRQ OK=
[   13.550000] enc28j60 spi2.0: enc28j60 ==========------ENC28J60 Interrupt-----============
[   13.550000] enc28j60 spi2.0: enc28j60 ==ENC28J60 IRQ OK=
[   14.330000] enc28j60 spi2.0: enc28j60 ==========------ENC28J60 Interrupt-----============
[   14.330000] enc28j60 spi2.0: enc28j60 ==ENC28J60 IRQ OK=


These above messages last forever on the console.

/proc/interrupts

           CPU0       
  0:          0    sw_vic  axp_mfd
  2:        270    sw_vic  serial
  7:       4032    sw_vic  sun5i-i2c.0
  8:         36    sw_vic  sun5i-i2c.1
  9:          0    sw_vic  sun5i-i2c.2
12:      33399    sw_vic  sun5i-spi
22:      33131    sw_vic  timer0
27:          0    sw_vic  dma_irq
28:       1164    sw_vic  enc28j60
32:      31306    sw_vic  sunxi-mmc
37:          0    sw_vic  nand
39:         27    sw_vic  ehci_hcd:usb2
44:      38880    sw_vic  sunxi lcd0
47:      18988    sw_vic  sunxi scaler0
53:          0    sw_vic  cedar_dev
64:          0    sw_vic  ohci_hcd:usb3


ifconfig with a static ip

eth0      Link encap:Ethernet  HWaddr 96:69:32:dc:50:c9 
          inet addr:192.168.192.215  Bcast:192.168.192.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:509 dropped:0 overruns:0 frame:128
          TX packets:143 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:6006 (5.8 KiB)
          Interrupt:28


The RX buffer is empty and full of errors. I cannot ping any machine in the network.
Is it a hardware failure or did i something wrong? Any ideas?

Kind Regards
Leo

mouha

Thanks Lorenzo,
I'll try ASAP and then check that I have - hope not- the same issue as Leo had.

lorenzo

Hi Leo, Mouha

I also have RX errors, because of wrong SPI read when interrupts occurs. I don't know which is the problem, but I haven't solved it yet.
If you try with wireshark sniffing the network you'll se ARP packets from enc28j60, so TX is ok. The problem is the RX side. It seems that memory is somehow corrupted, and data read have no sense. I also tried reducing SPI master clock speed, but I can't get enc28j60 working properly. About SPI speed, please set this parameters as follow:


max_speed_hz = 10000000


because enc28j60 support a maximum spi clock frequency of 10MHz. The script.bin in the zip file already have this parameter set correctly.

Hope that you can help me finding what's wrong with RX.

BR
Lorenzo

lorenzo

Hi all,

I've made another step ahead... I patched the module to make half-duplex DMA working (info here http://www.spinics.net/lists/netdev/msg164257.html).
Now RX works, but I still have errors because I've some bytes messed up in the packets, so the transmission can't work.

You can find patch, bin module (3.0.52+ Kernel) and script.bin here:
https://dl.dropbox.com/u/96533863/enc28j60_new.tar.gz

Please try it and help me solving this new issue!

Thank you.
BR
Lorenzo

mouha

nice  one !

Sorry I didn't have tested yet as I encouter other important that I need to resolve before.

leo

Hi Lorenzo,

i tried the patch with the new sunxi kernels (3.0.57 and 3.4.24) released 4 days ago.
I have the same behavior that you describe.
Anyway many thanks again.
I will take a look into it.

Kind Regards

Leo

lorenzo

Hi Leo,

do you have any idea if the problem with rx is related to spi, to DMA, or to enc28j60.c? I think it is something in SPI or DMA. It seems that tx bytes aren't messed up, only rx.

Thank you.
BR
Lorenzo

vinifr

Hi Lorenzo,

Can you provide your source code for download? I am gonna try to help. thk

lorenzo

Hi,

here is a link where you can find also the src file of enc28j60:

https://dl.dropbox.com/u/96533863/enc28j60_new_src.tar.gz

Thank you.
BR

Lorenzo

vinifr

#25
Hi,
For the foregoing below am using A13-Olinuxino_Rev_B.sch.

Well, I have seen some errors:

1) script.fex; the correct function for SPI is 3 not 4 and the pins are PE0(SPI2_CS), PE01(SPI2_CLK), PE02(SPI2_MOSI) and PE03(SPI2_MISO):

[spi2_para]
spi_used = 1
spi_cs_bitmap = 1
spi_cs0 = port:PE00<3><default><default><default>
spi_sclk = port:PE01<3><default><default><default>
spi_mosi = port:PE02<3><default><default><default>
spi_miso = port:PE03<3><default><default><default>


2) TXbuff maybe overwrite Rxbuff;
In spi_buf_read() is better to use:

u8 *tx_buf = priv->spi_transfer_buf_tx;
u8 *rx_buf = priv->spi_transfer_buf_rx;


But the original code also works if it is not used more than 4 bytes in tx_buf, is necessary to check every function call enc28j60_mem_read()...  ;D

lorenzo

Hi Viniciusfre,

according to this page http://linux-sunxi.org/A13/PIO, it seems that is the function 4 the correct one. Do you have different information about pin configuration? Why do you say that is the function 3 the correct one?

Are you working on original enc28j60 file or with the patched one? Why rx_buf and tx_buf should overwrite each other? tx_buf point to a different location respect to rx_buf? Am I losing something?

Do you have enc28j60 working with this modification?

Thank you.
BR
Lorenzo

vinifr

#27
Hi,

About pin: http://linux-sunxi.org/Fex_Guide#7.3_.5Bspi2_para.5D

Sorry, I was referring to the original enc28j60 file.

u8 *rx_buf = priv->spi_transfer_buf + 4;
u8 *tx_buf = priv->spi_transfer_buf;
...
tx_buf[0] = ENC28J60_READ_BUF_MEM;
tx_buf[1] = tx_buf[2] = tx_buf[3] = 0; /* don't care */

if tx_buf is greater than 4, rx_buf is overwritten. Example: memcpy(x.spi_transfer_buf, data, len); with len>4

I have not enc28j60, i'm just using a radio that is SPI in the bus 2(SPI2), so I thought I could help.  ;D

lorenzo

Oh yes, help will be very appreciated  :D...

The link  http://linux-sunxi.org/Fex_Guide#7.3_.5Bspi2_para.5D it's just a guide, you don't have to refer to that values for pin configuration. Pin functions changes among different cpus.

Ok for tx and rx, but I think that the patched version is not afflicted by this issue.

Thank you.
BR

Lorenzo

vinifr

#29
Hi lorenzo,

You have reason, correct function is 4...   :D

Your patch is ​​also right:

struct spi_transfer t = {
.tx_buf = tx_buf,
.rx_buf = NULL,
.len = SPI_OPLEN,
.cs_change = 1,
};

struct spi_transfer r = {
.tx_buf = NULL,
.rx_buf = data,
.len = len,
.cs_change = 0,
};

due to:

/* check in the __spi_async if use half duplex */
if(t->tx_buf && t->rx_buf)
    return -EINVAL;

right?

But it is better to keep u8 *rx_buf = priv->spi_transfer_buf + 4; u8 *tx_buf = priv->spi_transfer_buf;,
because is safer store in spi_transfer_buf instead of data. The code looks like this:

        u8 *rx_buf = priv->spi_transfer_buf + 4;
u8 *tx_buf = priv->spi_transfer_buf;

struct spi_transfer t = {
.tx_buf = tx_buf,
.rx_buf = NULL,
.len = SPI_OPLEN,
.cs_change = 0,
};

struct spi_transfer r = {
.tx_buf = NULL,
.rx_buf = rx_buf,
.len = len,
.cs_change = 1,
};

struct spi_message msg;
int ret;

tx_buf[0] = ENC28J60_READ_BUF_MEM; // tx_buf[0]=0x3A
tx_buf[1] = tx_buf[2] = tx_buf[3] = 0; /* don't care */

spi_message_init(&msg);
spi_message_add_tail(&t, &msg);
spi_message_add_tail(&r, &msg);
ret = spi_sync(priv->spi, &msg);
if (ret == 0) {
          memcpy(data, &rx_buf[SPI_OPLEN], len);
          ret = msg.status;
}
if (ret && netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
__func__, ret);

return ret;


Or we could use spi_write_then_read(). What do you think?

Is there still problem in the RX?