libxr 1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_spi.hpp
1#pragma once
2
3#include "main.h"
4
5#ifdef HAL_SPI_MODULE_ENABLED
6
7#ifdef SPI
8#undef SPI
9#endif
10
11#include "libxr_def.hpp"
12#include "libxr_rw.hpp"
13#include "spi.hpp"
14
15typedef enum
16{
17#ifdef SPI1
18 STM32_SPI1,
19#endif
20#ifdef SPI2
21 STM32_SPI2,
22#endif
23#ifdef SPI3
24 STM32_SPI3,
25#endif
26#ifdef SPI4
27 STM32_SPI4,
28#endif
29#ifdef SPI5
30 STM32_SPI5,
31#endif
32#ifdef SPI6
33 STM32_SPI6,
34#endif
35#ifdef SPI7
36 STM32_SPI7,
37#endif
38#ifdef SPI8
39 STM32_SPI8,
40#endif
41 STM32_SPI_NUMBER,
42 STM32_SPI_ID_ERROR
43} stm32_spi_id_t;
44
45stm32_spi_id_t STM32_SPI_GetID(SPI_TypeDef *addr); // NOLINT
46
47namespace LibXR
48{
49class STM32SPI : public SPI
50{
51 public:
54 : SPI(),
55 dma_buff_rx_(dma_buff_rx),
56 dma_buff_tx_(dma_buff_tx),
57 spi_handle_(spi_handle),
58 id_(STM32_SPI_GetID(spi_handle_->Instance)),
59 dma_enable_min_size_(dma_enable_min_size)
60 {
61 ASSERT(id_ != STM32_SPI_ID_ERROR);
62
63 map[id_] = this;
64 }
65
66 ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data,
67 OperationRW &op) override
68 {
69 uint32_t need_write = max(write_data.size_, read_data.size_);
70 ASSERT(need_write <= dma_buff_rx_.size_ && need_write <= dma_buff_tx_.size_);
71
72 if (spi_handle_->State != HAL_SPI_STATE_READY)
73 {
74 return ErrorCode::BUSY;
75 }
76
77 mem_read_ = false;
78
79 if (need_write > dma_enable_min_size_)
80 {
81 memcpy(dma_buff_tx_.addr_, write_data.addr_, need_write);
82 memset(dma_buff_rx_.addr_, 0, need_write);
83 rw_op_ = op;
84 read_buff_ = read_data;
85
86 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t *>(dma_buff_tx_.addr_),
87 static_cast<uint8_t *>(dma_buff_rx_.addr_), need_write);
88
89 op.MarkAsRunning();
90 if (op.type == OperationRW::OperationType::BLOCK)
91 {
92 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
93 }
94 return ErrorCode::OK;
95 }
96 else
97 {
98 memcpy(dma_buff_tx_.addr_, write_data.addr_, write_data.size_);
99 memset(dma_buff_rx_.addr_, 0, write_data.size_);
100 ErrorCode ans =
101 HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t *>(dma_buff_tx_.addr_),
102 static_cast<uint8_t *>(dma_buff_rx_.addr_), need_write,
103 20) == HAL_OK
104 ? ErrorCode::OK
105 : ErrorCode::BUSY;
106
107 memcpy(read_data.addr_, dma_buff_rx_.addr_, read_data.size_);
108
109 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
110
111 if (op.type == OperationRW::OperationType::BLOCK)
112 {
113 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
114 }
115
116 return ans;
117 }
118 }
119
121 {
122 switch (config.clock_polarity)
123 {
125 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
126 break;
128 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
129 break;
130 }
131
132 switch (config.clock_phase)
133 {
135 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
136 break;
138 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
139 break;
140 }
141
142 return HAL_SPI_Init(spi_handle_) == HAL_OK ? ErrorCode::OK : ErrorCode::BUSY;
143 }
144
145 ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op) override
146 {
147 uint32_t need_read = read_data.size_;
148
149 if (spi_handle_->State != HAL_SPI_STATE_READY)
150 {
151 return ErrorCode::BUSY;
152 }
153
154 mem_read_ = false;
155
156 uint8_t *dma_buffer_rx = reinterpret_cast<uint8_t *>(dma_buff_rx_.addr_);
157 uint8_t *dma_buffer_tx = reinterpret_cast<uint8_t *>(dma_buff_tx_.addr_);
158
159 if (need_read + 1 > dma_enable_min_size_)
160 {
161 memset(dma_buff_rx_.addr_, 0, need_read + 1);
162 memset(dma_buff_tx_.addr_, 0, need_read + 1);
163 dma_buffer_tx[0] = reg | 0x80;
164 rw_op_ = op;
165 read_buff_ = read_data;
166
167 mem_read_ = true;
168
169 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t *>(dma_buff_tx_.addr_),
170 static_cast<uint8_t *>(dma_buff_rx_.addr_),
171 need_read + 1);
172
173 op.MarkAsRunning();
174 if (op.type == OperationRW::OperationType::BLOCK)
175 {
176 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
177 }
178 return ErrorCode::OK;
179 }
180 else
181 {
182 memset(dma_buff_rx_.addr_, 0, need_read + 1);
183 memset(dma_buff_tx_.addr_, 0, need_read + 1);
184 dma_buffer_tx[0] = reg | 0x80;
185 ErrorCode ans =
186 HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t *>(dma_buff_tx_.addr_),
187 static_cast<uint8_t *>(dma_buff_rx_.addr_),
188 need_read + 1, 20) == HAL_OK
189 ? ErrorCode::OK
190 : ErrorCode::BUSY;
191
192 memcpy(read_data.addr_, dma_buffer_rx + 1, read_data.size_);
193
194 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
195
196 if (op.type == OperationRW::OperationType::BLOCK)
197 {
198 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
199 }
200
201 return ans;
202 }
203 }
204
205 ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op) override
206 {
207 uint32_t need_write = write_data.size_;
208
209 if (spi_handle_->State != HAL_SPI_STATE_READY)
210 {
211 return ErrorCode::BUSY;
212 }
213
214 mem_read_ = false;
215
216 uint8_t *dma_buffer_tx = reinterpret_cast<uint8_t *>(dma_buff_tx_.addr_);
217
218 if (need_write + 1 > dma_enable_min_size_)
219 {
220 memcpy(dma_buffer_tx + 1, write_data.addr_, need_write);
221 *dma_buffer_tx = reg & 0x7f;
222
223 rw_op_ = op;
224 read_buff_ = {nullptr, 0};
225
226 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t *>(dma_buff_tx_.addr_),
227 static_cast<uint8_t *>(dma_buff_rx_.addr_),
228 need_write + 1);
229
230 op.MarkAsRunning();
231 if (op.type == OperationRW::OperationType::BLOCK)
232 {
233 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
234 }
235 return ErrorCode::OK;
236 }
237 else
238 {
239 memcpy(dma_buffer_tx + 1, write_data.addr_, need_write);
240 *dma_buffer_tx = reg & 0x7f;
241 ErrorCode ans =
242 HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t *>(dma_buff_tx_.addr_),
243 static_cast<uint8_t *>(dma_buff_rx_.addr_),
244 need_write + 1, 20) == HAL_OK
245 ? ErrorCode::OK
246 : ErrorCode::BUSY;
247
248 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
249
250 if (op.type == OperationRW::OperationType::BLOCK)
251 {
252 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
253 }
254
255 return ans;
256 }
257 }
258
259 RawData dma_buff_rx_, dma_buff_tx_;
260
261 SPI_HandleTypeDef *spi_handle_;
262
263 stm32_spi_id_t id_ = STM32_SPI_ID_ERROR;
264
265 uint32_t dma_enable_min_size_ = 3;
266
267 OperationRW rw_op_;
268
269 RawData read_buff_;
270
271 bool mem_read_ = false;
272
273 static STM32SPI *map[STM32_SPI_NUMBER]; // NOLINT
274};
275
276} // namespace LibXR
277
278#endif
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
void UpdateStatus(bool in_isr, Args &&...args)
Updates operation status based on type.
Definition libxr_rw.hpp:205
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:236
union LibXR::Operation::@4 data
OperationType type
Definition libxr_rw.hpp:259
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
串行外设接口(SPI)抽象类。Abstract class for Serial Peripheral Interface (SPI).
Definition spi.hpp:13
@ EDGE_2
在第二个时钟边沿采样数据。Data sampled on the second clock edge.
@ EDGE_1
在第一个时钟边沿采样数据。Data sampled on the first clock edge.
SPI()
默认构造函数。Default constructor.
Definition spi.hpp:66
WriteOperation OperationRW
定义读写操作类型的别名。Defines an alias for the read/write operation type.
Definition spi.hpp:39
@ LOW
时钟空闲时为低电平。Clock idle low.
@ HIGH
时钟空闲时为高电平。Clock idle high.
ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op) override
从 SPI 设备的寄存器读取数据。 Reads data from a specific register of the SPI device.
ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op) override
进行 SPI 读写操作。Performs SPI read and write operations.
Definition stm32_spi.hpp:66
ErrorCode SetConfig(SPI::Configuration config) override
设置 SPI 配置参数。Sets SPI configuration parameters.
ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op) override
向 SPI 设备的寄存器写入数据。 Writes data to a specific register of the SPI device.
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:15
LibXR Color Control Library / LibXR终端颜色控制库
constexpr auto max(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最大值
constexpr auto min(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最小值
存储 SPI 配置参数的结构体。Structure for storing SPI configuration parameters.
Definition spi.hpp:46