• AVR Freaks

Hot!ENC28J60 Physical status reading problem

Author
ketan vadodariya
New Member
  • Total Posts : 19
  • Reward points : 0
  • Joined: 2019/07/04 04:30:36
  • Location: 0
  • Status: offline
2020/03/23 06:27:53 (permalink)
0

ENC28J60 Physical status reading problem

Dear All,
 
I'm using pic24 series controller with ENC28J60 interface and i integrated the TCP/IP lite-weight stack which is used for the PIC18 series controller.well everything is fine but data posting frequency is more then 7 second to the PC. i'm opening the tcp socket from the PIC and getting data from the my customise board.
 
Problem :- if i'm changing the speed of the SPI Interface i'm not able to read the physical status register of the ENC28J60 so because of this link-up is not happening 
 
i'm sharing the function 
/*this function is used for the reading status of the link-up */

bool ETH_CheckLinkUp()
{
uint16_t phstat2;
phstat2 = ENC28_PhyRead(J60_PHSTAT2);

if ( phstat2 & 0x0400 ) {
ethData.up = true;
DBG_LEVEL_1("ETH_checkLinkUp true!!\n");
return true;
} else {
if ( driverLogEnable == LOG_ERR ) {
DBG_LEVEL_1("ETH_checkLinkUp false!!\n");
}
return false;
}
}
 
SPI Configuration
 
void ethernetSPI2Initialization(void)
{
SPI2CON1bits.DISSCK = 0; // Internal serial clock is enabled
SPI2CON1bits.DISSDO = 0; // SDOx pin is controlled by the module
SPI2CON1bits.MODE16 = 0; // Communication is word-wide (16 bits)
SPI2CON1bits.MSTEN = 1; // Master mode enabled
SPI2CON1bits.SMP = 0; // Input data is sampled at the middle of data output time
SPI2CON1bits.CKE = 0; // Serial output data changes on transition from Idle clock state to active clock state
SPI2CON1bits.CKP = 0; // Idle state for clock is a low level; active state is a high level
SPI2CON2bits.SPIBEN = 0; // Enabling enhanced mode data transfer
SPI2STATbits.SPIROV = 0; // Clearing overflow indication
[<font]SPI2CON1bits.PPRE = 0b11;              //able to read the link-up status register if bit set as 0b10
[<font]SPI2CON1bits.SPRE = 0b110;           //able to read the link-up status register if bit set as 0b010
SPI2STATbits.SPIEN = 1; // Enable SPI module
RC3_SetHigh();

Nop();
}
 

please do needful.
 
 
 
 
 
post edited by ketan vadodariya - 2020/03/23 22:05:10
#1

10 Replies Related Threads

    barbiani
    Super Member
    • Total Posts : 241
    • Reward points : 0
    • Status: offline
    Re: ENC28J60 Physical status reading problem 2020/03/23 08:10:53 (permalink)
    0
    Seven seconds delay is definitely not caused by the SPI bus. Look elsewhere.
     
    You should get millisecond long round trips.
     
    Can you share code?
    #2
    ketan vadodariya
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2019/07/04 04:30:36
    • Location: 0
    • Status: offline
    Re: ENC28J60 Physical status reading problem 2020/03/23 09:44:34 (permalink)
    0
    Dear Sir,
     
    which delay you are talking about it ??
     
    #3
    ketan vadodariya
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2019/07/04 04:30:36
    • Location: 0
    • Status: offline
    Re: ENC28J60 Physical status reading problem 2020/03/23 10:00:52 (permalink)
    0
    Dear Sir,
     
    check the SPI Routine code 
     
    void ethernetSPI2Initialization(void)
    {

    SPI2CON1bits.DISSCK = 0; // Internal serial clock is enabled
    SPI2CON1bits.DISSDO = 0; // SDOx pin is controlled by the module
    SPI2CON1bits.MODE16 = 0; // Communication is word-wide (16 bits)
    SPI2CON1bits.MSTEN = 1; // Master mode enabled
    SPI2CON1bits.SMP = 0; // Input data is sampled at the middle of data output time

    SPI2CON1bits.CKE = 0; // Serial output data changes on transition from Idle clock state to active clock state

    SPI2CON1bits.CKP = 0; // Idle state for clock is a low level; active state is a high level

    SPI2CON2bits.SPIBEN = 0; // Enabling enhanced mode data transfer

    SPI2STATbits.SPIROV = 0; // Clearing overflow indication

    SPI2CON1bits.PPRE = 0b11;

    SPI2CON1bits.SPRE = 0b110;

    SPI2STATbits.SPIEN = 1; // Enable SPI module

    RC3_SetHigh();

    Nop();

    }

     

    uint8_t readOrWriteForSPI2_(uint8_t byte)
    {
    SPI2BUF = byte;
    while (SPI2STATbits.SPIRBF == 0) {};
    return SPI2BUF;
    }

    uint8_t ethernetMasterWrite(uint8_t data)
    {
    return (readOrWriteForSPI2_(data));
    }

    uint8_t ethernetMasterRead(uint8_t byte)
    {
    return (readOrWriteForSPI2_(byte));
    }

     


     
    this is the ENC28J60 driver code which is generated by the PIC18 Series
     


     
    #include "enc28j60.h"
    #include "mac_address.h"
    #include "ethernet_core.h"
    #include "../delay.h"
    #include "../pin/pin_manager.h"
    #include "../spi/spi.h"
    #include "../serial_log.h"
    #include "network.h"

    #ifdef DATA_POST_BY_ETHERNET
    uint8_t Control_Byte = 0x00;
    extern volatile uint8_t driverLogEnable;
    #define CHIP_SELECT_DELAY 1
    #define NOP() Nop()
    #define ETH_NCS_HIGH() ENC28J60CHIP_High()
    #define ETH_NCS_LOW() ENC28J60CHIP_Low()
    #ifdef WISENSOR_VERSION_1
    #define ETH_IRQ RD7_GetPinValue()
    #else
    #define ETH_IRQ RC2_GetPinValue()
    #endif
    #define ETH_SPI_READ8() readOrWriteForSPI2_(0xFF)
    #define ETH_SPI_WRITE8(a) readOrWriteForSPI2_(a)
    #define ETH_IRQ_LOW() ((ETH_IRQ == 0)?1:0)
    volatile ethernetDriver_t ethData;
    const mac48Address_t *eth_MAC = NULL;
    static uint16_t nextPacketPointer;
    static receiveStatusVector_t rxPacketStatusVector;
    sfr_bank_t lastBank;
    uint8_t erevid = 0;
    #define MAX_TX_PACKET (1500)
    #define TXSTART (0x1FFF - MAX_TX_PACKET)
    #define TXEND (0x1FFF)
    #define RXSTART (0)
    #define RXEND (TXSTART - 2)

    static uint8_t ENC28_Rcr8(enc28j60_registers_t);
    static uint16_t ENC28_Rcr16(enc28j60_registers_t);
    static void ENC28_Wcr8(enc28j60_registers_t , uint8_t);
    static void ENC28_Wcr16(enc28j60_registers_t , uint16_t);
    static void ENC28_Bfs(enc28j60_registers_t , char);
    static void ENC28_Bfc(enc28j60_registers_t , char);
    static uint16_t ENC28_PhyRead(enc28j60_phy_registers_t a);
    static void ENC28_PhyWrite(enc28j60_phy_registers_t a , uint16_t d);
    static void ENC28_BankSel(enc28j60_registers_t);

    uint16_t TXPacketSize;
    static void ENC28J60CHIP_Low(void)
    {
    delay_ms(CHIP_SELECT_DELAY);
    #ifdef WISENSOR_VERSION_1
    RE5_SetLow();
    #else
    RC3_SetLow();
    #endif
    Nop();
    }
    static void ENC28J60CHIP_High(void)
    {
    delay_ms(CHIP_SELECT_DELAY);
    #ifdef WISENSOR_VERSION_1
    RE5_SetHigh();
    #else
    RC3_SetHigh();
    #endif
    Nop();
    }
    /*******************************************************************************/
    /**
    * Bank Select
    * @param r
    */
    static void ENC28_BankSel(enc28j60_registers_t r)
    {
    uint8_t a = r & BANK_MASK;
    if ( a != sfr_common && a != lastBank ) {
    lastBank = a;
    // clear the bank bits
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(bfc_inst | 0x1F);
    ETH_SPI_WRITE8(0x03);
    ETH_NCS_HIGH();
    NOP();
    NOP();
    // set the needed bits
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(bfs_inst | 0x1F);
    ETH_SPI_WRITE8(a >> 6);
    ETH_NCS_HIGH();
    }
    }
    /**
    * Ethernet Initialization - Initializes TX/RX Buffer, MAC and PHY
    */
    void ENCJ60Initialazation(void)
    {
    // initialize the driver variables
    ethData.error = false; // no error
    ethData.up = false; // no link
    ethData.linkChange = false;
    ethData.bufferBusy = false; // transmit data buffer is free
    ethData.saveRDPT = 0;
    lastBank = sfr_bank0;
    __delay_us(100);
    ETH_NCS_HIGH();
    ETH_SendSystemReset(); // software reset
    __delay_ms(500);
    uint8_t result = 0 , timeout = 15;
    do {
    result = ENC28_Rcr8(J60_ESTAT);
    timeout = timeout - 1;
    delay_ms(5);
    DBG_LEVEL_1("ESTAT REGISTER VALUE IS = %02X \r\n" , result);
    } while (!(result & 0x01) && (timeout > 0));
    if ( driverLogEnable == LOG_ERR ) {
    DBG_LEVEL_1("timeout = %d \r\n" , timeout);
    if ( timeout == 0 ) DBG_LEVEL_1("ENC28J60_Init ERROR:TIMEOUT !!");
    }
    // Initialize RX tracking variables and other control state flags
    nextPacketPointer = RXSTART;
    ENC28_Bfs(J60_ECON2 , 0x80); // enable AUTOINC
    // Set up TX/RX buffer addresses
    ENC28_Wcr16(J60_ETXSTL , TXSTART);
    ENC28_Wcr16(J60_ETXNDL , TXEND);
    ENC28_Wcr16(J60_ERXSTL , RXSTART);
    ENC28_Wcr16(J60_ERXNDL , RXEND);
    ENC28_Wcr16(J60_ERDPTL , nextPacketPointer);
    ENC28_Wcr16(J60_ERDPTL , RXSTART);
    ENC28_Wcr16(J60_EWRPTL , TXSTART);
    // Configure the receive filter
    ENC28_Wcr8(J60_ERXFCON , 0b10101001); //UCEN,OR,CRCEN,MPEN,BCEN (unicast,crc,magic packet,broadcast)
    // what is my MAC address?
    eth_MAC = MAC_getAddress();
    // Initialize the MAC
    ENC28_Wcr8(J60_MACON1 , 0x0D); // TXPAUS, RXPAUS, MARXEN
    ENC28_Wcr8(J60_MACON3 , 0x22); // Pad < 60 bytes, Enable CRC, Frame Check, Half Duplex
    ENC28_Wcr8(J60_MACON4 , 0x40); // DEFER set
    ENC28_Wcr16(J60_MAIPGL , 0x0c12);
    ENC28_Wcr8(J60_MABBIPG , 0x12);
    ENC28_Wcr16(J60_MAMXFLL , MAX_TX_PACKET);
    ENC28_Wcr8(J60_MAADR1 , eth_MAC->mac_array[0]);
    NOP();
    ENC28_Wcr8(J60_MAADR2 , eth_MAC->mac_array[1]);
    NOP();
    ENC28_Wcr8(J60_MAADR3 , eth_MAC->mac_array[2]);
    NOP();
    ENC28_Wcr8(J60_MAADR4 , eth_MAC->mac_array[3]);
    NOP();
    ENC28_Wcr8(J60_MAADR5 , eth_MAC->mac_array[4]);
    NOP();
    ENC28_Wcr8(J60_MAADR6 , eth_MAC->mac_array[5]);
    NOP();
    ENC28_Wcr8(J60_ECON1 , 0x04); // RXEN enabled
    // Initialize the PHY
    ENC28_PhyWrite(J60_PHCON1 , 0x0000);
    ENC28_PhyWrite(J60_PHCON2 , 0x0100); // Do not transmit loopback
    ENC28_PhyWrite(J60_PHLCON , 0x0472); // LED control - LEDA = Link, LEDB = TX/RX, Stretched LED
    // LEDB is grounded so default is Half Duplex
    // Configure the IRQ's
    ENC28_Wcr8(J60_EIE , 0xDB); // Enable PKTIE,INTIE,LINKIE,TXIE,TXERIE,RXERIE
    ENC28_Wcr16(J60_PHIE , 0x12); //Enable PLNKIE and PGEIE
    erevid = ENC28_Rcr8(J60_EREVID);
    if ( erevid == 0xFF ) {
    erevid = 0;
    }
    if ( erevid == 0 ) {
    DBG_LEVEL_1("ENC28J60 INIT INFO: Chip erevid = %02X 'It won't expected ' Device not Found \r\n" , erevid);
    } else {
    DBG_LEVEL_1("ENC28J60 INIT INFO: Chip erevid = %02X \r\n" , erevid);
    }
    delay_ms(1000);

    ETH_CheckLinkUp();
    }
    /**
    * Poll Ethernet Controller for new events
    */
    void ETH_EventHandler(void)
    {
    eir_t eir_val;
    phstat2_t phstat2_val;
    // check for the IRQ pin
    if ( ETH_IRQ_LOW() ) {
    // MAC is sending an interrupt
    // what is the interrupt
    eir_val.val = ENC28_Rcr8(J60_EIR);

    phstat2_val.val = ENC28_Rcr16(J60_PHSTAT2);
    if ( eir_val.LINKIF ) // something about the link changed.... update the link parameters
    {
    ethData.linkChange = true;
    ethData.up = false;
    if ( ETH_CheckLinkUp() ) {
    }
    if ( phstat2_val.DPXSTAT ) // Update MAC duplex settings to match PHY duplex setting
    {
    ENC28_Wcr16(J60_MABBIPG , 0x15); // Switching to full duplex
    ENC28_Bfs(J60_PHSTAT2 , 0x01);
    } else {
    ENC28_Wcr16(J60_MABBIPG , 0x12); // Switching to half duplex
    ENC28_Bfc(J60_PHSTAT2 , 0x01);
    }
    }
    if ( eir_val.TXIF ) // finished sending a packet
    {
    ethData.bufferBusy = false;
    ENC28_Bfc(J60_EIR , 0x08);
    }
    if ( eir_val.PKTIF || ENC28_Rcr8(J60_EPKTCNT) ) // Packet receive buffer has at least 1 unprocessed packet
    {
    ethData.pktReady = true;
    }
    ENC28_Wcr8(J60_EIR , eir_val.val); // write the eir value back to clear any of the interrupts
    } else {
    }
    }
    void ETH_ResetReceiver(void)
    {
    uint8_t econ1;
    econ1 = ENC28_Rcr8(J60_ECON1);
    ENC28_Wcr8(J60_ECON1 , (econ1 | 0x40));
    }
    /**
    * Retrieve information about last received packet and the address of the next ones
    */
    void ETH_NextPacketUpdate()
    {
    // Set the RX Read Pointer to the beginning of the next unprocessed packet
    //Errata 14 inclusion
    //waiting till there are packets to read
    //while (!(epktcnt = ENC28_Rcr8(J60_EPKTCNT)));
    if ( nextPacketPointer == RXSTART ) {
    ENC28_Wcr16(J60_ERXRDPTL , RXEND);
    } else {
    ENC28_Wcr16(J60_ERXRDPTL , nextPacketPointer - 1);
    }
    ENC28_Wcr16(J60_ERDPTL , nextPacketPointer);
    ethernetReadBuffer(2 , (uint8_t*) & nextPacketPointer);
    ethernetReadBuffer(4 , (uint8_t*) & rxPacketStatusVector);
    rxPacketStatusVector.byteCount -= 4; // I don't care about the frame checksum at the end.
    // the checksum is 4 bytes.. so my payload is the byte count less 4.
    }
    /**
    * Read 1 byte from SFRs
    * @param a
    * @return
    */
    static uint8_t ENC28_Rcr8(enc28j60_registers_t a)
    {
    uint8_t v;
    ENC28_BankSel(a);
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(rcr_inst | (a & SFR_MASK));
    v = ETH_SPI_READ8();
    ETH_NCS_HIGH();
    return v;
    }
    /**
    * Read 2 bytes from SFRs
    * @param a
    * @return
    */
    static uint16_t ENC28_Rcr16(enc28j60_registers_t a)
    {
    uint16_t v;
    ENC28_BankSel(a);
    a &= SFR_MASK;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(rcr_inst | (a));
    ((char *) &v)[0] = ETH_SPI_READ8();
    ETH_NCS_HIGH();
    NOP();
    NOP();
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(rcr_inst | (a + 1));
    ((char *) &v)[1] = ETH_SPI_READ8();
    ETH_NCS_HIGH();
    return v;
    }
    /**
    * Write 1 byte to SFRs
    * @param a
    * @param v
    */
    static void ENC28_Wcr8(enc28j60_registers_t a , uint8_t v)
    {
    ENC28_BankSel(a);
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wcr_inst | (a & SFR_MASK));
    ETH_SPI_WRITE8(v);
    ETH_NCS_HIGH();
    }
    /**
    * Write 2 bytes to SFRs
    * @param a
    * @param v
    */
    static void ENC28_Wcr16(enc28j60_registers_t a , uint16_t v)
    {
    ENC28_BankSel(a);
    a &= SFR_MASK;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wcr_inst | (a));
    ETH_SPI_WRITE8(((char *) &v)[0]);
    ETH_NCS_HIGH();
    NOP();
    NOP();
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wcr_inst | (a + 1));
    ETH_SPI_WRITE8(((char *) &v)[1]);
    ETH_NCS_HIGH();
    }
    /**
    * SFR Bit Field Set
    * @param a
    * @param bits
    */
    static void ENC28_Bfs(enc28j60_registers_t a , char bits) // can only be used for ETH Control Registers
    {
    ENC28_BankSel(a);
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(bfs_inst | (a & SFR_MASK));
    ETH_SPI_WRITE8(bits);
    ETH_NCS_HIGH();
    }
    /**
    * SFR Bit Field Clear
    * @param a
    * @param bits
    */
    static void ENC28_Bfc(enc28j60_registers_t a , char bits)
    {
    ENC28_BankSel(a);
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(bfc_inst | (a & SFR_MASK));
    ETH_SPI_WRITE8(bits);
    ETH_NCS_HIGH();
    }
    /**
    * Write PHY register
    * @param a
    * @param d
    */
    static void ENC28_PhyWrite(enc28j60_phy_registers_t a , uint16_t d)
    {
    uint8_t v = 1;
    ENC28_Wcr8(J60_MIREGADR , a);
    ENC28_Wcr16(J60_MIWRL , d);
    while (v & 0x01) {
    v = ENC28_Rcr8(J60_MISTAT);
    }
    }
    /**
    * Read PHY register
    * @param a
    * @return
    */
    static uint16_t ENC28_PhyRead(enc28j60_phy_registers_t a)
    {
    ENC28_Wcr8(J60_MIREGADR , a);
    ENC28_Bfs(J60_MICMD , 0x01); // set the read flag
    uint8_t result = 0;
    __delay_us(11);


    do {
    result = ENC28_Rcr8(J60_MISTAT);

    } while (!(result & 0x01));
    ENC28_Bfc(J60_MICMD , 0x00); // clear the read flag
    return ENC28_Rcr16(J60_MIRDL);
    }
    /**
    * System Software Reset
    */
    void ETH_SendSystemReset(void)
    {
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(src_inst);
    ETH_NCS_HIGH();
    }
    /**
    * Check for the link presence
    * @return
    */
    bool ETH_CheckLinkUp()
    {
    uint16_t phstat2;
    phstat2 = ENC28_PhyRead(J60_PHSTAT2);
    DBG_LEVEL_1("phstat2 %04x", phstat2);

    if ( phstat2 & 0x0400 ) {
    ethData.up = true;
    DBG_LEVEL_1("ETH_checkLinkUp true!!\n");
    return true;
    } else {
    if ( driverLogEnable == LOG_ERR ) {
    DBG_LEVEL_1("ETH_checkLinkUp false!!\n");
    }
    return false;
    }
    }
    /**
    * Read 1 byte of data from the RX Buffer
    * @return
    */
    uint8_t ETH_Read8(void)
    {
    uint8_t b;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(rbm_inst);
    b = ETH_SPI_READ8();
    ETH_NCS_HIGH();
    return b;
    }
    /**
    * Read 2 bytes of data from the RX Buffer
    * @return
    */
    uint16_t ETH_Read16(void)
    {
    uint16_t b;
    ETH_NCS_LOW();
    ethernetReadBuffer(2 , (uint8_t*) & b);
    ETH_NCS_HIGH();
    return b;
    }
    /**
    * Read 3 bytes of data from the RX Buffer
    * @return
    */
    uint32_t ETH_Read24(void)
    {
    uint32_t b;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(rbm_inst);
    ((char *) &b)[2] = ETH_SPI_READ8();
    ((char *) &b)[1] = ETH_SPI_READ8();
    ((char *) &b)[0] = ETH_SPI_READ8();
    ETH_NCS_HIGH();
    return b;
    }
    /**
    * Read 4 bytes of data from the RX Buffer
    * @return
    */
    uint32_t ETH_Read32(void)
    {
    uint32_t b;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(rbm_inst);
    ((char *) &b)[3] = ETH_SPI_READ8();
    ((char *) &b)[2] = ETH_SPI_READ8();
    ((char *) &b)[1] = ETH_SPI_READ8();
    ((char *) &b)[0] = ETH_SPI_READ8();
    ETH_NCS_HIGH();
    return b;
    }
    /**
    * Write 1 byte of data to TX Buffer
    * @param data
    */
    void ETH_Write8(uint8_t data)
    {
    TXPacketSize += 1;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wbm_inst);
    ETH_SPI_WRITE8(data);
    ETH_NCS_HIGH();
    }
    /**
    * Write 2 bytes of data to TX Buffer
    * @param data
    */
    void ETH_Write16(uint16_t data)
    {
    TXPacketSize += 2;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wbm_inst);
    ETH_SPI_WRITE8((data >> 8) & 0xFF);
    ETH_SPI_WRITE8(data & 0xFF);
    ETH_NCS_HIGH();
    }
    /**
    * Write 3 bytes of data to TX Buffer
    * @param data
    */
    void ETH_Write24(uint32_t data)
    {
    TXPacketSize += 2;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wbm_inst);
    ETH_SPI_WRITE8(data >> 16);
    ETH_SPI_WRITE8(data >> 8);
    ETH_SPI_WRITE8(data);
    ETH_NCS_HIGH();
    }
    /**
    * Write 4 bytes of data to TX Buffer
    * @param data
    */
    void ETH_Write32(uint32_t data)
    {
    TXPacketSize += 4;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wbm_inst);
    ETH_SPI_WRITE8(data >> 24);
    ETH_SPI_WRITE8(data >> 16);
    ETH_SPI_WRITE8(data >> 8);
    ETH_SPI_WRITE8(data);
    ETH_NCS_HIGH();
    }
    uint16_t ETH_WriteString(const char *string)
    {
    uint16_t length = 0;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wbm_inst);
    while (*string) {
    ETH_SPI_WRITE8(*string++);
    length++;
    }
    ETH_NCS_HIGH();
    TXPacketSize += length;
    return length;
    }
    /**
    * Write a block of data to TX Buffer
    * @param data
    * @param length
    */
    uint16_t ETH_WriteBlock(const void* data , uint16_t length)
    {
    char *p = (char*) data;
    TXPacketSize += length;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wbm_inst);
    while (length--) {
    ETH_SPI_WRITE8(*p++);
    }
    ETH_NCS_HIGH();
    return length;
    }
    /**
    * Returns the available space size in the Ethernet TX Buffer
    * @param
    * @return available space left in the TX buffer
    */
    uint16_t ETH_GetFreeTxBufferSize(void)
    {
    return(uint16_t) (TXEND - ENC28_Rcr16(J60_EWRPTL));
    }
    /**
    * start a packet.
    * If the Ethernet transmitter is idle, then start a packet. Return is SUCCESS if the packet was started.
    * @param dest_mac
    * @param type
    * @return SUCCESS if packet started. BUFFER_BUSY or TX_LOGIC_NOT_IDLE if buffer or transmitter is busy respectively
    */
    error_msg ETH_WriteStart(const mac48Address_t *dest_mac , uint16_t type)
    {
    if ( ethData.bufferBusy ) {
    if ( driverLogEnable == LOG_ERR ) {
    #if LOG_LEVEL >= LOG_ERR
    DBG_LEVEL_1("in ETH_WriteStart BUFFER_BUSY ARP_Request failure");
    #endif
    }
    Reset();
    return BUFFER_BUSY;
    }
    if ( (ENC28_Rcr8(J60_ECON1) & 0x08) ) {
    return TX_LOGIC_NOT_IDLE;
    }
    // Set the Window Write Pointer to the beginning of the transmit buffer
    ENC28_Wcr16(J60_ETXSTL , TXSTART);
    ENC28_Wcr16(J60_EWRPTL , TXSTART);
    TXPacketSize = 0;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wbm_inst);
    ETH_SPI_WRITE8(Control_Byte);
    ETH_SPI_WRITE8(dest_mac->mac_array[0]);
    ETH_SPI_WRITE8(dest_mac->mac_array[1]);
    ETH_SPI_WRITE8(dest_mac->mac_array[2]);
    ETH_SPI_WRITE8(dest_mac->mac_array[3]);
    ETH_SPI_WRITE8(dest_mac->mac_array[4]);
    ETH_SPI_WRITE8(dest_mac->mac_array[5]);
    ETH_SPI_WRITE8(eth_MAC->mac_array[0]);
    ETH_SPI_WRITE8(eth_MAC->mac_array[1]);
    ETH_SPI_WRITE8(eth_MAC->mac_array[2]);
    ETH_SPI_WRITE8(eth_MAC->mac_array[3]);
    ETH_SPI_WRITE8(eth_MAC->mac_array[4]);
    ETH_SPI_WRITE8(eth_MAC->mac_array[5]);
    ETH_SPI_WRITE8(type >> 8);
    ETH_SPI_WRITE8(type & 0x0FF);
    ETH_NCS_HIGH();
    TXPacketSize += 15;
    ethData.bufferBusy = true;
    return SUCCESS;
    }
    /**
    * Start the Transmission
    * @return
    */
    error_msg ETH_Send(void)
    {
    ENC28_Wcr16(J60_ETXNDL , TXSTART + TXPacketSize);
    if ( !ethData.up ) {
    if ( driverLogEnable == LOG_ERR ) {
    DBG_LEVEL_1("in ETH_Send() LINK_NOT_FOUND");
    }
    return LINK_NOT_FOUND;
    }
    if ( !ethData.bufferBusy ) {
    if ( driverLogEnable == LOG_ERR ) {
    DBG_LEVEL_1("in ETH_Send() BUFFER_BUSY");
    }
    return BUFFER_BUSY;
    }
    ENC28_Bfs(J60_ECON1 , 0x08); // start the transmission
    ethData.bufferBusy = false;
    return SUCCESS;
    }
    /**
    * Clears number of bytes (length) from the RX buffer
    * @param length
    */
    void ETH_Dump(uint16_t length)
    {
    uint16_t newRXTail;
    length = (rxPacketStatusVector.byteCount <= length) ? rxPacketStatusVector.byteCount : length;
    if ( length ) {
    newRXTail = ENC28_Rcr16(J60_ERDPTL);
    newRXTail += length;
    //Write new RX tail
    ENC28_Wcr16(J60_ERDPTL , newRXTail);
    rxPacketStatusVector.byteCount -= length;
    }
    }
    /**
    * Clears all bytes from the RX buffer
    */
    void ETH_Flush(void)
    {
    ethData.pktReady = false;
    if ( nextPacketPointer == RXSTART )ENC28_Wcr16(J60_ERXRDPTL , RXEND);
    else ENC28_Wcr16(J60_ERXRDPTL , nextPacketPointer - 1);
    ENC28_Wcr16(J60_ERDPTL , nextPacketPointer);
    //Packet decrement
    ENC28_Bfs(J60_ECON2 , 0x40);
    }
    /**
    * Insert data in between of the TX Buffer
    * @param data
    * @param len
    * @param offset
    */
    void ETH_Insert(uint8_t * data , uint16_t len , uint16_t offset)
    {
    uint16_t current_tx_pointer = 0;
    offset += sizeof(Control_Byte);
    current_tx_pointer = ENC28_Rcr16(J60_EWRPTL);
    ENC28_Wcr16(J60_EWRPTL , TXSTART + offset);
    while (len--) {
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(wbm_inst); //WBM command
    ETH_SPI_WRITE8(*data++);
    ETH_NCS_HIGH();
    }
    ENC28_Wcr16(J60_EWRPTL , current_tx_pointer);
    }
    /**
    * Copy the data from RX Buffer to the TX Buffer using DMA setup
    * This is used for ICMP ECHO to eliminate the need to extract the arbitrary payload
    * @param len
    */
    error_msg ETH_Copy(uint16_t len)
    {
    uint16_t tx_buffer_address;
    uint16_t timer , temp_len;
    timer = 2 * len;
    // Wait until module is idle
    while ((ENC28_Rcr8(J60_ECON1) & 0x20) != 0 && --timer) NOP(); // sit here until the DMAST bit is clear
    if ( (ENC28_Rcr8(J60_ECON1) & 0x20) == 0 ) {
    tx_buffer_address = ENC28_Rcr16(J60_EWRPTL); // Current TX Write Pointer
    ENC28_Wcr16(J60_EDMADSTL , tx_buffer_address);
    ENC28_Wcr16(J60_EDMASTL , ENC28_Rcr16(J60_ERDPTL));
    tx_buffer_address += len;
    temp_len = ENC28_Rcr16(J60_ERDPTL) + len;
    if ( temp_len > RXEND ) {
    temp_len = temp_len - (RXEND) + RXSTART;
    ENC28_Wcr16(J60_EDMANDL , temp_len);
    } else {
    ENC28_Wcr16(J60_EDMANDL , temp_len);
    }
    // Clear CSUMEN to select a copy operation
    ENC28_Bfc(J60_ECON1 , 0x10);
    // start the DMA
    ENC28_Bfs(J60_ECON1 , 0x20);
    timer = 40 * len;
    while ((ENC28_Rcr8(J60_ECON1) & 0x20) != 0 && --timer) NOP(); // sit here until the DMAST bit is clear
    if ( (ENC28_Rcr8(J60_ECON1) & 0x20) == 0 ) {
    // clean up the source and destination window pointers
    ENC28_Wcr16(J60_EWRPTL , tx_buffer_address);
    TXPacketSize += len; // fix the packet length
    return SUCCESS;
    }
    }
    // RESET(); // reboot for now
    return DMA_TIMEOUT;
    }
    static uint16_t ETH_ComputeChecksum(uint16_t len , uint16_t seed)
    {
    uint32_t cksm;
    uint16_t v;
    cksm = seed;
    while (len > 1) {
    v = 0;
    ((char *) &v)[1] = ETH_Read8();
    ((char *) &v)[0] = ETH_Read8();
    cksm += v;
    len -= 2;
    }
    if ( len ) {
    v = 0;
    ((char *) &v)[1] = ENC28_Rcr8(rbm_inst);
    ((char *) &v)[0] = 0;
    cksm += v;
    }
    // wrap the checksum
    while (cksm >> 16) {
    cksm = (cksm & 0x0FFFF) + (cksm >> 16);
    }
    // invert the number.
    cksm = ~cksm;
    // Return the resulting checksum
    return cksm;
    }
    /**
    * Calculate the Checksum - Hardware Checksum
    * @param position
    * @param length
    * @return
    */
    uint16_t ETH_TxComputeChecksum(uint16_t position , uint16_t length , uint16_t seed)
    {
    uint32_t cksm;
    // cksm = seed;
    position += sizeof(Control_Byte);
    while ((ENC28_Rcr8(J60_ECON1) & 0x20) != 0); // sit here until the DMAST bit is clear
    ENC28_Wcr16(J60_EDMASTL , (TXSTART + position));
    ENC28_Wcr16(J60_EDMANDL , TXSTART + position + (length - 1));
    if ( !(ENC28_Rcr8(J60_ECON1) & 0x10) ) //Make sure CSUMEN is not set already
    {
    // Set CSUMEN and DMAST to select and start a checksum operation
    ENC28_Bfs(J60_ECON1 , 0x30);
    while ((ENC28_Rcr8(J60_ECON1) & 0x20) != 0); // sit here until the DMAST bit is clear
    ENC28_Bfc(J60_ECON1 , 0x10);
    cksm = ENC28_Rcr16(J60_EDMACSL);
    if ( seed ) {
    seed = ~(seed);
    cksm += seed;
    while (cksm >> 16) {
    cksm = (cksm & 0x0FFFF) + (cksm >> 16);
    }
    }
    cksm = htons(cksm);
    }
    return cksm;
    }
    /**
    * Calculate RX checksum - Software checksum
    * @param len
    * @param seed
    * @return
    */
    uint16_t ETH_RxComputeChecksum(uint16_t len , uint16_t seed)
    {
    uint16_t rxptr;
    uint32_t cksm;
    // Save the read pointer starting address
    rxptr = ENC28_Rcr16(J60_ERDPTL);
    cksm = ETH_ComputeChecksum(len , seed);
    // Restore old read pointer location
    ENC28_Wcr16(J60_ERDPTL , rxptr);
    //if (!cksm) {
    // return 0;
    //}
    // Return the resulting checksum
    return(((cksm & 0xFF00) >> 8) | ((cksm & 0x00FF) << 8));
    }
    /**
    * To get the MAC address
    * @param mac
    */
    void ETH_GetMAC(uint8_t *macAddr)
    {
    *macAddr++ = ENC28_Rcr8(J60_MAADR1);
    *macAddr++ = ENC28_Rcr8(J60_MAADR2);
    *macAddr++ = ENC28_Rcr8(J60_MAADR3);
    *macAddr++ = ENC28_Rcr8(J60_MAADR4);
    *macAddr++ = ENC28_Rcr8(J60_MAADR5);
    *macAddr++ = ENC28_Rcr8(J60_MAADR6);
    }
    /**
    * To set the MAC address
    * @param mac
    */
    void ETH_SetMAC(uint8_t *macAddr)
    {
    ENC28_Wcr8(J60_MAADR1 , *macAddr++);
    ENC28_Wcr8(J60_MAADR2 , *macAddr++);
    ENC28_Wcr8(J60_MAADR3 , *macAddr++);
    ENC28_Wcr8(J60_MAADR4 , *macAddr++);
    ENC28_Wcr8(J60_MAADR5 , *macAddr++);
    ENC28_Wcr8(J60_MAADR6 , *macAddr++);
    }
    void ETH_SaveRDPT(void)
    {
    ethData.saveRDPT = ENC28_Rcr16(J60_ERDPTL);
    }
    uint16_t ETH_GetReadPtr(void)
    {
    return ENC28_Rcr16(J60_ERDPTL);
    }
    void ETH_SetReadPtr(uint16_t rdptr)
    {
    ENC28_Wcr16(J60_ERDPTL , rdptr);
    }
    void ETH_MoveBackReadPtr(uint16_t offset)
    {
    uint16_t rdptr;
    rdptr = ENC28_Rcr16(J60_ERDPTL);
    ENC28_Wcr16(J60_ERDPTL , rdptr - offset);
    ETH_SetRxByteCount(offset);
    }
    void ETH_ResetReadPtr()
    {
    ENC28_Wcr16(J60_ERDPTL , RXSTART);
    }
    uint16_t ETH_GetWritePtr()
    {
    return ENC28_Rcr16(J60_EWRPTL);
    }
    uint16_t ETH_GetRxByteCount()
    {
    return(rxPacketStatusVector.byteCount);
    }
    void ETH_SetRxByteCount(uint16_t count)
    {
    rxPacketStatusVector.byteCount += count;
    }
    void ETH_ResetByteCount(void)
    {
    ethData.saveWRPT = ENC28_Rcr16(J60_EWRPTL);
    }
    uint16_t ETH_GetByteCount(void)
    {
    uint16_t wptr;
    wptr = ENC28_Rcr16(J60_EWRPTL);
    return(wptr - ethData.saveWRPT);
    }
    void ETH_SaveWRPT(void)
    {
    ethData.saveWRPT = ENC28_Rcr16(J60_EWRPTL);
    }
    uint16_t ETH_ReadSavedWRPT(void)
    {
    return ethData.saveWRPT;
    }
    uint16_t ETH_GetStatusVectorByteCount(void)
    {
    return(rxPacketStatusVector.byteCount);
    }
    void ETH_SetStatusVectorByteCount(uint16_t bc)
    {
    rxPacketStatusVector.byteCount = bc;
    }
    void ETH_TxReset(void)
    {
    uint8_t econ1;
    econ1 = ENC28_Rcr8(J60_ECON1);
    ENC28_Wcr8(J60_ECON1 , (econ1 | 0x08));
    ethData.bufferBusy = false;
    ETH_ResetByteCount();
    ENC28_Wcr16(J60_ETXSTL , TXSTART);
    ENC28_Wcr16(J60_EWRPTL , TXSTART);
    }
    void ethernetReadBuffer(uint16_t len , uint8_t* data)
    {
    uint16_t i = 0;
    ETH_NCS_LOW();
    ETH_SPI_WRITE8(0x3a);
    while (i < len) {
    data = ETH_SPI_READ8();
    i++;
    }
    ETH_NCS_HIGH();
    }

    #endif
     


     
    post edited by ketan vadodariya - 2020/03/23 22:02:07
    #4
    Aussie Susan
    Super Member
    • Total Posts : 3686
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: ENC28J60 Physical status reading problem 2020/03/23 18:06:27 (permalink)
    0
    Please use code tags ('[ c o d e ]' and '[ / c o d e ]' without the spaces). Without them your code is unreadable.
    Also, what are the CONFIG settings?
    He is talking about the 7 seconds posting frequency to the PC you mention in the 2nd line of your first post.
    When you say you change the SPI clock rate, what do you change it from and to?
    Susan
     
    #5
    ketan vadodariya
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2019/07/04 04:30:36
    • Location: 0
    • Status: offline
    Re: ENC28J60 Physical status reading problem 2020/03/23 21:41:12 (permalink)
    0
    Dear Sir,
     
    this is the current SPI clock setting if i'm changing the primary bit from 0b10 to 0b11 and secondary bit 0b010 to bit 0b110( 8mhz) then physical status register of the ENC28J60 is not able to read 
     
    SPI2CON1bits.PPRE = 0b10; //able to read the link-up status register if bit set as 0b10
    SPI2CON1bits.SPRE = 0b010; //able to read the link-up status register if bit set as 0b010


     
    There is not delay in the posting . but if i'm requesting from PC and to controller response is to late so i thought because of the SPI Clock rate so i change to maximum then i'm not able to read it
     
    post edited by ketan vadodariya - 2020/03/23 21:59:54
    #6
    Aussie Susan
    Super Member
    • Total Posts : 3686
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: ENC28J60 Physical status reading problem 2020/03/24 18:25:42 (permalink)
    0
    OK - now we need to know exactly WHICH PIC18 you are using as some may have restrictions on the SPI clock speed.
    Also we need to see how the oscillator is set up. For that, can you tell us the frequency of the crystal (or external clock or whatever) and the config settings.
    Susan
    #7
    ketan vadodariya
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2019/07/04 04:30:36
    • Location: 0
    • Status: offline
    Re: ENC28J60 Physical status reading problem 2020/03/24 23:11:56 (permalink)
    0
    Dear Sir,
     
    I'm not using PIC18 Controller but i'm using TCP/IP Lite-weight stack which is i think developed for the PIC18 Series
     
    here i shared system configuration for the PIC24FJ128GA310 Controller. i'm using external 8mhz crystal with PLL so clock frequency will be the 32Mhz and peripheral clock frequency is 16Mhz
     

    // PIC24FJ128GA310 Configuration Bit Settings
    #ifdef OSCIOFCN_OFF
    #pragma config OSCIOFCN=OFF
    #else
    #pragma config OSCIOFNC = OFF
    #endif
    //
    //// CONFIG4
    //#pragma config DSWDTPS = DSWDTPS1F // Deep Sleep Watchdog Timer Postscale Select bits (1:68719476736 (25.7 Days))
    //#pragma config DSWDTOSC = LPRC // DSWDT Reference Clock Select (DSWDT uses LPRC as reference clock)
    //#pragma config DSBOREN = ON // Deep Sleep BOR Enable bit (DSBOR Enabled)
    //#pragma config DSWDTEN = OFF // Deep Sleep Watchdog Timer Enable (DSWDT Enabled)
    //#pragma config DSSWEN = ON // DSEN Bit Enable (Deep Sleep is controlled by the register bit DSEN)
    #pragma config DSWDTPS = DSWDTPS1F // Deep Sleep Watchdog Timer Postscale Select bits (1:68719476736 (25.7 Days))
    #pragma config DSWDTOSC = LPRC // DSWDT Reference Clock Select (DSWDT uses LPRC as reference clock)
    #pragma config DSBOREN = ON // Deep Sleep BOR Enable bit (DSBOR Enabled)
    #pragma config DSWDTEN = ON // Deep Sleep Watchdog Timer Enable (DSWDT Enabled)
    #pragma config DSSWEN = ON // DSEN Bit Enable (Deep Sleep is controlled by the register bit DSEN)
    // CONFIG3
    #pragma config WPFP = WPFP127 // Write Protection Flash Page Segment Boundary (Page 127 (0x1FC00))
    #pragma config VBTBOR = ON // VBAT BOR enable bit (VBAT BOR enabled)
    #pragma config SOSCSEL = ON // SOSC Selection bits (SOSC circuit selected)
    #pragma config WDTWIN = PS75_0 // Watch Dog Timer Window Width (Watch Dog Timer Window Width is 25 percent)
    #pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset Enable)
    #pragma config WPDIS = WPDIS // Segment Write Protection Disable (Disabled)
    #pragma config WPCFG = WPCFGDIS // Write Protect Configuration Page Select (Disabled)
    #pragma config WPEND = WPENDMEM // Segment Write Protection End Page Select (Write Protect from WPFP to the last page of memory)
    // CONFIG2
    #pragma config POSCMD = XT // Primary Oscillator Select (XT Oscillator Enabled)
    #pragma config BOREN1 = EN // BOR Override bit (BOR Enabled [When BOREN=1])
    #pragma config IOL1WAY = ON // IOLOCK One-Way Set Enable bit (Once set, the IOLOCK bit cannot be cleared)
    #pragma config FCKSM = CSECME // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Clock switching and Fail-Safe Clock Monitor are disabled)
    #pragma config FNOSC = PRI // Initial Oscillator Select (Primary Oscillator (XT, HS, EC))
    #pragma config ALTVREF = DLT_AV_DLT_CV // Alternate VREF/CVREF Pins Selection bit (Voltage reference input, ADC =RA9/RA10 Comparator =RA9,RA10)
    #pragma config IESO = ON // Internal External Switchover (Enabled)
    // CONFIG1
    #pragma config WDTPS = PS1024 // Watchdog Timer Postscaler Select (1:32,768)
    #pragma config FWPSA = PR128 // WDT Prescaler Ratio Select (1:128)
    #pragma config FWDTEN = WDT_ACT // Watchdog Timer Enable (WDT enabled in hardware
    #pragma config WINDIS = OFF // Windowed WDT Disable (Standard Watchdog Timer)
    #pragma config ICS = PGx2 // Emulator Pin Placement Select bits (Emulator functions are shared with PGEC2/PGED2)
    #pragma config LPCFG = OFF // Low power regulator control (Disabled)
    #pragma config GWRP = OFF // General Segment Write Protect (Disabled)
    #pragma config GCP = OFF // General Segment Code Protect (Code protection is disabled)
    #pragma config JTAGEN = OFF // JTAG Port Enable (Disabled)

    void SYSTEMS_Clock(void)
    {
    OSCTUN = 0b000000;
    RCONbits.SWDTEN = 0; // Disable Watch Dog Timer

    // Clock switch to incorporate PLL
    __builtin_write_OSCCONH(0x03);
    __builtin_write_OSCCONL(OSCCON | 0x01);
    while (OSCCONbits.COSC!= 0b011);
    while (OSCCONbits.LOCK!= 1);
    SOSC_Configuration();

    }

    #8
    crennolet
    Super Member
    • Total Posts : 166
    • Reward points : 0
    • Joined: 2012/03/15 09:51:58
    • Location: 0
    • Status: offline
    Re: ENC28J60 Physical status reading problem 2020/03/25 07:21:13 (permalink)
    +1 (3)
    You have: 
    FWDTEN = WDT_ACT
    and then:
    RCONbits.SWDTEN = 0; // Disable Watch Dog Timer
    I'm not familiar with all the pic24 series chips, but my datasheets typically say that, if the watchdog timer is enabled, the state of the software enable doesn't matter. 
     
     
    #9
    ketan vadodariya
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2019/07/04 04:30:36
    • Location: 0
    • Status: offline
    Re: ENC28J60 Physical status reading problem 2020/03/25 23:37:31 (permalink)
    0
    Dear Sir,
     
    That is not causing the problem of the reset 
     
    This is the about the ENC28j60 reading problem of the physical stataus register 
    #10
    crennolet
    Super Member
    • Total Posts : 166
    • Reward points : 0
    • Joined: 2012/03/15 09:51:58
    • Location: 0
    • Status: offline
    Re: ENC28J60 Physical status reading problem 2020/03/26 17:18:25 (permalink)
    +1 (3)
    Ketan,
     
    The data sheet for the device you say you are using says that, with your configuration, the SWDTEN bit has no effect. And with the pre and post scaler settings, watchdog timer resets will occur at 4.2 second intervals.
     
    Speaking as an *old* programmer, when things get weird and you can't figure out why things aren't working, it's time to start looking at places you don't think could be causing the problem.
    #11
    Jump to:
    © 2020 APG vNext Commercial Version 4.5