Line data Source code
1 1 : /**
2 : * @file drivers/stepper/stepper_trinamic.h
3 : *
4 : * @brief Public API for Trinamic Stepper Controller Specific Functions
5 : *
6 : */
7 :
8 : /*
9 : * SPDX-FileCopyrightText: Copyright (c) 2024 Carl Zeiss Meditec AG
10 : * SPDX-FileCopyrightText: Copyright (c) 2025 Prevas A/S
11 : *
12 : * SPDX-License-Identifier: Apache-2.0
13 : */
14 :
15 : #ifndef ZEPHYR_INCLUDE_DRIVERS_STEPPER_STEPPER_TRINAMIC_H_
16 : #define ZEPHYR_INCLUDE_DRIVERS_STEPPER_STEPPER_TRINAMIC_H_
17 :
18 : /**
19 : * @brief Trinamic Stepper Controller Interface
20 : * @defgroup trinamic_stepper_interface Trinamic Stepper Controller Interface
21 : * @ingroup stepper_interface
22 : * @{
23 : */
24 :
25 : #include <stdint.h>
26 : #include <zephyr/drivers/stepper.h>
27 :
28 : #ifdef __cplusplus
29 : extern "C" {
30 : #endif
31 :
32 : /**
33 : * @brief Trinamic stepper controller ramp generator data limits
34 : */
35 1 : #define TMC_RAMP_VSTART_MAX GENMASK(17, 0)
36 0 : #define TMC_RAMP_VSTART_MIN 0
37 0 : #define TMC_RAMP_V1_MAX GENMASK(19, 0)
38 0 : #define TMC_RAMP_V1_MIN 0
39 0 : #define TMC_RAMP_VMAX_MAX (GENMASK(22, 0) - 512)
40 0 : #define TMC_RAMP_VMAX_MIN 0
41 0 : #define TMC_RAMP_A1_MAX GENMASK(15, 0)
42 0 : #define TMC_RAMP_A1_MIN 0
43 0 : #define TMC_RAMP_AMAX_MAX GENMASK(15, 0)
44 0 : #define TMC_RAMP_AMAX_MIN 0
45 0 : #define TMC_RAMP_D1_MAX GENMASK(15, 0)
46 0 : #define TMC_RAMP_D1_MIN 1
47 0 : #define TMC_RAMP_DMAX_MAX GENMASK(15, 0)
48 0 : #define TMC_RAMP_DMAX_MIN 0
49 0 : #define TMC_RAMP_VSTOP_MAX GENMASK(17, 0)
50 0 : #define TMC_RAMP_VSTOP_MIN 1
51 0 : #define TMC_RAMP_TZEROWAIT_MAX (GENMASK(15, 0) - 512)
52 0 : #define TMC_RAMP_TZEROWAIT_MIN 0
53 0 : #define TMC_RAMP_IHOLD_IRUN_MAX GENMASK(4, 0)
54 0 : #define TMC_RAMP_IHOLD_IRUN_MIN 0
55 0 : #define TMC_RAMP_IHOLDDELAY_MAX GENMASK(3, 0)
56 0 : #define TMC_RAMP_IHOLDDELAY_MIN 0
57 0 : #define TMC_RAMP_VACTUAL_SHIFT 22
58 0 : #define TMC_RAMP_XACTUAL_SHIFT 31
59 :
60 : /* TMC50XX specific */
61 0 : #define TMC_RAMP_VCOOLTHRS_MAX GENMASK(22, 0)
62 0 : #define TMC_RAMP_VCOOLTHRS_MIN 0
63 0 : #define TMC_RAMP_VHIGH_MAX GENMASK(22, 0)
64 0 : #define TMC_RAMP_VHIGH_MIN 0
65 :
66 : /* TMC51XX specific */
67 0 : #define TMC_RAMP_TPOWERDOWN_MAX GENMASK(7, 0)
68 0 : #define TMC_RAMP_TPOWERDOWN_MIN 0
69 0 : #define TMC_RAMP_TPWMTHRS_MAX GENMASK(19, 0)
70 0 : #define TMC_RAMP_TPWMTHRS_MIN 0
71 0 : #define TMC_RAMP_TCOOLTHRS_MAX GENMASK(19, 0)
72 0 : #define TMC_RAMP_TCOOLTHRS_MIN 0
73 0 : #define TMC_RAMP_THIGH_MAX GENMASK(19, 0)
74 0 : #define TMC_RAMP_THIGH_MIN 0
75 :
76 : /**
77 : * @brief Trinamic Stepper Ramp Generator data
78 : */
79 1 : struct tmc_ramp_generator_data {
80 0 : uint32_t vstart;
81 0 : uint32_t v1;
82 0 : uint32_t vmax;
83 0 : uint16_t a1;
84 0 : uint16_t amax;
85 0 : uint16_t d1;
86 0 : uint16_t dmax;
87 0 : uint32_t vstop;
88 0 : uint16_t tzerowait;
89 0 : uint32_t iholdrun;
90 : union {
91 : /* TMC50XX specific */
92 : struct {
93 0 : uint32_t vcoolthrs;
94 0 : uint32_t vhigh;
95 : };
96 : /* TMC51XX specific */
97 : struct {
98 0 : uint32_t tpowerdown;
99 0 : uint32_t tpwmthrs;
100 0 : uint32_t tcoolthrs;
101 0 : uint32_t thigh;
102 : };
103 0 : };
104 : };
105 :
106 : /**
107 : * @brief Check if Ramp DT data is within limits
108 : */
109 1 : #define CHECK_RAMP_DT_DATA(node) \
110 : COND_CODE_1(DT_PROP_EXISTS(node, vstart), \
111 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, vstart), TMC_RAMP_VSTART_MIN, \
112 : TMC_RAMP_VSTART_MAX), "vstart out of range"), ()); \
113 : COND_CODE_1(DT_PROP_EXISTS(node, v1), \
114 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, v1), TMC_RAMP_V1_MIN, \
115 : TMC_RAMP_V1_MAX), "v1 out of range"), ()); \
116 : COND_CODE_1(DT_PROP_EXISTS(node, vmax), \
117 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, vmax), TMC_RAMP_VMAX_MIN, \
118 : TMC_RAMP_VMAX_MAX), "vmax out of range"), ()); \
119 : COND_CODE_1(DT_PROP_EXISTS(node, a1), \
120 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, a1), TMC_RAMP_A1_MIN, \
121 : TMC_RAMP_A1_MAX), "a1 out of range"), ()); \
122 : COND_CODE_1(DT_PROP_EXISTS(node, amax), \
123 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, amax), TMC_RAMP_AMAX_MIN, \
124 : TMC_RAMP_AMAX_MAX), "amax out of range"), ()); \
125 : COND_CODE_1(DT_PROP_EXISTS(node, d1), \
126 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, d1), TMC_RAMP_D1_MIN, \
127 : TMC_RAMP_D1_MAX), "d1 out of range"), ()); \
128 : COND_CODE_1(DT_PROP_EXISTS(node, dmax), \
129 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, dmax), TMC_RAMP_DMAX_MIN, \
130 : TMC_RAMP_DMAX_MAX), "dmax out of range"), ()); \
131 : COND_CODE_1(DT_PROP_EXISTS(node, vstop), \
132 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, vstop), TMC_RAMP_VSTOP_MIN, \
133 : TMC_RAMP_VSTOP_MAX), "vstop out of range"), ()); \
134 : COND_CODE_1(DT_PROP_EXISTS(node, tzerowait), \
135 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, tzerowait), TMC_RAMP_TZEROWAIT_MIN, \
136 : TMC_RAMP_TZEROWAIT_MAX), "tzerowait out of range"), ()); \
137 : COND_CODE_1(DT_PROP_EXISTS(node, ihold), \
138 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, ihold), TMC_RAMP_IHOLD_IRUN_MIN, \
139 : TMC_RAMP_IHOLD_IRUN_MAX), "ihold out of range"), ()); \
140 : COND_CODE_1(DT_PROP_EXISTS(node, irun), \
141 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, irun), TMC_RAMP_IHOLD_IRUN_MIN, \
142 : TMC_RAMP_IHOLD_IRUN_MAX), "irun out of range"), ()); \
143 : COND_CODE_1(DT_PROP_EXISTS(node, iholddelay), \
144 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, iholddelay), TMC_RAMP_IHOLDDELAY_MIN, \
145 : TMC_RAMP_IHOLDDELAY_MAX), "iholddelay out of range"), ());\
146 : /* TMC50XX specific */ \
147 : COND_CODE_1(DT_PROP_EXISTS(node, vcoolthrs), \
148 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, vcoolthrs), TMC_RAMP_VCOOLTHRS_MIN, \
149 : TMC_RAMP_VCOOLTHRS_MAX), "vcoolthrs out of range"), ()); \
150 : COND_CODE_1(DT_PROP_EXISTS(node, vhigh), \
151 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, vhigh), TMC_RAMP_VHIGH_MIN, \
152 : TMC_RAMP_VHIGH_MAX), "vhigh out of range"), ()); \
153 : /* TMC51XX specific */ \
154 : COND_CODE_1(DT_PROP_EXISTS(node, tpowerdown), \
155 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, tpowerdown), TMC_RAMP_TPOWERDOWN_MIN, \
156 : TMC_RAMP_TPOWERDOWN_MAX), "tpowerdown out of range"), ());\
157 : COND_CODE_1(DT_PROP_EXISTS(node, tpwmthrs), \
158 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, tpwmthrs), TMC_RAMP_TPWMTHRS_MIN, \
159 : TMC_RAMP_TPWMTHRS_MAX), "tpwmthrs out of range"), ()); \
160 : COND_CODE_1(DT_PROP_EXISTS(node, tcoolthrs), \
161 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, tcoolthrs), TMC_RAMP_TCOOLTHRS_MIN, \
162 : TMC_RAMP_TCOOLTHRS_MAX), "tcoolthrs out of range"), ()); \
163 : COND_CODE_1(DT_PROP_EXISTS(node, thigh), \
164 : BUILD_ASSERT(IN_RANGE(DT_PROP(node, thigh), TMC_RAMP_THIGH_MIN, \
165 : TMC_RAMP_THIGH_MAX), "thigh out of range"), ());
166 :
167 : /**
168 : * @brief Get Trinamic Stepper Ramp Generator data from DT
169 : *
170 : * @param node DT node identifier
171 : *
172 : * @return struct tmc_ramp_generator_data
173 : */
174 1 : #define TMC_RAMP_DT_SPEC_GET_COMMON(node) \
175 : .vstart = DT_PROP(node, vstart), \
176 : .v1 = DT_PROP(node, v1), \
177 : .vmax = DT_PROP(node, vmax), \
178 : .a1 = DT_PROP(node, a1), \
179 : .amax = DT_PROP(node, amax), \
180 : .d1 = DT_PROP(node, d1), \
181 : .dmax = DT_PROP(node, dmax), \
182 : .vstop = DT_PROP(node, vstop), \
183 : .tzerowait = DT_PROP(node, tzerowait), \
184 : .iholdrun = (TMC5XXX_IRUN(DT_PROP(node, irun)) | \
185 : TMC5XXX_IHOLD(DT_PROP(node, ihold)) | \
186 : TMC5XXX_IHOLDDELAY(DT_PROP(node, iholddelay))),
187 :
188 0 : #define TMC_RAMP_DT_SPEC_GET_TMC50XX(node) \
189 : { \
190 : TMC_RAMP_DT_SPEC_GET_COMMON(node) \
191 : .vhigh = DT_PROP(node, vhigh), \
192 : .vcoolthrs = DT_PROP(node, vcoolthrs), \
193 : }
194 :
195 0 : #define TMC_RAMP_DT_SPEC_GET_TMC51XX(node) \
196 : { \
197 : TMC_RAMP_DT_SPEC_GET_COMMON(DT_DRV_INST(node)) \
198 : .tpowerdown = DT_INST_PROP(node, tpowerdown), \
199 : .tpwmthrs = DT_INST_PROP(node, tpwmthrs), \
200 : .tcoolthrs = DT_INST_PROP(node, tcoolthrs), \
201 : .thigh = DT_INST_PROP(node, thigh), \
202 : }
203 :
204 : /**
205 : * @brief Configure Trinamic Stepper Ramp Generator
206 : *
207 : * @param dev Pointer to the stepper motor controller instance
208 : * @param ramp_data Pointer to a struct containing the required ramp parameters
209 : *
210 : * @retval -EIO General input / output error
211 : * @retval -ENOSYS If not implemented by device driver
212 : * @retval 0 Success
213 : */
214 1 : int tmc50xx_stepper_set_ramp(const struct device *dev,
215 : const struct tmc_ramp_generator_data *ramp_data);
216 :
217 : /**
218 : * @brief Set the maximum velocity of the stepper motor
219 : *
220 : * @param dev Pointer to the stepper motor controller instance
221 : * @param velocity Maximum velocity in microsteps per second.
222 : *
223 : * @retval -EIO General input / output error
224 : * @retval 0 Success
225 : */
226 1 : int tmc50xx_stepper_set_max_velocity(const struct device *dev, uint32_t velocity);
227 :
228 : /**
229 : * @}
230 : */
231 :
232 : #ifdef __cplusplus
233 : }
234 : #endif
235 :
236 : #endif /* ZEPHYR_INCLUDE_DRIVERS_STEPPER_STEPPER_TRINAMIC_H_ */
|