libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
spi.hpp
1#pragma once
2
3#include "double_buffer.hpp"
4#include "libxr.hpp"
5
6namespace LibXR
7{
8
14class SPI
15{
16 public:
21 enum class ClockPolarity : uint8_t
22 {
23 LOW = 0,
24 HIGH = 1
25 };
26
31 enum class ClockPhase : uint8_t
32 {
33 EDGE_1 = 0,
34 EDGE_2 = 1
35 };
36
37 enum class Prescaler : uint8_t
38 {
39 DIV_1 = 0,
40 DIV_2 = 1,
41 DIV_4 = 2,
42 DIV_8 = 3,
43 DIV_16 = 4,
44 DIV_32 = 5,
45 DIV_64 = 6,
46 DIV_128 = 7,
47 DIV_256 = 8,
48 DIV_512 = 9,
49 DIV_1024 = 10,
50 DIV_2048 = 11,
51 DIV_4096 = 12,
52 DIV_8192 = 13,
53 DIV_16384 = 14,
54 DIV_32768 = 15,
55 DIV_65536 = 16,
56 UNKNOWN = 0xFF
57 };
58
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
93
105
111 SPI(RawData rx_buffer, RawData tx_buffer)
112 : rx_buffer_(rx_buffer),
113 tx_buffer_(tx_buffer),
114 double_buffer_rx_(rx_buffer),
115 double_buffer_tx_(tx_buffer)
116 {
117 }
118
127 virtual ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data,
128 OperationRW& op, bool in_isr = false) = 0;
129
137 virtual ErrorCode Read(RawData read_data, OperationRW& op, bool in_isr = false)
138 {
139 return ReadAndWrite(read_data, ConstRawData(nullptr, 0), op, in_isr);
140 }
141
149 virtual ErrorCode Write(ConstRawData write_data, OperationRW& op, bool in_isr = false)
150 {
151 return ReadAndWrite(RawData(nullptr, 0), write_data, op, in_isr);
152 }
153
159 virtual ErrorCode SetConfig(Configuration config) = 0;
160
166 virtual uint32_t GetMaxBusSpeed() const = 0;
167
172 virtual Prescaler GetMaxPrescaler() const = 0;
173
179 uint32_t GetBusSpeed() const
180 {
181 const uint32_t DIV = PrescalerToDiv(config_.prescaler);
182 const uint32_t SRC = GetMaxBusSpeed();
183 if (DIV == 0u || SRC == 0u)
184 {
185 return 0u;
186 }
187 return SRC / DIV;
188 }
189
199 Prescaler CalcPrescaler(uint32_t target_max_bus_speed, uint32_t target_min_bus_speed,
200 bool increase)
201 {
202 const uint32_t SRC = GetMaxBusSpeed();
203 if (SRC == 0u)
204 {
205 return Prescaler::UNKNOWN;
206 }
207
208 if (target_max_bus_speed && target_min_bus_speed &&
209 target_min_bus_speed > target_max_bus_speed)
210 {
211 uint32_t t = target_min_bus_speed;
212 target_min_bus_speed = target_max_bus_speed;
213 target_max_bus_speed = t;
214 }
215
216 const uint8_t MAX_IDX = static_cast<uint8_t>(GetMaxPrescaler());
217
218 ASSERT(MAX_IDX != static_cast<uint8_t>(Prescaler::UNKNOWN));
219
220 auto fits = [&](Prescaler p) -> bool
221 {
222 const uint32_t DIV = PrescalerToDiv(p);
223 if (DIV == 0u)
224 {
225 return false;
226 }
227 const uint32_t F = SRC / DIV;
228 if (target_max_bus_speed && F > target_max_bus_speed)
229 {
230 return false;
231 }
232 if (target_min_bus_speed && F < target_min_bus_speed)
233 {
234 return false;
235 }
236 return true;
237 };
238
239 if (increase)
240 {
241 for (uint8_t i = 0; i <= MAX_IDX; ++i)
242 {
243 Prescaler p = static_cast<Prescaler>(i);
244 if (fits(p))
245 {
246 return p;
247 }
248 }
249 }
250 else
251 {
252 for (int i = static_cast<int>(MAX_IDX); i >= 0; --i)
253 {
254 Prescaler p = static_cast<Prescaler>(i);
255 if (fits(p))
256 {
257 return p;
258 }
259 }
260 }
261
262 const uint32_t F_FASTEST = SRC / PrescalerToDiv(Prescaler::DIV_1);
263 const Prescaler P_SLOWEST = static_cast<Prescaler>(MAX_IDX);
264 const uint32_t F_SLOWEST = SRC / PrescalerToDiv(P_SLOWEST);
265
266 if (target_min_bus_speed && F_FASTEST < target_min_bus_speed)
267 {
268 return Prescaler::DIV_1;
269 }
270 if (target_max_bus_speed && F_SLOWEST > target_max_bus_speed)
271 {
272 return P_SLOWEST;
273 }
274
275 if (increase)
276 {
277 for (uint8_t i = 0; i <= MAX_IDX; ++i)
278 {
279 Prescaler p = static_cast<Prescaler>(i);
280 const uint32_t F = SRC / PrescalerToDiv(p);
281 if (!target_max_bus_speed || F <= target_max_bus_speed)
282 {
283 return p;
284 }
285 }
286 return P_SLOWEST;
287 }
288 else
289 {
290 for (int i = static_cast<int>(MAX_IDX); i >= 0; --i)
291 {
292 Prescaler p = static_cast<Prescaler>(i);
293 const uint32_t F = SRC / PrescalerToDiv(p);
294 if (!target_min_bus_speed || F >= target_min_bus_speed)
295 {
296 return p;
297 }
298 }
299 return Prescaler::DIV_1;
300 }
301 }
302
308 {
309 if (IsDoubleBuffer())
310 {
311 return {double_buffer_rx_.ActiveBuffer(), double_buffer_rx_.Size()};
312 }
313 else
314 {
315 return rx_buffer_;
316 }
317 }
318
324 {
325 if (IsDoubleBuffer())
326 {
327 return {double_buffer_tx_.ActiveBuffer(), double_buffer_tx_.Size()};
328 }
329 else
330 {
331 return tx_buffer_;
332 }
333 }
334
339 {
340 if (IsDoubleBuffer())
341 {
342 double_buffer_rx_.Switch();
343 double_buffer_tx_.Switch();
344 }
345 }
346
350 void SetActiveLength(size_t len) { double_buffer_tx_.SetActiveLength(len); }
351
355 size_t GetActiveLength() const { return double_buffer_tx_.GetActiveLength(); }
356
365 virtual ErrorCode Transfer(size_t size, OperationRW& op, bool in_isr = false) = 0;
366
377 virtual ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW& op,
378 bool in_isr = false) = 0;
379
390 virtual ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW& op,
391 bool in_isr = false) = 0;
392
397 inline Configuration& GetConfig() { return config_; }
398
405 inline bool IsDoubleBuffer() const { return config_.double_buffer; }
406
407 private:
408 Configuration config_;
409 RawData rx_buffer_, tx_buffer_;
410 DoubleBuffer double_buffer_rx_, double_buffer_tx_;
411};
412
413} // namespace LibXR
只读原始数据视图 / Immutable raw data view
双缓冲区管理类 / 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
可写原始数据视图 / Mutable raw data view
串行外设接口(SPI)抽象类。 Abstract class for Serial Peripheral Interface (SPI).
Definition spi.hpp:15
ClockPhase
定义 SPI 时钟相位 / Defines the SPI clock phase.
Definition spi.hpp:32
@ 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:307
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:405
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:179
Prescaler CalcPrescaler(uint32_t target_max_bus_speed, uint32_t target_min_bus_speed, bool increase)
计算 SPI 分频系数 / Calculates the SPI prescaler.
Definition spi.hpp:199
SPI(RawData rx_buffer, RawData tx_buffer)
构造函数 / Constructor.
Definition spi.hpp:111
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:350
virtual ErrorCode Write(ConstRawData write_data, OperationRW &op, bool in_isr=false)
进行 SPI 写入操作 / Performs SPI write operation.
Definition spi.hpp:149
void SwitchBuffer()
切换缓冲区 / Switches the buffer.
Definition spi.hpp:338
RawData GetTxBuffer()
获取发送数据的缓冲区 / Gets the buffer for storing data to be sent.
Definition spi.hpp:323
size_t GetActiveLength() const
获取缓冲区的有效数据长度 / Gets the length of valid data in the buffer.
Definition spi.hpp:355
ClockPolarity
定义 SPI 时钟极性 / Defines the SPI clock polarity.
Definition spi.hpp:22
@ 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:137
Configuration & GetConfig()
获取 SPI 配置参数 / Gets the SPI configuration parameters.
Definition spi.hpp:397
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
Operation< ErrorCode > WriteOperation
写操作的完成通知描述符 / Write completion descriptor.
存储 SPI 配置参数的结构体。 Structure for storing SPI configuration parameters.
Definition spi.hpp:86
bool double_buffer
是否使用双缓冲区 / Whether to use double buffer.
Definition spi.hpp:91
ClockPhase clock_phase
SPI 时钟相位 / SPI clock phase.
Definition spi.hpp:89
Prescaler prescaler
SPI 分频系数 / SPI prescaler.
Definition spi.hpp:90
ClockPolarity clock_polarity
SPI 时钟极性 / SPI clock polarity.
Definition spi.hpp:87
存储 SPI 读写操作信息的结构体。 Structure for storing SPI read/write operation information.
Definition spi.hpp:100
OperationRW op
读写操作类型 / Type of read/write operation.
Definition spi.hpp:103
ConstRawData write_data
待写入的数据缓冲区 / Buffer for data to be written.
Definition spi.hpp:102
RawData read_data
读取的数据缓冲区 / Buffer for storing read data.
Definition spi.hpp:101