3#include "ch32_usb_endpoint.hpp"
31 *GetDmaAddr(ep_num) = (uint32_t)value;
40 case USB::Endpoint::EPNumber::EP1:
41 USBFSD->UEP4_1_MOD |= USBFS_UEP1_BUF_MOD;
43 case USB::Endpoint::EPNumber::EP2:
44 USBFSD->UEP2_3_MOD |= USBFS_UEP2_BUF_MOD;
46 case USB::Endpoint::EPNumber::EP3:
47 USBFSD->UEP2_3_MOD |= USBFS_UEP3_BUF_MOD;
49 case USB::Endpoint::EPNumber::EP4:
50 USBFSD->UEP4_1_MOD |= USBFS_UEP4_BUF_MOD;
52 case USB::Endpoint::EPNumber::EP5:
53 USBFSD->UEP5_6_MOD |= USBFS_UEP5_BUF_MOD;
55 case USB::Endpoint::EPNumber::EP6:
56 USBFSD->UEP5_6_MOD |= USBFS_UEP6_BUF_MOD;
58 case USB::Endpoint::EPNumber::EP7:
59 USBFSD->UEP7_MOD |= USBFS_UEP7_BUF_MOD;
68 *GetTxLenAddr(ep_num) = value;
75 case USB::Endpoint::EPNumber::EP1:
76 USBFSD->UEP4_1_MOD |= USBFS_UEP1_TX_EN;
78 case USB::Endpoint::EPNumber::EP2:
79 USBFSD->UEP2_3_MOD |= USBFS_UEP2_TX_EN;
81 case USB::Endpoint::EPNumber::EP3:
82 USBFSD->UEP2_3_MOD |= USBFS_UEP3_TX_EN;
84 case USB::Endpoint::EPNumber::EP4:
85 USBFSD->UEP4_1_MOD |= USBFS_UEP4_TX_EN;
87 case USB::Endpoint::EPNumber::EP5:
88 USBFSD->UEP5_6_MOD |= USBFS_UEP5_TX_EN;
90 case USB::Endpoint::EPNumber::EP6:
91 USBFSD->UEP5_6_MOD |= USBFS_UEP6_TX_EN;
93 case USB::Endpoint::EPNumber::EP7:
94 USBFSD->UEP7_MOD |= USBFS_UEP7_TX_EN;
104 case USB::Endpoint::EPNumber::EP1:
105 USBFSD->UEP4_1_MOD &= ~USBFS_UEP1_TX_EN;
107 case USB::Endpoint::EPNumber::EP2:
108 USBFSD->UEP2_3_MOD &= ~USBFS_UEP2_TX_EN;
110 case USB::Endpoint::EPNumber::EP3:
111 USBFSD->UEP2_3_MOD &= ~USBFS_UEP3_TX_EN;
113 case USB::Endpoint::EPNumber::EP4:
114 USBFSD->UEP4_1_MOD &= ~USBFS_UEP4_TX_EN;
116 case USB::Endpoint::EPNumber::EP5:
117 USBFSD->UEP5_6_MOD &= ~USBFS_UEP5_TX_EN;
119 case USB::Endpoint::EPNumber::EP6:
120 USBFSD->UEP5_6_MOD &= ~USBFS_UEP6_TX_EN;
122 case USB::Endpoint::EPNumber::EP7:
123 USBFSD->UEP7_MOD &= ~USBFS_UEP7_TX_EN;
133 case USB::Endpoint::EPNumber::EP1:
134 USBFSD->UEP4_1_MOD |= USBFS_UEP1_RX_EN;
136 case USB::Endpoint::EPNumber::EP2:
137 USBFSD->UEP2_3_MOD |= USBFS_UEP2_RX_EN;
139 case USB::Endpoint::EPNumber::EP3:
140 USBFSD->UEP2_3_MOD |= USBFS_UEP3_RX_EN;
142 case USB::Endpoint::EPNumber::EP4:
143 USBFSD->UEP4_1_MOD |= USBFS_UEP4_RX_EN;
145 case USB::Endpoint::EPNumber::EP5:
146 USBFSD->UEP5_6_MOD |= USBFS_UEP5_RX_EN;
148 case USB::Endpoint::EPNumber::EP6:
149 USBFSD->UEP5_6_MOD |= USBFS_UEP6_RX_EN;
151 case USB::Endpoint::EPNumber::EP7:
152 USBFSD->UEP7_MOD |= USBFS_UEP7_RX_EN;
162 case USB::Endpoint::EPNumber::EP1:
163 USBFSD->UEP4_1_MOD &= ~USBFS_UEP1_RX_EN;
165 case USB::Endpoint::EPNumber::EP2:
166 USBFSD->UEP2_3_MOD &= ~USBFS_UEP2_RX_EN;
168 case USB::Endpoint::EPNumber::EP3:
169 USBFSD->UEP2_3_MOD &= ~USBFS_UEP3_RX_EN;
171 case USB::Endpoint::EPNumber::EP4:
172 USBFSD->UEP4_1_MOD &= ~USBFS_UEP4_RX_EN;
174 case USB::Endpoint::EPNumber::EP5:
175 USBFSD->UEP5_6_MOD &= ~USBFS_UEP5_RX_EN;
177 case USB::Endpoint::EPNumber::EP6:
178 USBFSD->UEP5_6_MOD &= ~USBFS_UEP6_RX_EN;
180 case USB::Endpoint::EPNumber::EP7:
181 USBFSD->UEP7_MOD &= ~USBFS_UEP7_RX_EN;
194 if (ep_num == USB::Endpoint::EPNumber::EP0)
200 if (dir == USB::Endpoint::Direction::OUT)
211CH32EndpointOtgFs::CH32EndpointOtgFs(EPNumber ep_num, Direction dir,
213 : Endpoint(ep_num, dir, is_isochronous ? buffer : SelectBuffer(ep_num, dir, buffer)),
214 is_isochronous_(is_isochronous),
217 map_otg_fs_[EPNumberToInt8(GetNumber())][
static_cast<uint8_t
>(dir)] =
this;
219 SetDmaBuffer(GetNumber(), dma_buffer_.addr_, is_isochronous ?
false :
true);
221 if (dir == Direction::IN)
223 SetTxLen(GetNumber(), 0);
224 *GetTxCtrlAddr(GetNumber()) = USBFS_UEP_T_RES_NAK;
228 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_NAK;
232void CH32EndpointOtgFs::Configure(
const Config& cfg)
234 auto& ep_cfg = GetConfig();
237 if (GetNumber() != EPNumber::EP0 && !is_isochronous_)
239 ep_cfg.double_buffer =
true;
243 ep_cfg.double_buffer =
false;
246 ep_cfg.max_packet_size = GetBuffer().size_;
248 SetTxLen(GetNumber(), 0);
250 if (!is_isochronous_)
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());
259 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_NAK;
260 *GetTxCtrlAddr(GetNumber()) = USBFS_UEP_T_RES_NAK;
261 if (GetDirection() == Direction::IN)
263 EnableTx(GetNumber());
267 EnableRx(GetNumber());
271 SetDmaBuffer(GetNumber(), dma_buffer_.addr_, is_isochronous_ ?
false :
true);
273 SetState(State::IDLE);
276void CH32EndpointOtgFs::Close()
278 DisableTx(GetNumber());
279 DisableRx(GetNumber());
281 *GetTxCtrlAddr(GetNumber()) = USBFS_UEP_T_RES_NAK;
282 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_NAK;
284 SetState(State::DISABLED);
287ErrorCode CH32EndpointOtgFs::Transfer(
size_t size)
289 if (GetState() == State::BUSY)
291 return ErrorCode::BUSY;
294 auto buffer = GetBuffer();
295 if (buffer.
size_ < size)
297 return ErrorCode::NO_BUFF;
300 bool is_in = (GetDirection() == Direction::IN);
302 if (is_in && UseDoubleBuffer())
309 SetTxLen(GetNumber(), size);
310 auto addr = GetTxCtrlAddr(GetNumber());
312 if (GetNumber() != EPNumber::EP0)
314 *addr = (is_isochronous_ ? USBFS_UEP_T_RES_NONE : USBFS_UEP_T_RES_ACK) |
315 (*addr & (~USBFS_UEP_T_RES_MASK));
319 *addr = USBFS_UEP_T_RES_ACK | (tog_ ? USBFS_UEP_T_TOG : 0);
324 auto addr = GetRxCtrlAddr(GetNumber());
326 if (GetNumber() != EPNumber::EP0)
328 *addr = (is_isochronous_ ? USBFS_UEP_R_RES_NONE : USBFS_UEP_R_RES_ACK) |
329 (*addr & (~USBFS_UEP_R_RES_MASK));
333 *addr = USBFS_UEP_R_RES_ACK | (tog_ ? USBFS_UEP_R_TOG : 0);
337 if (GetNumber() == EPNumber::EP0)
342 last_transfer_size_ = size;
343 SetState(State::BUSY);
344 return ErrorCode::OK;
347ErrorCode CH32EndpointOtgFs::Stall()
349 if (GetState() != State::IDLE)
351 return ErrorCode::BUSY;
354 bool is_in = (GetDirection() == Direction::IN);
357 *GetTxCtrlAddr(GetNumber()) |= USBFS_UEP_T_RES_STALL;
361 *GetRxCtrlAddr(GetNumber()) |= USBFS_UEP_R_RES_STALL;
363 SetState(State::STALLED);
364 return ErrorCode::OK;
367ErrorCode CH32EndpointOtgFs::ClearStall()
369 if (GetState() != State::STALLED)
371 return ErrorCode::FAILED;
374 bool is_in = (GetDirection() == Direction::IN);
377 *GetTxCtrlAddr(GetNumber()) &= ~USBFS_UEP_T_RES_STALL;
381 *GetRxCtrlAddr(GetNumber()) &= ~USBFS_UEP_R_RES_STALL;
383 SetState(State::IDLE);
384 return ErrorCode::OK;
387void CH32EndpointOtgFs::TransferComplete(
size_t size)
389 if (GetDirection() == Direction::IN)
391 size = last_transfer_size_;
394 if (GetDirection() == Direction::OUT &&
395 (USBFSD->INT_FG & USBFS_U_TOG_OK) != USBFS_U_TOG_OK)
400 if (GetNumber() == EPNumber::EP0 && GetDirection() == Direction::OUT)
403 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_ACK;
406 if (GetDirection() == Direction::IN)
408 *GetTxCtrlAddr(GetNumber()) =
409 (*GetTxCtrlAddr(GetNumber()) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
410 USBFSD->INT_FG = USBFS_UIF_TRANSFER;
413 OnTransferCompleteCallback(
true, size);
416void CH32EndpointOtgFs::SwitchBuffer()
418 if (GetDirection() == Direction::IN)
420 tog_ = (*GetTxCtrlAddr(GetNumber()) & USBFS_UEP_T_TOG) == USBFS_UEP_T_TOG;
421 SetActiveBlock(!tog_);
425 tog_ = (*GetRxCtrlAddr(GetNumber()) & USBFS_UEP_R_TOG) == USBFS_UEP_R_TOG;
426 SetActiveBlock(tog_);
原始数据封装类。 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
static constexpr uint8_t EPNumberToInt8(EPNumber ep)
端点号转换为uint8_t / Convert endpoint number to uint8_t
Direction
端点方向 Endpoint direction