1 
2 /**
3  * @file xmc_ecat.h
4  * @date 2015-12-27
5  *
6  * @cond
7  *********************************************************************************************************************
8  * XMClib v2.1.24 - XMC Peripheral Driver Library
9  *
10  * Copyright (c) 2015-2019, Infineon Technologies AG
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
14  * following conditions are met:
15  *
16  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
17  * disclaimer.
18  *
19  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
20  * disclaimer in the documentation and/or other materials provided with the distribution.
21  *
22  * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
23  * products derived from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
34  * Infineon Technologies AG dave@infineon.com).
35  *********************************************************************************************************************
36  *
37  * Change History
38  * --------------
39  *
40  * 2015-12-27:
41  *     - Initial Version<br>
42  *
43  * @endcond
44  */
45 
46 /**
47  * @addtogroup XMClib XMC Peripheral Library
48  * @{
49  */
50 
51 /**
52  * @addtogroup ECAT
53  * @brief EtherCAT Low level driver for XMC4800/XMC4300 series.
54  *
55  * EtherCAT is an Ethernet-based fieldbus system.
56  * The EtherCAT Slave Controller (ECAT) read the data addressed to them while the telegram passes through the device.
57  * An EtherCAT Slave Controller (ESC) takes care of the EtherCAT communication as an interface between the EtherCAT
58  * fieldbus and the slave application. EtherCAT uses standard IEEE 802.3 Ethernet frames, thus a standard network
59  * controller can be used and no special hardware is required on master side. EtherCAT has a reserved EtherType of
60  * 0x88A4 that distinguishes it from other Ethernet frames. Thus, EtherCAT can run in parallel to other Ethernet
61  * protocols. EtherCAT does not require the IP protocol, however it can be encapsulated in IP/UDP. The EtherCAT
62  * Slave Controller processes the frame in hardware. Thus, communication performance is independent from processor
63  * power.
64  *
65  * The XMC_ECAT low level driver provides functions to configure and initialize the ECAT hardware peripheral.
66  * For EHTERCAT stack integration, the necessary hardware accees layer APIs shall be explicitly implemented depending
67  * upon the stack provider. The XMC_ECAT lld layer provides only the hardware initialization functions for start up and
68  * basic functionalities.
69  * @{
70  */
71 
72 #ifndef XMC_ECAT_H
73 #define XMC_ECAT_H
74 
75 /**********************************************************************************************************************
76  * HEADER FILES
77  *********************************************************************************************************************/
78 
79 #include "xmc_common.h"
80 
81 #if defined (ECAT0)
82 
83 #include "xmc_ecat_map.h"
84 
85 /**********************************************************************************************************************
86  * MACROS
87  *********************************************************************************************************************/
88 
89 /**********************************************************************************************************************
90  * ENUMS
91  *********************************************************************************************************************/
92 
93 /**
94  * ECAT status return values
95  */
96 typedef enum XMC_ECAT_STATUS
97 {
98   XMC_ECAT_STATUS_OK    = 0U, /**< Driver accepted application request */
99   XMC_ECAT_STATUS_BUSY  = 1U, /**< Driver is busy and cannot handle request */
100   XMC_ECAT_STATUS_ERROR = 2U  /**< Driver could not fulfil application request */
101 } XMC_ECAT_STATUS_t;
102 
103 /**
104  * EtherCAT event enumeration types
105  */
106 typedef enum XMC_ECAT_EVENT
107 {
108   XMC_ECAT_EVENT_AL_CONTROL = ECAT_AL_EVENT_MASK_AL_CE_MASK_Msk, /**< Application control event mask */
109   XMC_ECAT_EVENT_DC_LATCH = ECAT_AL_EVENT_MASK_DC_LE_MASK_Msk,  /**< Distributed Clock latch event mask */
110   XMC_ECAT_EVENT_DC_SYNC0 = ECAT_AL_EVENT_MASK_ST_S0_MASK_Msk, /**< State of distributed clock sync-0 event mask */
111   XMC_ECAT_EVENT_DC_SYNC1 = ECAT_AL_EVENT_MASK_ST_S1_MASK_Msk, /**< State of distributed clock sync-1 event mask */
112   XMC_ECAT_EVENT_SM_ACTIVATION_REGISTER = ECAT_AL_EVENT_MASK_SM_A_MASK_Msk, /**< SyncManager activation register mask*/
113   XMC_ECAT_EVENT_EEPROM = ECAT_AL_EVENT_MASK_EEP_E_MASK_Msk, /**< EEPROM Emulation event mask*/
114   XMC_ECAT_EVENT_WATCHDOG = ECAT_AL_EVENT_MASK_WP_D_MASK_Msk, /**< WATCHDOG process data event mask*/
115   XMC_ECAT_EVENT_SM0 = ECAT_AL_EVENT_MASK_SMI_0_MASK_Msk, /**< Sync Manager 0 event mask*/
116   XMC_ECAT_EVENT_SM1 = ECAT_AL_EVENT_MASK_SMI_1_MASK_Msk, /**< Sync Manager 1 event mask*/
117   XMC_ECAT_EVENT_SM2 = ECAT_AL_EVENT_MASK_SMI_2_MASK_Msk, /**< Sync Manager 2 event mask*/
118   XMC_ECAT_EVENT_SM3 = ECAT_AL_EVENT_MASK_SMI_3_MASK_Msk, /**< Sync Manager 3 event mask*/
119   XMC_ECAT_EVENT_SM4 = ECAT_AL_EVENT_MASK_SMI_4_MASK_Msk, /**< Sync Manager 4 event mask*/
120   XMC_ECAT_EVENT_SM5 = ECAT_AL_EVENT_MASK_SMI_5_MASK_Msk, /**< Sync Manager 5 event mask*/
121   XMC_ECAT_EVENT_SM6 = ECAT_AL_EVENT_MASK_SMI_6_MASK_Msk, /**< Sync Manager 6 event mask*/
122   XMC_ECAT_EVENT_SM7 = ECAT_AL_EVENT_MASK_SMI_7_MASK_Msk  /**< Sync Manager 7 event mask*/
123 } XMC_ECAT_EVENT_t;
124 
125 /**********************************************************************************************************************
126  * DATA STRUCTURES
127  *********************************************************************************************************************/
128 
129 /* Anonymous structure/union guard start */
130 #if defined (__CC_ARM)
131 #pragma push
132 #pragma anon_unions
133 #elif defined (__TASKING__)
134 #pragma warning 586
135 #endif
136 
137 /**
138  * ECAT port control data structure
139  */
140 typedef struct XMC_ECAT_PORT_CTRL
141 {
142   union
143   {
144     struct
145     {
146       uint32_t enable_rstreq: 1;     /**< Master can trigger a reset of the XMC4700 / XMC4800 (::bool) */
147       uint32_t: 7;                   /**< Reserved bits */
148       uint32_t latch_input0: 2;      /**< Latch input 0 selection (::XMC_ECAT_PORT_LATCHIN0_t) */
149       uint32_t: 2;                   /**< Reserved bits */
150       uint32_t latch_input1: 2;      /**< Latch input 1 selection (::XMC_ECAT_PORT_LATCHIN1_t) */
151       uint32_t: 2;                   /**< Reserved bits */
152       uint32_t phyaddr_offset: 5;    /**< Ethernet PHY address offset, address of port 0 */
153       uint32_t: 1;                   /**< Reserved bits */
154       uint32_t mdio: 2;              /**< Bidirectional, push-pull management data I/O line (::XMC_ETH_MAC_PORT_CTRL_MDIO_t) */
155       uint32_t: 8;                   /**< Reserved bits */
156     };
157 
158     uint32_t raw;
159   } common;
160 
161   union
162   {
163     struct
164     {
165       uint32_t rxd0: 2;     /**< Receive data bit 0 (::XMC_ECAT_PORT0_CTRL_RXD0_t) */
166       uint32_t rxd1: 2;     /**< Receive data bit 1 (::XMC_ECAT_PORT0_CTRL_RXD1_t) */
167       uint32_t rxd2: 2;     /**< Receive data bit 2 (::XMC_ECAT_PORT0_CTRL_RXD2_t) */
168       uint32_t rxd3: 2;     /**< Receive data bit 3 (::XMC_ECAT_PORT0_CTRL_RXD3_t) */
169       uint32_t rx_err: 2;   /**< RX Error (::XMC_ECAT_PORT0_CTRL_RX_ERR_t) */
170       uint32_t rx_dv: 2;    /**< RX Data valid (::XMC_ECAT_PORT0_CTRL_RX_DV_t) */
171       uint32_t rx_clk: 2;   /**< RX Clock (::XMC_ECAT_PORT0_CTRL_RX_CLK_t) */
172       uint32_t: 2;          /**< Reserved bits */
173       uint32_t link: 2;     /**< Link status (::XMC_ECAT_PORT0_CTRL_LINK_t) */
174       uint32_t: 10;         /**< Reserved bits */
175       uint32_t tx_clk: 2;   /**< TX Clock (::XMC_ECAT_PORT0_CTRL_TX_CLK_t) */
176       uint32_t tx_shift: 2; /**< TX signal delay (::XMC_ECAT_PORT0_CTRL_TX_SHIFT_t) */
177     };
178 
179     uint32_t raw;
180   } port0;
181 
182   union
183   {
184     struct
185     {
186       uint32_t rxd0: 2;     /**< Receive data bit 0 (::XMC_ECAT_PORT_CTRL_RXD0_t) */
187       uint32_t rxd1: 2;     /**< Receive data bit 1 (::XMC_ECAT_PORT_CTRL_RXD1_t) */
188       uint32_t rxd2: 2;     /**< Receive data bit 2 (::XMC_ECAT_PORT_CTRL_RXD2_t) */
189       uint32_t rxd3: 2;     /**< Receive data bit 3 (::XMC_ECAT_PORT_CTRL_RXD3_t) */
190       uint32_t rx_err: 2;   /**< RX Error (::XMC_ECAT_PORT_CTRL_RX_ERR_t) */
191       uint32_t rx_dv: 2;    /**< RX Data valid (::XMC_ECAT_PORT_CTRL_RX_DV_t) */
192       uint32_t rx_clk: 2;   /**< RX Clock (::XMC_ECAT_PORT_CTRL_RX_CLK_t) */
193       uint32_t: 2;          /**< Reserved bits */
194       uint32_t link: 2;     /**< Link status (::XMC_ECAT_PORT_CTRL_LINK_t) */
195       uint32_t: 10;         /**< Reserved bits */
196       uint32_t tx_clk: 2;   /**< TX Clock (::XMC_ECAT_PORT_CTRL_TX_CLK_t) */
197       uint32_t tx_shift: 2; /**< TX signal delay (::XMC_ECAT_PORT1_CTRL_TX_SHIFT_t) */
198     };
199 
200     uint32_t raw;
201   } port1;
202 
203 } XMC_ECAT_PORT_CTRL_t;
204 
205 /**
206  * ECAT EEPROM configuration area data structure
207  */
208 typedef union XMC_ECAT_CONFIG
209 {
210   struct
211   {
212     uint32_t : 8;
213 
214     uint32_t : 2;
215     uint32_t enable_dc_sync_out : 1;
216     uint32_t enable_dc_latch_in : 1;
217     uint32_t enable_enhanced_link_p0 : 1;
218     uint32_t enable_enhanced_link_p1 : 1;
219     uint32_t : 2;
220 
221     uint32_t : 16;
222 
223     uint16_t sync_pulse_length; /**< Initialization value for Pulse Length of SYNC Signals register*/
224 
225     uint32_t : 16;
226 
227     uint16_t station_alias; /**< Initialization value for Configured Station Alias Address register */
228 
229     uint16_t : 16;
230 
231     uint16_t : 16;
232 
233     uint16_t checksum;
234   };
235 
236   uint32_t dword[4]; /**< Four 32 bit double word equivalent to 8 16 bit configuration area word. */
237 } XMC_ECAT_CONFIG_t;
238 
239 /* Anonymous structure/union guard end */
240 #if defined (__CC_ARM)
241 #pragma pop
242 #elif defined (__TASKING__)
243 #pragma warning restore
244 #endif
245 
246 /**********************************************************************************************************************
247  * API PROTOTYPES
248  *********************************************************************************************************************/
249 
250 #ifdef __cplusplus
251 extern "C" {
252 #endif
253 
254 /**
255  * @param config XMC_ECAT_CONFIG_t
256  * @return XMC_ECAT_STATUS_t ECAT Initialization status
257  *
258  * \par<b>Description: </b><br>
259  * Initialize the Ethernet MAC peripheral <br>
260  *
261  * \par
262  * The function sets the link speed, applies the duplex mode, sets auto-negotiation
263  * and loop-back settings.
264  */
265 void XMC_ECAT_Init(XMC_ECAT_CONFIG_t *const config);
266 
267 /**
268  * @param None
269  * @return None
270  *
271  * \par<b>Description: </b><br>
272  * Enable the EtherCAT peripheral <br>
273  *
274  * \par
275  * The function de-asserts the peripheral reset.
276  */
277 void XMC_ECAT_Enable(void);
278 
279 /**
280  * @param None
281  * @return None
282  *
283  * \par<b>Description: </b><br>
284  * Disable the EtherCAT peripheral <br>
285  *
286  * \par
287  * The function asserts the peripheral reset.
288  */
289 void XMC_ECAT_Disable(void);
290 
291 /**
292  * @param phy_addr PHY address
293  * @param reg_addr Register address
294  * @param data The destination to which the read data needs to be copied to.
295  *
296  * @return XMC_ECAT_STATUS_t EtherCAT Read PHY API return status
297  *
298  * \par<b>Description: </b><br>
299  * Read a PHY register <br>
300  *
301  * \par
302  * The function reads a PHY register. It essentially polls busy bit during max
303  * PHY_TIMEOUT time and reads the information into 'data' when not busy.
304  */
305 XMC_ECAT_STATUS_t XMC_ECAT_ReadPhy(uint8_t phy_addr, uint8_t reg_addr, uint16_t *data);
306 
307 /**
308  * @param phy_addr PHY address
309  * @param reg_addr Register address
310  * @param data The data to write
311  * @return XMC_ECAT_STATUS_t EtherCAT Write PHY API return status
312  *
313  * \par<b>Description: </b><br>
314  * Write a PHY register <br>
315  *
316  * \par
317  * The function reads a PHY register. It essentially writes the data and polls
318  * the busy bit until it is no longer busy.
319  */
320 XMC_ECAT_STATUS_t XMC_ECAT_WritePhy(uint8_t phy_addr, uint8_t reg_addr, uint16_t data);
321 
322 /**
323  * @param port_ctrl Port control configuration
324  * @return None
325  *
326  * \par<b>Description: </b><br>
327  * Set port control configuration <br>
328  *
329  * \par
330  * The function sets the port control by writing the configuration into the ECAT CON register.
331  *
332  */
XMC_ECAT_SetPortControl(const XMC_ECAT_PORT_CTRL_t port_ctrl)333 __STATIC_INLINE void XMC_ECAT_SetPortControl(const XMC_ECAT_PORT_CTRL_t port_ctrl)
334 {
335   ECAT0_CON->CON = (uint32_t)port_ctrl.common.raw;
336   ECAT0_CON->CONP0 = (uint32_t)port_ctrl.port0.raw;
337   ECAT0_CON->CONP1 = (uint32_t)port_ctrl.port1.raw;
338 }
339 
340 /**
341  * @param event Single or logically OR'd events specified in the enum type @refXMC_ECAT_EVENT_t
342  * @return None
343  *
344  * \par<b>Description: </b><br>
345  * Enable ECAT event(s) <br>
346  *
347  * \par
348  * The function can be used to enable ECAT event(s).
349  */
350 void XMC_ECAT_EnableEvent(uint32_t event);
351 
352 /**
353  * @param event Single or logically OR'd events specified in the enum type @refXMC_ECAT_EVENT_t
354  * @return None
355  *
356  * \par<b>Description: </b><br>
357  * Disable an ECAT event(s) <br>
358  *
359  * \par
360  * The function can be used to disable ECAT event(s).
361  */
362 void XMC_ECAT_DisableEvent(uint32_t event);
363 
364 /**
365  * @param None
366  * @return uint32_t Event status
367  *
368  * \par<b>Description: </b><br>
369  * Get event status <br>
370  *
371  * \par
372  * The function returns the ECAT status and interrupt status as a single word. The user
373  * can then check the status of the events by using an appropriate mask.
374  */
375 uint32_t XMC_ECAT_GetEventStatus(void);
376 
377 
378 /**
379  * @param channel SyncManager channel number.
380  * @return None
381  *
382  * \par<b>Description: </b><br>
383  * Disables selected SyncManager channel <br>
384  *
385  * \par
386  * Sets bit 0 of the corresponding 0x807 register.
387  */
388 void XMC_ECAT_DisableSyncManChannel(const uint8_t channel);
389 
390 /**
391  * @param channel SyncManager channel number.
392  * @return None
393  *
394  * \par<b>Description: </b><br>
395  * Enables selected SyncManager channel <br>
396  *
397  * \par
398  * Resets bit 0 of the corresponding 0x807 register.
399  */
400 void XMC_ECAT_EnableSyncManChannel(const uint8_t channel);
401 
402 /**
403  * @param None
404  * @return uint16_t Content of register 0x220-0x221
405  *
406  * \par<b>Description: </b><br>
407  * Get content of AL event register <br>
408  *
409  * \par
410  * Get the first two bytes of the AL Event register (0x220-0x221).
411  */
XMC_ECAT_GetALEventRegister(void)412 __STATIC_INLINE uint16_t XMC_ECAT_GetALEventRegister(void)
413 {
414   return ((uint16_t)ECAT0->AL_EVENT_REQ);
415 }
416 
417 /**
418  * @param None
419  * @return uint16_t Content of register 0x220-0x221
420  *
421  * \par<b>Description: </b><br>
422  * Get content of AL event register <br>
423  *
424  * \par
425  * Get the first two bytes of the AL Event register (0x220-0x221).
426  */
XMC_ECAT_GetALEventMask(void)427 __STATIC_INLINE uint16_t XMC_ECAT_GetALEventMask(void)
428 {
429   return ((uint16_t)ECAT0->AL_EVENT_MASK);
430 }
431 
432 /**
433  * @param intMask Interrupt mask (disabled interrupt shall be zero)
434  * @return None
435  *
436  * \par<b>Description: </b><br>
437  * Sets application event mask register <br>
438  *
439  * \par
440  * Performs a logical OR with the AL Event Mask register (0x0204 : 0x0205).
441  */
XMC_ECAT_SetALEventMask(uint16_t intMask)442 __STATIC_INLINE void XMC_ECAT_SetALEventMask(uint16_t intMask)
443 {
444   ECAT0->AL_EVENT_MASK |= (uint32_t)(intMask);
445 }
446 
447 
448 #ifdef __cplusplus
449 }
450 #endif
451 
452 /**
453  * @}
454  */
455 
456 /**
457  * @}
458  */
459 
460 #endif /* defined (ECAT) */
461 
462 #endif /* XMC_ECAT_H */
463