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)
11STM32Endpoint::STM32Endpoint(EPNumber ep_num, stm32_usb_dev_id_t
id,
12 PCD_HandleTypeDef* hpcd, Direction dir,
size_t fifo_size,
14 : Endpoint(ep_num, dir, buffer), hpcd_(hpcd), fifo_size_(fifo_size), id_(id)
16 ASSERT(fifo_size >= 8);
17 ASSERT(is_power_of_two(fifo_size) || fifo_size % 4 == 0);
18 ASSERT(is_power_of_two(buffer.
size_) || buffer.
size_ % 4 == 0);
20#if defined(USB_OTG_HS)
21 if (
id == STM32_USB_OTG_HS)
23 map_hs_[EPNumberToInt8(GetNumber())][
static_cast<uint8_t
>(dir)] =
this;
26#if defined(USB_OTG_FS)
27 if (
id == STM32_USB_OTG_FS)
29 map_fs_[EPNumberToInt8(GetNumber())][
static_cast<uint8_t
>(dir)] =
this;
33 if (dir == Direction::IN)
35 HAL_PCDEx_SetTxFiFo(hpcd_, EPNumberToInt8(GetNumber()), fifo_size / 4);
37 else if (dir == Direction::OUT && ep_num == USB::Endpoint::EPNumber::EP0)
39 HAL_PCDEx_SetRxFiFo(hpcd_, fifo_size / 4);
45STM32Endpoint::STM32Endpoint(EPNumber ep_num, stm32_usb_dev_id_t
id,
46 PCD_HandleTypeDef* hpcd, Direction dir,
47 size_t hw_buffer_offset,
size_t hw_buffer_size,
49 : Endpoint(ep_num, dir, buffer),
51 hw_buffer_size_(hw_buffer_size),
52 double_hw_buffer_(double_hw_buffer),
55 ASSERT(hw_buffer_size >= 8);
57 ASSERT(is_power_of_two(hw_buffer_size));
58 ASSERT(is_power_of_two(buffer.
size_) || buffer.
size_ % 4 == 0);
60 map_otg_fs_[EPNumberToInt8(GetNumber())][
static_cast<uint8_t
>(dir)] =
this;
62 size_t buffer_offset = hw_buffer_offset;
66 buffer_offset |= ((hw_buffer_offset + hw_buffer_size) << 16);
69 HAL_PCDEx_PMAConfig(hpcd_, EPNumberToAddr(GetNumber(), dir),
70 double_hw_buffer ? PCD_DBL_BUF : PCD_SNG_BUF, buffer_offset);
79 uint8_t type =
static_cast<uint8_t
>(cfg.
type);
81 size_t packet_size_limit = 0;
88#if defined(PCD_SPEED_HIGH_IN_FULL)
89 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
90 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
92 if (hpcd_->Init.speed == PCD_SPEED_FULL)
95 packet_size_limit = 64;
99 packet_size_limit = 512;
103#if defined(PCD_SPEED_HIGH_IN_FULL)
104 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
105 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
107 if (hpcd_->Init.speed == PCD_SPEED_FULL)
110 packet_size_limit = 64;
114 packet_size_limit = 1024;
118#if defined(PCD_SPEED_HIGH_IN_FULL)
119 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
120 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
122 if (hpcd_->Init.speed == PCD_SPEED_FULL)
125 packet_size_limit = 1023;
129 packet_size_limit = 1024;
133 packet_size_limit = 64;
139#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
140 if (packet_size_limit > fifo_size_)
142 packet_size_limit = fifo_size_;
147 if (packet_size_limit > hw_buffer_size_)
149 packet_size_limit = hw_buffer_size_;
155 if (packet_size_limit > buffer.
size_)
157 packet_size_limit = buffer.
size_;
162 if (max_packet_size > packet_size_limit)
164 max_packet_size = packet_size_limit;
167 ep_cfg.max_packet_size = max_packet_size;
169 if (max_packet_size < 8)
174 if (HAL_PCD_EP_Open(hpcd_, addr, max_packet_size, type) == HAL_OK)
187 HAL_PCD_EP_Close(hpcd_, addr);
195 return ErrorCode::BUSY;
201 PCD_EPTypeDef* ep = is_in ? &hpcd_->IN_ep[ep_addr & EP_ADDR_MSK]
202 : &hpcd_->OUT_ep[ep_addr & EP_ADDR_MSK];
206 if (buffer.
size_ < size)
208 return ErrorCode::NO_BUFF;
211 ep->xfer_buff =
reinterpret_cast<uint8_t*
>(buffer.
addr_);
220 ep->is_in = is_in ? 1U : 0U;
221 ep->num = ep_addr & EP_ADDR_MSK;
223#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
224 if (hpcd_->Init.dma_enable == 1U)
226 ep->dma_addr =
reinterpret_cast<uint32_t
>(ep->xfer_buff);
228#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
231 SCB_CleanDCache_by_Addr(
reinterpret_cast<uint32_t*
>(buffer.
addr_),
232 static_cast<int32_t
>(size));
241 ep->xfer_fill_db = 1U;
242 ep->xfer_len_db = size;
248#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
249 auto ans = USB_EPStartXfer(hpcd_->Instance, ep, hpcd_->Init.dma_enable);
251 auto ans = USB_EPStartXfer(hpcd_->Instance, ep);
255 OnTransferCompleteCallback(
false, 0);
261 return ErrorCode::OK;
266 return ErrorCode::FAILED;
274 return ErrorCode::BUSY;
278 if (HAL_PCD_EP_SetStall(hpcd_, addr) == HAL_OK)
281 return ErrorCode::OK;
286 return ErrorCode::FAILED;
294 return ErrorCode::FAILED;
302 return ErrorCode::OK;
305 if (HAL_PCD_EP_ClrStall(hpcd_, addr) == HAL_OK)
308 return ErrorCode::OK;
313 return ErrorCode::FAILED;
331static STM32Endpoint* GetEndpoint(PCD_HandleTypeDef* hpcd, uint8_t epnum,
bool is_in)
333 auto id = STM32USBDeviceGetID(hpcd);
334#if defined(USB_OTG_HS)
335 if (
id == STM32_USB_OTG_HS)
337 return STM32Endpoint::map_hs_[epnum & 0x7F][
static_cast<uint8_t
>(is_in)];
340#if defined(USB_OTG_FS)
341 if (
id == STM32_USB_OTG_FS)
343 return STM32Endpoint::map_fs_[epnum & 0x7F][
static_cast<uint8_t
>(is_in)];
347 if (
id == STM32_USB_FS_DEV)
349 return STM32Endpoint::map_otg_fs_[epnum & 0x7F][
static_cast<uint8_t
>(is_in)];
355extern "C" void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
357 auto id = STM32USBDeviceGetID(hpcd);
359 ASSERT(
id < STM32_USB_DEV_ID_NUM);
361 auto ep = GetEndpoint(hpcd, epnum,
true);
363 if (!ep || ep->hpcd_ != hpcd)
368 PCD_EPTypeDef* ep_handle = &hpcd->IN_ep[epnum & EP_ADDR_MSK];
370 size_t actual_transfer_size = ep_handle->xfer_count;
372 ep->OnTransferCompleteCallback(
true, actual_transfer_size);
375extern "C" void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
377 auto id = STM32USBDeviceGetID(hpcd);
379 ASSERT(
id < STM32_USB_DEV_ID_NUM);
381 auto ep = GetEndpoint(hpcd, epnum,
false);
383 if (!ep || ep->hpcd_ != hpcd)
388 PCD_EPTypeDef* ep_handle = &hpcd->OUT_ep[epnum & EP_ADDR_MSK];
390 size_t actual_transfer_size = ep_handle->xfer_count;
392#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
393 SCB_InvalidateDCache_by_Addr(ep->GetBuffer().addr_,
394 static_cast<int32_t
>(actual_transfer_size));
397 ep->OnTransferCompleteCallback(
true, actual_transfer_size);
400extern "C" void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
402 auto id = STM32USBDeviceGetID(hpcd);
404 ASSERT(
id < STM32_USB_DEV_ID_NUM);
406 auto ep = GetEndpoint(hpcd, epnum,
true);
408 if (!ep || ep->hpcd_ != hpcd)
413 ep->OnTransferCompleteCallback(
true, 0);
416extern "C" void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
418 auto id = STM32USBDeviceGetID(hpcd);
420 ASSERT(
id < STM32_USB_DEV_ID_NUM);
422 auto ep = GetEndpoint(hpcd, epnum,
false);
424 if (!ep || ep->hpcd_ != hpcd)
429 ep->OnTransferCompleteCallback(
true, 0);
原始数据封装类。 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