1 /*
2 * Copyright (c) 2024 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8
9 #ifndef HPM_ESC_DRV_H
10 #define HPM_ESC_DRV_H
11
12 #include "hpm_common.h"
13 #include "hpm_esc_regs.h"
14
15 /**
16 *
17 * @brief ESC driver APIs
18 * @defgroup esc_interface ESC driver APIs
19 * @ingroup esc_interfaces
20 * @{
21 */
22
23 /**
24 * @brief ESC error codes
25 */
26 enum {
27 status_esc_eeprom_ack_error = MAKE_STATUS(status_group_esc, 0), /**< ESC EEPROM ack error */
28 status_esc_eeprom_checksum_error = MAKE_STATUS(status_group_esc, 1), /**< ESC EEPROM checksum error */
29 };
30
31
32 typedef enum {
33 latch_source_from_ntm = 0,
34 latch_source_from_trigger_mux = 1,
35 } esc_latch_source_t;
36
37 typedef enum {
38 esc_eeprom_idle_cmd = 0, /* clear error bits */
39 esc_eeprom_read_cmd = 1,
40 esc_eeprom_write_cmd = 2,
41 esc_eeprom_reload_cmd = 4,
42 } esc_eeprom_cmd_t;
43
44 typedef enum {
45 esc_ctrl_signal_func_alt_nmii_link0 = 0,
46 esc_ctrl_signal_func_alt_nmii_link1 = 1,
47 esc_ctrl_signal_func_alt_nmii_link2 = 2,
48 esc_ctrl_signal_func_alt_link_act0 = 3,
49 esc_ctrl_signal_func_alt_link_act1 = 4,
50 esc_ctrl_signal_func_alt_link_act2 = 5,
51 esc_ctrl_signal_func_alt_led_run = 6,
52 esc_ctrl_signal_func_alt_led_err = 7,
53 esc_ctrl_signal_func_alt_reset_out = 8,
54 } esc_ctrl_signal_function_t;
55
56
57 typedef struct {
58 bool eeprom_emulation;
59 bool eeprom_size_over_16kbit;
60 bool core_clock_en;
61 bool phy_refclk_en;
62 } esc_eeprom_clock_config_t;
63
64
65 #ifdef __cplusplus
66 extern "C" {
67 #endif
68
69 /**
70 * @brief ESC peripheral clock
71 *
72 * @param[in] ptr ESC base address
73 * @param[in] enable Set true to enable or false to disable
74 */
esc_core_enable_clock(ESC_Type * ptr,bool enable)75 static inline void esc_core_enable_clock(ESC_Type *ptr, bool enable)
76 {
77 if (enable) {
78 ptr->GPR_CFG0 |= ESC_GPR_CFG0_CLK100_EN_MASK;
79 } else {
80 ptr->GPR_CFG0 &= ~ESC_GPR_CFG0_CLK100_EN_MASK;
81 }
82 }
83
84 /**
85 * @brief ESC PHY clock
86 *
87 * @param[in] ptr ESC base address
88 * @param[in] enable Set true to enable or false to disable
89 */
esc_phy_enable_clock(ESC_Type * ptr,bool enable)90 static inline void esc_phy_enable_clock(ESC_Type *ptr, bool enable)
91 {
92 if (enable) {
93 ptr->PHY_CFG1 |= ESC_PHY_CFG1_REFCK_25M_OE_MASK; /*!< enable PHY 25M refck */
94 } else {
95 ptr->PHY_CFG1 &= ~ESC_PHY_CFG1_REFCK_25M_OE_MASK; /*!< disable PHY 25M refck */
96 }
97 }
98
99 /**
100 * @brief ESC config eeprom attributes(emulation and size) and peripheral clock
101 *
102 * @param[in] ptr ESC base address
103 * @param[in] config esc_eeprom_clock_config_t
104 */
esc_config_eeprom_and_clock(ESC_Type * ptr,esc_eeprom_clock_config_t * config)105 static inline void esc_config_eeprom_and_clock(ESC_Type *ptr, esc_eeprom_clock_config_t *config)
106 {
107 uint32_t gpr_cfg0 = ptr->GPR_CFG0;
108
109 if (config->eeprom_emulation) {
110 gpr_cfg0 |= ESC_GPR_CFG0_EEPROM_EMU_MASK;
111 gpr_cfg0 &= ~(ESC_GPR_CFG0_PROM_SIZE_MASK | ESC_GPR_CFG0_I2C_SCLK_EN_MASK);
112 } else {
113 gpr_cfg0 &= ~ESC_GPR_CFG0_EEPROM_EMU_MASK;
114 gpr_cfg0 |= ESC_GPR_CFG0_I2C_SCLK_EN_MASK;
115 if (config->eeprom_size_over_16kbit) {
116 gpr_cfg0 |= ESC_GPR_CFG0_PROM_SIZE_MASK;
117 } else {
118 gpr_cfg0 &= ~ESC_GPR_CFG0_PROM_SIZE_MASK;
119 }
120 }
121 ptr->GPR_CFG0 = gpr_cfg0;
122 esc_core_enable_clock(ptr, config->core_clock_en);
123 esc_phy_enable_clock(ptr, config->phy_refclk_en);
124 }
125
126 /**
127 * @brief ESC assign specific function to CTRL signal
128 *
129 * @param[in] ptr ESC base address
130 * @param[in] index CTRL signal index(0-8)
131 * @param[in] func specific function
132 * @param[in] invert invert signal
133 */
esc_config_ctrl_signal_function(ESC_Type * ptr,uint8_t index,esc_ctrl_signal_function_t func,bool invert)134 static inline void esc_config_ctrl_signal_function(ESC_Type *ptr, uint8_t index, esc_ctrl_signal_function_t func, bool invert)
135 {
136 ptr->IO_CFG[index] = ESC_IO_CFG_FUNC_ALT_SET(func) | ESC_IO_CFG_INVERT_SET(invert);
137 }
138
139 /**
140 * @brief ESC config nmii_link signal source
141 *
142 * @param[in] ptr ESC base address
143 * @param[in] link0_from_io true for signal from configured IO; false for signal from register(GPR_CFG2) value
144 * @param[in] link1_from_io true for signal from configured IO; false for signal from register(GPR_CFG2) value
145 * @param[in] link2_from_io true for signal from configured IO; false for signal from register(GPR_CFG2) value
146 */
esc_config_nmii_link_source(ESC_Type * ptr,bool link0_from_io,bool link1_from_io,bool link2_from_io)147 static inline void esc_config_nmii_link_source(ESC_Type *ptr, bool link0_from_io, bool link1_from_io, bool link2_from_io)
148 {
149 if (link0_from_io) {
150 ptr->GPR_CFG2 |= ESC_GPR_CFG2_NMII_LINK0_FROM_IO_MASK;
151 } else {
152 ptr->GPR_CFG2 &= ~ESC_GPR_CFG2_NMII_LINK0_FROM_IO_MASK;
153 ptr->GPR_CFG2 |= ESC_GPR_CFG2_NMII_LINK0_GPR_MASK; /* config GRP to indicate LINK0 is invalid by default */
154 }
155
156 if (link1_from_io) {
157 ptr->GPR_CFG2 |= ESC_GPR_CFG2_NMII_LINK1_FROM_IO_MASK;
158 } else {
159 ptr->GPR_CFG2 &= ~ESC_GPR_CFG2_NMII_LINK1_FROM_IO_MASK;
160 ptr->GPR_CFG2 |= ESC_GPR_CFG2_NMII_LINK1_GPR_MASK; /* config GRP to indicate LINK1 is invalid by default */
161 }
162
163 if (link2_from_io) {
164 ptr->GPR_CFG2 |= ESC_GPR_CFG2_NMII_LINK2_FROM_IO_MASK;
165 } else {
166 ptr->GPR_CFG2 &= ~ESC_GPR_CFG2_NMII_LINK2_FROM_IO_MASK;
167 ptr->GPR_CFG2 |= ESC_GPR_CFG2_NMII_LINK2_GPR_MASK; /* config GRP to indicate LINK2 is invalid by default */
168 }
169 }
170
171 /* config ESC reset request source: ESC core or GRP_REG value */
172 /**
173 * @brief ESC config reset signal source
174 *
175 * @param[in] ptr ESC base address
176 * @param[in] reset_from_ecat_core true for reset signal from ecat core; false for reset signal from register(GPR_CFG1) value
177 */
esc_config_reset_source(ESC_Type * ptr,bool reset_from_ecat_core)178 static inline void esc_config_reset_source(ESC_Type *ptr, bool reset_from_ecat_core)
179 {
180 if (reset_from_ecat_core) {
181 ptr->GPR_CFG1 |= ESC_GPR_CFG1_RSTO_OVRD_ENJ_MASK;
182 } else {
183 ptr->GPR_CFG1 &= ~ESC_GPR_CFG1_RSTO_OVRD_ENJ_MASK;
184 }
185 }
186
187 /**
188 * @brief ESC generate reset signal to ESC_RESET interrupt and RESET_OUT pin
189 * @note the reset signal source should be configured in esc_config_reset_source before
190 *
191 * @param[in] ptr ESC base address
192 */
esc_pdi_reset(ESC_Type * ptr)193 static inline void esc_pdi_reset(ESC_Type *ptr)
194 {
195 ptr->ESC_RST_PDI = 0x52; /* R */
196 ptr->ESC_RST_PDI = 0x45; /* E */
197 ptr->ESC_RST_PDI = 0x53; /* S */
198 }
199
200 /*!
201 * @brief ESC read PHY register via ESC MII Management Interface
202 *
203 * @param[in] ptr ESC base address
204 * @param[in] phy_addr PHY address.
205 * @param[in] reg_addr Register address.
206 * @param[in] data PHY data returned.
207 */
208
209 hpm_stat_t esc_mdio_read(ESC_Type *ptr, uint8_t phy_addr, uint8_t reg_addr, uint16_t *data);
210
211 /*!
212 * @brief ESc write PHY register via ESC MII Management Interface
213 *
214 * @param[in] ptr ESC base address
215 * @param[in] phy_addr PHY address.
216 * @param[in] reg_addr Register address.
217 * @param[in] data Write to PHY register.
218 */
219 hpm_stat_t esc_mdio_write(ESC_Type *ptr, uint8_t phy_addr, uint8_t reg_addr, uint16_t data);
220
221 /*!
222 * @brief ESC check eeprom loading data status
223 * @note EtherCAT communication is possible even if the EEPROM is blank
224 *
225 * @param[in] ptr ESC base address.
226 * @retval status_success: loding data successfully and correctlly.
227 * @retval status_esc_eeprom_ack_error: loding data checksum error(eeprom blank).
228 * @retval status_esc_eeprom_checksum_error: no ack error.
229 * @retval status_timeout: loding data timeout.
230 */
231 hpm_stat_t esc_check_eeprom_loading(ESC_Type *ptr);
232
233 /*!
234 * @brief ESC get eeprom cmd, this using in eeprom emulation function
235 *
236 * @param[in] ptr ESC base address
237 * @return uint8_t esc_eeprom_cmd_t.
238 */
esc_get_eeprom_cmd(ESC_Type * ptr)239 static inline uint8_t esc_get_eeprom_cmd(ESC_Type *ptr)
240 {
241 return ESC_EEPROM_CTRL_STAT_CMD_GET(ptr->EEPROM_CTRL_STAT);
242 }
243
244 /*!
245 * @brief ESC ack eeprom cmd in eeprom emualtion function
246 *
247 * @param[in] ptr ESC base address
248 * @param[in] cmd esc_eeprom_cmd_t
249 * @param[in] ack_err eeprom ack error occurrred
250 * @param[in] crc_err eeprom checksum error occurrred
251 */
esc_eeprom_emulation_ack(ESC_Type * ptr,esc_eeprom_cmd_t cmd,bool ack_err,bool crc_err)252 static inline void esc_eeprom_emulation_ack(ESC_Type *ptr, esc_eeprom_cmd_t cmd, bool ack_err, bool crc_err)
253 {
254 uint16_t temp = ESC_EEPROM_CTRL_STAT_CMD_SET(cmd);
255 if (ack_err) {
256 temp |= ESC_EEPROM_CTRL_STAT_ERR_ACK_CMD_MASK;
257 }
258 if (crc_err) {
259 temp |= ESC_EEPROM_CTRL_STAT_CKSM_ERR_MASK;
260 }
261
262 ptr->EEPROM_CTRL_STAT = temp;
263 }
264
265 /*!
266 * @brief ESC get eeprom byte address
267 *
268 * @param[in] ptr ESC base address
269 * @return byte address
270 */
esc_get_eeprom_byte_address(ESC_Type * ptr)271 static inline uint32_t esc_get_eeprom_byte_address(ESC_Type *ptr)
272 {
273 return (ptr->EEPROM_ADDR) << 1U;
274 }
275
276 /*!
277 * @brief ESC get eeprom word(2 bytes) address
278 *
279 * @param[in] ptr ESC base address
280 * @return word address
281 */
esc_get_eeprom_word_address(ESC_Type * ptr)282 static inline uint32_t esc_get_eeprom_word_address(ESC_Type *ptr)
283 {
284 return ptr->EEPROM_ADDR;
285 }
286
287 /*!
288 * @brief ESC read eeprom data from register, this function is using in eeprom emulation function
289 *
290 * @param[in] ptr ESC base address
291 * @return eeprom data
292 */
esc_read_eeprom_data(ESC_Type * ptr)293 static inline uint64_t esc_read_eeprom_data(ESC_Type *ptr)
294 {
295 return ptr->EEPROM_DATA;
296 }
297
298 /*!
299 * @brief ESC write eeprom data to register, this function is using in eeprom emulation function
300 *
301 * @param[in] ptr ESC base address
302 * @param[in] data eeprom data
303 */
esc_write_eeprom_data(ESC_Type * ptr,uint64_t data)304 static inline void esc_write_eeprom_data(ESC_Type *ptr, uint64_t data)
305 {
306 ptr->EEPROM_DATA = data;
307 }
308
309 /*!
310 * @brief ESC config latch0 signal source
311 *
312 * @param[in] ptr ESC base address
313 * @param[in] latch0_from_ntm true for signal from ntm system, false for signal from IO
314 */
esc_config_latch0_source(ESC_Type * ptr,bool latch0_from_ntm)315 static inline void esc_config_latch0_source(ESC_Type *ptr, bool latch0_from_ntm)
316 {
317 if (latch0_from_ntm) {
318 ptr->GPR_CFG1 &= ~ESC_GPR_CFG1_LATCH0_FROM_IO_MASK;
319 } else {
320 ptr->GPR_CFG1 |= ESC_GPR_CFG1_LATCH0_FROM_IO_MASK;
321 }
322 }
323
324 /*!
325 * @brief ESC config latch1 signal source
326 *
327 * @param[in] ptr ESC base address
328 * @param[in] latch0_from_trigmux true for signal from trigmux system, false for signal from IO
329 */
esc_config_latch1_source(ESC_Type * ptr,bool latch0_from_trigmux)330 static inline void esc_config_latch1_source(ESC_Type *ptr, bool latch0_from_trigmux)
331 {
332 if (latch0_from_trigmux) {
333 ptr->GPR_CFG1 &= ~ESC_GPR_CFG1_LATCH1_FROM_IO_MASK;
334 } else {
335 ptr->GPR_CFG1 |= ESC_GPR_CFG1_LATCH1_FROM_IO_MASK;
336 }
337 }
338
339
340
341 #ifdef __cplusplus
342 }
343 #endif
344 /**
345 * @}
346 */
347 #endif /* HPM_ESC_DRV_H */
348