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