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)
30{
31 *GetDmaAddr(ep_num) = (uint32_t)value;
32 switch (ep_num)
33 {
34 case USB::Endpoint::EPNumber::EP1:
35 USBFSD->UEP4_1_MOD |= USBFS_UEP1_BUF_MOD;
36 break;
37 case USB::Endpoint::EPNumber::EP2:
38 USBFSD->UEP2_3_MOD |= USBFS_UEP2_BUF_MOD;
39 break;
40 case USB::Endpoint::EPNumber::EP3:
41 USBFSD->UEP2_3_MOD |= USBFS_UEP3_BUF_MOD;
42 break;
43 case USB::Endpoint::EPNumber::EP4:
44 USBFSD->UEP4_1_MOD |= USBFS_UEP4_BUF_MOD;
45 break;
46 case USB::Endpoint::EPNumber::EP5:
47 USBFSD->UEP5_6_MOD |= USBFS_UEP5_BUF_MOD;
48 break;
49 case USB::Endpoint::EPNumber::EP6:
50 USBFSD->UEP5_6_MOD |= USBFS_UEP6_BUF_MOD;
51 break;
52 case USB::Endpoint::EPNumber::EP7:
53 USBFSD->UEP7_MOD |= USBFS_UEP7_BUF_MOD;
54 break;
55 default:
56 break;
57 }
58}
59
60static void SetTxLen(USB::Endpoint::EPNumber ep_num, uint32_t value)
61{
62 *GetTxLenAddr(ep_num) = value;
63}
64
65static void EnableTx(USB::Endpoint::EPNumber ep_num)
66{
67 switch (ep_num)
68 {
69 case USB::Endpoint::EPNumber::EP1:
70 USBFSD->UEP4_1_MOD |= USBFS_UEP1_TX_EN;
71 break;
72 case USB::Endpoint::EPNumber::EP2:
73 USBFSD->UEP2_3_MOD |= USBFS_UEP2_TX_EN;
74 break;
75 case USB::Endpoint::EPNumber::EP3:
76 USBFSD->UEP2_3_MOD |= USBFS_UEP3_TX_EN;
77 break;
78 case USB::Endpoint::EPNumber::EP4:
79 USBFSD->UEP4_1_MOD |= USBFS_UEP4_TX_EN;
80 break;
81 case USB::Endpoint::EPNumber::EP5:
82 USBFSD->UEP5_6_MOD |= USBFS_UEP5_TX_EN;
83 break;
84 case USB::Endpoint::EPNumber::EP6:
85 USBFSD->UEP5_6_MOD |= USBFS_UEP6_TX_EN;
86 break;
87 case USB::Endpoint::EPNumber::EP7:
88 USBFSD->UEP7_MOD |= USBFS_UEP7_TX_EN;
89 break;
90 default:
91 break;
92 }
93}
94static void DisableTx(USB::Endpoint::EPNumber ep_num)
95{
96 switch (ep_num)
97 {
98 case USB::Endpoint::EPNumber::EP1:
99 USBFSD->UEP4_1_MOD &= ~USBFS_UEP1_TX_EN;
100 break;
101 case USB::Endpoint::EPNumber::EP2:
102 USBFSD->UEP2_3_MOD &= ~USBFS_UEP2_TX_EN;
103 break;
104 case USB::Endpoint::EPNumber::EP3:
105 USBFSD->UEP2_3_MOD &= ~USBFS_UEP3_TX_EN;
106 break;
107 case USB::Endpoint::EPNumber::EP4:
108 USBFSD->UEP4_1_MOD &= ~USBFS_UEP4_TX_EN;
109 break;
110 case USB::Endpoint::EPNumber::EP5:
111 USBFSD->UEP5_6_MOD &= ~USBFS_UEP5_TX_EN;
112 break;
113 case USB::Endpoint::EPNumber::EP6:
114 USBFSD->UEP5_6_MOD &= ~USBFS_UEP6_TX_EN;
115 break;
116 case USB::Endpoint::EPNumber::EP7:
117 USBFSD->UEP7_MOD &= ~USBFS_UEP7_TX_EN;
118 break;
119 default:
120 break;
121 }
122}
123static void EnableRx(USB::Endpoint::EPNumber ep_num)
124{
125 switch (ep_num)
126 {
127 case USB::Endpoint::EPNumber::EP1:
128 USBFSD->UEP4_1_MOD |= USBFS_UEP1_RX_EN;
129 break;
130 case USB::Endpoint::EPNumber::EP2:
131 USBFSD->UEP2_3_MOD |= USBFS_UEP2_RX_EN;
132 break;
133 case USB::Endpoint::EPNumber::EP3:
134 USBFSD->UEP2_3_MOD |= USBFS_UEP3_RX_EN;
135 break;
136 case USB::Endpoint::EPNumber::EP4:
137 USBFSD->UEP4_1_MOD |= USBFS_UEP4_RX_EN;
138 break;
139 case USB::Endpoint::EPNumber::EP5:
140 USBFSD->UEP5_6_MOD |= USBFS_UEP5_RX_EN;
141 break;
142 case USB::Endpoint::EPNumber::EP6:
143 USBFSD->UEP5_6_MOD |= USBFS_UEP6_RX_EN;
144 break;
145 case USB::Endpoint::EPNumber::EP7:
146 USBFSD->UEP7_MOD |= USBFS_UEP7_RX_EN;
147 break;
148 default:
149 break;
150 }
151}
152static void DisableRx(USB::Endpoint::EPNumber ep_num)
153{
154 switch (ep_num)
155 {
156 case USB::Endpoint::EPNumber::EP1:
157 USBFSD->UEP4_1_MOD &= ~USBFS_UEP1_RX_EN;
158 break;
159 case USB::Endpoint::EPNumber::EP2:
160 USBFSD->UEP2_3_MOD &= ~USBFS_UEP2_RX_EN;
161 break;
162 case USB::Endpoint::EPNumber::EP3:
163 USBFSD->UEP2_3_MOD &= ~USBFS_UEP3_RX_EN;
164 break;
165 case USB::Endpoint::EPNumber::EP4:
166 USBFSD->UEP4_1_MOD &= ~USBFS_UEP4_RX_EN;
167 break;
168 case USB::Endpoint::EPNumber::EP5:
169 USBFSD->UEP5_6_MOD &= ~USBFS_UEP5_RX_EN;
170 break;
171 case USB::Endpoint::EPNumber::EP6:
172 USBFSD->UEP5_6_MOD &= ~USBFS_UEP6_RX_EN;
173 break;
174 case USB::Endpoint::EPNumber::EP7:
175 USBFSD->UEP7_MOD &= ~USBFS_UEP7_RX_EN;
176 break;
177 default:
178 break;
179 }
180}
181// NOLINTEND
182
183// NOLINTNEXTLINE
184static LibXR::RawData SelectBuffer(USB::Endpoint::EPNumber ep_num,
186 const LibXR::RawData& buffer)
187{
188 if (ep_num == USB::Endpoint::EPNumber::EP0)
189 {
190 return buffer;
191 }
192 else
193 {
194 if (dir == USB::Endpoint::Direction::OUT)
195 {
196 return LibXR::RawData(buffer.addr_, 128);
197 }
198 else
199 {
200 return LibXR::RawData(reinterpret_cast<uint8_t*>(buffer.addr_) + 128, 128);
201 }
202 }
203}
204
205CH32EndpointOtgFs::CH32EndpointOtgFs(EPNumber ep_num, Direction dir,
206 LibXR::RawData buffer)
207 : Endpoint(ep_num, dir, SelectBuffer(ep_num, dir, buffer)), dma_buffer_(buffer)
208{
209 map_otg_fs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
210
211 SetDmaBuffer(GetNumber(), dma_buffer_.addr_);
212
213 if (dir == Direction::IN)
214 {
215 SetTxLen(GetNumber(), 0);
216 *GetTxCtrlAddr(GetNumber()) = USBFS_UEP_T_RES_NAK;
217 }
218 else
219 {
220 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_NAK;
221 }
222}
223
224void CH32EndpointOtgFs::Configure(const Config& cfg)
225{
226 auto& ep_cfg = GetConfig();
227 ep_cfg = cfg;
228 ep_cfg.max_packet_size = 64;
229
230 if (GetNumber() != EPNumber::EP0)
231 {
232 ep_cfg.double_buffer = true;
233 }
234 else
235 {
236 ep_cfg.double_buffer = false;
237 }
238
239 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_NAK | USBFS_UEP_R_AUTO_TOG;
240 *GetTxCtrlAddr(GetNumber()) = USBFS_UEP_T_RES_NAK | USBFS_UEP_T_AUTO_TOG;
241
242 SetTxLen(GetNumber(), 0);
243
244 EnableTx(GetNumber());
245 EnableRx(GetNumber());
246 SetDmaBuffer(GetNumber(), dma_buffer_.addr_);
247
249}
250
252{
253 DisableTx(GetNumber());
254 DisableRx(GetNumber());
255
256 *GetTxCtrlAddr(GetNumber()) = USBFS_UEP_T_RES_NAK;
257 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_NAK;
258
260}
261
262ErrorCode CH32EndpointOtgFs::Transfer(size_t size)
263{
264 if (GetState() == State::BUSY)
265 {
266 return ErrorCode::BUSY;
267 }
268
269 auto buffer = GetBuffer();
270 if (buffer.size_ < size)
271 {
272 return ErrorCode::NO_BUFF;
273 }
274
275 bool is_in = (GetDirection() == Direction::IN);
276
277 if (is_in && UseDoubleBuffer())
278 {
279 SwitchBuffer();
280 }
281
282 if (is_in)
283 {
284 SetTxLen(GetNumber(), size);
285 auto addr = GetTxCtrlAddr(GetNumber());
286
287 if (GetNumber() != EPNumber::EP0)
288 {
289 *addr = USBFS_UEP_T_RES_ACK | (*addr & (~USBFS_UEP_T_RES_MASK));
290 }
291 else
292 {
293 *addr = USBFS_UEP_T_RES_ACK | (tog_ ? USBFS_UEP_T_TOG : 0);
294 }
295 }
296 else
297 {
298 auto addr = GetRxCtrlAddr(GetNumber());
299
300 if (GetNumber() != EPNumber::EP0)
301 {
302 *addr = USBFS_UEP_R_RES_ACK | (*addr & (~USBFS_UEP_R_RES_MASK));
303 }
304 else
305 {
306 *addr = USBFS_UEP_R_RES_ACK | (tog_ ? USBFS_UEP_R_TOG : 0);
307 }
308 }
309
310 if (GetNumber() == EPNumber::EP0)
311 {
312 tog_ = !tog_;
313 }
314
315 last_transfer_size_ = size;
317 return ErrorCode::OK;
318}
319
320ErrorCode CH32EndpointOtgFs::Stall()
321{
322 if (GetState() != State::IDLE)
323 {
324 return ErrorCode::BUSY;
325 }
326
327 bool is_in = (GetDirection() == Direction::IN);
328 if (is_in)
329 {
330 *GetTxCtrlAddr(GetNumber()) |= USBFS_UEP_T_RES_STALL;
331 }
332 else
333 {
334 *GetRxCtrlAddr(GetNumber()) |= USBFS_UEP_R_RES_STALL;
335 }
337 return ErrorCode::OK;
338}
339
341{
342 if (GetState() != State::STALLED)
343 {
344 return ErrorCode::FAILED;
345 }
346
347 bool is_in = (GetDirection() == Direction::IN);
348 if (is_in)
349 {
350 *GetTxCtrlAddr(GetNumber()) &= ~USBFS_UEP_T_RES_STALL;
351 }
352 else
353 {
354 *GetRxCtrlAddr(GetNumber()) &= ~USBFS_UEP_R_RES_STALL;
355 }
357 return ErrorCode::OK;
358}
359
360void CH32EndpointOtgFs::TransferComplete(size_t size)
361{
363 {
364 size = last_transfer_size_;
365 }
366
367 if (GetDirection() == Direction::OUT &&
368 (USBFSD->INT_FG & USBFS_U_TOG_OK) != USBFS_U_TOG_OK) // NOLINT
369 {
370 return;
371 }
372
374 {
375 tog_ = true;
376 *GetRxCtrlAddr(GetNumber()) = USBFS_UEP_R_RES_ACK;
377 }
378
380 {
381 *GetTxCtrlAddr(GetNumber()) =
382 (*GetTxCtrlAddr(GetNumber()) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
383 USBFSD->INT_FG = USBFS_UIF_TRANSFER; // NOLINT
384 }
385
386 OnTransferCompleteCallback(false, size);
387}
388
390{
392 {
393 tog_ = (*GetTxCtrlAddr(GetNumber()) & USBFS_UEP_T_TOG) == USBFS_UEP_T_TOG;
394 SetActiveBlock(!tog_);
395 }
396 else
397 {
398 tog_ = (*GetRxCtrlAddr(GetNumber()) & USBFS_UEP_R_TOG) == USBFS_UEP_R_TOG;
399 SetActiveBlock(tog_);
400 }
401}
402
403#endif
void SwitchBuffer() override
切换缓冲区 Switch buffer
ErrorCode ClearStall() override
清除端点停止状态 Clear endpoint stop status
void Close() override
关闭端点(软禁用/资源复位) Close (soft disable)
ErrorCode Stall() override
停止端点传输 Stop endpoint transfer
void Configure(const Config &cfg) override
二次初始化/配置端点协议参数(由Pool/Manager分配后调用) Configure endpoint protocol parameters (call after pool allocation...
ErrorCode Transfer(size_t size) override
传输数据 Transfer data
原始数据封装类。 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
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
@ 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