3#include "ch32_usb_endpoint.hpp"
32 *get_dma_addr(ep_num) = (uint32_t)value;
41 case USB::Endpoint::EPNumber::EP1:
42 USBFSD->UEP4_1_MOD |= USBFS_UEP1_BUF_MOD;
44 case USB::Endpoint::EPNumber::EP2:
45 USBFSD->UEP2_3_MOD |= USBFS_UEP2_BUF_MOD;
47 case USB::Endpoint::EPNumber::EP3:
48 USBFSD->UEP2_3_MOD |= USBFS_UEP3_BUF_MOD;
50 case USB::Endpoint::EPNumber::EP4:
51 USBFSD->UEP4_1_MOD |= USBFS_UEP4_BUF_MOD;
53 case USB::Endpoint::EPNumber::EP5:
54 USBFSD->UEP5_6_MOD |= USBFS_UEP5_BUF_MOD;
56 case USB::Endpoint::EPNumber::EP6:
57 USBFSD->UEP5_6_MOD |= USBFS_UEP6_BUF_MOD;
59 case USB::Endpoint::EPNumber::EP7:
60 USBFSD->UEP7_MOD |= USBFS_UEP7_BUF_MOD;
69 *get_tx_len_addr(ep_num) = value;
76 case USB::Endpoint::EPNumber::EP1:
77 USBFSD->UEP4_1_MOD |= USBFS_UEP1_TX_EN;
79 case USB::Endpoint::EPNumber::EP2:
80 USBFSD->UEP2_3_MOD |= USBFS_UEP2_TX_EN;
82 case USB::Endpoint::EPNumber::EP3:
83 USBFSD->UEP2_3_MOD |= USBFS_UEP3_TX_EN;
85 case USB::Endpoint::EPNumber::EP4:
86 USBFSD->UEP4_1_MOD |= USBFS_UEP4_TX_EN;
88 case USB::Endpoint::EPNumber::EP5:
89 USBFSD->UEP5_6_MOD |= USBFS_UEP5_TX_EN;
91 case USB::Endpoint::EPNumber::EP6:
92 USBFSD->UEP5_6_MOD |= USBFS_UEP6_TX_EN;
94 case USB::Endpoint::EPNumber::EP7:
95 USBFSD->UEP7_MOD |= USBFS_UEP7_TX_EN;
105 case USB::Endpoint::EPNumber::EP1:
106 USBFSD->UEP4_1_MOD &= ~USBFS_UEP1_TX_EN;
108 case USB::Endpoint::EPNumber::EP2:
109 USBFSD->UEP2_3_MOD &= ~USBFS_UEP2_TX_EN;
111 case USB::Endpoint::EPNumber::EP3:
112 USBFSD->UEP2_3_MOD &= ~USBFS_UEP3_TX_EN;
114 case USB::Endpoint::EPNumber::EP4:
115 USBFSD->UEP4_1_MOD &= ~USBFS_UEP4_TX_EN;
117 case USB::Endpoint::EPNumber::EP5:
118 USBFSD->UEP5_6_MOD &= ~USBFS_UEP5_TX_EN;
120 case USB::Endpoint::EPNumber::EP6:
121 USBFSD->UEP5_6_MOD &= ~USBFS_UEP6_TX_EN;
123 case USB::Endpoint::EPNumber::EP7:
124 USBFSD->UEP7_MOD &= ~USBFS_UEP7_TX_EN;
134 case USB::Endpoint::EPNumber::EP1:
135 USBFSD->UEP4_1_MOD |= USBFS_UEP1_RX_EN;
137 case USB::Endpoint::EPNumber::EP2:
138 USBFSD->UEP2_3_MOD |= USBFS_UEP2_RX_EN;
140 case USB::Endpoint::EPNumber::EP3:
141 USBFSD->UEP2_3_MOD |= USBFS_UEP3_RX_EN;
143 case USB::Endpoint::EPNumber::EP4:
144 USBFSD->UEP4_1_MOD |= USBFS_UEP4_RX_EN;
146 case USB::Endpoint::EPNumber::EP5:
147 USBFSD->UEP5_6_MOD |= USBFS_UEP5_RX_EN;
149 case USB::Endpoint::EPNumber::EP6:
150 USBFSD->UEP5_6_MOD |= USBFS_UEP6_RX_EN;
152 case USB::Endpoint::EPNumber::EP7:
153 USBFSD->UEP7_MOD |= USBFS_UEP7_RX_EN;
163 case USB::Endpoint::EPNumber::EP1:
164 USBFSD->UEP4_1_MOD &= ~USBFS_UEP1_RX_EN;
166 case USB::Endpoint::EPNumber::EP2:
167 USBFSD->UEP2_3_MOD &= ~USBFS_UEP2_RX_EN;
169 case USB::Endpoint::EPNumber::EP3:
170 USBFSD->UEP2_3_MOD &= ~USBFS_UEP3_RX_EN;
172 case USB::Endpoint::EPNumber::EP4:
173 USBFSD->UEP4_1_MOD &= ~USBFS_UEP4_RX_EN;
175 case USB::Endpoint::EPNumber::EP5:
176 USBFSD->UEP5_6_MOD &= ~USBFS_UEP5_RX_EN;
178 case USB::Endpoint::EPNumber::EP6:
179 USBFSD->UEP5_6_MOD &= ~USBFS_UEP6_RX_EN;
181 case USB::Endpoint::EPNumber::EP7:
182 USBFSD->UEP7_MOD &= ~USBFS_UEP7_RX_EN;
195 if (ep_num == USB::Endpoint::EPNumber::EP0)
200 const size_t half = buffer.
size_ / 2u;
203 if (dir == USB::Endpoint::Direction::OUT)
211CH32EndpointOtgFs::CH32EndpointOtgFs(EPNumber ep_num, Direction dir,
213 : Endpoint(ep_num, dir,
214 (single_direction || ep_num == EPNumber::EP0)
216 : select_buffer(ep_num, dir, buffer)),
217 single_direction_(single_direction),
220 map_otg_fs_[EPNumberToInt8(GetNumber())][
static_cast<uint8_t
>(dir)] =
this;
222 set_dma_buffer(GetNumber(), dma_buffer_.addr_,
false);
224 if (dir == Direction::IN)
226 set_tx_len(GetNumber(), 0);
227 *get_tx_ctrl_addr(GetNumber()) = USBFS_UEP_T_RES_NAK;
231 *get_rx_ctrl_addr(GetNumber()) = USBFS_UEP_R_RES_NAK;
235void CH32EndpointOtgFs::Configure(
const Config& cfg)
237 auto& ep_cfg = GetConfig();
239 is_isochronous_ = (cfg.type == Type::ISOCHRONOUS);
241 const bool is_ep0 = (GetNumber() == EPNumber::EP0);
242 const bool is_bidir_noniso = !is_ep0 && !single_direction_ && !is_isochronous_;
243 const bool is_single_noniso = !is_ep0 && single_direction_ && !is_isochronous_;
244 const uint16_t type_limit = is_isochronous_ ? 1023u : 64u;
252 ASSERT(dma_buffer_.size_ >=
static_cast<size_t>(requested_mps) * 2u);
255 ep_cfg.double_buffer = is_single_noniso;
263 set_tx_len(GetNumber(), 0);
265 if (!is_isochronous_)
267 *get_rx_ctrl_addr(GetNumber()) = USBFS_UEP_R_RES_NAK | USBFS_UEP_R_AUTO_TOG;
268 *get_tx_ctrl_addr(GetNumber()) = USBFS_UEP_T_RES_NAK | USBFS_UEP_T_AUTO_TOG;
269 enable_tx(GetNumber());
270 enable_rx(GetNumber());
274 *get_rx_ctrl_addr(GetNumber()) = USBFS_UEP_R_RES_NAK;
275 *get_tx_ctrl_addr(GetNumber()) = USBFS_UEP_T_RES_NAK;
276 if (GetDirection() == Direction::IN)
278 enable_tx(GetNumber());
282 enable_rx(GetNumber());
286 set_dma_buffer(GetNumber(), dma_buffer_.addr_, ep_cfg.double_buffer);
288 SetState(State::IDLE);
291void CH32EndpointOtgFs::Close()
293 disable_tx(GetNumber());
294 disable_rx(GetNumber());
296 *get_tx_ctrl_addr(GetNumber()) = USBFS_UEP_T_RES_NAK;
297 *get_rx_ctrl_addr(GetNumber()) = USBFS_UEP_R_RES_NAK;
299 SetState(State::DISABLED);
302ErrorCode CH32EndpointOtgFs::Transfer(
size_t size)
304 if (GetState() == State::BUSY)
306 return ErrorCode::BUSY;
309 auto buffer = GetBuffer();
310 if (buffer.
size_ < size)
312 return ErrorCode::NO_BUFF;
315 bool is_in = (GetDirection() == Direction::IN);
317 if (is_in && UseDoubleBuffer())
324 set_tx_len(GetNumber(), size);
325 auto addr = get_tx_ctrl_addr(GetNumber());
327 if (GetNumber() != EPNumber::EP0)
329 *addr = (is_isochronous_ ? USBFS_UEP_T_RES_NONE : USBFS_UEP_T_RES_ACK) |
330 (*addr & (~USBFS_UEP_T_RES_MASK));
334 *addr = USBFS_UEP_T_RES_ACK | (tog_ ? USBFS_UEP_T_TOG : 0);
339 auto addr = get_rx_ctrl_addr(GetNumber());
341 if (GetNumber() != EPNumber::EP0)
343 *addr = (is_isochronous_ ? USBFS_UEP_R_RES_NONE : USBFS_UEP_R_RES_ACK) |
344 (*addr & (~USBFS_UEP_R_RES_MASK));
348 *addr = USBFS_UEP_R_RES_ACK | (tog_ ? USBFS_UEP_R_TOG : 0);
352 if (GetNumber() == EPNumber::EP0)
357 last_transfer_size_ = size;
358 SetState(State::BUSY);
359 return ErrorCode::OK;
364 const bool is_in = (GetDirection() == Direction::IN);
365 if (GetState() != State::IDLE && !(GetState() == State::BUSY && !is_in))
367 return ErrorCode::BUSY;
372 *get_tx_ctrl_addr(GetNumber()) |= USBFS_UEP_T_RES_STALL;
376 *get_rx_ctrl_addr(GetNumber()) |= USBFS_UEP_R_RES_STALL;
378 SetState(State::STALLED);
379 return ErrorCode::OK;
384 if (GetState() != State::STALLED)
386 return ErrorCode::FAILED;
389 bool is_in = (GetDirection() == Direction::IN);
392 *get_tx_ctrl_addr(GetNumber()) &= ~USBFS_UEP_T_RES_STALL;
396 *get_rx_ctrl_addr(GetNumber()) &= ~USBFS_UEP_R_RES_STALL;
398 SetState(State::IDLE);
399 return ErrorCode::OK;
402void CH32EndpointOtgFs::TransferComplete(
size_t size)
404 const bool IS_IN = (GetDirection() == Direction::IN);
405 const bool IS_OUT = !IS_IN;
406 const bool IS_EP0 = (GetNumber() == EPNumber::EP0);
407 const bool IS_ISO = (GetType() == Type::ISOCHRONOUS);
416 *get_tx_ctrl_addr(GetNumber()) =
417 (*get_tx_ctrl_addr(GetNumber()) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
419 size = last_transfer_size_;
427 *get_rx_ctrl_addr(GetNumber()) =
428 (*get_rx_ctrl_addr(GetNumber()) & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_NAK;
436 const bool TOG_OK = ((USBFSD->INT_ST & USBFS_U_TOG_OK) == USBFS_U_TOG_OK);
439 SetState(State::IDLE);
440 (void)Transfer(last_transfer_size_);
447 if (GetState() == State::BUSY && !IS_EP0 && !IS_ISO)
452 if (IS_EP0 && IS_OUT)
455 *get_rx_ctrl_addr(GetNumber()) = USBFS_UEP_R_RES_ACK;
458 OnTransferCompleteCallback(
true, size);
461void CH32EndpointOtgFs::SwitchBuffer()
463 if (GetDirection() == Direction::IN)
465 tog_ = (*get_tx_ctrl_addr(GetNumber()) & USBFS_UEP_T_TOG) == USBFS_UEP_T_TOG;
466 SetActiveBlock(!tog_);
470 tog_ = (*get_rx_ctrl_addr(GetNumber()) & USBFS_UEP_R_TOG) == USBFS_UEP_R_TOG;
471 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
constexpr auto min(LeftType a, RightType b) -> std::common_type_t< LeftType, RightType >
计算两个数的最小值