xmclib/XMCLib/inc/xmc_ecat.h
2024-10-17 17:09:59 +02:00

462 lines
16 KiB
C

/**
* @file xmc_ecat.h
* @date 2015-12-27
*
* @cond
*********************************************************************************************************************
* XMClib v2.1.16 - XMC Peripheral Driver Library
*
* Copyright (c) 2015-2017, Infineon Technologies AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
* following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
* Infineon Technologies AG dave@infineon.com).
*********************************************************************************************************************
*
* Change History
* --------------
*
* 2015-12-27:
* - Initial Version<br>
*
* @endcond
*/
/**
* @addtogroup XMClib XMC Peripheral Library
* @{
*/
/**
* @addtogroup ECAT
* @brief EtherCAT Low level driver for XMC4800/XMC4300 series.
*
* EtherCAT is an Ethernet-based fieldbus system.
* The EtherCAT Slave Controller (ECAT) read the data addressed to them while the telegram passes through the device.
* An EtherCAT Slave Controller (ESC) takes care of the EtherCAT communication as an interface between the EtherCAT
* fieldbus and the slave application. EtherCAT uses standard IEEE 802.3 Ethernet frames, thus a standard network
* controller can be used and no special hardware is required on master side. EtherCAT has a reserved EtherType of
* 0x88A4 that distinguishes it from other Ethernet frames. Thus, EtherCAT can run in parallel to other Ethernet
* protocols. EtherCAT does not require the IP protocol, however it can be encapsulated in IP/UDP. The EtherCAT
* Slave Controller processes the frame in hardware. Thus, communication performance is independent from processor
* power.
*
* The XMC_ECAT low level driver provides functions to configure and initialize the ECAT hardware peripheral.
* For EHTERCAT stack integration, the necessary hardware accees layer APIs shall be explicitly implemented depending
* upon the stack provider. The XMC_ECAT lld layer provides only the hardware initialization functions for start up and
* basic functionalities.
* @{
*/
#ifndef XMC_ECAT_H
#define XMC_ECAT_H
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "xmc_common.h"
#if defined (ECAT0)
#include "xmc_ecat_map.h"
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/**********************************************************************************************************************
* ENUMS
*********************************************************************************************************************/
/**
* ECAT status return values
*/
typedef enum XMC_ECAT_STATUS
{
XMC_ECAT_STATUS_OK = 0U, /**< Driver accepted application request */
XMC_ECAT_STATUS_BUSY = 1U, /**< Driver is busy and cannot handle request */
XMC_ECAT_STATUS_ERROR = 2U /**< Driver could not fulfil application request */
} XMC_ECAT_STATUS_t;
/**
* EtherCAT event enumeration types
*/
typedef enum XMC_ECAT_EVENT
{
XMC_ECAT_EVENT_AL_CONTROL = ECAT_AL_EVENT_MASK_AL_CE_MASK_Msk, /**< Application control event mask */
XMC_ECAT_EVENT_DC_LATCH = ECAT_AL_EVENT_MASK_DC_LE_MASK_Msk, /**< Distributed Clock latch event mask */
XMC_ECAT_EVENT_DC_SYNC0 = ECAT_AL_EVENT_MASK_ST_S0_MASK_Msk, /**< State of distributed clock sync-0 event mask */
XMC_ECAT_EVENT_DC_SYNC1 = ECAT_AL_EVENT_MASK_ST_S1_MASK_Msk, /**< State of distributed clock sync-1 event mask */
XMC_ECAT_EVENT_SM_ACTIVATION_REGISTER = ECAT_AL_EVENT_MASK_SM_A_MASK_Msk, /**< SyncManager activation register mask*/
XMC_ECAT_EVENT_EEPROM = ECAT_AL_EVENT_MASK_EEP_E_MASK_Msk, /**< EEPROM Emulation event mask*/
XMC_ECAT_EVENT_WATCHDOG = ECAT_AL_EVENT_MASK_WP_D_MASK_Msk, /**< WATCHDOG process data event mask*/
XMC_ECAT_EVENT_SM0 = ECAT_AL_EVENT_MASK_SMI_0_MASK_Msk, /**< Sync Manager 0 event mask*/
XMC_ECAT_EVENT_SM1 = ECAT_AL_EVENT_MASK_SMI_1_MASK_Msk, /**< Sync Manager 1 event mask*/
XMC_ECAT_EVENT_SM2 = ECAT_AL_EVENT_MASK_SMI_2_MASK_Msk, /**< Sync Manager 2 event mask*/
XMC_ECAT_EVENT_SM3 = ECAT_AL_EVENT_MASK_SMI_3_MASK_Msk, /**< Sync Manager 3 event mask*/
XMC_ECAT_EVENT_SM4 = ECAT_AL_EVENT_MASK_SMI_4_MASK_Msk, /**< Sync Manager 4 event mask*/
XMC_ECAT_EVENT_SM5 = ECAT_AL_EVENT_MASK_SMI_5_MASK_Msk, /**< Sync Manager 5 event mask*/
XMC_ECAT_EVENT_SM6 = ECAT_AL_EVENT_MASK_SMI_6_MASK_Msk, /**< Sync Manager 6 event mask*/
XMC_ECAT_EVENT_SM7 = ECAT_AL_EVENT_MASK_SMI_7_MASK_Msk /**< Sync Manager 7 event mask*/
} XMC_ECAT_EVENT_t;
/**********************************************************************************************************************
* DATA STRUCTURES
*********************************************************************************************************************/
/* Anonymous structure/union guard start */
#if defined (__CC_ARM)
#pragma push
#pragma anon_unions
#elif defined (__TASKING__)
#pragma warning 586
#endif
/**
* ECAT port control data structure
*/
typedef struct XMC_ECAT_PORT_CTRL
{
union
{
struct
{
uint32_t enable_rstreq: 1; /**< Master can trigger a reset of the XMC4700 / XMC4800 (::bool) */
uint32_t: 7; /**< Reserved bits */
uint32_t latch_input0: 2; /**< Latch input 0 selection (::XMC_ECAT_PORT_LATCHIN0_t) */
uint32_t: 2; /**< Reserved bits */
uint32_t latch_input1: 2; /**< Latch input 1 selection (::XMC_ECAT_PORT_LATCHIN1_t) */
uint32_t: 2; /**< Reserved bits */
uint32_t phyaddr_offset: 5; /**< Ethernet PHY address offset, address of port 0 */
uint32_t: 1; /**< Reserved bits */
uint32_t mdio: 2; /**< Bidirectional, push-pull management data I/O line (::XMC_ETH_MAC_PORT_CTRL_MDIO_t) */
uint32_t: 8; /**< Reserved bits */
};
uint32_t raw;
} common;
union
{
struct
{
uint32_t rxd0: 2; /**< Receive data bit 0 (::XMC_ECAT_PORT0_CTRL_RXD0_t) */
uint32_t rxd1: 2; /**< Receive data bit 1 (::XMC_ECAT_PORT0_CTRL_RXD1_t) */
uint32_t rxd2: 2; /**< Receive data bit 2 (::XMC_ECAT_PORT0_CTRL_RXD2_t) */
uint32_t rxd3: 2; /**< Receive data bit 3 (::XMC_ECAT_PORT0_CTRL_RXD3_t) */
uint32_t rx_err: 2; /**< RX Error (::XMC_ECAT_PORT0_CTRL_RX_ERR_t) */
uint32_t rx_dv: 2; /**< RX Data valid (::XMC_ECAT_PORT0_CTRL_RX_DV_t) */
uint32_t rx_clk: 2; /**< RX Clock (::XMC_ECAT_PORT0_CTRL_RX_CLK_t) */
uint32_t: 2; /**< Reserved bits */
uint32_t link: 2; /**< Link status (::XMC_ECAT_PORT0_CTRL_LINK_t) */
uint32_t: 10; /**< Reserved bits */
uint32_t tx_clk: 2; /**< TX Clock (::XMC_ECAT_PORT0_CTRL_TX_CLK_t) */
uint32_t tx_shift: 2; /**< TX signal delay (::XMC_ECAT_PORT0_CTRL_TX_SHIFT_t) */
};
uint32_t raw;
} port0;
union
{
struct
{
uint32_t rxd0: 2; /**< Receive data bit 0 (::XMC_ECAT_PORT_CTRL_RXD0_t) */
uint32_t rxd1: 2; /**< Receive data bit 1 (::XMC_ECAT_PORT_CTRL_RXD1_t) */
uint32_t rxd2: 2; /**< Receive data bit 2 (::XMC_ECAT_PORT_CTRL_RXD2_t) */
uint32_t rxd3: 2; /**< Receive data bit 3 (::XMC_ECAT_PORT_CTRL_RXD3_t) */
uint32_t rx_err: 2; /**< RX Error (::XMC_ECAT_PORT_CTRL_RX_ERR_t) */
uint32_t rx_dv: 2; /**< RX Data valid (::XMC_ECAT_PORT_CTRL_RX_DV_t) */
uint32_t rx_clk: 2; /**< RX Clock (::XMC_ECAT_PORT_CTRL_RX_CLK_t) */
uint32_t: 2; /**< Reserved bits */
uint32_t link: 2; /**< Link status (::XMC_ECAT_PORT_CTRL_LINK_t) */
uint32_t: 10; /**< Reserved bits */
uint32_t tx_clk: 2; /**< TX Clock (::XMC_ECAT_PORT_CTRL_TX_CLK_t) */
uint32_t tx_shift: 2; /**< TX signal delay (::XMC_ECAT_PORT1_CTRL_TX_SHIFT_t) */
};
uint32_t raw;
} port1;
} XMC_ECAT_PORT_CTRL_t;
/**
* ECAT EEPROM configuration area data structure
*/
typedef union XMC_ECAT_CONFIG
{
struct
{
uint32_t : 8;
uint32_t : 2;
uint32_t enable_dc_sync_out : 1;
uint32_t enable_dc_latch_in : 1;
uint32_t enable_enhanced_link_p0 : 1;
uint32_t enable_enhanced_link_p1 : 1;
uint32_t : 2;
uint32_t : 16;
uint16_t sync_pulse_length; /**< Initialization value for Pulse Length of SYNC Signals register*/
uint32_t : 16;
uint16_t station_alias; /**< Initialization value for Configured Station Alias Address register */
uint16_t : 16;
uint16_t : 16;
uint16_t checksum;
};
uint32_t dword[4]; /**< Four 32 bit double word equivalent to 8 16 bit configuration area word. */
} XMC_ECAT_CONFIG_t;
/* Anonymous structure/union guard end */
#if defined (__CC_ARM)
#pragma pop
#elif defined (__TASKING__)
#pragma warning restore
#endif
/**********************************************************************************************************************
* API PROTOTYPES
*********************************************************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @param config XMC_ECAT_CONFIG_t
* @return XMC_ECAT_STATUS_t ECAT Initialization status
*
* \par<b>Description: </b><br>
* Initialize the Ethernet MAC peripheral <br>
*
* \par
* The function sets the link speed, applies the duplex mode, sets auto-negotiation
* and loop-back settings.
*/
void XMC_ECAT_Init(XMC_ECAT_CONFIG_t *const config);
/**
* @param None
* @return None
*
* \par<b>Description: </b><br>
* Enable the EtherCAT peripheral <br>
*
* \par
* The function de-asserts the peripheral reset.
*/
void XMC_ECAT_Enable(void);
/**
* @param None
* @return None
*
* \par<b>Description: </b><br>
* Disable the EtherCAT peripheral <br>
*
* \par
* The function asserts the peripheral reset.
*/
void XMC_ECAT_Disable(void);
/**
* @param phy_addr PHY address
* @param reg_addr Register address
* @param data The destination to which the read data needs to be copied to.
*
* @return XMC_ECAT_STATUS_t EtherCAT Read PHY API return status
*
* \par<b>Description: </b><br>
* Read a PHY register <br>
*
* \par
* The function reads a PHY register. It essentially polls busy bit during max
* PHY_TIMEOUT time and reads the information into 'data' when not busy.
*/
XMC_ECAT_STATUS_t XMC_ECAT_ReadPhy(uint8_t phy_addr, uint8_t reg_addr, uint16_t *data);
/**
* @param phy_addr PHY address
* @param reg_addr Register address
* @param data The data to write
* @return XMC_ECAT_STATUS_t EtherCAT Write PHY API return status
*
* \par<b>Description: </b><br>
* Write a PHY register <br>
*
* \par
* The function reads a PHY register. It essentially writes the data and polls
* the busy bit until it is no longer busy.
*/
XMC_ECAT_STATUS_t XMC_ECAT_WritePhy(uint8_t phy_addr, uint8_t reg_addr, uint16_t data);
/**
* @param port_ctrl Port control configuration
* @return None
*
* \par<b>Description: </b><br>
* Set port control configuration <br>
*
* \par
* The function sets the port control by writing the configuration into the ECAT CON register.
*
*/
__STATIC_INLINE void XMC_ECAT_SetPortControl(const XMC_ECAT_PORT_CTRL_t port_ctrl)
{
ECAT0_CON->CON = (uint32_t)port_ctrl.common.raw;
ECAT0_CON->CONP0 = (uint32_t)port_ctrl.port0.raw;
ECAT0_CON->CONP1 = (uint32_t)port_ctrl.port1.raw;
}
/**
* @param event Single or logically OR'd events specified in the enum type @refXMC_ECAT_EVENT_t
* @return None
*
* \par<b>Description: </b><br>
* Enable ECAT event(s) <br>
*
* \par
* The function can be used to enable ECAT event(s).
*/
void XMC_ECAT_EnableEvent(uint32_t event);
/**
* @param event Single or logically OR'd events specified in the enum type @refXMC_ECAT_EVENT_t
* @return None
*
* \par<b>Description: </b><br>
* Disable an ECAT event(s) <br>
*
* \par
* The function can be used to disable ECAT event(s).
*/
void XMC_ECAT_DisableEvent(uint32_t event);
/**
* @param None
* @return uint32_t Event status
*
* \par<b>Description: </b><br>
* Get event status <br>
*
* \par
* The function returns the ECAT status and interrupt status as a single word. The user
* can then check the status of the events by using an appropriate mask.
*/
uint32_t XMC_ECAT_GetEventStatus(void);
/**
* @param channel SyncManager channel number.
* @return None
*
* \par<b>Description: </b><br>
* Disables selected SyncManager channel <br>
*
* \par
* Sets bit 0 of the corresponding 0x807 register.
*/
void XMC_ECAT_DisableSyncManChannel(const uint8_t channel);
/**
* @param channel SyncManager channel number.
* @return None
*
* \par<b>Description: </b><br>
* Enables selected SyncManager channel <br>
*
* \par
* Resets bit 0 of the corresponding 0x807 register.
*/
void XMC_ECAT_EnableSyncManChannel(const uint8_t channel);
/**
* @param None
* @return uint16_t Content of register 0x220-0x221
*
* \par<b>Description: </b><br>
* Get content of AL event register <br>
*
* \par
* Get the first two bytes of the AL Event register (0x220-0x221).
*/
__STATIC_INLINE uint16_t XMC_ECAT_GetALEventRegister(void)
{
return ((uint16_t)ECAT0->AL_EVENT_REQ);
}
/**
* @param None
* @return uint16_t Content of register 0x220-0x221
*
* \par<b>Description: </b><br>
* Get content of AL event register <br>
*
* \par
* Get the first two bytes of the AL Event register (0x220-0x221).
*/
__STATIC_INLINE uint16_t XMC_ECAT_GetALEventMask(void)
{
return ((uint16_t)ECAT0->AL_EVENT_MASK);
}
/**
* @param intMask Interrupt mask (disabled interrupt shall be zero)
* @return None
*
* \par<b>Description: </b><br>
* Sets application event mask register <br>
*
* \par
* Performs a logical OR with the AL Event Mask register (0x0204 : 0x0205).
*/
__STATIC_INLINE void XMC_ECAT_SetALEventMask(uint16_t intMask)
{
ECAT0->AL_EVENT_MASK |= (uint32_t)(intMask);
}
#ifdef __cplusplus
}
#endif
/**
* @}
*/
/**
* @}
*/
#endif /* defined (ECAT) */
#endif /* XMC_ECAT_H */