AM2634-Q1: Ethercat Slave controller thorugh SPI

Part Number: AM2634-Q1
Other Parts Discussed in Thread: AM2634,

Tool/software:

Dear Team,

We are using AM2634-Q1 Processor for one of the Safety application with Ethercat Communication as a slave configuration and Microchip LAN9252 as the ethercat slave controller. We have interfaced the LAN9252 through SPI communication to AM2634 processor. We could see in example, the Ethercat is been implemented over Ethernet interface. Is there any similar example available to interface Ethercat Slave controller through SPI.

Regards,

Arjun D

Director - Technology

ELDAPS Technology Solutions Pvt Ltd.

  • Hi Arjun.,

    We currently only have support for EtherCAT Subdevice over Ethernet. Do you mean ethercat frames are transmitted over SPI interface?

  • Hi Nilabh Anand,

    The AM2634 processor is interfaced to LAN9252 Ethercat device Controller IC over SPI interface. We are trying to communicate the IC over SPI.

    So we are trying to explore any reference been implemented from TI Host Controller for Ethercat Slave configuration through SPI interface.

    Let us know if any reference guide we have to implement Ethercat Slave over SPI interface

    Regards,

    Arjun D

    Director - Technology

    ELDAPS Technology Solutions Pvt Ltd.

  • Hi Arjun,

    Thanks I understood the question now.

    Unfortunately, We do not have the Ethercat Slave configuration through SPI interface reference. May I know why are you using the offchip ethercat interface when AM263x has a inbuilt EtherCAT interface available through the PRU ICSS interface. You can get more details here:

    EtherCAT (ti.com)

  • Hi Nilabh Anand,

    The LAN 9252 chip selected has 2/3 port with integrated PHY in a single chip. Is there any advantage using the inbuilt EtherCAT interface available in AM263x processor than SPI based LAN 9252 chip? Also we would like to use this for one safety application where Free-RTOS based application cannot used. If there is availability of any Ethercat Slave application with No-RTOS or Safety RTOS example from TI? We would like to reduce our development time.

    Regards,

    Arjun D

    Director - Technology

    ELDAPS Technology Solutions Pvt Ltd.

  • Is there any advantage using the inbuilt EtherCAT interface available in AM263x processor

    The advantage is you get cycle time as low as 31.25us and the cost of Ethercat slave controller is not additional and freedom to choose the PHY device.

    Also we would like to use this for one safety application where Free-RTOS based application cannot used. If there is availability of any Ethercat Slave application with No-RTOS or Safety RTOS example from TI? We would like to reduce our development time.

    For the EtherCAT driver and stack is already OS agnostic, you will need to go with modifying the application to NO-RTOS. But in my understanding for safety with EtherCAT you can use FSoE protocol at application level, I will need more details on the use case is it automotive that you are planning to use safe RTOS.

    I will try to loop in our safety expert also to see how we can help you here.

  • Hi Nilabh Anand,

    Thanks for your support...!

    We could able to complete our demonstration with our customer regarding the Ethercat Communication with LP-AM263x Eval kit using the example application given by TI as the base code. We developed our application where we would like to send and receive 160 Bytes of data respectively and the data shall be communicated to and fro to other control cards in CAN bus which is connected to Eval kit. We could able to achieve that and demonstrated successfully.

    Since the end application shall be in Railways, the Hardware and software shall be subjected to safety principles and get it certified. Since now we demonstrated with Free-RTOS which will not be acceptable by our end customer.

    I know you have mentioned already that you have no plans to implement the same in Bare metal with No-RTOS. We request you to provide some samples or some hints to implement the same with bare metal regarding Ethercat.

    Regards,

    Arjun D

    Director - Technology

    ELDAPS Technology Solutions Pvt Ltd.

  • We could able to complete our demonstration with our customer regarding the Ethercat Communication with LP-AM263x Eval kit using the example application given by TI as the base code.

    Hi Arjun, Glad to know this.

    We developed our application where we would like to send and receive 160 Bytes of data respectively and the data shall be communicated to and fro to other control cards in CAN bus which is connected to Eval kit. We could able to achieve that and demonstrated successfully.

    I want to understand this better, So you are sending data via CAN to AM263x which is further transported via EtherCAT.If possible could you please share a block diagram.

    Since the end application shall be in Railways, the Hardware and software shall be subjected to safety principles and get it certified. Since now we demonstrated with Free-RTOS which will not be acceptable by our end customer.

    What is the SIL requirement here?

    I know you have mentioned already that you have no plans to implement the same in Bare metal with No-RTOS. We request you to provide some samples or some hints to implement the same with bare metal regarding Ethercat.

    The EtherCAT stack is NO-RTOS based so changes needed here will be in the application code,

    1. Take a no-rtos example where instead of having the tasks for below functions you will need to remove the tasks and replace it with suitable bare metal code. Then periodically call these while in the main while(1)  loop. 

    https://e2e.ti.com/resized-image/__size/320x240/__key/communityserver-components-multipleuploadfilemanager/4224bbea_2D00_0b78_2D00_4ef6_2D00_b18a_2D00_41cfe5d0c7a0-500225-complete/pastedimage1727865345728v1.png

  • Dear Nilabh Anand,

    Please find the brief block diagram. The SIL-requirement is Level-3. Thanks for your hints and suggestions on Bare metal, We will try in application and let you know ASAP. 

    Regards,

    Arjun D

    Director - Technology

    ELDAPS Technology Solutions Pvt Ltd.

  • Hi Arjun thanks for the block diagram, I had attached a list of all the freertos based tasks. But looks like the image was corrupted somehow, I am attaching the same for your reference

  • TaskP_Object task1Object;               // ECAT mainloop
    #ifdef ENABLE_PDI_TASK
    TaskP_Object pdiTaskObject;             // ECAT sw ISR
    #endif
    TaskP_Object ledTaskObject;             // LED Control Task
    #ifdef ENABLE_SYNC_TASK
    TaskP_Object sync0TaskObject;           // ECAT SYNC0 ISR
    TaskP_Object sync1TaskObject;           // ECAT SYNC1 ISR
    #endif

    These are the tasks that you need be implemented in a BareMetal environment.

    The reference to these are in folder: examples\industrial_comms\ethercat_slave_beckhoff_ssc_demo\tiescutils.c

  • Dear Nilabh Anand,

    As mentioned in the previous thread, we are using SPI based Ethercat Controller chip LAN9252 as per our customer needs. We have received the Drivers to communicate through SPI for their Microchip based dsPIC33 Microcontroller. Attaching the LAN 9252 HW Abtraction layer code and SPI Driver code for the same.

    We would like to interface the same chip with our AM2634 Processor. If you see in the attached code, 9252 Abtraction layer shall be kept same and some modifications required in SPI driver code in terms of AM2634 SPI Read & Write functions to replace dsPIC33 Microcontroller.

    We used the below function to port SPI read and SPI write function for AM2634. But we could not able to read the exact data required.

    /* Load the MCSPI_TX register with the data to be transmitted */
    CSL_REG32_WR(SPIbaseAddr + MCSPI_CHTX(SPIchNum), data);

    /* Return the data present in the MCSPI_RX register. */
    return (CSL_REG32_RD(SPIbaseAddr + MCSPI_CHRX(SPIchNum)));

    Before doing this we modified mcspi_loopback example to communicate to LAN9252. It was working as expected and the data has been read from chip. But if we want to port whole application using HLD functions used in the example, we have to rewrite the SPI driver code as attached. We request, is there any function available only to read a byte and write a byte of SPI data so that we can replace in SPI Driver code attached which has all the data formatting and Ethercat core related code. Otherwise we need to make lot of modifications as per the example provided with HLD.

    /*******************************************************************************
     PIC32 SPI Interface Driver
    
      Company:
        Microchip Technology Inc.
    
      File Name:
        SPIDriver.c
    
      Summary:
        Contains the functional implementation of dsPIC33 SPI Interface Driver
    
      Description:
        This file contains the functional implementation of dsPIC33 SPI Interface Driver
    	
      Change History:
        Version		Changes
    	0.1			Initial version.
    	0.2			-
    	0.3			-	
    	0.4 		-
    *******************************************************************************/
    
    /*******************************************************************************
    Copyright (c) 2017 released Microchip Technology Inc.  All rights reserved.
    
    Microchip licenses to you the right to use, modify, copy and distribute
    Software only when embedded on a Microchip microcontroller or digital signal
    controller that is integrated into your product or third party product
    (pursuant to the sublicense terms in the accompanying license agreement).
    
    You should refer to the license agreement accompanying this Software for
    additional information regarding your rights and obligations.
    
    SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
    EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
    MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
    IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
    CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
    OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
    INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
    CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
    SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
    (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
     *******************************************************************************/
     
    #include "9252_HW.h"
    #include "SPIDriver.h"
    
    #define ADDRESS_AUTO_INCREMENT 0x4000
    
    /*******************************************************************************
      Function:
    	UINT32 SPIReadDWord (UINT16 Address, UINT8 *ReadBuffer)
      Summary:
        This function reads the LAN9252 CSR registers.        
      
    *****************************************************************************/
    void SPIReadDWord (UINT16 Address, UINT8 *ReadBuffer)
    {
       //Assert CS line
        CSLOW();
     
        //Write Command
        SPIWriteByte(CMD_FAST_READ);
        //Write Address
        SPISendAddr(Address);
          
        //Dummy Byte
        SPIWriteByte(CMD_FAST_READ_DUMMY);
        //Read Bytes
        *(ReadBuffer + 0) = SPIReadByte();
        *(ReadBuffer + 1) = SPIReadByte();
        *(ReadBuffer + 2) = SPIReadByte();
        *(ReadBuffer + 3) = SPIReadByte();
        
        //De-Assert CS line
        CSHIGH();
    }
    
    /*******************************************************************************
      Function:
    	void SPISendAddr (UINT16 Address)
      Summary:
        This function write address to SPI data bus.        
      
    *****************************************************************************/
    void SPISendAddr (UINT16 Address)
    {
        //Write Address
        SPIWriteByte((UINT8)((Address & 0xFF00) >> 8));
        SPIWriteByte((UINT8)(Address & 0xFF));
    }
    
    /*******************************************************************************
      Function:
    	void SPIReadBurstMode (UINT8 *ReadBuffer)
      Summary:
        This function read 4 bytes continuosly.        
      
    *****************************************************************************/
    void SPIReadBurstMode (UINT8 *ReadBuffer)
    {
        //Read Bytes
        *ReadBuffer = SPIReadByte();
        *(ReadBuffer + 1) = SPIReadByte();
        *(ReadBuffer + 2) = SPIReadByte();
        *(ReadBuffer + 3) = SPIReadByte();
    }
    
    /*******************************************************************************
      Function:
    	void SPIWriteBurstMode (void const *Val)
      Summary:
        This function writes 4 bytes continuosly.        
      
    *****************************************************************************/
    void SPIWriteBurstMode (UINT8 const *Val)
    {   
        //Write Bytes
        SPIWriteByte(*Val); 
        SPIWriteByte(*(Val + 1)); 
        SPIWriteByte(*(Val + 2));
        SPIWriteByte(*(Val + 3));
    }
    
    
    /*******************************************************************************
      Function:
    	void SPIWriteBytes(UINT16 Address, UINT8 const *Val, UINT8 nLength)
      Summary:
        This function writes the LAN9252 CSR registers.        
      
    *****************************************************************************/
    void SPIWriteBytes(UINT16 Address, UINT8 const *Val, UINT16 nLength)
    {
        //Assert CS line
        CSLOW();
        //Write Command
        SPIWriteByte(CMD_SERIAL_WRITE);
        //Write Address
        SPISendAddr(Address | ADDRESS_AUTO_INCREMENT);
     
        //Write Bytes
        while(nLength--)
        {
         	SPIWriteByte(*(Val++));
        }
            
        //De-Assert CS line
        CSHIGH();
    }
    
    /*******************************************************************************
      Function:
    	void SPIWriteDWord (UINT16 Address, UINT32 Val)
      Summary:
        This function writes the LAN9252 CSR registers.        
      
    *****************************************************************************/
    void SPIWriteDWord (UINT16 Address, UINT8 const *Val)
    {
        //Assert CS line
        CSLOW();
        //Write Command
        SPIWriteByte(CMD_SERIAL_WRITE);
        //Write Address
        SPISendAddr(Address); 
        //Write Bytes
        SPIWriteByte(*Val);
        SPIWriteByte(*(Val + 1));
        SPIWriteByte(*(Val + 2));
        SPIWriteByte(*(Val + 3));
    
        //De-Assert CS line
        CSHIGH();
    }
    
    /*******************************************************************************
      Function:
       void SPIReadRegUsingCSR(UINT8 *ReadBuffer, UINT16 Address, UINT8 Count)
      Summary:
        This function reads the EtherCAT core registers using LAN9252 CSR registers.        
      
    *****************************************************************************/
    void SPIReadRegUsingCSR(UINT8 *ReadBuffer, UINT16 Address, UINT16 Count)
    {
        UINT8 u8Buffer[4] = {0};
     
        u8Buffer[0] = (UINT8)(Address & 0x00FF);
        u8Buffer[1] = (UINT8)((Address & 0xFF00) >> 8);
        u8Buffer[2] = (UINT8) Count;
        u8Buffer[3] = ESC_READ_BYTE;
    
        SPIWriteDWord (ESC_CSR_CMD_REG, &u8Buffer[0]);
    #if 0
        do
        {
           SPIReadDWord (ESC_CSR_CMD_REG, &u8Buffer[0]);
    		
        }while(u8Buffer[3] & ESC_CSR_BUSY);
    #endif
        
        DELAY_1US();
        
        SPIReadDWord (ESC_CSR_DATA_REG, ReadBuffer);
        
           
        return;
    }
    
    /*******************************************************************************
      Function:
       void SPIWriteRegUsingCSR( UINT8 *WriteBuffer, UINT16 Address)
      Summary:
        This function writes the EtherCAT core registers using LAN9252 CSR registers.        
      
    *****************************************************************************/
    void SPIWriteRegUsingCSR( UINT8 *WriteBuffer, UINT16 Address)
    {
        UINT8 u8Buffer[4] = {0};
          
    
        SPIWriteDWord (ESC_CSR_DATA_REG, WriteBuffer);
        
        u8Buffer[0] = (UINT8)(Address & 0x00FF);
        u8Buffer[1] = (UINT8)((Address & 0xFF00) >> 8);
        u8Buffer[2] = 4;
        u8Buffer[3] = ESC_WRITE_BYTE;
    
        SPIWriteDWord (ESC_CSR_CMD_REG, &u8Buffer[0]);
        DELAY_1US();
    #if 0
        do
        {
            SPIReadDWord (ESC_CSR_CMD_REG, &u8Buffer[0]);
    
        }while(u8Buffer[3] & ESC_CSR_BUSY);
    #endif
    
        return;
    }
    
    
    /*******************************************************************************
      Function:
       void SPIReadPDRamRegister(UINT8 *ReadBuffer, UINT16 Address, UINT16 Count)
      Summary:
        This function reads the PDRAM using LAN9252 FIFO.        
      
    *****************************************************************************/
    void SPIReadPDRamRegister(UINT8 *ReadBuffer, UINT16 Address, UINT16 Count)
    {
        UINT8 u8Buffer[4] = {0};
        UINT16 u16Buffer[4] = {0};
        UINT16 i, nlength, nBitPosition, act_read_bytes;//nReadSpaceAvblCount
    
         /*Reset or Abort any previous commands.*/
        u16Buffer[1] = PRAM_RW_ABORT_MASK;                                                
        SPIWriteDWord (PRAM_READ_CMD_REG, (UINT8*)&u16Buffer[0]);
        
        /*Write Address and Length Register (PRAM_READ_ADDR_LEN) with the
        starting UINT8 address and length) and Set PRAM Read Busy (PRAM_READ_BUSY) bit(-EtherCAT Process RAM Read Command Register)
        to start read operation*/
        u16Buffer[0] = Address;
        u16Buffer[1] = Count;	
        u16Buffer[2] = 0x0;
        u16Buffer[3] = 0x8000;
        SPIWriteBytes (PRAM_READ_CMD_REG, (UINT8*)&u16Buffer[0],8);
        /*Read PRAM Read Data Available (PRAM_READ_AVAIL) bit is set*/
        do
        {
            SPIReadDWord (PRAM_READ_CMD_REG,(UINT8 *)&u8Buffer[0]);
        }while(!(u8Buffer[0] & IS_PRAM_SPACE_AVBL_MASK));
    
        //nReadSpaceAvblCount = u8Buffer[1] & (PRAM_SPACE_AVBL_COUNT_MASK>>8);
    
        /*Fifo registers are aliased address. In indexed it will read indexed data reg 0x04, but it will point to reg 0
         In other modes read 0x04 FIFO register since all registers are aliased*/
    
    
        //Lets do it in auto increment mode
        CSLOW();
    
        //Write Command
        SPIWriteByte(CMD_FAST_READ);
    
        SPISendAddr(PRAM_READ_FIFO_REG);
        
        //Dummy Byte
        SPIWriteByte(CMD_FAST_READ_DUMMY);
    
        nBitPosition = (Address & 0x03);
        act_read_bytes = 4 - nBitPosition;
        nlength = Count > act_read_bytes ? act_read_bytes : Count;
        
        
        SPIReadBurstMode ((UINT8*)&u8Buffer[0]);
            
        memcpy(ReadBuffer ,&u8Buffer[nBitPosition], nlength);
        i = nlength;
        Count -= nlength;
        
        while(Count)
        {
        	DELAY_1US();
    	
    	
            SPIReadBurstMode ((UINT8*)&u8Buffer[0]);
            nlength = Count > 4 ? 4 : Count;
            memcpy((ReadBuffer+i) ,&u8Buffer[0], nlength);
    
        
            i += nlength;
            Count -= nlength;
        }
    
        CSHIGH();
    
        return;
    }
            
         
    /*******************************************************************************
      Function:
       void SPIWritePDRamRegister(UINT8 *WriteBuffer, UINT16 Address, UINT16 Count)
      Summary:
        This function writes the PDRAM using LAN9252 FIFO.        
      
    *****************************************************************************/
    void SPIWritePDRamRegister(UINT8 const *WriteBuffer, UINT16 Address, UINT16 Count)
    {
        UINT16 u16Buffer[4] = {0};
        UINT16 i,nlength, nBytePosition ; //nWrtSpcAvlCount;
    
        /*Reset or Abort any previous commands.*/
        u16Buffer[1] = PRAM_RW_ABORT_MASK;                                                
    
        SPIWriteDWord (PRAM_WRITE_CMD_REG, (UINT8*)&u16Buffer[0]);
    
        /*Make sure there is no previous write is pending
        (PRAM Write Busy) bit is a 0 */
        do
        {
           SPIReadDWord (PRAM_WRITE_CMD_REG, (UINT8*)&u16Buffer[0]);
    
        }while((u16Buffer[1] & PRAM_RW_BUSY_16B));
    
        /*Write Address and Length Register (ECAT_PRAM_WR_ADDR_LEN) with the
        starting UINT8 address and length) and write to the EtherCAT Process RAM Write Command Register (ECAT_PRAM_WR_CMD) with the  PRAM Write Busy
        (PRAM_WRITE_BUSY) bit set*/
        u16Buffer[0] = Address;
        u16Buffer[1] = Count;
        u16Buffer[2] = 0x0;
        u16Buffer[3] = 0x8000;
        
       SPIWriteBytes (PRAM_WRITE_ADDR_LEN_REG, (UINT8*)&u16Buffer[0],8);
    
       /*Read PRAM write Data Available (PRAM_READ_AVAIL) bit is set*/
        do
        {
           SPIReadDWord (PRAM_WRITE_CMD_REG,(UINT8*)&u16Buffer[0]);
    
        }while(!(u16Buffer[0] & IS_PRAM_SPACE_AVBL_MASK));
    
        /*Write data to Write FIFO) */ 
        /*get the byte lenth for first read*/
        nBytePosition = (Address & 0x03);
        
        //4-nBytePosition - is the actual data read
        nlength = ((4-nBytePosition) > Count) ? Count:(4-nBytePosition);
    
        memset(&u16Buffer[0],0x00,4);
        memcpy(&u16Buffer[nBytePosition>>1],WriteBuffer, nlength);
    
        //Auto increment mode
        CSLOW();
    
        //Write Command
        SPIWriteByte(CMD_SERIAL_WRITE);
    
        SPISendAddr(PRAM_WRITE_FIFO_REG);
        
        //Write Bytes
        SPIWriteBurstMode((UINT8*)&u16Buffer[0]);
            
        Count-=nlength;
        i=nlength;
    
        while(Count)
        {
    		DELAY_1US();
            nlength = Count > 4 ? 4 : Count;
            memset(&u16Buffer[0],0x00,4);
            memcpy(&u16Buffer[0], (WriteBuffer+i), nlength);
            
            /*Read PRAM write Data Available (PRAM_READ_AVAIL) bit is set*/
    	    SPIWriteBurstMode ((UINT8*)&u16Buffer[0]);
            i+=nlength;
            Count-=nlength;
        }
    
        CSHIGH();
        return;
    }
    
    /*******************************************************************************
      Function:
       void PDIReadReg(UINT8 *ReadBuffer, UINT16 Address, UINT16 Count)
      Summary:
        This function reads the ESC registers using LAN9252 CSR or FIFO.         
      
    *****************************************************************************/
    void PDIReadReg(UINT8 *ReadBuffer, UINT16 Address, UINT16 Count)
    {
        if (Address >= 0x1000)
        {
            SPIReadPDRamRegister(ReadBuffer, Address,Count);
        }
        else
        {
            SPIReadRegUsingCSR(ReadBuffer, Address, Count);
        }
    }
    
    /*******************************************************************************
      Function:
       void PDIWriteReg( UINT8 const *WriteBuffer, UINT16 Address, UINT16 Count)
      Summary:
        This function writes the ESC registers using LAN9252 CSR or FIFO.        
      
    *****************************************************************************/
    void PDIWriteReg( UINT8 const *WriteBuffer, UINT16 Address, UINT16 Count)
    {
       
       if (Address >= 0x1000)
       {
    	SPIWritePDRamRegister(WriteBuffer, Address,Count);
       }
       else
       {
    	SPIWriteRegUsingCSR(WriteBuffer, Address);
       }
        
    }
    
    /*******************************************************************************
      Function:
    	UINT32 PDIReadLAN9252DirectReg( UINT16 Address)
      Summary:
        This function reads the LAN9252 CSR registers(Not ESC registers).        
      
    *****************************************************************************/
    void PDIReadLAN9252DirectReg( UINT16 Address, UINT8 *data)
    {   
        SPIReadDWord (Address, data);
     }
    
    /*******************************************************************************
      Function:
    	void PDIWriteLAN9252DirectReg( UINT32 Val, UINT16 Address)
      Summary:
        This function writes the LAN9252 CSR registers(Not ESC registers).        
      
    *****************************************************************************/
    void PDIWriteLAN9252DirectReg( UINT32 Val, UINT16 Address)
    {
        SPIWriteDWord (Address, (UINT8*)&Val);
    }
    
    /*******************************************************************************
      Function:
    	void PDI_Init()
      Summary:
        This function initialize the PDI(SPI).        
      
    *****************************************************************************/
    void PDI_Init()
    {
    	/* Initialise SPI Communication */
    	SPI0_Initialize();
    }
    
    void CSLOW()
    {
    	/* Chip Enable signal Activate */
    	SPI0_CSEnable();
    }
    
    void CSHIGH()
    {
    	/* Chip Enable signal Deactivate */
    	SPI0_CSDisable();
    }
    
    
    inline void SPIPut(UINT8 data)
    {
    	/* Send data byte through SPI */
    	SPI0_TXData(data);
    }
    
    inline UINT8 SPIGet()
    {
    	/* Read data byte through SPI */
    	return SPI0_RXData();
    }
    
    /*******************************************************************************
      Function:
       void SPIWrite(UINT8 data)
      Summary:
        This function write one byte.
    
      Description:
        This function write one byte.
    
    *****************************************************************************/
    inline void SPIWriteByte(UINT8 data)
    {
        SPIPut(data);
        SPIGet();
    }
    /*******************************************************************************
      Function:
       void SPIRead(void)
      Summary:
        This function read one byte.
    
      Description:
        This function read one byte.
    
    *****************************************************************************/
    inline UINT8 SPIReadByte()
    {
        SPIPut(0);
        return ((UINT8)SPIGet());
     }
    
    /*******************************************************************************
      Function:
       void SPIOpen(void)
      Summary:
        This function configures the SPI module of SOC.
    
      Description:
        This function configures the SPI module of SOC.
    
    *****************************************************************************/
    
    void DELAY_1US()
    {
    	ClockP_usleep(1);
    }
    
    
    
    /*******************************************************************************
     LAN9252 Hardware Abtraction Layer - Implementation file
    
      Company:
        Microchip Technology Inc.
    
      File Name:
        9252_HW.c
    
      Description:
        This file  cContains the functional implementation of LAN9252 Hardware Abtraction Layer
    	
      Change History:
        Version		Changes
    	0.1			Initial version.
    	0.2			-
    	0.3			-
    	0.4			*Disabled Sync Manager & Application Layer Event Requests.
    				*Commented out the ISR call backs related to Sync Manager & AL Event Request.
    	1.0			*Enabled Sync Manager & Application Layer Event Requests.
    				*Added ISR call backs related to Sync Manager & AL Event Request.
      	1.1			*Cleanup the code
    	1.3			*Re-arranged the functions.
    				*SOC specific functions moved to corresponding PDI files.
    				*Eg: ISR routine, SPI/PMP is renamed to PDI.
    *******************************************************************************/
    
    /*******************************************************************************
    Copyright (c) 2015 released Microchip Technology Inc.  All rights reserved.
    
    Microchip licenses to you the right to use, modify, copy and distribute
    Software only when embedded on a Microchip microcontroller or digital signal
    controller that is integrated into your product or third party product
    (pursuant to the sublicense terms in the accompanying license agreement).
    
    You should refer to the license agreement accompanying this Software for
    additional information regarding your rights and obligations.
    
    SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
    EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
    MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
    IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
    CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
    OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
    INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
    CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
    SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
    (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
     *******************************************************************************/
    
    ///////////////////////////////////////////////////////////////////////////////
    // Included files
    #include "ecat_def.h"
    #include "ecatslv.h"
    
    #define  _9252_HW_ 1
    #include "9252_HW.h"
    
    #undef    _9252_HW_
    
    #include "ecatappl.h"
    
    
    ///////////////////////////////////////////////////////////////////////////////
    // Internal Type Defines
    
    
    ///////////////////////////////////////////////////////////////////////////////
    // Internal Variables
    
    volatile    UINT32 restore_intsts;
    
    ///////////////////////////////////////////////////////////////////////////////
    // Internal functions
    ///////////////////////////////////////////////////////////////////////////////
    // Exported HW Access functions
    
    
    /*******************************************************************************
      Function:
        UINT8 HW_Init(void)
    
      Summary:
        This function intialize the Process Data Interface (PDI) and the host controller.
    
      Description:
        
      *****************************************************************************/
    #define LAN9252_BYTE_ORDER_REG          0x64
    #define LAN9252_CSR_INT_CONF            0x54
    #define LAN9252_CSR_INT_EN              0x5C
    #define LAN9252_CSR_INT_STS             0x58
    
    /*******************************************************************************
      Function:
        void LAN9252_Init(void)
    
      Summary:
        This function initializes LAN9252.
    
      Description:
      *****************************************************************************/
      
    void LAN9252_Init(void)
    {
    
        UINT16 intMask;
        UINT32 data;
        
        //Read BYTE-ORDER register 0x64.
        do
        {
            PDIReadLAN9252DirectReg( LAN9252_BYTE_ORDER_REG, (UINT8 *)&data);
         }while(0x87654321 != data);
        
         
        do
        {
            intMask = 0x93;
            HW_EscWriteDWord(intMask, ESC_AL_EVENTMASK_OFFSET);
           
            intMask = 0;
            HW_EscReadDWord(intMask, ESC_AL_EVENTMASK_OFFSET);
        } while (intMask != 0x93);
    
       
        intMask = 0;
        HW_EscWriteDWord(intMask, ESC_AL_EVENTMASK_OFFSET);
            
        //IRQ enable,IRQ polarity, IRQ buffer type in Interrupt Configuration register.
        //Write 0x54 - 0x00000101
        data = 0x00000101;
        PDIWriteLAN9252DirectReg(data, LAN9252_CSR_INT_CONF);
        
        //Write in Interrupt Enable register -->
        //Write 0x5c - 0x00000001
        data = 0x00000001;
        PDIWriteLAN9252DirectReg(data, LAN9252_CSR_INT_EN);
    
    
        //Read Interrupt Status register
        PDIReadLAN9252DirectReg(LAN9252_CSR_INT_STS,(UINT8 *)&data);
    
    
    #ifdef DC_SUPPORTED
        PDI_Init_SYNC_Interrupts();
    #endif
    
        PDI_Timer_Interrupt();    
        PDI_IRQ_Interrupt();
        
        /* enable all interrupts */
        PDI_Enable_Global_interrupt();
       
        return;
    
    }
    
    
    /*******************************************************************************
      Function:
        void HW_Release(void)
    
      Summary:
        This function shall be implemented if hardware resources need to be release
            when the sample application stops
    
      Description:
      *****************************************************************************/
    
    void HW_Release(void)
    {
    
    }
    
    
    /*******************************************************************************
      Function:
        UINT16 HW_GetALEventRegister(void)
    
      Summary:
        This function gets the current content of ALEvent register.
    
      Description:
        Returns first two Bytes of ALEvent register (0x220)
      *****************************************************************************/
    
    UINT16 HW_GetALEventRegister(void)
    {
        UINT32 EscALEvent = 0;
        HW_EscRead((MEM_ADDR *)&EscALEvent, 0x220, 4);
        return (UINT16)(EscALEvent & 0xffff);
    }
    
    
    /*******************************************************************************
      Function:
        UINT16 HW_GetALEventRegister_Isr(void)
    
      Summary:
        The SPI PDI requires an extra ESC read access functions from interrupts service routines.
            The behaviour is equal to "HW_GetALEventRegister()"
    
      Description:
        Returns  first two Bytes of ALEvent register (0x220)
      *****************************************************************************/
      
    UINT16 HW_GetALEventRegister_Isr(void)
    {
        UINT32 EscALEvent = 0;
        HW_EscReadIsr((MEM_ADDR *)&EscALEvent, 0x220, 4);
        return EscALEvent;
    }
    
    /*******************************************************************************
      Function:
        void HW_EscRead( MEM_ADDR *pData, UINT16 Address, UINT16 Len )
    
      Summary:
        This function operates the SPI read access to the EtherCAT ASIC.
    
      Description:
        Input param:
         pData    - Pointer to a byte array which holds data to write or saves read data.
         Address  - EtherCAT ASIC address ( upper limit is 0x1FFF )    for access.
         Len      - Access size in Bytes.
      *****************************************************************************/
    
    void HW_EscRead( MEM_ADDR *pData, UINT16 Address, UINT16 Len )
    {
        volatile UINT32 int_status;
        UINT16 i;
        UINT8 *pTmpData = (UINT8 *)pData;
    
      
        /* loop for all bytes to be read */
        while ( Len > 0 )
        {
            if (Address >= MIN_PD_READ_ADDRESS)
            {
                i = Len;
            }
            else
            {
                i= (Len > 4) ? 4 : Len;
    
                if(Address & 01)
                {
                   i=1;
                }
                else if (Address & 02)
                {
                   i= (i&1) ? 1:2;
                }
                else if (i == 03)
                {
                    i=1;
                }
            }
    
            int_status = PDI_Disable_Global_Interrupt();
            PDIReadReg(pTmpData, Address, i);
            PDI_Restore_Global_Interrupt(int_status);
    
            Len -= i;
            pTmpData += i;
            Address += i;
        }
    
    }
    
    /////////////////////////////////////////////////////////////////////////////////////////
    /**
     \param pData        Pointer to a byte array which holds data to write or saves read data.
     \param Address     EtherCAT ASIC address ( upper limit is 0x1FFF )    for access.
     \param Len            Access size in Bytes.
    
    \brief  The SPI PDI requires an extra ESC read access functions from interrupts service routines.
            The behaviour is equal to "HW_EscRead()"
    *////////////////////////////////////////////////////////////////////////////////////////
    
    /*******************************************************************************
      Function:
        void HW_EscReadIsr( MEM_ADDR *pData, UINT16 Address, UINT16 Len )
    
      Summary:
        The SPI PDI requires an extra ESC read access functions from interrupts service routines.
            The behaviour is equal to "HW_EscRead()"
    
      Description:
        Input param:
        pData          - Pointer to a byte array which holds data to write or saves read data.
        param Address  - EtherCAT ASIC address ( upper limit is 0x1FFF ) for access.
        param Len      - Access size in Bytes.
      *****************************************************************************/
    
    void HW_EscReadIsr( MEM_ADDR *pData, UINT16 Address, UINT16 Len )
    {
    
       UINT16 i;
       UINT8 *pTmpData = (UINT8 *)pData;
    
        /* send the address and command to the ESC */
    
        /* loop for all bytes to be read */
       while ( Len > 0 )
       {
    
            if (Address >= MIN_PD_READ_ADDRESS)
            {
                i = Len;
            }
            else
            {
                i= (Len > 4) ? 4 : Len;
    
                if(Address & 01)
                {
                   i=1;
                }
                else if (Address & 02)
                {
                   i= (i&1) ? 1:2;
                }
                else if (i == 03)
                {
                    i=1;
                }
            }
    
            PDIReadReg(pTmpData, Address,i);
    
            Len -= i;
            pTmpData += i;
            Address += i;
        }
       
    }
    
    
    /*******************************************************************************
      Function:
        void HW_EscWrite( MEM_ADDR *pData, UINT16 Address, UINT16 Len )
    
      Summary:
        This function operates the SPI write access to the EtherCAT ASIC.
    
      Description:
        Input param:
        pData          - Pointer to a byte array which holds data to write or saves write data.
        param Address  - EtherCAT ASIC address ( upper limit is 0x1FFF ) for access.
        param Len      - Access size in Bytes.
      *****************************************************************************/
    
    void HW_EscWrite( MEM_ADDR *pData, UINT16 Address, UINT16 Len )
    {
        volatile UINT32 int_status;
        UINT16 i;
        UINT8 *pTmpData = (UINT8 *)pData;
    
        /* loop for all bytes to be written */
        while ( Len )
        {
    
            if (Address >= MIN_PD_WRITE_ADDRESS)
            {
                i = Len;
            }
            else
            {
                i= (Len > 4) ? 4 : Len;
    
                if(Address & 01)
                {
                   i=1;
                }
                else if (Address & 02)
                {
                   i= (i&1) ? 1:2;
                }
                else if (i == 03)
                {
                    i=1;
                }
            }
    
            int_status = PDI_Disable_Global_Interrupt();
              
            /* start transmission */
            PDIWriteReg(pTmpData, Address, i);
            PDI_Restore_Global_Interrupt(int_status);
    
              
            /* next address */
            Len -= i;
            pTmpData += i;
            Address += i;
    
        }
    }
    
    
    /*******************************************************************************
      Function:
        void HW_EscWriteIsr( MEM_ADDR *pData, UINT16 Address, UINT16 Len )
    
      Summary:
        The SPI PDI requires an extra ESC write access functions from interrupts service routines.
            The behaviour is equal to "HW_EscWrite()"
    
      Description:
        Input param:
        pData          - Pointer to a byte array which holds data to write or saves write data.
        param Address  - EtherCAT ASIC address ( upper limit is 0x1FFF ) for access.
        param Len      - Access size in Bytes.
      *****************************************************************************/
    
    void HW_EscWriteIsr( MEM_ADDR *pData, UINT16 Address, UINT16 Len )
    {
    
        UINT16 i ;
        UINT8 *pTmpData = (UINT8 *)pData;
    
      
        /* loop for all bytes to be written */
        while ( Len )
        {
    
            if (Address >= MIN_PD_WRITE_ADDRESS)
            {
                i = Len;
            }
            else
            {
                i= (Len > 4) ? 4 : Len;
    
                if(Address & 01)
                {
                   i=1;
                }
                else if (Address & 02)
                {
                   i= (i&1) ? 1:2;
                }
                else if (i == 03)
                {
                    i=1;
                }
            }
            
           /* start transmission */
           PDIWriteReg(pTmpData, Address, i);
           
           /* next address */
            Len -= i;
            pTmpData += i;
            Address += i;
        }
    
    }
    
    
    
    

    Regards,

    Arjun D

    Director - Technology

    ELDAPS Technology Solutions Pvt Ltd.

  • Hi Arjun,

    But if we want to port whole application using HLD functions used in the example, we have to rewrite the SPI driver code as attached. We request, is there any function available only to read a byte and write a byte of SPI data so that we can replace in SPI Driver code attached which has all the data formatting and Ethercat core related code. Otherwise we need to make lot of modifications as per the example provided with HLD.

    This is something would need to be taken care on your end.

    Still my recommendation would be to use the inbuilt ETherCAT module rather than using the external ethercat over SPI.

  • Dear Nilabh,

    Thanks for your kind support. We have updated SPI drivers with LLD functions and ported successfully.

    We are also having our road map to use inbuilt Ethercat function with TI for next version as we have proved our functionality with the Eval Kit. We are also in progress of implementing Ethercat with No-RTOS.

    Regards,

    Arjun D

    Founder & Director

    ELDAPS Technology Solutions Pvt Ltd.