libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_usb.cpp
1#include "stm32_usb.hpp"
2
3#if defined(HAL_PCD_MODULE_ENABLED) && !defined(LIBXR_SYSTEM_ThreadX)
4
5using namespace LibXR;
6
7STM32VirtualUART *STM32VirtualUART::map[1];
8
9int8_t libxr_stm32_virtual_uart_init(void)
10{
11 STM32VirtualUART *uart = STM32VirtualUART::map[0];
12 USBD_CDC_SetTxBuffer(STM32VirtualUART::map[0]->usb_handle_,
13 uart->tx_buffer_.ActiveBuffer(), 0);
14 USBD_CDC_SetRxBuffer(STM32VirtualUART::map[0]->usb_handle_,
15 uart->rx_buffer_.ActiveBuffer());
16 return (USBD_OK);
17}
18
19int8_t libxr_stm32_virtual_uart_deinit(void) { return (USBD_OK); }
20
21int8_t libxr_stm32_virtual_uart_control(uint8_t cmd, uint8_t *pbuf, uint16_t len)
22{
23 UNUSED(cmd);
24 UNUSED(pbuf);
25 UNUSED(len);
26 return (USBD_OK);
27}
28
29int8_t libxr_stm32_virtual_uart_receive(uint8_t *pbuf, uint32_t *Len)
30{
31 STM32VirtualUART *uart = STM32VirtualUART::map[0];
32
33#if __DCACHE_PRESENT
34 SCB_InvalidateDCache_by_Addr(pbuf, *Len);
35#endif
36
37 uart->read_port_->queue_data_->PushBatch(pbuf, *Len);
39
40 USBD_CDC_ReceivePacket(STM32VirtualUART::map[0]->usb_handle_);
41
42 return (USBD_OK);
43}
44
45int8_t libxr_stm32_virtual_uart_transmit(uint8_t *pbuf, uint32_t *Len, uint8_t epnum)
46{
47 UNUSED(epnum);
48 UNUSED(pbuf);
49
50 STM32VirtualUART *uart = STM32VirtualUART::map[0];
51
52 WriteInfoBlock &current_info = uart->write_info_active_;
53
54 uart->write_port_->Finish(true, ErrorCode::OK, current_info, *Len);
55
56 if (!uart->tx_buffer_.HasPending())
57 {
58 return USBD_OK;
59 }
60
61 if (uart->write_port_->queue_info_->Pop(current_info) != ErrorCode::OK)
62 {
63 ASSERT(false);
64 return USBD_OK;
65 }
66
67 uart->tx_buffer_.Switch();
68
69#if defined(STM32F1)
70 uart->write_size_ = current_info.data.size_;
71 uart->writing_ = true;
72#endif
73
74 USBD_CDC_SetTxBuffer(uart->usb_handle_, uart->tx_buffer_.ActiveBuffer(),
75 current_info.data.size_);
76#if __DCACHE_PRESENT
77 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(uart->tx_buffer_.ActiveBuffer()),
78 *Len);
79#endif
80 USBD_CDC_TransmitPacket(uart->usb_handle_);
81
82 current_info.op.MarkAsRunning();
83
84 WriteInfoBlock next_info;
85
86 if (uart->write_port_->queue_info_->Peek(next_info) != ErrorCode::OK)
87 {
88 return USBD_OK;
89 }
90
91 if (uart->write_port_->queue_data_->PopBatch(uart->tx_buffer_.PendingBuffer(),
92 next_info.data.size_) != ErrorCode::OK)
93 {
94 ASSERT(false);
95 return USBD_OK;
96 }
97
98 uart->tx_buffer_.EnablePending();
99
100 return (USBD_OK);
101}
102
103#if defined(STM32F1)
104extern "C" void STM32_USB_ISR_Handler_F1(void)
105{
106 if (STM32VirtualUART::map[0] == nullptr)
107 {
108 return;
109 }
110
111 auto p_data_class = reinterpret_cast<USBD_CDC_HandleTypeDef *>(
112 STM32VirtualUART::map[0]->usb_handle_->pClassData);
113
114 if (p_data_class == nullptr)
115 {
116 return;
117 }
118
119 if (STM32VirtualUART::map[0]->writing_ && p_data_class->TxState == 0)
120 {
121 STM32VirtualUART::map[0]->writing_ = false;
122 libxr_stm32_virtual_uart_transmit(STM32VirtualUART::map[0]->tx_buffer_.ActiveBuffer(),
123 &STM32VirtualUART::map[0]->write_size_, 0);
124 }
125}
126#endif
127
128ErrorCode STM32VirtualUART::WriteFun(WritePort &port)
129{
130 STM32VirtualUART *uart = CONTAINER_OF(&port, STM32VirtualUART, _write_port);
131 auto p_data_class =
132 reinterpret_cast<USBD_CDC_HandleTypeDef *>(uart->usb_handle_->pClassData);
133
134 WriteInfoBlock info;
135
136 if (p_data_class == nullptr)
137 {
138 port.queue_info_->Pop(info);
139 port.queue_data_->PopBatch(uart->tx_buffer_.PendingBuffer(), info.data.size_);
140 port.Finish(false, ErrorCode::INIT_ERR, info, 0);
141 return ErrorCode::INIT_ERR;
142 }
143
144 if (uart->tx_buffer_.HasPending())
145 {
146 return ErrorCode::FULL;
147 }
148
149 if (port.queue_info_->Peek(info) != ErrorCode::OK)
150 {
151 return ErrorCode::EMPTY;
152 }
153
154 if (port.queue_data_->PopBatch(uart->tx_buffer_.PendingBuffer(), info.data.size_) !=
155 ErrorCode::OK)
156 {
157 ASSERT(false);
158 return ErrorCode::EMPTY;
159 }
160
161 uart->tx_buffer_.EnablePending();
162
163#if defined(STM32F1)
164 if (!uart->writing_ && p_data_class->TxState == 0)
165#else
166 if (p_data_class->TxState == 0)
167#endif
168 {
169 uart->tx_buffer_.Switch();
170 port.queue_info_->Pop(uart->write_info_active_);
171
172#if defined(STM32F1)
173 uart->write_size_ = info.data.size_;
174 uart->writing_ = true;
175#endif
176
177 USBD_CDC_SetTxBuffer(uart->usb_handle_, uart->tx_buffer_.ActiveBuffer(),
178 info.data.size_);
179#if __DCACHE_PRESENT
180 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(uart->tx_buffer_.ActiveBuffer()),
181 info.data.size_);
182#endif
183 USBD_CDC_TransmitPacket(uart->usb_handle_);
184
185 info.op.MarkAsRunning();
186
187 return ErrorCode::FAILED;
188 }
189 return ErrorCode::FAILED;
190}
191
192ErrorCode STM32VirtualUART::ReadFun(ReadPort &port)
193{
194 UNUSED(port);
195 return ErrorCode::EMPTY;
196}
197
198STM32VirtualUART::STM32VirtualUART(USBD_HandleTypeDef &usb_handle, uint8_t *tx_buffer,
199 uint8_t *rx_buffer, uint32_t tx_queue_size)
200 : UART(&_read_port, &_write_port),
201 usb_handle_(&usb_handle),
202 tx_buffer_(RawData(tx_buffer, APP_TX_DATA_SIZE)),
203 rx_buffer_(RawData(rx_buffer, APP_RX_DATA_SIZE)),
204 _write_port(tx_queue_size, APP_TX_DATA_SIZE),
205 _read_port(APP_RX_DATA_SIZE)
206{
207 map[0] = this;
208
209 static USBD_CDC_ItfTypeDef usbd_cdc_itf = Apply<USBD_CDC_ItfTypeDef>();
210
211 USBD_CDC_RegisterInterface(usb_handle_, &usbd_cdc_itf);
212
213 _write_port = WriteFun;
214 _read_port = ReadFun;
215
216 USBD_CDC_ReceivePacket(usb_handle_);
217}
218
220{
221 UNUSED(config);
222 return ErrorCode::OK;
223}
224
225#endif
size_t size_
数据大小(字节)。 The size of the data (in bytes).
uint8_t * PendingBuffer()
获取备用缓冲区的指针 Returns the pending (inactive) buffer
void EnablePending()
手动启用 pending 状态 Manually sets the pending state to true
bool HasPending() const
判断是否有待切换的缓冲区 Checks whether a pending buffer is ready
void Switch()
切换到备用缓冲区(若其有效) Switches to the pending buffer if it's valid
uint8_t * ActiveBuffer()
获取当前正在使用的缓冲区指针 Returns the currently active buffer
ErrorCode PushBatch(const Data *data, size_t size)
批量推入数据 / Pushes multiple elements into the queue
ErrorCode PopBatch(Data *data, size_t size)
批量弹出数据 / Pops multiple elements from the queue
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:202
原始数据封装类。 A class for encapsulating raw data.
ReadPort class for handling read operations.
Definition libxr_rw.hpp:268
virtual void ProcessPendingReads(bool in_isr)
Processes pending reads.
Definition libxr_rw.cpp:132
ErrorCode SetConfig(UART::Configuration config)
设置 UART 配置 / Sets the UART configuration
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
Definition uart.hpp:19
ReadPort * read_port_
读取端口 / Read port
Definition uart.hpp:51
WritePort * write_port_
写入端口 / Write port
Definition uart.hpp:52
WritePort class for handling write operations.
Definition libxr_rw.hpp:403
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info, uint32_t size)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.cpp:216
LibXR 命名空间
Definition ch32_gpio.hpp:9
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:245
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:241
UART 配置结构体 / UART configuration structure.
Definition uart.hpp:44