libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_usb_endpoint_otghs.cpp
1#include <cstdint>
2
3#include "ch32_usb_endpoint.hpp"
4#include "ep.hpp"
5#include "libxr_time.hpp"
6#include "timebase.hpp"
7
8using namespace LibXR;
9
10#if defined(USBHSD)
11
12// NOLINTBEGIN
13static inline volatile uint8_t* GetTxControlAddr(USB::Endpoint::EPNumber ep_num)
14{
15 return reinterpret_cast<volatile uint8_t*>(
16 reinterpret_cast<volatile uint8_t*>(&USBHSD->UEP0_TX_CTRL) +
17 static_cast<int>(ep_num) * 4);
18}
19
20static inline volatile uint8_t* GetRxControlAddr(USB::Endpoint::EPNumber ep_num)
21{
22 return reinterpret_cast<volatile uint8_t*>(
23 reinterpret_cast<volatile uint8_t*>(&USBHSD->UEP0_TX_CTRL) +
24 static_cast<int>(ep_num) * 4 + 1);
25}
26
27static inline volatile uint16_t* GetTxLenAddr(USB::Endpoint::EPNumber ep_num)
28{
29 return reinterpret_cast<volatile uint16_t*>(
30 reinterpret_cast<volatile uint8_t*>(&USBHSD->UEP0_TX_LEN) +
31 static_cast<int>(ep_num) * 4);
32}
33
34static inline volatile uint32_t* GetTxDmaAddr(USB::Endpoint::EPNumber ep_num)
35{
36 if (ep_num == USB::Endpoint::EPNumber::EP0) return &USBHSD->UEP0_DMA;
37 return reinterpret_cast<volatile uint32_t*>(
38 reinterpret_cast<volatile uint32_t*>(&USBHSD->UEP1_TX_DMA) +
39 (static_cast<int>(ep_num) - 1));
40}
41
42static inline volatile uint32_t* GetRxDmaAddr(USB::Endpoint::EPNumber ep_num)
43{
44 if (ep_num == USB::Endpoint::EPNumber::EP0) return &USBHSD->UEP0_DMA;
45 return reinterpret_cast<volatile uint32_t*>(
46 reinterpret_cast<volatile uint32_t*>(&USBHSD->UEP1_RX_DMA) +
47 (static_cast<int>(ep_num) - 1));
48}
49
50static void SetTxLen(USB::Endpoint::EPNumber ep_num, uint32_t value)
51{
52 *GetTxLenAddr(ep_num) = value;
53}
54
55static void SetTxDmaBuffer(USB::Endpoint::EPNumber ep_num, void* buffer,
56 uint32_t buffer_size, bool double_buffer)
57{
58 uint8_t* buf_base = reinterpret_cast<uint8_t*>(buffer);
59 uint8_t* buf_alt = buf_base + buffer_size / 2;
60
61 // EP0 特殊
62 if (ep_num == USB::Endpoint::EPNumber::EP0)
63 {
64 USBHSD->UEP0_DMA = (uint32_t)buf_base;
65 }
66 else
67 {
68 *GetTxDmaAddr(ep_num) = (uint32_t)buf_base;
69 if (double_buffer) *GetRxDmaAddr(ep_num) = (uint32_t)buf_alt;
70 }
71
72 int idx = static_cast<int>(ep_num);
73 if (double_buffer && ep_num != USB::Endpoint::EPNumber::EP0)
74 USBHSD->BUF_MODE |= (1 << idx);
75 else
76 USBHSD->BUF_MODE &= ~(1 << idx);
77}
78
79static void SetRxDmaBuffer(USB::Endpoint::EPNumber ep_num, void* buffer,
80 uint32_t buffer_size, bool double_buffer)
81{
82 uint8_t* buf_base = reinterpret_cast<uint8_t*>(buffer);
83 uint8_t* buf_alt = buf_base + buffer_size / 2;
84
85 if (ep_num == USB::Endpoint::EPNumber::EP0)
86 {
87 USBHSD->UEP0_DMA = (uint32_t)buf_base;
88 }
89 else
90 {
91 *GetRxDmaAddr(ep_num) = (uint32_t)buf_base;
92 if (double_buffer) *GetTxDmaAddr(ep_num) = (uint32_t)buf_alt;
93 }
94
95 int idx = static_cast<int>(ep_num);
96 if (double_buffer && ep_num != USB::Endpoint::EPNumber::EP0)
97 USBHSD->BUF_MODE |= (1 << idx);
98 else
99 USBHSD->BUF_MODE &= ~(1 << idx);
100}
101
102static void EnableTx(USB::Endpoint::EPNumber ep_num)
103{
104 switch (ep_num)
105 {
106 case USB::Endpoint::EPNumber::EP0:
107 USBHSD->ENDP_CONFIG |= USBHS_UEP0_T_EN;
108 break;
109 case USB::Endpoint::EPNumber::EP1:
110 USBHSD->ENDP_CONFIG |= USBHS_UEP1_T_EN;
111 break;
112 case USB::Endpoint::EPNumber::EP2:
113 USBHSD->ENDP_CONFIG |= USBHS_UEP2_T_EN;
114 break;
115 case USB::Endpoint::EPNumber::EP3:
116 USBHSD->ENDP_CONFIG |= USBHS_UEP3_T_EN;
117 break;
118 case USB::Endpoint::EPNumber::EP4:
119 USBHSD->ENDP_CONFIG |= USBHS_UEP4_T_EN;
120 break;
121 case USB::Endpoint::EPNumber::EP5:
122 USBHSD->ENDP_CONFIG |= USBHS_UEP5_T_EN;
123 break;
124 case USB::Endpoint::EPNumber::EP6:
125 USBHSD->ENDP_CONFIG |= USBHS_UEP6_T_EN;
126 break;
127 case USB::Endpoint::EPNumber::EP7:
128 USBHSD->ENDP_CONFIG |= USBHS_UEP7_T_EN;
129 break;
130 case USB::Endpoint::EPNumber::EP8:
131 USBHSD->ENDP_CONFIG |= USBHS_UEP8_T_EN;
132 break;
133 case USB::Endpoint::EPNumber::EP9:
134 USBHSD->ENDP_CONFIG |= USBHS_UEP9_T_EN;
135 break;
136 case USB::Endpoint::EPNumber::EP10:
137 USBHSD->ENDP_CONFIG |= USBHS_UEP10_T_EN;
138 break;
139 case USB::Endpoint::EPNumber::EP11:
140 USBHSD->ENDP_CONFIG |= USBHS_UEP11_T_EN;
141 break;
142 case USB::Endpoint::EPNumber::EP12:
143 USBHSD->ENDP_CONFIG |= USBHS_UEP12_T_EN;
144 break;
145 case USB::Endpoint::EPNumber::EP13:
146 USBHSD->ENDP_CONFIG |= USBHS_UEP13_T_EN;
147 break;
148 case USB::Endpoint::EPNumber::EP14:
149 USBHSD->ENDP_CONFIG |= USBHS_UEP14_T_EN;
150 break;
151 case USB::Endpoint::EPNumber::EP15:
152 USBHSD->ENDP_CONFIG |= USBHS_UEP15_T_EN;
153 break;
154 default:
155 break;
156 }
157}
158
159static void DisableTx(USB::Endpoint::EPNumber ep_num)
160{
161 switch (ep_num)
162 {
163 case USB::Endpoint::EPNumber::EP0:
164 USBHSD->ENDP_CONFIG &= ~USBHS_UEP0_T_EN;
165 break;
166 case USB::Endpoint::EPNumber::EP1:
167 USBHSD->ENDP_CONFIG &= ~USBHS_UEP1_T_EN;
168 break;
169 case USB::Endpoint::EPNumber::EP2:
170 USBHSD->ENDP_CONFIG &= ~USBHS_UEP2_T_EN;
171 break;
172 case USB::Endpoint::EPNumber::EP3:
173 USBHSD->ENDP_CONFIG &= ~USBHS_UEP3_T_EN;
174 break;
175 case USB::Endpoint::EPNumber::EP4:
176 USBHSD->ENDP_CONFIG &= ~USBHS_UEP4_T_EN;
177 break;
178 case USB::Endpoint::EPNumber::EP5:
179 USBHSD->ENDP_CONFIG &= ~USBHS_UEP5_T_EN;
180 break;
181 case USB::Endpoint::EPNumber::EP6:
182 USBHSD->ENDP_CONFIG &= ~USBHS_UEP6_T_EN;
183 break;
184 case USB::Endpoint::EPNumber::EP7:
185 USBHSD->ENDP_CONFIG &= ~USBHS_UEP7_T_EN;
186 break;
187 case USB::Endpoint::EPNumber::EP8:
188 USBHSD->ENDP_CONFIG &= ~USBHS_UEP8_T_EN;
189 break;
190 case USB::Endpoint::EPNumber::EP9:
191 USBHSD->ENDP_CONFIG &= ~USBHS_UEP9_T_EN;
192 break;
193 case USB::Endpoint::EPNumber::EP10:
194 USBHSD->ENDP_CONFIG &= ~USBHS_UEP10_T_EN;
195 break;
196 case USB::Endpoint::EPNumber::EP11:
197 USBHSD->ENDP_CONFIG &= ~USBHS_UEP11_T_EN;
198 break;
199 case USB::Endpoint::EPNumber::EP12:
200 USBHSD->ENDP_CONFIG &= ~USBHS_UEP12_T_EN;
201 break;
202 case USB::Endpoint::EPNumber::EP13:
203 USBHSD->ENDP_CONFIG &= ~USBHS_UEP13_T_EN;
204 break;
205 case USB::Endpoint::EPNumber::EP14:
206 USBHSD->ENDP_CONFIG &= ~USBHS_UEP14_T_EN;
207 break;
208 case USB::Endpoint::EPNumber::EP15:
209 USBHSD->ENDP_CONFIG &= ~USBHS_UEP15_T_EN;
210 break;
211 default:
212 break;
213 }
214}
215
216static void EnableRx(USB::Endpoint::EPNumber ep_num)
217{
218 switch (ep_num)
219 {
220 case USB::Endpoint::EPNumber::EP0:
221 USBHSD->ENDP_CONFIG |= USBHS_UEP0_R_EN;
222 break;
223 case USB::Endpoint::EPNumber::EP1:
224 USBHSD->ENDP_CONFIG |= USBHS_UEP1_R_EN;
225 break;
226 case USB::Endpoint::EPNumber::EP2:
227 USBHSD->ENDP_CONFIG |= USBHS_UEP2_R_EN;
228 break;
229 case USB::Endpoint::EPNumber::EP3:
230 USBHSD->ENDP_CONFIG |= USBHS_UEP3_R_EN;
231 break;
232 case USB::Endpoint::EPNumber::EP4:
233 USBHSD->ENDP_CONFIG |= USBHS_UEP4_R_EN;
234 break;
235 case USB::Endpoint::EPNumber::EP5:
236 USBHSD->ENDP_CONFIG |= USBHS_UEP5_R_EN;
237 break;
238 case USB::Endpoint::EPNumber::EP6:
239 USBHSD->ENDP_CONFIG |= USBHS_UEP6_R_EN;
240 break;
241 case USB::Endpoint::EPNumber::EP7:
242 USBHSD->ENDP_CONFIG |= USBHS_UEP7_R_EN;
243 break;
244 case USB::Endpoint::EPNumber::EP8:
245 USBHSD->ENDP_CONFIG |= USBHS_UEP8_R_EN;
246 break;
247 case USB::Endpoint::EPNumber::EP9:
248 USBHSD->ENDP_CONFIG |= USBHS_UEP9_R_EN;
249 break;
250 case USB::Endpoint::EPNumber::EP10:
251 USBHSD->ENDP_CONFIG |= USBHS_UEP10_R_EN;
252 break;
253 case USB::Endpoint::EPNumber::EP11:
254 USBHSD->ENDP_CONFIG |= USBHS_UEP11_R_EN;
255 break;
256 case USB::Endpoint::EPNumber::EP12:
257 USBHSD->ENDP_CONFIG |= USBHS_UEP12_R_EN;
258 break;
259 case USB::Endpoint::EPNumber::EP13:
260 USBHSD->ENDP_CONFIG |= USBHS_UEP13_R_EN;
261 break;
262 case USB::Endpoint::EPNumber::EP14:
263 USBHSD->ENDP_CONFIG |= USBHS_UEP14_R_EN;
264 break;
265 case USB::Endpoint::EPNumber::EP15:
266 USBHSD->ENDP_CONFIG |= USBHS_UEP15_R_EN;
267 break;
268 default:
269 break;
270 }
271}
272
273static void DisableRx(USB::Endpoint::EPNumber ep_num)
274{
275 switch (ep_num)
276 {
277 case USB::Endpoint::EPNumber::EP0:
278 USBHSD->ENDP_CONFIG &= ~USBHS_UEP0_R_EN;
279 break;
280 case USB::Endpoint::EPNumber::EP1:
281 USBHSD->ENDP_CONFIG &= ~USBHS_UEP1_R_EN;
282 break;
283 case USB::Endpoint::EPNumber::EP2:
284 USBHSD->ENDP_CONFIG &= ~USBHS_UEP2_R_EN;
285 break;
286 case USB::Endpoint::EPNumber::EP3:
287 USBHSD->ENDP_CONFIG &= ~USBHS_UEP3_R_EN;
288 break;
289 case USB::Endpoint::EPNumber::EP4:
290 USBHSD->ENDP_CONFIG &= ~USBHS_UEP4_R_EN;
291 break;
292 case USB::Endpoint::EPNumber::EP5:
293 USBHSD->ENDP_CONFIG &= ~USBHS_UEP5_R_EN;
294 break;
295 case USB::Endpoint::EPNumber::EP6:
296 USBHSD->ENDP_CONFIG &= ~USBHS_UEP6_R_EN;
297 break;
298 case USB::Endpoint::EPNumber::EP7:
299 USBHSD->ENDP_CONFIG &= ~USBHS_UEP7_R_EN;
300 break;
301 case USB::Endpoint::EPNumber::EP8:
302 USBHSD->ENDP_CONFIG &= ~USBHS_UEP8_R_EN;
303 break;
304 case USB::Endpoint::EPNumber::EP9:
305 USBHSD->ENDP_CONFIG &= ~USBHS_UEP9_R_EN;
306 break;
307 case USB::Endpoint::EPNumber::EP10:
308 USBHSD->ENDP_CONFIG &= ~USBHS_UEP10_R_EN;
309 break;
310 case USB::Endpoint::EPNumber::EP11:
311 USBHSD->ENDP_CONFIG &= ~USBHS_UEP11_R_EN;
312 break;
313 case USB::Endpoint::EPNumber::EP12:
314 USBHSD->ENDP_CONFIG &= ~USBHS_UEP12_R_EN;
315 break;
316 case USB::Endpoint::EPNumber::EP13:
317 USBHSD->ENDP_CONFIG &= ~USBHS_UEP13_R_EN;
318 break;
319 case USB::Endpoint::EPNumber::EP14:
320 USBHSD->ENDP_CONFIG &= ~USBHS_UEP14_R_EN;
321 break;
322 case USB::Endpoint::EPNumber::EP15:
323 USBHSD->ENDP_CONFIG &= ~USBHS_UEP15_R_EN;
324 break;
325 default:
326 break;
327 }
328}
329// NOLINTEND
330
331CH32EndpointOtgHs::CH32EndpointOtgHs(EPNumber ep_num, Direction dir,
332 LibXR::RawData buffer, bool double_buffer)
333 : Endpoint(ep_num, dir, buffer), hw_double_buffer_(double_buffer), dma_buffer_(buffer)
334{
335 map_otg_hs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
336
337 if (dir == Direction::IN)
338 {
339 SetTxDmaBuffer(GetNumber(), dma_buffer_.addr_, dma_buffer_.size_, double_buffer);
340 }
341 else
342 {
343 SetRxDmaBuffer(GetNumber(), dma_buffer_.addr_, dma_buffer_.size_, double_buffer);
344 }
345
346 if (dir == Direction::IN)
347 {
348 SetTxLen(GetNumber(), 0);
349 *GetTxControlAddr(GetNumber()) = USBHS_UEP_T_RES_NAK;
350 }
351 else
352 {
353 *GetRxControlAddr(GetNumber()) = USBHS_UEP_R_RES_NAK;
354 }
355}
356
357void CH32EndpointOtgHs::Configure(const Config& cfg)
358{
359 auto& ep_cfg = GetConfig();
360 ep_cfg = cfg;
361
362 if (GetNumber() != EPNumber::EP0 && hw_double_buffer_)
363 {
364 ep_cfg.double_buffer = true;
365 }
366 else
367 {
368 if (ep_cfg.double_buffer)
369 {
370 // Please enable double buffer for this endpoint
371 ASSERT(false);
372 }
373 ep_cfg.double_buffer = false;
374 }
375
376 if (ep_cfg.max_packet_size > GetBuffer().size_)
377 {
378 ep_cfg.max_packet_size = GetBuffer().size_;
379 }
380
381 *GetRxControlAddr(GetNumber()) = USBHS_UEP_R_RES_NAK;
382 *GetTxControlAddr(GetNumber()) = USBHS_UEP_T_RES_NAK;
383
384 SetTxLen(GetNumber(), 0);
385
387 {
388 EnableTx(GetNumber());
389 DisableRx(GetNumber());
390 SetTxDmaBuffer(GetNumber(), dma_buffer_.addr_, dma_buffer_.size_, hw_double_buffer_);
391 }
392 else
393 {
394 DisableTx(GetNumber());
395 EnableRx(GetNumber());
396 SetRxDmaBuffer(GetNumber(), dma_buffer_.addr_, dma_buffer_.size_, hw_double_buffer_);
397 }
398
400}
401
403{
404 DisableTx(GetNumber());
405 DisableRx(GetNumber());
406
407 *GetTxControlAddr(GetNumber()) = USBHS_UEP_T_RES_NAK;
408 *GetRxControlAddr(GetNumber()) = USBHS_UEP_R_RES_NAK;
409
411}
412
413ErrorCode CH32EndpointOtgHs::Transfer(size_t size)
414{
415 if (GetState() == State::BUSY)
416 {
417 return ErrorCode::BUSY;
418 }
419
420 auto buffer = GetBuffer();
421 if (buffer.size_ < size)
422 {
423 return ErrorCode::NO_BUFF;
424 }
425
426 bool is_in = (GetDirection() == Direction::IN);
427
428 if (is_in && UseDoubleBuffer())
429 {
430 SwitchBuffer();
431 }
432
433 if (GetNumber() == EPNumber::EP0)
434 {
435 if (size == 0)
436 {
437 tog0_ = true;
438 tog1_ = false;
439 }
440 }
441
442 last_transfer_size_ = size;
444
445 if (is_in)
446 {
447 SetTxLen(GetNumber(), size);
448 auto addr = GetTxControlAddr(GetNumber());
449
450 *addr = USBHS_UEP_T_RES_ACK |
451 (*addr & (~(USBHS_UEP_T_RES_MASK | USBHS_UEP_T_TOG_MDATA))) |
452 (tog0_ ? USBHS_UEP_T_TOG_DATA1 : 0);
453 }
454 else
455 {
456 auto addr = GetRxControlAddr(GetNumber());
457
458 *addr = USBHS_UEP_R_RES_ACK |
459 (*addr & (~(USBHS_UEP_R_RES_MASK | USBHS_UEP_R_TOG_MDATA))) |
460 (tog0_ ? USBHS_UEP_R_TOG_DATA1 : 0);
461 }
462
463 if (GetNumber() == EPNumber::EP0)
464 {
465 tog0_ = !tog0_;
466 }
467
468 return ErrorCode::OK;
469}
470
471ErrorCode CH32EndpointOtgHs::Stall()
472{
473 if (GetState() != State::IDLE)
474 {
475 return ErrorCode::BUSY;
476 }
477
478 bool is_in = (GetDirection() == Direction::IN);
479 if (is_in)
480 {
481 *GetTxControlAddr(GetNumber()) |= USBHS_UEP_T_RES_STALL;
482 }
483 else
484 {
485 *GetRxControlAddr(GetNumber()) |= USBHS_UEP_R_RES_STALL;
486 }
488 return ErrorCode::OK;
489}
490
492{
493 if (GetState() != State::STALLED)
494 {
495 return ErrorCode::FAILED;
496 }
497
498 bool is_in = (GetDirection() == Direction::IN);
499 if (is_in)
500 {
501 *GetTxControlAddr(GetNumber()) &= ~USBHS_UEP_T_RES_STALL;
502 }
503 else
504 {
505 *GetRxControlAddr(GetNumber()) &= ~USBHS_UEP_R_RES_STALL;
506 }
508 return ErrorCode::OK;
509}
510
511void CH32EndpointOtgHs::TransferComplete(size_t size)
512{
514 {
515 tog0_ = !tog0_;
516 }
517
519 {
520 *GetTxControlAddr(GetNumber()) =
521 (*GetTxControlAddr(GetNumber()) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_NAK;
522
523 USBHSD->INT_FG = USBHS_UIF_TRANSFER; // NOLINT
524
525 size = last_transfer_size_;
526 }
527
528 if (GetDirection() == Direction::OUT &&
529 (USBHSD->INT_ST & USBHS_UIS_TOG_OK) != USBHS_UIS_TOG_OK) // NOLINT
530 {
531 return;
532 }
533
535 {
536 tog0_ = true;
537 tog1_ = false;
538 *GetRxControlAddr(GetNumber()) = USBHS_UEP_R_RES_ACK;
539 }
540
541 OnTransferCompleteCallback(true, size);
542}
543
545{
547 {
548 SetActiveBlock(!tog0_);
549 }
550 else
551 {
552 SetActiveBlock(tog0_);
553 }
554}
555
556#endif
void Close() override
关闭端点(软禁用/资源复位) Close (soft disable)
ErrorCode Stall() override
停止端点传输 Stop endpoint transfer
ErrorCode ClearStall() override
清除端点停止状态 Clear endpoint stop status
ErrorCode Transfer(size_t size) override
传输数据 Transfer data
void Configure(const Config &cfg) override
二次初始化/配置端点协议参数(由Pool/Manager分配后调用) Configure endpoint protocol parameters (call after pool allocation...
void SwitchBuffer() override
切换缓冲区 Switch buffer
原始数据封装类。 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
@ EP0
端点0 / Endpoint 0
@ IN
输入方向 / IN direction
@ OUT
输出方向 / OUT direction
Direction GetDirection() const
获取端点方向 Get endpoint direction
Definition ep.hpp:186
bool UseDoubleBuffer() const
是否使用双缓冲区 / Use double buffer
Definition ep.hpp:248
Config & GetConfig()
获取当前配置 Get endpoint config
Definition ep.hpp:365
EPNumber GetNumber() const
获取端点号 Get endpoint number
Definition ep.hpp:174
@ DISABLED
禁用 / Disabled
@ STALLED
挂起 / Stalled
virtual void SetActiveBlock(bool active_block)
设置当前活动缓冲区 Set active buffer
Definition ep.hpp:384
void SetState(State state)
设置端点状态 Set endpoint state
Definition ep.hpp:220
State GetState() const
获取端点状态 Get endpoint state
Definition ep.hpp:212
RawData GetBuffer() const
获取端点缓冲区 Get endpoint buffer
Definition ep.hpp:256
LibXR 命名空间
Definition ch32_gpio.hpp:9