1#include "stm32_usb_ep.hpp"
5#if defined(HAL_PCD_MODULE_ENABLED)
7static inline bool is_power_of_two(
unsigned int n) {
return n > 0 && (n & (n - 1)) == 0; }
9#if defined(USB_OTG_HS) || defined(USB_OTG_FS)
10STM32Endpoint::STM32Endpoint(EPNumber ep_num, stm32_usb_dev_id_t
id,
11 PCD_HandleTypeDef* hpcd, Direction dir,
size_t fifo_size,
13 : Endpoint(ep_num, dir, buffer), hpcd_(hpcd), fifo_size_(fifo_size), id_(id)
15 ASSERT(fifo_size >= 8);
16 ASSERT(is_power_of_two(fifo_size) || fifo_size % 64 == 0);
17 ASSERT(is_power_of_two(buffer.
size_) || buffer.
size_ % 64 == 0);
19#if defined(USB_OTG_HS)
20 if (
id == STM32_USB_OTG_HS)
22 map_hs_[EPNumberToInt8(GetNumber())][
static_cast<uint8_t
>(dir)] =
this;
25#if defined(USB_OTG_FS)
26 if (
id == STM32_USB_OTG_FS)
28 map_fs_[EPNumberToInt8(GetNumber())][
static_cast<uint8_t
>(dir)] =
this;
32 if (dir == Direction::IN)
34 HAL_PCDEx_SetTxFiFo(hpcd_, EPNumberToInt8(GetNumber()), fifo_size / 4);
36 else if (dir == Direction::OUT && ep_num == USB::Endpoint::EPNumber::EP0)
38 HAL_PCDEx_SetRxFiFo(hpcd_, fifo_size / 4);
44STM32Endpoint::STM32Endpoint(EPNumber ep_num, stm32_usb_dev_id_t
id,
45 PCD_HandleTypeDef* hpcd, Direction dir,
46 size_t hw_buffer_offset,
size_t hw_buffer_size,
48 : Endpoint(ep_num, dir, buffer),
50 hw_buffer_size_(hw_buffer_size),
51 double_hw_buffer_(double_hw_buffer),
54 ASSERT(hw_buffer_size >= 8);
56 ASSERT(is_power_of_two(hw_buffer_size));
57 ASSERT(is_power_of_two(buffer.
size_) || buffer.
size_ % 64 == 0);
59 map_otg_fs_[EPNumberToInt8(GetNumber())][
static_cast<uint8_t
>(dir)] =
this;
61 size_t buffer_offset = hw_buffer_offset;
65 buffer_offset |= ((hw_buffer_offset + hw_buffer_size) << 16);
68 HAL_PCDEx_PMAConfig(hpcd_, EPNumberToAddr(GetNumber(), dir),
69 double_hw_buffer ? PCD_DBL_BUF : PCD_SNG_BUF, buffer_offset);
78 uint8_t type =
static_cast<uint8_t
>(cfg.
type);
80 size_t packet_size_limit = 0;
87#if defined(PCD_SPEED_HIGH_IN_FULL)
88 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
89 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
91 if (hpcd_->Init.speed == PCD_SPEED_FULL)
94 packet_size_limit = 64;
98 packet_size_limit = 512;
102#if defined(PCD_SPEED_HIGH_IN_FULL)
103 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
104 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
106 if (hpcd_->Init.speed == PCD_SPEED_FULL)
109 packet_size_limit = 64;
113 packet_size_limit = 1024;
117#if defined(PCD_SPEED_HIGH_IN_FULL)
118 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
119 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
121 if (hpcd_->Init.speed == PCD_SPEED_FULL)
124 packet_size_limit = 1023;
128 packet_size_limit = 1024;
132 packet_size_limit = 64;
138#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
139 if (packet_size_limit > fifo_size_)
141 packet_size_limit = fifo_size_;
146 if (packet_size_limit > hw_buffer_size_)
148 packet_size_limit = hw_buffer_size_;
154 if (packet_size_limit > buffer.
size_)
156 packet_size_limit = buffer.
size_;
161 if (max_packet_size > packet_size_limit)
163 max_packet_size = packet_size_limit;
166 ep_cfg.max_packet_size = max_packet_size;
168 if (max_packet_size < 8)
173 if (HAL_PCD_EP_Open(hpcd_, addr, max_packet_size, type) == HAL_OK)
186 HAL_PCD_EP_Close(hpcd_, addr);
194 return ErrorCode::BUSY;
200 PCD_EPTypeDef* ep = is_in ? &hpcd_->IN_ep[ep_addr & EP_ADDR_MSK]
201 : &hpcd_->OUT_ep[ep_addr & EP_ADDR_MSK];
205 if (buffer.
size_ < size)
207 return ErrorCode::NO_BUFF;
210 ep->xfer_buff =
reinterpret_cast<uint8_t*
>(buffer.
addr_);
219 ep->is_in = is_in ? 1U : 0U;
220 ep->num = ep_addr & EP_ADDR_MSK;
222#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
223 if (hpcd_->Init.dma_enable == 1U)
225 ep->dma_addr =
reinterpret_cast<uint32_t
>(ep->xfer_buff);
227#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
230 SCB_CleanDCache_by_Addr(
reinterpret_cast<uint32_t*
>(buffer.
addr_),
231 static_cast<int32_t
>(size));
240 ep->xfer_fill_db = 1U;
241 ep->xfer_len_db = size;
247#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
248 auto ans = USB_EPStartXfer(hpcd_->Instance, ep, hpcd_->Init.dma_enable);
250 auto ans = USB_EPStartXfer(hpcd_->Instance, ep);
254 OnTransferCompleteCallback(
false, 0);
260 return ErrorCode::OK;
265 return ErrorCode::FAILED;
273 return ErrorCode::BUSY;
277 if (HAL_PCD_EP_SetStall(hpcd_, addr) == HAL_OK)
280 return ErrorCode::OK;
285 return ErrorCode::FAILED;
293 return ErrorCode::FAILED;
301 return ErrorCode::OK;
304 if (HAL_PCD_EP_ClrStall(hpcd_, addr) == HAL_OK)
307 return ErrorCode::OK;
312 return ErrorCode::FAILED;
330static STM32Endpoint* GetEndpoint(PCD_HandleTypeDef* hpcd, uint8_t epnum,
bool is_in)
332 auto id = STM32USBDeviceGetID(hpcd);
333#if defined(USB_OTG_HS)
334 if (
id == STM32_USB_OTG_HS)
336 return STM32Endpoint::map_hs_[epnum & 0x7F][
static_cast<uint8_t
>(is_in)];
339#if defined(USB_OTG_FS)
340 if (
id == STM32_USB_OTG_FS)
342 return STM32Endpoint::map_fs_[epnum & 0x7F][
static_cast<uint8_t
>(is_in)];
346 if (
id == STM32_USB_FS_DEV)
348 return STM32Endpoint::map_otg_fs_[epnum & 0x7F][
static_cast<uint8_t
>(is_in)];
354extern "C" void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
356 auto id = STM32USBDeviceGetID(hpcd);
358 ASSERT(
id < STM32_USB_DEV_ID_NUM);
360 auto ep = GetEndpoint(hpcd, epnum,
true);
362 if (!ep || ep->hpcd_ != hpcd)
367 PCD_EPTypeDef* ep_handle = &hpcd->IN_ep[epnum & EP_ADDR_MSK];
369 size_t actual_transfer_size = ep_handle->xfer_count;
371 ep->OnTransferCompleteCallback(
true, actual_transfer_size);
374extern "C" void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
376 auto id = STM32USBDeviceGetID(hpcd);
378 ASSERT(
id < STM32_USB_DEV_ID_NUM);
380 auto ep = GetEndpoint(hpcd, epnum,
false);
382 if (!ep || ep->hpcd_ != hpcd)
387 PCD_EPTypeDef* ep_handle = &hpcd->OUT_ep[epnum & EP_ADDR_MSK];
389 size_t actual_transfer_size = ep_handle->xfer_count;
391#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
392 SCB_InvalidateDCache_by_Addr(ep->GetBuffer().addr_,
393 static_cast<int32_t
>(actual_transfer_size));
396 ep->OnTransferCompleteCallback(
true, actual_transfer_size);
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
ErrorCode Transfer(size_t size) override
传输数据 Transfer data
ErrorCode ClearStall() override
清除端点停止状态 Clear endpoint stop status
void Configure(const Config &cfg) override
二次初始化/配置端点协议参数(由Pool/Manager分配后调用) Configure endpoint protocol parameters (call after pool allocation...
void Close() override
关闭端点(软禁用/资源复位) Close (soft disable)
ErrorCode Stall() override
停止端点传输 Stop endpoint transfer
size_t MaxTransferSize() const override
返回最大可传输字节数 Return the maximum transferable size at this time
@ OUT
输出方向 / OUT direction
static constexpr uint8_t EPNumberToAddr(EPNumber ep, Direction dir)
端点号转换为端点地址 / Convert endpoint number to endpoint address
Direction GetDirection() const
获取端点方向 Get endpoint direction
bool UseDoubleBuffer() const
是否使用双缓冲区 / Use double buffer
virtual void SwitchBuffer()
切换缓冲区 Switch buffer
Config & GetConfig()
获取当前配置 Get endpoint config
@ ISOCHRONOUS
等时端点 / Isochronous
@ INTERRUPT
中断端点 / Interrupt
EPNumber GetNumber() const
获取端点号 Get endpoint number
uint16_t MaxPacketSize() const
获取最大包长 Get max packet size
void SetState(State state)
设置端点状态 Set endpoint state
State GetState() const
获取端点状态 Get endpoint state
RawData GetBuffer() const
获取端点缓冲区 Get endpoint buffer
端点配置结构体 Endpoint configuration struct
Type type
端点类型 / Endpoint type
uint16_t max_packet_size
最大包长 / Max packet size
Direction direction
端点方向 / Endpoint direction