• AVR Freaks

Hot!Unable to write to MIREGADR register and a few other MAC/MII registers on the ENC28J60

Author
sramnath
Starting Member
  • Total Posts : 18
  • Reward points : 0
  • Joined: 2019/10/22 17:59:49
  • Location: 0
  • Status: offline
2019/10/25 18:28:26 (permalink)
0

Unable to write to MIREGADR register and a few other MAC/MII registers on the ENC28J60

Hello,
I am testing the read/write of registers on the ENC28J60. I am able to read/write to some registers, but it is sometimes wrong. For example, I am able to read the EREVID register to get my silicon revision number, and I am able to set the clock on CLKOUT to the different divider frequencies (which I can see change on my scope). 
 
However, when I try to write to the MIREGADR register in order to write to PHLCON register to light up the LEDs on the device, I am unable to do so. When I read the value back, I always get back a '0'.
 
The am performing the same spi_write function that I do for any other register. However, to read back the value, I give an extra 8 dummy cycles as specified by the datasheet before I get any data. I am also sure that I satisfy the 210 ns hold time requirement for reading from MAC/MII registers. I am operating in SPI mode 0,0 as specified by the datasheet. 
 
In my tests, I write to and read back values from about 80 registers over different banks, avoiding read-only registers, reserved registers. I pass 46/80 tests. If I pass a constant 'small' value such as 3, I pass 38/80 tests. The registers that I'm failing are ETH, MAC and MII registers. For example, I can write to register 0x7 in bank 2 which is MAIPGH or address 0x02 in bank 2 which is 0x2 and read back the same value, but I can't write to 0x8 in bank 2, which is MACLCON1 and read back the same value. 
 
I am able to change the bank I think correctly since I am able to set the clocks correctly and access the EREVID register, and both these registers are in different register banks. 
 
Here is my spi_write function : 
 
void spi_write(uint8_t address, uint8_t data){    uint16_t controlWord = setBufWriteToAddress(address, data);    bool transferOK;     memset((void *) masterRxBuffer, 0, SPI_MSG_LENGTH);    controlReg.count = SPI_MSG_LENGTH;    controlReg.txBuf = (void *) masterTxBuffer_write;    controlReg.rxBuf = (void *) masterRxBuffer;     /* Toggle user LED, indicating a SPI transfer is in progress */    GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);     /* Bitbanging attempt for Chip Select */    GPIO_write(Board_GPIO_CSN0, 0);     /* Perform SPI transfer */    transferOK = SPI_transfer(masterSpi, &controlReg);//    if (transferOK) {//       Display_printf(display, 0, 0, "Master received: %s", masterRxBuffer);//    }//    else {//       Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");//    }    /* Bitbanging attempt for Chip Select */    GPIO_write(Board_GPIO_CSN0, 1);    if (!transferOK){        Display_printf(display, 0, 0, "Unsuccessful SPI transfer\n");        while(1);    }    GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_OFF);      sleep(0.5);} uint8_t spi_read(uint8_t address){    uint8_t readVal;     // this fills up masterTxBuffer_write with the data, correctly as verified by scope    uint16_t controlWord = setBufReadFromAddress(address);     bool transferOK;     memset((void *) masterRxBuffer, 0, SPI_MSG_LENGTH);    controlReg.count = SPI_MSG_LENGTH;    controlReg.txBuf = (void *) masterTxBuffer_write;    controlReg.rxBuf = (void *) masterRxBuffer;     /* Toggle user LED, indicating a SPI transfer is in progress */    GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);     /* Bitbanging attempt for Chip Select */    GPIO_write(Board_GPIO_CSN0, 0);     /* Perform SPI transfer */    transferOK = SPI_transfer(masterSpi, &controlReg);    if (!transferOK){        Display_printf(display, 0, 0, "Unsuccessful SPI transfer\n");        while(1);    }     /* Bitbanging attempt for Chip Select */    GPIO_write(Board_GPIO_CSN0, 1);     readVal = masterRxBuffer[0] & 0x00ff;    GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_OFF);     sleep(0.5);    return readVal;}
 
Please let me know how I might proceed.
 
Warm regards,
Samyukta
post edited by sramnath - 2019/10/25 18:39:04
#1

4 Replies Related Threads

    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11982
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: Unable to write to MIREGADR register and a few other MAC/MII registers on the ENC28J60 2019/10/25 20:52:50 (permalink)
    0
    I don't know anything about the ENC28J60, but skimming the data sheet would make me think that MIREGADR is not readable via SPI.
    #2
    ric
    Super Member
    • Total Posts : 28368
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Unable to write to MIREGADR register and a few other MAC/MII registers on the ENC28J60 2019/10/25 20:57:27 (permalink)
    0
    I have never used this chip, so these comments are purely from reading the datasheet
    sramnath
    ... when I try to write to the MIREGADR register in order to write to PHLCON register to light up the LEDs on the device, I am unable to do so. When I read the value back, I always get back a '0'.

    No-where in the data sheet does it mention that you can read this register.
    There is no detailed explanation of the MIREGADR register (showing which bits are writeable or readable) as there is for most other registers. The "details" on page 19 just say what to write to it to access other registers.
     
    If it always reads back as zero, that could simply mean it is a write-only register.
     
    post edited by ric - 2019/10/25 20:58:31

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #3
    sramnath
    Starting Member
    • Total Posts : 18
    • Reward points : 0
    • Joined: 2019/10/22 17:59:49
    • Location: 0
    • Status: offline
    Re: Unable to write to MIREGADR register and a few other MAC/MII registers on the ENC28J60 2019/10/28 09:04:01 (permalink)
    0
    I see, thank you for your replies, and you are both right in that it doesn't say that either of those registers are readable.
     
    I chose another tactic to see if I was writing correctly and decided to try and read the physical registers to which I wrote, and also tried to read PHID1 which should always return 0083. Here is my code for the same : 
     
    uint16_t spi_readPHYReg(uint8_t address){
        /* Write the address of the PHY reg to read from MIREGADR (bank 2, address 0x14) */
        uint8_t readValH;
        uint8_t readValL;
        uint16_t readVal;
        selectMemBank(2);
        spi_write(0x14, address);
     
        /* Begin operation by setting MIRRD bit */
        // Bit field set/clear doesn't work for MAC registers so reading the value back first and then
        // changing it to set only the MICMD.MIRRD bit
        uint8_t MICMD_val = 0x3 & (spi_readMACReg(0x12)); // the MICMD register has only the last two bits R/W
        spi_write(0x12, (MICMD_val & 0xfe) | 0x1 );
       
        /* Wait at least 10.24 us before starting any other R/W operation */ 
        usleep(20);
     
        /* Polling the MISTAT.BUSY until the PHY read completes */
        selectMemBank(3);
        while(spi_readMACReg(0xa) & 0x1);
     
        /* Clear MICMD.MIIRD bit when you are done */
        selectMemBank(2);
        // Bit field set/clear doesn't work for MAC registers so reading the value back first and then
        // changing it to clear only the MICMD.MIRRD bit
        MICMD_val = 0x3 & (spi_readMACReg(0x12));
        spi_write(0x12,(MICMD_val & 0xfe));
     
        /* Now read the MIRDL and MIRDH registers (order is unimportant) */
        readValL = spi_readMACReg(0x18);
        readValH = spi_readMACReg(0x19);
        readVal = readValH << 8 | readValL;
        selectMemBank(0);
        return readVal;
    }
     
     
    I am always getting a return value of 4096 (0x1000) no matter which physical register I try to read, even the PHID1 which is readable and is supposed to return 0x0083 always. I also tried the same with PHLCON, and received 0x1000. I am inserting an extra dummy byte in between the read command and the data receive clock cycles to read MAC/MII registers, I am using a physical GPIO pin to drive chip select so I am sure that I am satisfying the hold-time constraint of at least 210 ns when readning from/writing to MAC/MII registers.
     
    So one thing that I am doing which is slightly non-standard is that I  send in 32 clock cycles to read/write MAC/MII registers. This is because I cannot change the data size dynamically in the SPI driver that I am using. I send two SPI transfers of size 16 bits each. The first byte in the first transfer contains the opcode and address, second byte in the first transfer is the 'dummy' byte, the first byte in the second transfer is the byte that provides the clock cycles to receive data from MAC/MII registers, and the second byte in the second transfer is another dummy byte because I can't just send in 8 clock cycles. On the scope, it looks like this:
     
    https://ibb.co/XVW50fz
    https://ibb.co/zfpyN5P
    https://ibb.co/wrGztB2
     
    Could sending in the extra dummy byte be a problem? Am I writing an extra register or something without meaning to?
     
     
     
     
     
     
     
    #4
    sramnath
    Starting Member
    • Total Posts : 18
    • Reward points : 0
    • Joined: 2019/10/22 17:59:49
    • Location: 0
    • Status: offline
    Re: Unable to write to MIREGADR register and a few other MAC/MII registers on the ENC28J60 2019/10/28 10:56:11 (permalink)
    5 (2)
    Edit : Yes, the two sixteen bit frames was the issue. I used three 8-bit frames instead, and to read/write, I used two 8-bit frames and manually toggled the CS pin.
     
     
    post edited by sramnath - 2019/10/28 19:00:27
    #5
    Jump to:
    © 2020 APG vNext Commercial Version 4.5