1 
2 /**
3  * @file xmc_ecat.c
4  * @date 2017-04-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-10-21:
41  *     - Initial Version
42  *
43  * 2015-12-27:
44  *     - Add clock gating control in enable/disable APIs
45  *
46  * 2017-04-27:
47  *     - Changed XMC_ECAT_ReadPhy() and XMC_ECAT_WritePhy() to release the MII access and check that the master enables take over of MII management control
48  *
49  * @endcond
50  */
51 
52 /*******************************************************************************
53  * HEADER FILES
54  *******************************************************************************/
55 
56 #include <xmc_ecat.h>
57 
58 #if defined (ECAT0)
59 
60 #include <xmc_scu.h>
61 
62 /*******************************************************************************
63  * MACROS
64  *******************************************************************************/
65 
66 /*******************************************************************************
67  * API IMPLEMENTATION
68  *******************************************************************************/
69 /* The function defines the access state to the MII management for the PDI interface*/
XMC_ECAT_lRequestPhyAccessToMII(void)70 __STATIC_INLINE void XMC_ECAT_lRequestPhyAccessToMII(void)
71 {
72   ECAT0->MII_PDI_ACS_STATE = 0x1;
73 }
74 
XMC_ECAT_lReleasePhyAccessToMII(void)75 __STATIC_INLINE void XMC_ECAT_lReleasePhyAccessToMII(void)
76 {
77   ECAT0->MII_PDI_ACS_STATE = 0x0;
78 }
79 
80 /* EtherCAT module clock ungating and deassert reset API (Enables ECAT) */
XMC_ECAT_Enable(void)81 void XMC_ECAT_Enable(void)
82 {
83   XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_ECAT0);
84   XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_ECAT0);
85 
86   while (XMC_SCU_RESET_IsPeripheralResetAsserted(XMC_SCU_PERIPHERAL_RESET_ECAT0) == true){}
87 }
88 
89 /* EtherCAT module clock gating and assert reset API (Disables ECAT)*/
XMC_ECAT_Disable(void)90 void XMC_ECAT_Disable(void)
91 {
92   XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_ECAT0);
93   while (XMC_SCU_RESET_IsPeripheralResetAsserted(XMC_SCU_PERIPHERAL_RESET_ECAT0) == false){}
94 
95   XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_ECAT0);
96 }
97 
98 /* EtherCAT initialization function */
XMC_ECAT_Init(XMC_ECAT_CONFIG_t * const config)99 void XMC_ECAT_Init(XMC_ECAT_CONFIG_t *const config)
100 {
101   XMC_ECAT_Enable();
102 
103   /* The process memory is not accessible until the ESC Configuration Area is loaded successfully. */
104 
105   /* words 0x0-0x3 */
106   ECAT0->EEP_DATA[0U] = config->dword[0U];
107   ECAT0->EEP_DATA[1U] = config->dword[1U];
108   ECAT0->EEP_CONT_STAT |= (uint16_t)((uint16_t)0x4U << (uint16_t)ECAT_EEP_CONT_STAT_CMD_REG_Pos);
109 
110   /* words 0x4-0x7 */
111   ECAT0->EEP_DATA[0U] = config->dword[2U];
112   ECAT0->EEP_DATA[1U] = config->dword[3U];
113   ECAT0->EEP_CONT_STAT |= (uint16_t)((uint16_t)0x4U << (uint16_t)ECAT_EEP_CONT_STAT_CMD_REG_Pos);
114 
115   while (ECAT0->EEP_CONT_STAT & ECAT_EEP_CONT_STAT_L_STAT_Msk)
116   {
117     /* Wait until the EEPROM_Loaded signal is active */
118   }
119 
120 }
121 
122 /* EtherCAT application event enable API */
XMC_ECAT_EnableEvent(uint32_t event)123 void XMC_ECAT_EnableEvent(uint32_t event)
124 {
125   ECAT0->AL_EVENT_MASK |= event;
126 }
127 /* EtherCAT application event disable API */
XMC_ECAT_DisableEvent(uint32_t event)128 void XMC_ECAT_DisableEvent(uint32_t event)
129 {
130   ECAT0->AL_EVENT_MASK &= ~event;
131 }
132 
133 /* EtherCAT application event status reading API */
XMC_ECAT_GetEventStatus(void)134 uint32_t XMC_ECAT_GetEventStatus(void)
135 {
136   return (ECAT0->AL_EVENT_REQ);
137 }
138 
139 /* EtherCAT SyncManager channel disable function*/
XMC_ECAT_DisableSyncManChannel(const uint8_t channel)140 void XMC_ECAT_DisableSyncManChannel(const uint8_t channel)
141 {
142   ((ECAT0_SM_Type *)(void*)((uint8_t *)(void*)ECAT0_SM0 + (channel * 8U)))->SM_PDI_CTR |= 0x1U;
143 }
144 
145 /* EtherCAT SyncManager channel enable function*/
XMC_ECAT_EnableSyncManChannel(const uint8_t channel)146 void XMC_ECAT_EnableSyncManChannel(const uint8_t channel)
147 {
148   ((ECAT0_SM_Type *)(void*)((uint8_t *)(void*)ECAT0_SM0 + (channel * 8U)))->SM_PDI_CTR &= (uint8_t)(~0x1U);
149 }
150 
151 
152 /* EtherCAT PHY register read function*/
XMC_ECAT_ReadPhy(uint8_t phy_addr,uint8_t reg_addr,uint16_t * data)153 XMC_ECAT_STATUS_t XMC_ECAT_ReadPhy(uint8_t phy_addr, uint8_t reg_addr, uint16_t *data)
154 {
155   XMC_ECAT_STATUS_t status;
156 
157   if ((ECAT0->MII_ECAT_ACS_STATE != 0) || ((ECAT0->MII_PDI_ACS_STATE & ECAT_MII_PDI_ACS_STATE_FORCE_PDI_ACS_S_Msk) != 0))
158   {
159   status =  XMC_ECAT_STATUS_ERROR;
160   }
161   else
162   {
163     XMC_ECAT_lRequestPhyAccessToMII();
164 
165     ECAT0->MII_PHY_ADR = phy_addr;
166     ECAT0->MII_PHY_REG_ADR = reg_addr;
167 
168     ECAT0->MII_CONT_STAT = 0x0100U;  /* read instruction */
169     while ((ECAT0->MII_CONT_STAT & ECAT_MII_CONT_STAT_BUSY_Msk) != 0U){}
170 
171     if ((ECAT0->MII_CONT_STAT & ECAT_MII_CONT_STAT_ERROR_Msk) != 0U)
172     {
173       ECAT0->MII_CONT_STAT = 0; /* Clear error */
174       status = XMC_ECAT_STATUS_ERROR;
175     }
176     else
177     {
178       *data = (uint16_t)ECAT0->MII_PHY_DATA;
179       status = XMC_ECAT_STATUS_OK;
180     }
181 
182     XMC_ECAT_lReleasePhyAccessToMII();
183   }
184 
185   return status;
186 }
187 
188 /* EtherCAT PHY register write function*/
XMC_ECAT_WritePhy(uint8_t phy_addr,uint8_t reg_addr,uint16_t data)189 XMC_ECAT_STATUS_t XMC_ECAT_WritePhy(uint8_t phy_addr, uint8_t reg_addr, uint16_t data)
190 {
191   XMC_ECAT_STATUS_t status;
192 
193   if ((ECAT0->MII_ECAT_ACS_STATE != 0) || ((ECAT0->MII_PDI_ACS_STATE & ECAT_MII_PDI_ACS_STATE_FORCE_PDI_ACS_S_Msk) != 0))
194   {
195   status =  XMC_ECAT_STATUS_ERROR;
196   }
197   else
198   {
199     XMC_ECAT_lRequestPhyAccessToMII();
200 
201     ECAT0->MII_PHY_ADR = phy_addr;
202     ECAT0->MII_PHY_REG_ADR = reg_addr;
203     ECAT0->MII_PHY_DATA = data;
204 
205     ECAT0->MII_CONT_STAT = 0x0200U;  /* write instruction */
206     while ((ECAT0->MII_CONT_STAT & ECAT_MII_CONT_STAT_BUSY_Msk) != 0U){}
207 
208     if ((ECAT0->MII_CONT_STAT & ECAT_MII_CONT_STAT_ERROR_Msk) != 0U)
209     {
210       ECAT0->MII_CONT_STAT = 0; /* Clear error */
211       status = XMC_ECAT_STATUS_ERROR;
212     }
213     else
214     {
215       status = XMC_ECAT_STATUS_OK;
216     }
217 
218     XMC_ECAT_lReleasePhyAccessToMII();
219   }
220 
221   return status;
222 }
223 
224 #endif
225