libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
spi.hpp
1#pragma once
2
3#include "double_buffer.hpp"
4#include "libxr.hpp"
5
6namespace LibXR
7{
8
13class SPI
14{
15 public:
20 enum class ClockPolarity : uint8_t
21 {
22 LOW = 0,
23 HIGH = 1
24 };
25
30 enum class ClockPhase : uint8_t
31 {
32 EDGE_1 = 0,
33 EDGE_2 = 1
34 };
35
36 enum class Prescaler : uint8_t
37 {
38 DIV_1 = 0,
39 DIV_2 = 1,
40 DIV_4 = 2,
41 DIV_8 = 3,
42 DIV_16 = 4,
43 DIV_32 = 5,
44 DIV_64 = 6,
45 DIV_128 = 7,
46 DIV_256 = 8,
47 DIV_512 = 9,
48 DIV_1024 = 10,
49 DIV_2048 = 11,
50 DIV_4096 = 12,
51 DIV_8192 = 13,
52 DIV_16384 = 14,
53 DIV_32768 = 15,
54 DIV_65536 = 16,
55 UNKNOWN = 0xFF
56 };
57
64
70 static constexpr uint32_t PrescalerToDiv(Prescaler prescaler)
71 {
72 if (prescaler == Prescaler::UNKNOWN)
73 {
74 return 0u;
75 }
76 const uint8_t ORD = static_cast<uint8_t>(prescaler);
77 return (ORD <= 30) ? (1u << ORD) : 0u;
78 }
79
92
104
110 SPI(RawData rx_buffer, RawData tx_buffer)
111 : rx_buffer_(rx_buffer),
112 tx_buffer_(tx_buffer),
113 double_buffer_rx_(rx_buffer),
114 double_buffer_tx_(tx_buffer)
115 {
116 }
117
126 virtual ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data,
127 OperationRW& op, bool in_isr = false) = 0;
128
136 virtual ErrorCode Read(RawData read_data, OperationRW& op, bool in_isr = false)
137 {
138 return ReadAndWrite(read_data, ConstRawData(nullptr, 0), op, in_isr);
139 }
140
148 virtual ErrorCode Write(ConstRawData write_data, OperationRW& op, bool in_isr = false)
149 {
150 return ReadAndWrite(RawData(nullptr, 0), write_data, op, in_isr);
151 }
152
158 virtual ErrorCode SetConfig(Configuration config) = 0;
159
165 virtual uint32_t GetMaxBusSpeed() const = 0;
166
171 virtual Prescaler GetMaxPrescaler() const = 0;
172
178 uint32_t GetBusSpeed() const
179 {
180 const uint32_t DIV = PrescalerToDiv(config_.prescaler);
181 const uint32_t SRC = GetMaxBusSpeed();
182 if (DIV == 0u || SRC == 0u)
183 {
184 return 0u;
185 }
186 return SRC / DIV;
187 }
188
198 Prescaler CalcPrescaler(uint32_t target_max_bus_speed, uint32_t target_min_bus_speed,
199 bool increase)
200 {
201 const uint32_t SRC = GetMaxBusSpeed();
202 if (SRC == 0u)
203 {
204 return Prescaler::UNKNOWN;
205 }
206
207 if (target_max_bus_speed && target_min_bus_speed &&
208 target_min_bus_speed > target_max_bus_speed)
209 {
210 uint32_t t = target_min_bus_speed;
211 target_min_bus_speed = target_max_bus_speed;
212 target_max_bus_speed = t;
213 }
214
215 const uint8_t MAX_IDX = static_cast<uint8_t>(GetMaxPrescaler());
216
217 ASSERT(MAX_IDX != static_cast<uint8_t>(Prescaler::UNKNOWN));
218
219 auto fits = [&](Prescaler p) -> bool
220 {
221 const uint32_t DIV = PrescalerToDiv(p);
222 if (DIV == 0u)
223 {
224 return false;
225 }
226 const uint32_t F = SRC / DIV;
227 if (target_max_bus_speed && F > target_max_bus_speed)
228 {
229 return false;
230 }
231 if (target_min_bus_speed && F < target_min_bus_speed)
232 {
233 return false;
234 }
235 return true;
236 };
237
238 if (increase)
239 {
240 for (uint8_t i = 0; i <= MAX_IDX; ++i)
241 {
242 Prescaler p = static_cast<Prescaler>(i);
243 if (fits(p))
244 {
245 return p;
246 }
247 }
248 }
249 else
250 {
251 for (int i = static_cast<int>(MAX_IDX); i >= 0; --i)
252 {
253 Prescaler p = static_cast<Prescaler>(i);
254 if (fits(p))
255 {
256 return p;
257 }
258 }
259 }
260
261 const uint32_t F_FASTEST = SRC / PrescalerToDiv(Prescaler::DIV_1);
262 const Prescaler P_SLOWEST = static_cast<Prescaler>(MAX_IDX);
263 const uint32_t F_SLOWEST = SRC / PrescalerToDiv(P_SLOWEST);
264
265 if (target_min_bus_speed && F_FASTEST < target_min_bus_speed)
266 {
267 return Prescaler::DIV_1;
268 }
269 if (target_max_bus_speed && F_SLOWEST > target_max_bus_speed)
270 {
271 return P_SLOWEST;
272 }
273
274 if (increase)
275 {
276 for (uint8_t i = 0; i <= MAX_IDX; ++i)
277 {
278 Prescaler p = static_cast<Prescaler>(i);
279 const uint32_t F = SRC / PrescalerToDiv(p);
280 if (!target_max_bus_speed || F <= target_max_bus_speed)
281 {
282 return p;
283 }
284 }
285 return P_SLOWEST;
286 }
287 else
288 {
289 for (int i = static_cast<int>(MAX_IDX); i >= 0; --i)
290 {
291 Prescaler p = static_cast<Prescaler>(i);
292 const uint32_t F = SRC / PrescalerToDiv(p);
293 if (!target_min_bus_speed || F >= target_min_bus_speed)
294 {
295 return p;
296 }
297 }
298 return Prescaler::DIV_1;
299 }
300 }
301
307 {
308 if (IsDoubleBuffer())
309 {
310 return {double_buffer_rx_.ActiveBuffer(), double_buffer_rx_.Size()};
311 }
312 else
313 {
314 return rx_buffer_;
315 }
316 }
317
323 {
324 if (IsDoubleBuffer())
325 {
326 return {double_buffer_tx_.ActiveBuffer(), double_buffer_tx_.Size()};
327 }
328 else
329 {
330 return tx_buffer_;
331 }
332 }
333
338 {
339 if (IsDoubleBuffer())
340 {
341 double_buffer_rx_.Switch();
342 double_buffer_tx_.Switch();
343 }
344 }
345
349 void SetActiveLength(size_t len) { double_buffer_tx_.SetActiveLength(len); }
350
354 size_t GetActiveLength() const { return double_buffer_tx_.GetActiveLength(); }
355
364 virtual ErrorCode Transfer(size_t size, OperationRW& op, bool in_isr = false) = 0;
365
376 virtual ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW& op,
377 bool in_isr = false) = 0;
378
389 virtual ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW& op,
390 bool in_isr = false) = 0;
391
396 inline Configuration& GetConfig() { return config_; }
397
404 inline bool IsDoubleBuffer() const { return config_.double_buffer; }
405
406 private:
407 Configuration config_;
408 RawData rx_buffer_, tx_buffer_;
409 DoubleBuffer double_buffer_rx_, double_buffer_tx_;
410};
411
412} // namespace LibXR
常量原始数据封装类。 A class for encapsulating constant raw data.
双缓冲区管理类 / Double buffer manager class
void SetActiveLength(size_t length)
设置当前活动缓冲区的数据长度 Sets the size of the active buffer
size_t Size() const
获取每个缓冲区的大小(单位:字节) Gets the size of each buffer in bytes
uint8_t * ActiveBuffer() const
获取当前正在使用的缓冲区指针 Returns the currently active buffer
size_t GetActiveLength() const
获取当前活动缓冲区中准备好的数据长度 Gets the size of valid data in active buffer
void Switch()
切换到备用缓冲区(若其有效) Switches to the pending buffer if it's valid
原始数据封装类。 A class for encapsulating raw data.
串行外设接口(SPI)抽象类。Abstract class for Serial Peripheral Interface (SPI).
Definition spi.hpp:14
ClockPhase
定义 SPI 时钟相位。Defines the SPI clock phase.
Definition spi.hpp:31
@ EDGE_2
在第二个时钟边沿采样数据。Data sampled on the second clock edge.
@ EDGE_1
在第一个时钟边沿采样数据。Data sampled on the first clock edge.
@ DIV_8192
分频系数为 8192。Division factor is 8192.
@ DIV_16
分频系数为 16。Division factor is 16.
@ DIV_2
分频系数为 2。Division factor is 2.
@ DIV_4096
分频系数为 4096。Division factor is 4096.
@ DIV_64
分频系数为 64。Division factor is 64.
@ DIV_16384
分频系数为 16384。Division factor is 16384.
@ DIV_1
分频系数为 1。Division factor is 1.
@ DIV_2048
分频系数为 2048。Division factor is 2048.
@ UNKNOWN
未知分频系数。Unknown prescaler.
@ DIV_32768
分频系数为 32768。Division factor is 32768.
@ DIV_65536
分频系数为 65536。Division factor is 65536.
@ DIV_256
分频系数为 256。Division factor is 256.
@ DIV_128
分频系数为 128。Division factor is 128.
@ DIV_4
分频系数为 4。Division factor is 4.
@ DIV_32
分频系数为 32。Division factor is 32.
@ DIV_512
分频系数为 512。Division factor is 512.
@ DIV_8
分频系数为 8。Division factor is 8.
@ DIV_1024
分频系数为 1024。Division factor is 1024.
RawData GetRxBuffer()
获取接收数据的缓冲区。Gets the buffer for storing received data.
Definition spi.hpp:306
static constexpr uint32_t PrescalerToDiv(Prescaler prescaler)
将分频系数转换为除数。Converts a prescaler to a divisor.
Definition spi.hpp:70
virtual Prescaler GetMaxPrescaler() const =0
获取 SPI 设备的最大分频系数。Gets the maximum prescaler of the SPI device.
virtual ErrorCode SetConfig(Configuration config)=0
设置 SPI 配置参数。Sets SPI configuration parameters.
virtual ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op, bool in_isr=false)=0
从 SPI 设备的寄存器读取数据。 Reads data from a specific register of the SPI device.
virtual ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op, bool in_isr=false)=0
向 SPI 设备的寄存器写入数据。 Writes data to a specific register of the SPI device.
virtual ErrorCode Transfer(size_t size, OperationRW &op, bool in_isr=false)=0
进行一次SPI传输(使用当前缓冲区数据,零拷贝,支持双缓冲)。 Performs a SPI transfer (zero-copy, supports double buffering).
bool IsDoubleBuffer() const
检查是否使用双缓冲区。Checks if double buffering is enabled.
Definition spi.hpp:404
virtual ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op, bool in_isr=false)=0
进行 SPI 读写操作。Performs SPI read and write operations.
uint32_t GetBusSpeed() const
获取 SPI 设备的当前总线速度。Gets the current bus speed of the SPI device.
Definition spi.hpp:178
Prescaler CalcPrescaler(uint32_t target_max_bus_speed, uint32_t target_min_bus_speed, bool increase)
计算 SPI 分频系数。Calculates the SPI prescaler.
Definition spi.hpp:198
SPI(RawData rx_buffer, RawData tx_buffer)
构造函数。Constructor.
Definition spi.hpp:110
virtual uint32_t GetMaxBusSpeed() const =0
获取 SPI 设备的最大时钟速度。Gets the maximum clock speed of the SPI device.
void SetActiveLength(size_t len)
设置缓冲区的有效数据长度。Sets the length of valid data in the buffer.
Definition spi.hpp:349
virtual ErrorCode Write(ConstRawData write_data, OperationRW &op, bool in_isr=false)
进行 SPI 写入操作。Performs SPI write operation.
Definition spi.hpp:148
void SwitchBuffer()
切换缓冲区。Switches the buffer.
Definition spi.hpp:337
RawData GetTxBuffer()
获取发送数据的缓冲区。Gets the buffer for storing data to be sent.
Definition spi.hpp:322
size_t GetActiveLength() const
获取缓冲区的有效数据长度。Gets the length of valid data in the buffer.
Definition spi.hpp:354
ClockPolarity
定义 SPI 时钟极性。Defines the SPI clock polarity.
Definition spi.hpp:21
@ LOW
时钟空闲时为低电平。Clock idle low.
@ HIGH
时钟空闲时为高电平。Clock idle high.
virtual ErrorCode Read(RawData read_data, OperationRW &op, bool in_isr=false)
进行 SPI 读取操作。Performs SPI read operation.
Definition spi.hpp:136
Configuration & GetConfig()
获取 SPI 配置参数。Gets the SPI configuration parameters.
Definition spi.hpp:396
LibXR 命名空间
Definition ch32_can.hpp:14
Operation< ErrorCode > WriteOperation
Write operation type.
Definition libxr_rw.hpp:241
存储 SPI 配置参数的结构体。Structure for storing SPI configuration parameters.
Definition spi.hpp:85
bool double_buffer
是否使用双缓冲区。Whether to use double buffer.
Definition spi.hpp:90
ClockPhase clock_phase
SPI 时钟相位。SPI clock phase.
Definition spi.hpp:88
Prescaler prescaler
SPI 分频系数。SPI prescaler.
Definition spi.hpp:89
ClockPolarity clock_polarity
SPI 时钟极性。SPI clock polarity.
Definition spi.hpp:86
存储 SPI 读写操作信息的结构体。Structure for storing SPI read/write operation information.
Definition spi.hpp:99
OperationRW op
读写操作类型。Type of read/write operation.
Definition spi.hpp:102
ConstRawData write_data
待写入的数据缓冲区。Buffer for data to be written.
Definition spi.hpp:101
RawData read_data
读取的数据缓冲区。Buffer for storing read data.
Definition spi.hpp:100