From 35544e81ee4b88188a5dfac93b296afd4fa55cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 18:27:06 +0200 Subject: [PATCH 01/15] enc28j60: Reuse read/writedata() for read/writedatabyte() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The read/writedatabyte() functions are just a special case of read/writedata() with a simpler API, so reuse these instead of duplicating code. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index dd00dddeb..1ee77ad9f 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -160,16 +160,6 @@ setregbank(uint8_t bank) } /*---------------------------------------------------------------------------*/ static void -writedatabyte(uint8_t byte) -{ - enc28j60_arch_spi_select(); - /* The Write Buffer Memory (WBM) command is 0 1 1 1 1 0 1 0 */ - enc28j60_arch_spi_write(0x7a); - enc28j60_arch_spi_write(byte); - enc28j60_arch_spi_deselect(); -} -/*---------------------------------------------------------------------------*/ -static void writedata(uint8_t *data, int datalen) { int i; @@ -182,16 +172,10 @@ writedata(uint8_t *data, int datalen) enc28j60_arch_spi_deselect(); } /*---------------------------------------------------------------------------*/ -static uint8_t -readdatabyte(void) +static void +writedatabyte(uint8_t byte) { - uint8_t r; - enc28j60_arch_spi_select(); - /* THe Read Buffer Memory (RBM) command is 0 0 1 1 1 0 1 0 */ - enc28j60_arch_spi_write(0x3a); - r = enc28j60_arch_spi_read(); - enc28j60_arch_spi_deselect(); - return r; + writedata(&byte, 1); } /*---------------------------------------------------------------------------*/ static int @@ -208,6 +192,14 @@ readdata(uint8_t *buf, int len) return i; } /*---------------------------------------------------------------------------*/ +static uint8_t +readdatabyte(void) +{ + uint8_t r; + readdata(&r, 1); + return r; +} +/*---------------------------------------------------------------------------*/ static void softreset(void) { From 48f269e4f5f85ce6c8b26041c643463faf8c8d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 18:33:19 +0200 Subject: [PATCH 02/15] enc28j60: Fix RCR command for MAC and MII registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Read Control Register command requires that a dummy byte be read before the register value for the MAC and MII registers. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index 1ee77ad9f..a112e8ac3 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -113,6 +113,7 @@ #define MAADR4 0x03 /* MAADR<23:16> */ #define MAADR5 0x00 /* MAADR<15:8> */ #define MAADR6 0x01 /* MAADR<7:0> */ +#define MISTAT 0x0a #define EPKTCNT_BANK 0x01 #define ERXFCON 0x18 @@ -128,10 +129,27 @@ PROCESS(enc_watchdog_process, "Enc28j60 watchdog"); static uint8_t initialized = 0; +static uint8_t bank = ERXTX_BANK; static uint8_t enc_mac_addr[6]; static int received_packets = 0; static int sent_packets = 0; +/*---------------------------------------------------------------------------*/ +static uint8_t +is_mac_mii_reg(uint8_t reg) +{ + /* MAC or MII register (otherwise, ETH register)? */ + switch(bank) { + case MACONX_BANK: + return reg < EIE; + case MAADRX_BANK: + return reg <= MAADR2 || reg == MISTAT; + case ERXTX_BANK: + case EPKTCNT_BANK: + default: + return 0; + } +} /*---------------------------------------------------------------------------*/ static uint8_t readreg(uint8_t reg) @@ -139,6 +157,10 @@ readreg(uint8_t reg) uint8_t r; enc28j60_arch_spi_select(); enc28j60_arch_spi_write(0x00 | (reg & 0x1f)); + if(is_mac_mii_reg(reg)) { + /* MAC and MII registers require that a dummy byte be read first. */ + enc28j60_arch_spi_read(); + } r = enc28j60_arch_spi_read(); enc28j60_arch_spi_deselect(); return r; @@ -154,9 +176,10 @@ writereg(uint8_t reg, uint8_t data) } /*---------------------------------------------------------------------------*/ static void -setregbank(uint8_t bank) +setregbank(uint8_t new_bank) { - writereg(ECON1, (readreg(ECON1) & 0xfc) | (bank & 0x03)); + writereg(ECON1, (readreg(ECON1) & 0xfc) | (new_bank & 0x03)); + bank = new_bank; } /*---------------------------------------------------------------------------*/ static void @@ -207,6 +230,7 @@ softreset(void) /* The System Command (soft reset) is 1 1 1 1 1 1 1 1 */ enc28j60_arch_spi_write(0xff); enc28j60_arch_spi_deselect(); + bank = ERXTX_BANK; } /*---------------------------------------------------------------------------*/ static void From ba6a0bc3811b2244e23a260c941b4fe46a941e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 18:46:56 +0200 Subject: [PATCH 03/15] enc28j60: Add workaround for erratum #2 "CLKRDY set early" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A delay of 1 ms must be added after the System Reset Command. Still wait for ESTAT.CLKRDY afterwards as a precaution. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index a112e8ac3..0e6d86a44 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -298,11 +298,14 @@ reset(void) see Section 2.2 “Oscillator Start-up Timer. */ + softreset(); + + /* Workaround for erratum #2. */ + clock_delay_usec(1000); + /* Wait for OST */ while((readreg(ESTAT) & ESTAT_CLKRDY) == 0); - softreset(); - setregbank(ERXTX_BANK); /* Set up receive buffer */ writereg(ERXSTL, RX_BUF_START & 0xff); From b21da96e678edfd963cc0062a4ddd4001109a255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 18:54:45 +0200 Subject: [PATCH 04/15] enc28j60: Print revision during initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is useful as debug information since the revisions of this device have notable differences. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index 0e6d86a44..7c5acc5f0 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -114,6 +114,7 @@ #define MAADR5 0x00 /* MAADR<15:8> */ #define MAADR6 0x01 /* MAADR<7:0> */ #define MISTAT 0x0a +#define EREVID 0x12 #define EPKTCNT_BANK 0x01 #define ERXFCON 0x18 @@ -233,6 +234,24 @@ softreset(void) bank = ERXTX_BANK; } /*---------------------------------------------------------------------------*/ +#if DEBUG +static uint8_t +readrev(void) +{ + uint8_t rev; + setregbank(MAADRX_BANK); + rev = readreg(EREVID); + switch(rev) { + case 2: + return 1; + case 6: + return 7; + default: + return rev; + } +} +#endif +/*---------------------------------------------------------------------------*/ static void reset(void) { @@ -464,6 +483,8 @@ enc28j60_init(uint8_t *mac_addr) reset(); + PRINTF("ENC28J60 rev. B%d\n", readrev()); + initialized = 1; } /*---------------------------------------------------------------------------*/ From 2b08c32528014a2def6686028adae54f6f1df609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 21:10:56 +0200 Subject: [PATCH 05/15] enc28j60: The MACON2 register is reserved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The register 0x01 in bank 2, named MACON2 in the code, is actually reserved, so its contents must not be changed. This register has been marked as reserved from the revision B of the data sheet in July 2006. The current revision of the data sheet is E, and it is quite clear about this register. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index 7c5acc5f0..41816e3be 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -84,7 +84,6 @@ #define MACONX_BANK 0x02 #define MACON1 0x00 -#define MACON2 0x01 #define MACON3 0x02 #define MACON4 0x03 #define MABBIPG 0x04 @@ -97,8 +96,6 @@ #define MACON1_RXPAUS 0x04 #define MACON1_MARXEN 0x01 -#define MACON2_MARST 0x80 - #define MACON3_PADCFG_FULL 0xe0 #define MACON3_TXCRCEN 0x10 #define MACON3_FRMLNEN 0x02 @@ -351,13 +348,11 @@ reset(void) initialization. This only needs to be done once; the order of programming is unimportant. - 1. Clear the MARST bit in MACON2 to pull the MAC out of Reset. - - 2. Set the MARXEN bit in MACON1 to enable the MAC to receive + 1. Set the MARXEN bit in MACON1 to enable the MAC to receive frames. If using full duplex, most applications should also set TXPAUS and RXPAUS to allow IEEE defined flow control to function. - 3. Configure the PADCFG, TXCRCEN and FULDPX bits of MACON3. Most + 2. Configure the PADCFG, TXCRCEN and FULDPX bits of MACON3. Most applications should enable automatic padding to at least 60 bytes and always append a valid CRC. For convenience, many applications may wish to set the FRMLNEN bit as well to enable frame length @@ -365,41 +360,38 @@ reset(void) will be connected to a full-duplex configured remote node; otherwise, it should be left clear. - 4. Configure the bits in MACON4. Many applications may not need to + 3. Configure the bits in MACON4. Many applications may not need to modify the Reset default. - 5. Program the MAMXFL registers with the maximum frame length to + 4. Program the MAMXFL registers with the maximum frame length to be permitted to be received or transmitted. Normal network nodes are designed to handle packets that are 1518 bytes or less. - 6. Configure the Back-to-Back Inter-Packet Gap register, + 5. Configure the Back-to-Back Inter-Packet Gap register, MABBIPG. Most applications will program this register with 15h when Full-Duplex mode is used and 12h when Half-Duplex mode is used. - 7. Configure the Non-Back-to-Back Inter-Packet Gap register low + 6. Configure the Non-Back-to-Back Inter-Packet Gap register low byte, MAIPGL. Most applications will program this register with 12h. - 8. If half duplex is used, the Non-Back-to-Back Inter-Packet Gap + 7. If half duplex is used, the Non-Back-to-Back Inter-Packet Gap register high byte, MAIPGH, should be programmed. Most applications will program this register to 0Ch. - 9. If Half-Duplex mode is used, program the Retransmission and + 8. If Half-Duplex mode is used, program the Retransmission and Collision Window registers, MACLCON1 and MACLCON2. Most applications will not need to change the default Reset values. If the network is spread over exceptionally long cables, the default value of MACLCON2 may need to be increased. - 10. Program the local MAC address into the + 9. Program the local MAC address into the MAADR0:MAADR5 registers. */ setregbank(MACONX_BANK); - /* Pull MAC out of reset */ - writereg(MACON2, 0);//readreg(MACON2) & (~MACON2_MARST)); - /* Turn on reception and IEEE-defined flow control */ writereg(MACON1, readreg(MACON1) | (MACON1_MARXEN + MACON1_TXPAUS + MACON1_RXPAUS)); From 121b066f04669b3c8b6b3055fcc26549f0f41e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 21:53:12 +0200 Subject: [PATCH 06/15] enc28j60: Update the MACON4 configuration comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This only applies to half duplex, so the actual configuration of MACON4 does not need to be changed. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index 41816e3be..99e6d3ebc 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -360,8 +360,8 @@ reset(void) will be connected to a full-duplex configured remote node; otherwise, it should be left clear. - 3. Configure the bits in MACON4. Many applications may not need to - modify the Reset default. + 3. Configure the bits in MACON4. For conformance to the IEEE 802.3 + standard, set the DEFER bit. 4. Program the MAMXFL registers with the maximum frame length to be permitted to be received or transmitted. Normal network nodes From 31e0c87a6f2a995b0eb1f3d2b83ace33b220a3d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 21:22:19 +0200 Subject: [PATCH 07/15] enc28j60: Do not initialize MAIPGH for full duplex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MAIPGH should be programmed only if half duplex is used. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index 99e6d3ebc..7ee55c393 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -411,7 +411,6 @@ reset(void) /* Set non-back-to-back packet gap */ writereg(MAIPGL, 0x12); - writereg(MAIPGH, 0x0c); /* Set MAC address */ setregbank(MAADRX_BANK); From 8a20e7c05ca47e3c0d7748b1fdcd48554f03220c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 22:00:46 +0200 Subject: [PATCH 08/15] enc28j60: Fix the MAC address configuration comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MAADRx register numbering was wrong. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index 7ee55c393..b4164147c 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -386,8 +386,7 @@ reset(void) the network is spread over exceptionally long cables, the default value of MACLCON2 may need to be increased. - 9. Program the local MAC address into the - MAADR0:MAADR5 registers. + 9. Program the local MAC address into the MAADR1:MAADR6 registers. */ setregbank(MACONX_BANK); From 356d17737c880dbf7362958c9afeb3d4c7b09641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 21:28:45 +0200 Subject: [PATCH 09/15] enc28j60: ERXFCON needs to be set only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index b4164147c..c0d6b30a3 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -335,11 +335,7 @@ reset(void) /* Receive filters */ setregbank(EPKTCNT_BANK); - /* writereg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | - ERXFCON_MCEN | ERXFCON_BCEN);*/ - /* XXX: can't seem to get the unicast filter to work right now, - using promiscous mode for now. */ - writereg(ERXFCON, 0); + writereg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN); /* 6.5 MAC Initialization Settings @@ -420,10 +416,6 @@ reset(void) writereg(MAADR2, enc_mac_addr[1]); writereg(MAADR1, enc_mac_addr[0]); - /* Receive filters */ - setregbank(EPKTCNT_BANK); - writereg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN); - /* 6.6 PHY Initialization Settings From 2cd3eaf310aa1ded99f4aa8c5e1b8cdce1ba3aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 22:07:45 +0200 Subject: [PATCH 10/15] enc28j60: Implement and use the BFS and BFC commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Bit Field Set and Bit Field Clear commands are more efficient than the Read Control Register + Write Control Register combination, so use them whenever possible, i.e. for the ETH registers. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index c0d6b30a3..1e694bff0 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -174,6 +174,32 @@ writereg(uint8_t reg, uint8_t data) } /*---------------------------------------------------------------------------*/ static void +setregbitfield(uint8_t reg, uint8_t mask) +{ + if(is_mac_mii_reg(reg)) { + writereg(reg, readreg(reg) | mask); + } else { + enc28j60_arch_spi_select(); + enc28j60_arch_spi_write(0x80 | (reg & 0x1f)); + enc28j60_arch_spi_write(mask); + enc28j60_arch_spi_deselect(); + } +} +/*---------------------------------------------------------------------------*/ +static void +clearregbitfield(uint8_t reg, uint8_t mask) +{ + if(is_mac_mii_reg(reg)) { + writereg(reg, readreg(reg) & ~mask); + } else { + enc28j60_arch_spi_select(); + enc28j60_arch_spi_write(0xa0 | (reg & 0x1f)); + enc28j60_arch_spi_write(mask); + enc28j60_arch_spi_deselect(); + } +} +/*---------------------------------------------------------------------------*/ +static void setregbank(uint8_t new_bank) { writereg(ECON1, (readreg(ECON1) & 0xfc) | (new_bank & 0x03)); @@ -388,12 +414,11 @@ reset(void) setregbank(MACONX_BANK); /* Turn on reception and IEEE-defined flow control */ - writereg(MACON1, readreg(MACON1) | (MACON1_MARXEN + MACON1_TXPAUS + - MACON1_RXPAUS)); + setregbitfield(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS); /* Set padding, crc, full duplex */ - writereg(MACON3, readreg(MACON3) | (MACON3_PADCFG_FULL + MACON3_TXCRCEN + - MACON3_FULDPX + MACON3_FRMLNEN)); + setregbitfield(MACON3, MACON3_PADCFG_FULL | MACON3_TXCRCEN | MACON3_FULDPX | + MACON3_FRMLNEN); /* Don't modify MACON4 */ @@ -445,7 +470,7 @@ reset(void) /* Don't worry about PHY configuration for now */ /* Turn on autoincrement for buffer access */ - writereg(ECON2, readreg(ECON2) | ECON2_AUTOINC); + setregbitfield(ECON2, ECON2_AUTOINC); /* Turn on reception */ writereg(ECON1, ECON1_RXEN); @@ -536,12 +561,12 @@ enc28j60_send(uint8_t *data, uint16_t datalen) } /* Clear EIR.TXIF */ - writereg(EIR, readreg(EIR) & (~EIR_TXIF)); + clearregbitfield(EIR, EIR_TXIF); /* Don't care about interrupts for now */ /* Send the packet */ - writereg(ECON1, readreg(ECON1) | ECON1_TXRTS); + setregbitfield(ECON1, ECON1_TXRTS); while((readreg(ECON1) & ECON1_TXRTS) > 0); if((readreg(ESTAT) & ESTAT_TXABRT) != 0) { @@ -626,7 +651,7 @@ enc28j60_read(uint8_t *buffer, uint16_t bufsize) writereg(ERXRDPTL, next & 0xff); writereg(ERXRDPTH, next >> 8); - writereg(ECON2, readreg(ECON2) | ECON2_PKTDEC); + setregbitfield(ECON2, ECON2_PKTDEC); if(err) { PRINTF("enc28j60: rx err: flushed %d\n", len); From 15d1b177d621ebb06d0423a8e3f3bea89c18836a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 22:19:41 +0200 Subject: [PATCH 11/15] enc28j60: Use hardware padding for transmissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no reason to use software when a feature is available in hardware. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index 1e694bff0..e1df67504 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -498,8 +498,6 @@ enc28j60_init(uint8_t *mac_addr) int enc28j60_send(uint8_t *data, uint16_t datalen) { - int padding = 0; - if(!initialized) { return -1; } @@ -535,30 +533,13 @@ enc28j60_send(uint8_t *data, uint16_t datalen) /* Write the transmission control register as the first byte of the output packet. We write 0x00 to indicate that the default configuration (the values in MACON3) will be used. */ -#define WITH_MANUAL_PADDING 1 -#if WITH_MANUAL_PADDING -#define PADDING_MIN_SIZE 60 - writedatabyte(0x0B); /* POVERRIDE, PCRCEN, PHUGEEN. Not PPADEN */ - if(datalen < PADDING_MIN_SIZE) { - padding = PADDING_MIN_SIZE - datalen; - } else { - padding = 0; - } -#else /* WITH_MANUAL_PADDING */ writedatabyte(0x00); /* MACON3 */ - padding = 0; -#endif /* WITH_MANUAL_PADDING */ /* Write a pointer to the last data byte. */ - writereg(ETXNDL, (TX_BUF_START + datalen + 0 + padding) & 0xff); - writereg(ETXNDH, (TX_BUF_START + datalen + 0 + padding) >> 8); + writereg(ETXNDL, (TX_BUF_START + datalen + 0) & 0xff); + writereg(ETXNDH, (TX_BUF_START + datalen + 0) >> 8); writedata(data, datalen); - if(padding > 0) { - uint8_t padding_buf[60]; - memset(padding_buf, 0, padding); - writedata(padding_buf, padding); - } /* Clear EIR.TXIF */ clearregbitfield(EIR, EIR_TXIF); From 8c6e3e348ad28a2e894cf9b84f5bfa16226176fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 22:21:39 +0200 Subject: [PATCH 12/15] enc28j60: Program ETXND after the data packet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just follow the steps from the data sheet to transmit a packet. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index e1df67504..e6953eda6 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -535,12 +535,12 @@ enc28j60_send(uint8_t *data, uint16_t datalen) configuration (the values in MACON3) will be used. */ writedatabyte(0x00); /* MACON3 */ + writedata(data, datalen); + /* Write a pointer to the last data byte. */ writereg(ETXNDL, (TX_BUF_START + datalen + 0) & 0xff); writereg(ETXNDH, (TX_BUF_START + datalen + 0) >> 8); - writedata(data, datalen); - /* Clear EIR.TXIF */ clearregbitfield(EIR, EIR_TXIF); From 8615b77da0f8713b42c775363611bb860506052f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 22:29:51 +0200 Subject: [PATCH 13/15] enc28j60: Print the status vector in case of transmit error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes debugging easier. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index e6953eda6..04ea33c51 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -498,6 +498,8 @@ enc28j60_init(uint8_t *mac_addr) int enc28j60_send(uint8_t *data, uint16_t datalen) { + uint16_t dataend; + if(!initialized) { return -1; } @@ -538,8 +540,9 @@ enc28j60_send(uint8_t *data, uint16_t datalen) writedata(data, datalen); /* Write a pointer to the last data byte. */ - writereg(ETXNDL, (TX_BUF_START + datalen + 0) & 0xff); - writereg(ETXNDH, (TX_BUF_START + datalen + 0) >> 8); + dataend = TX_BUF_START + datalen; + writereg(ETXNDL, dataend & 0xff); + writereg(ETXNDH, dataend >> 8); /* Clear EIR.TXIF */ clearregbitfield(EIR, EIR_TXIF); @@ -550,15 +553,28 @@ enc28j60_send(uint8_t *data, uint16_t datalen) setregbitfield(ECON1, ECON1_TXRTS); while((readreg(ECON1) & ECON1_TXRTS) > 0); +#if DEBUG if((readreg(ESTAT) & ESTAT_TXABRT) != 0) { - PRINTF("enc28j60: tx err: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", datalen, + uint16_t erdpt; + uint8_t tsv[7]; + erdpt = (readreg(ERDPTH) << 8) | readreg(ERDPTL); + writereg(ERDPTL, (dataend + 1) & 0xff); + writereg(ERDPTH, (dataend + 1) >> 8); + readdata(tsv, sizeof(tsv)); + writereg(ERDPTL, erdpt & 0xff); + writereg(ERDPTH, erdpt >> 8); + PRINTF("enc28j60: tx err: %d: %02x:%02x:%02x:%02x:%02x:%02x\n" + " tsv: %02x%02x%02x%02x%02x%02x%02x\n", datalen, 0xff & data[0], 0xff & data[1], 0xff & data[2], - 0xff & data[3], 0xff & data[4], 0xff & data[5]); + 0xff & data[3], 0xff & data[4], 0xff & data[5], + tsv[6], tsv[5], tsv[4], tsv[3], tsv[2], tsv[1], tsv[0]); } else { PRINTF("enc28j60: tx: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", datalen, 0xff & data[0], 0xff & data[1], 0xff & data[2], 0xff & data[3], 0xff & data[4], 0xff & data[5]); } +#endif + sent_packets++; PRINTF("enc28j60: sent_packets %d\n", sent_packets); return datalen; From b4c32954a6c5a9278c8fcbb8c147cd6780859023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 22:43:03 +0200 Subject: [PATCH 14/15] enc28j60: Fix workaround for erratum #14 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only odd addresses may be programmed to the ERXRDPT registers, so initialize them to RX_BUF_END instead of RX_BUF_START. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index 04ea33c51..2c0d5783d 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -356,8 +356,8 @@ reset(void) writereg(ERXNDH, RX_BUF_END >> 8); writereg(ERDPTL, RX_BUF_START & 0xff); writereg(ERDPTH, RX_BUF_START >> 8); - writereg(ERXRDPTL, RX_BUF_START & 0xff); - writereg(ERXRDPTH, RX_BUF_START >> 8); + writereg(ERXRDPTL, RX_BUF_END & 0xff); + writereg(ERXRDPTH, RX_BUF_END >> 8); /* Receive filters */ setregbank(EPKTCNT_BANK); From 6b76ead49c54b39256f92e42fe38de437d075bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 14 Jul 2015 23:02:22 +0200 Subject: [PATCH 15/15] enc28j60: Prevent enc28j60_read() from running before init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a precaution in case enc28j60-ip64-driver.c is skipped. Signed-off-by: Benoît Thébaudeau --- dev/enc28j60/enc28j60.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index 2c0d5783d..60dded31a 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -589,6 +589,10 @@ enc28j60_read(uint8_t *buffer, uint16_t bufsize) uint8_t status[2]; uint8_t length[2]; + if(!initialized) { + return -1; + } + err = 0; setregbank(EPKTCNT_BANK);