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
125 virtual ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data,
126 OperationRW &op) = 0;
127
134 virtual ErrorCode Read(RawData read_data, OperationRW &op)
135 {
136 return ReadAndWrite(read_data, ConstRawData(nullptr, 0), op);
137 }
138
145 virtual ErrorCode Write(ConstRawData write_data, OperationRW &op)
146 {
147 return ReadAndWrite(RawData(nullptr, 0), write_data, op);
148 }
149
155 virtual ErrorCode SetConfig(Configuration config) = 0;
156
162 virtual uint32_t GetMaxBusSpeed() const = 0;
163
168 virtual Prescaler GetMaxPrescaler() const = 0;
169
175 uint32_t GetBusSpeed() const
176 {
177 const uint32_t DIV = PrescalerToDiv(config_.prescaler);
178 const uint32_t SRC = GetMaxBusSpeed();
179 if (DIV == 0u || SRC == 0u)
180 {
181 return 0u;
182 }
183 return SRC / DIV;
184 }
185
195 Prescaler CalcPrescaler(uint32_t target_max_bus_speed, uint32_t target_min_bus_speed,
196 bool increase)
197 {
198 const uint32_t SRC = GetMaxBusSpeed();
199 if (SRC == 0u)
200 {
201 return Prescaler::UNKNOWN;
202 }
203
204 if (target_max_bus_speed && target_min_bus_speed &&
205 target_min_bus_speed > target_max_bus_speed)
206 {
207 uint32_t t = target_min_bus_speed;
208 target_min_bus_speed = target_max_bus_speed;
209 target_max_bus_speed = t;
210 }
211
212 const uint8_t MAX_IDX = static_cast<uint8_t>(GetMaxPrescaler());
213
214 ASSERT(MAX_IDX != static_cast<uint8_t>(Prescaler::UNKNOWN));
215
216 auto fits = [&](Prescaler p) -> bool
217 {
218 const uint32_t DIV = PrescalerToDiv(p);
219 if (DIV == 0u)
220 {
221 return false;
222 }
223 const uint32_t F = SRC / DIV;
224 if (target_max_bus_speed && F > target_max_bus_speed)
225 {
226 return false;
227 }
228 if (target_min_bus_speed && F < target_min_bus_speed)
229 {
230 return false;
231 }
232 return true;
233 };
234
235 if (increase)
236 {
237 for (uint8_t i = 0; i <= MAX_IDX; ++i)
238 {
239 Prescaler p = static_cast<Prescaler>(i);
240 if (fits(p))
241 {
242 return p;
243 }
244 }
245 }
246 else
247 {
248 for (int i = static_cast<int>(MAX_IDX); i >= 0; --i)
249 {
250 Prescaler p = static_cast<Prescaler>(i);
251 if (fits(p))
252 {
253 return p;
254 }
255 }
256 }
257
258 const uint32_t F_FASTEST = SRC / PrescalerToDiv(Prescaler::DIV_1);
259 const Prescaler P_SLOWEST = static_cast<Prescaler>(MAX_IDX);
260 const uint32_t F_SLOWEST = SRC / PrescalerToDiv(P_SLOWEST);
261
262 if (target_min_bus_speed && F_FASTEST < target_min_bus_speed)
263 {
264 return Prescaler::DIV_1;
265 }
266 if (target_max_bus_speed && F_SLOWEST > target_max_bus_speed)
267 {
268 return P_SLOWEST;
269 }
270
271 if (increase)
272 {
273 for (uint8_t i = 0; i <= MAX_IDX; ++i)
274 {
275 Prescaler p = static_cast<Prescaler>(i);
276 const uint32_t F = SRC / PrescalerToDiv(p);
277 if (!target_max_bus_speed || F <= target_max_bus_speed)
278 {
279 return p;
280 }
281 }
282 return P_SLOWEST;
283 }
284 else
285 {
286 for (int i = static_cast<int>(MAX_IDX); i >= 0; --i)
287 {
288 Prescaler p = static_cast<Prescaler>(i);
289 const uint32_t F = SRC / PrescalerToDiv(p);
290 if (!target_min_bus_speed || F >= target_min_bus_speed)
291 {
292 return p;
293 }
294 }
295 return Prescaler::DIV_1;
296 }
297 }
298
304 {
305 if (IsDoubleBuffer())
306 {
307 return {double_buffer_rx_.ActiveBuffer(), double_buffer_rx_.Size()};
308 }
309 else
310 {
311 return rx_buffer_;
312 }
313 }
314
320 {
321 if (IsDoubleBuffer())
322 {
323 return {double_buffer_tx_.ActiveBuffer(), double_buffer_tx_.Size()};
324 }
325 else
326 {
327 return tx_buffer_;
328 }
329 }
330
335 {
336 if (IsDoubleBuffer())
337 {
338 double_buffer_rx_.Switch();
339 double_buffer_tx_.Switch();
340 }
341 }
342
346 void SetActiveLength(size_t len) { double_buffer_tx_.SetActiveLength(len); }
347
351 size_t GetActiveLength() const { return double_buffer_tx_.GetActiveLength(); }
352
360 virtual ErrorCode Transfer(size_t size, OperationRW &op) = 0;
361
371 virtual ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op) = 0;
372
382 virtual ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op) = 0;
383
388 inline Configuration &GetConfig() { return config_; }
389
396 inline bool IsDoubleBuffer() const { return config_.double_buffer; }
397
398 private:
399 Configuration config_;
400 RawData rx_buffer_, tx_buffer_;
401 DoubleBuffer double_buffer_rx_, double_buffer_tx_;
402};
403
404} // 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:303
virtual ErrorCode Transfer(size_t size, OperationRW &op)=0
进行一次SPI传输(使用当前缓冲区数据,零拷贝,支持双缓冲)。 Performs a SPI transfer (zero-copy, supports double buffering).
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 MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op)=0
向 SPI 设备的寄存器写入数据。 Writes data to a specific register of the SPI device.
virtual ErrorCode SetConfig(Configuration config)=0
设置 SPI 配置参数。Sets SPI configuration parameters.
bool IsDoubleBuffer() const
检查是否使用双缓冲区。Checks if double buffering is enabled.
Definition spi.hpp:396
virtual ErrorCode Write(ConstRawData write_data, OperationRW &op)
进行 SPI 写入操作。Performs SPI write operation.
Definition spi.hpp:145
uint32_t GetBusSpeed() const
获取 SPI 设备的当前总线速度。Gets the current bus speed of the SPI device.
Definition spi.hpp:175
virtual ErrorCode Read(RawData read_data, OperationRW &op)
进行 SPI 读取操作。Performs SPI read operation.
Definition spi.hpp:134
Prescaler CalcPrescaler(uint32_t target_max_bus_speed, uint32_t target_min_bus_speed, bool increase)
计算 SPI 分频系数。Calculates the SPI prescaler.
Definition spi.hpp:195
virtual ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op)=0
从 SPI 设备的寄存器读取数据。 Reads data from a specific register of the SPI device.
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:346
virtual ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op)=0
进行 SPI 读写操作。Performs SPI read and write operations.
void SwitchBuffer()
切换缓冲区。Switches the buffer.
Definition spi.hpp:334
RawData GetTxBuffer()
获取发送数据的缓冲区。Gets the buffer for storing data to be sent.
Definition spi.hpp:319
size_t GetActiveLength() const
获取缓冲区的有效数据长度。Gets the length of valid data in the buffer.
Definition spi.hpp:351
ClockPolarity
定义 SPI 时钟极性。Defines the SPI clock polarity.
Definition spi.hpp:21
@ LOW
时钟空闲时为低电平。Clock idle low.
@ HIGH
时钟空闲时为高电平。Clock idle high.
Configuration & GetConfig()
获取 SPI 配置参数。Gets the SPI configuration parameters.
Definition spi.hpp:388
LibXR 命名空间
Operation< ErrorCode > WriteOperation
Write operation type.
Definition libxr_rw.hpp:238
存储 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