libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_usb_endpoint_otgfs.cpp
1#include <cstdint>
2
3#include "ch32_usb_endpoint.hpp"
4#include "ep.hpp"
5
6using namespace LibXR;
7
8#if defined(USBFSD)
9
10// NOLINTBEGIN
11
12static inline volatile uint8_t* GetTxCtrlAddr(USB::Endpoint::EPNumber ep)
13{
14 return &USBFSD->UEP0_TX_CTRL + 4 * (USB::Endpoint::EPNumberToInt8(ep));
15}
16static inline volatile uint8_t* GetRxCtrlAddr(USB::Endpoint::EPNumber ep)
17{
18 return &USBFSD->UEP0_RX_CTRL + 4 * (USB::Endpoint::EPNumberToInt8(ep));
19}
20static inline volatile uint16_t* GetTxLenAddr(USB::Endpoint::EPNumber ep)
21{
22 return &USBFSD->UEP0_TX_LEN + 2 * (USB::Endpoint::EPNumberToInt8(ep));
23}
24static inline volatile uint32_t* GetDmaAddr(USB::Endpoint::EPNumber ep)
25{
26 return &USBFSD->UEP0_DMA + USB::Endpoint::EPNumberToInt8(ep);
27}
28
29static void SetDmaBuffer(USB::Endpoint::EPNumber ep_num, void* value, bool double_buffer)
30{
31 *GetDmaAddr(ep_num) = (uint32_t)value;
32
33 if (!double_buffer)
34 {
35 return;
36 }
37
38 switch (ep_num)
39 {
40 case USB::Endpoint::EPNumber::EP1:
41 USBFSD->UEP4_1_MOD |= USBFS_UEP1_BUF_MOD;
42 break;
43 case USB::Endpoint::EPNumber::EP2:
44 USBFSD->UEP2_3_MOD |= USBFS_UEP2_BUF_MOD;
45 break;
46 case USB::Endpoint::EPNumber::EP3:
47 USBFSD->UEP2_3_MOD |= USBFS_UEP3_BUF_MOD;
48 break;
49 case USB::Endpoint::EPNumber::EP4:
50 USBFSD->UEP4_1_MOD |= USBFS_UEP4_BUF_MOD;
51 break;
52 case USB::Endpoint::EPNumber::EP5:
53 USBFSD->UEP5_6_MOD |= USBFS_UEP5_BUF_MOD;
54 break;
55 case USB::Endpoint::EPNumber::EP6:
56 USBFSD->UEP5_6_MOD |= USBFS_UEP6_BUF_MOD;
57 break;
58 case USB::Endpoint::EPNumber::EP7:
59 USBFSD->UEP7_MOD |= USBFS_UEP7_BUF_MOD;
60 break;
61 default:
62 break;
63 }
64}
65
66static void SetTxLen(USB::Endpoint::EPNumber ep_num, uint32_t value)
67{
68 *GetTxLenAddr(ep_num) = value;
69}
70
71static void EnableTx(USB::Endpoint::EPNumber ep_num)
72{
73 switch (ep_num)
74 {
75 case USB::Endpoint::EPNumber::EP1:
76 USBFSD->UEP4_1_MOD |= USBFS_UEP1_TX_EN;
77 break;
78 case USB::Endpoint::EPNumber::EP2:
79 USBFSD->UEP2_3_MOD |= USBFS_UEP2_TX_EN;
80 break;
81 case USB::Endpoint::EPNumber::EP3:
82 USBFSD->UEP2_3_MOD |= USBFS_UEP3_TX_EN;
83 break;
84 case USB::Endpoint::EPNumber::EP4:
85 USBFSD->UEP4_1_MOD |= USBFS_UEP4_TX_EN;
86 break;
87 case USB::Endpoint::EPNumber::EP5:
88 USBFSD->UEP5_6_MOD |= USBFS_UEP5_TX_EN;
89 break;
90 case USB::Endpoint::EPNumber::EP6:
91 USBFSD->UEP5_6_MOD |= USBFS_UEP6_TX_EN;
92 break;
93 case USB::Endpoint::EPNumber::EP7:
94 USBFSD->UEP7_MOD |= USBFS_UEP7_TX_EN;
95 break;
96 default:
97 break;
98 }
99}
100static void DisableTx(USB::Endpoint::EPNumber ep_num)
101{
102 switch (ep_num)
103 {
104 case USB::Endpoint::EPNumber::EP1:
105 USBFSD->UEP4_1_MOD &= ~USBFS_UEP1_TX_EN;
106 break;
107 case USB::Endpoint::EPNumber::EP2:
108 USBFSD->UEP2_3_MOD &= ~USBFS_UEP2_TX_EN;
109 break;
110 case USB::Endpoint::EPNumber::EP3:
111 USBFSD->UEP2_3_MOD &= ~USBFS_UEP3_TX_EN;
112 break;
113 case USB::Endpoint::EPNumber::EP4:
114 USBFSD->UEP4_1_MOD &= ~USBFS_UEP4_TX_EN;
115 break;
116 case USB::Endpoint::EPNumber::EP5:
117 USBFSD->UEP5_6_MOD &= ~USBFS_UEP5_TX_EN;
118 break;
119 case USB::Endpoint::EPNumber::EP6:
120 USBFSD->UEP5_6_MOD &= ~USBFS_UEP6_TX_EN;
121 break;
122 case USB::Endpoint::EPNumber::EP7:
123 USBFSD->UEP7_MOD &= ~USBFS_UEP7_TX_EN;
124 break;
125 default:
126 break;
127 }
128}
129static void EnableRx(USB::Endpoint::EPNumber ep_num)
130{
131 switch (ep_num)
132 {
133 case USB::Endpoint::EPNumber::EP1:
134 USBFSD->UEP4_1_MOD |= USBFS_UEP1_RX_EN;
135 break;
136 case USB::Endpoint::EPNumber::EP2:
137 USBFSD->UEP2_3_MOD |= USBFS_UEP2_RX_EN;
138 break;
139 case USB::Endpoint::EPNumber::EP3:
140 USBFSD->UEP2_3_MOD |= USBFS_UEP3_RX_EN;
141 break;
142 case USB::Endpoint::EPNumber::EP4:
143 USBFSD->UEP4_1_MOD |= USBFS_UEP4_RX_EN;
144 break;
145 case USB::Endpoint::EPNumber::EP5:
146 USBFSD->UEP5_6_MOD |= USBFS_UEP5_RX_EN;
147 break;
148 case USB::Endpoint::EPNumber::EP6:
149 USBFSD->UEP5_6_MOD |= USBFS_UEP6_RX_EN;
150 break;
151 case USB::Endpoint::EPNumber::EP7:
152 USBFSD->UEP7_MOD |= USBFS_UEP7_RX_EN;
153 break;
154 default:
155 break;
156 }
157}
158static void DisableRx(USB::Endpoint::EPNumber ep_num)
159{
160 switch (ep_num)
161 {
162 case USB::Endpoint::EPNumber::EP1:
163 USBFSD->UEP4_1_MOD &= ~USBFS_UEP1_RX_EN;
164 break;
165 case USB::Endpoint::EPNumber::EP2:
166 USBFSD->UEP2_3_MOD &= ~USBFS_UEP2_RX_EN;
167 break;
168 case USB::Endpoint::EPNumber::EP3:
169 USBFSD->UEP2_3_MOD &= ~USBFS_UEP3_RX_EN;
170 break;
171 case USB::Endpoint::EPNumber::EP4:
172 USBFSD->UEP4_1_MOD &= ~USBFS_UEP4_RX_EN;
173 break;
174 case USB::Endpoint::EPNumber::EP5:
175 USBFSD->UEP5_6_MOD &= ~USBFS_UEP5_RX_EN;
176 break;
177 case USB::Endpoint::EPNumber::EP6:
178 USBFSD->UEP5_6_MOD &= ~USBFS_UEP6_RX_EN;
179 break;
180 case USB::Endpoint::EPNumber::EP7:
181 USBFSD->UEP7_MOD &= ~USBFS_UEP7_RX_EN;
182 break;
183 default:
184 break;
185 }
186}
187// NOLINTEND
188
189// NOLINTNEXTLINE
190static LibXR::RawData SelectBuffer(USB::Endpoint::EPNumber ep_num,
192 const LibXR::RawData& buffer)
193{
194 if (ep_num == USB::Endpoint::EPNumber::EP0)
195 {
196 return buffer;
197 }
198 else
199 {
200 if (dir == USB::Endpoint::Direction::OUT)
201 {
202 return LibXR::RawData(buffer.addr_, 128);
203 }
204 else
205 {
206 return LibXR::RawData(reinterpret_cast<uint8_t*>(buffer.addr_) + 128, 128);
207 }
208 }
209}
210
211CH32EndpointOtgFs::CH32EndpointOtgFs(EPNumber ep_num, Direction dir,
212 LibXR::RawData buffer, bool is_isochronous)
213 : Endpoint(ep_num, dir, is_isochronous ? buffer : SelectBuffer(ep_num, dir, buffer)),
214 is_isochronous_(is_isochronous),
215 dma_buffer_(buffer)
216{
217 map_otg_fs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
218
219 SetDmaBuffer(GetNumber(), dma_buffer_.addr_, is_isochronous ? false : true);
220
221 if (dir == Direction::IN)
222 {
223 SetTxLen(GetNumber(), 0);
224 *GetTxCtrlAddr(GetNumber()) = USBFS_UEP_T_RES_NAK;
225 }
226 else
227 {
228 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_NAK;
229 }
230}
231
232void CH32EndpointOtgFs::Configure(const Config& cfg)
233{
234 auto& ep_cfg = GetConfig();
235 ep_cfg = cfg;
236
237 if (GetNumber() != EPNumber::EP0 && !is_isochronous_)
238 {
239 ep_cfg.double_buffer = true;
240 }
241 else
242 {
243 ep_cfg.double_buffer = false;
244 }
245
246 ep_cfg.max_packet_size = GetBuffer().size_;
247
248 SetTxLen(GetNumber(), 0);
249
250 if (!is_isochronous_)
251 {
252 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_NAK | USBFS_UEP_R_AUTO_TOG;
253 *GetTxCtrlAddr(GetNumber()) = USBFS_UEP_T_RES_NAK | USBFS_UEP_T_AUTO_TOG;
254 EnableTx(GetNumber());
255 EnableRx(GetNumber());
256 }
257 else
258 {
259 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_NAK;
260 *GetTxCtrlAddr(GetNumber()) = USBFS_UEP_T_RES_NAK;
261 if (GetDirection() == Direction::IN)
262 {
263 EnableTx(GetNumber());
264 }
265 else
266 {
267 EnableRx(GetNumber());
268 }
269 }
270
271 SetDmaBuffer(GetNumber(), dma_buffer_.addr_, is_isochronous_ ? false : true);
272
273 SetState(State::IDLE);
274}
275
276void CH32EndpointOtgFs::Close()
277{
278 DisableTx(GetNumber());
279 DisableRx(GetNumber());
280
281 *GetTxCtrlAddr(GetNumber()) = USBFS_UEP_T_RES_NAK;
282 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_NAK;
283
284 SetState(State::DISABLED);
285}
286
287ErrorCode CH32EndpointOtgFs::Transfer(size_t size)
288{
289 if (GetState() == State::BUSY)
290 {
291 return ErrorCode::BUSY;
292 }
293
294 auto buffer = GetBuffer();
295 if (buffer.size_ < size)
296 {
297 return ErrorCode::NO_BUFF;
298 }
299
300 bool is_in = (GetDirection() == Direction::IN);
301
302 if (is_in && UseDoubleBuffer())
303 {
304 SwitchBuffer();
305 }
306
307 if (is_in)
308 {
309 SetTxLen(GetNumber(), size);
310 auto addr = GetTxCtrlAddr(GetNumber());
311
312 if (GetNumber() != EPNumber::EP0)
313 {
314 *addr = (is_isochronous_ ? USBFS_UEP_T_RES_NONE : USBFS_UEP_T_RES_ACK) |
315 (*addr & (~USBFS_UEP_T_RES_MASK));
316 }
317 else
318 {
319 *addr = USBFS_UEP_T_RES_ACK | (tog_ ? USBFS_UEP_T_TOG : 0);
320 }
321 }
322 else
323 {
324 auto addr = GetRxCtrlAddr(GetNumber());
325
326 if (GetNumber() != EPNumber::EP0)
327 {
328 *addr = (is_isochronous_ ? USBFS_UEP_R_RES_NONE : USBFS_UEP_R_RES_ACK) |
329 (*addr & (~USBFS_UEP_R_RES_MASK));
330 }
331 else
332 {
333 *addr = USBFS_UEP_R_RES_ACK | (tog_ ? USBFS_UEP_R_TOG : 0);
334 }
335 }
336
337 if (GetNumber() == EPNumber::EP0)
338 {
339 tog_ = !tog_;
340 }
341
342 last_transfer_size_ = size;
343 SetState(State::BUSY);
344 return ErrorCode::OK;
345}
346
347ErrorCode CH32EndpointOtgFs::Stall()
348{
349 if (GetState() != State::IDLE)
350 {
351 return ErrorCode::BUSY;
352 }
353
354 bool is_in = (GetDirection() == Direction::IN);
355 if (is_in)
356 {
357 *GetTxCtrlAddr(GetNumber()) |= USBFS_UEP_T_RES_STALL;
358 }
359 else
360 {
361 *GetRxCtrlAddr(GetNumber()) |= USBFS_UEP_R_RES_STALL;
362 }
363 SetState(State::STALLED);
364 return ErrorCode::OK;
365}
366
367ErrorCode CH32EndpointOtgFs::ClearStall()
368{
369 if (GetState() != State::STALLED)
370 {
371 return ErrorCode::FAILED;
372 }
373
374 bool is_in = (GetDirection() == Direction::IN);
375 if (is_in)
376 {
377 *GetTxCtrlAddr(GetNumber()) &= ~USBFS_UEP_T_RES_STALL;
378 }
379 else
380 {
381 *GetRxCtrlAddr(GetNumber()) &= ~USBFS_UEP_R_RES_STALL;
382 }
383 SetState(State::IDLE);
384 return ErrorCode::OK;
385}
386
387void CH32EndpointOtgFs::TransferComplete(size_t size)
388{
389 if (GetDirection() == Direction::IN)
390 {
391 size = last_transfer_size_;
392 }
393
394 if (GetDirection() == Direction::OUT &&
395 (USBFSD->INT_FG & USBFS_U_TOG_OK) != USBFS_U_TOG_OK) // NOLINT
396 {
397 return;
398 }
399
400 if (GetNumber() == EPNumber::EP0 && GetDirection() == Direction::OUT)
401 {
402 tog_ = true;
403 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_ACK;
404 }
405
406 if (GetDirection() == Direction::IN)
407 {
408 *GetTxCtrlAddr(GetNumber()) =
409 (*GetTxCtrlAddr(GetNumber()) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
410 USBFSD->INT_FG = USBFS_UIF_TRANSFER; // NOLINT
411 }
412
413 OnTransferCompleteCallback(true, size);
414}
415
416void CH32EndpointOtgFs::SwitchBuffer()
417{
418 if (GetDirection() == Direction::IN)
419 {
420 tog_ = (*GetTxCtrlAddr(GetNumber()) & USBFS_UEP_T_TOG) == USBFS_UEP_T_TOG;
421 SetActiveBlock(!tog_);
422 }
423 else
424 {
425 tog_ = (*GetRxCtrlAddr(GetNumber()) & USBFS_UEP_R_TOG) == USBFS_UEP_R_TOG;
426 SetActiveBlock(tog_);
427 }
428}
429
430#endif
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
EPNumber
端点号 / Endpoint number
Definition ep.hpp:39
static constexpr uint8_t EPNumberToInt8(EPNumber ep)
端点号转换为uint8_t / Convert endpoint number to uint8_t
Definition ep.hpp:92
Direction
端点方向 Endpoint direction
Definition ep.hpp:29
LibXR 命名空间