Internal Interface Wrap
API reference
Loading...
Searching...
No Matches
BaseSpi.h
Go to the documentation of this file.
1
21#pragma once
22
23#include "HardwareTypes.h"
24#include <cstdint>
25#include <string_view>
26
32//--------------------------------------
33// HardFOC SPI Error Codes (Table)
34//--------------------------------------
43#define HF_SPI_ERR_LIST(X) \
44 /* Success codes */ \
45 X(SPI_SUCCESS, 0, "Success") \
46 /* General errors */ \
47 X(SPI_ERR_FAILURE, 1, "General failure") \
48 X(SPI_ERR_NOT_INITIALIZED, 2, "Not initialized") \
49 X(SPI_ERR_ALREADY_INITIALIZED, 3, "Already initialized") \
50 X(SPI_ERR_INVALID_PARAMETER, 4, "Invalid parameter") \
51 X(SPI_ERR_NULL_POINTER, 5, "Null pointer") \
52 X(SPI_ERR_OUT_OF_MEMORY, 6, "Out of memory") \
53 /* Bus errors */ \
54 X(SPI_ERR_BUS_BUSY, 7, "Bus busy") \
55 X(SPI_ERR_BUS_ERROR, 8, "Bus error") \
56 X(SPI_ERR_BUS_NOT_AVAILABLE, 9, "Bus not available") \
57 X(SPI_ERR_BUS_TIMEOUT, 10, "Bus timeout") \
58 /* Transfer errors */ \
59 X(SPI_ERR_TRANSFER_FAILED, 11, "Transfer failed") \
60 X(SPI_ERR_TRANSFER_TIMEOUT, 12, "Transfer timeout") \
61 X(SPI_ERR_TRANSFER_TOO_LONG, 13, "Transfer too long") \
62 X(SPI_ERR_TRANSFER_SIZE_MISMATCH, 14, "Transfer size mismatch") \
63 /* Device errors */ \
64 X(SPI_ERR_DEVICE_NOT_FOUND, 15, "Device not found") \
65 X(SPI_ERR_DEVICE_NOT_RESPONDING, 16, "Device not responding") \
66 X(SPI_ERR_CS_CONTROL_FAILED, 17, "Chip select control failed") \
67 /* Hardware errors */ \
68 X(SPI_ERR_HARDWARE_FAULT, 18, "Hardware fault") \
69 X(SPI_ERR_COMMUNICATION_FAILURE, 19, "Communication failure") \
70 X(SPI_ERR_VOLTAGE_OUT_OF_RANGE, 20, "Voltage out of range") \
71 X(SPI_ERR_CLOCK_ERROR, 21, "Clock error") \
72 /* Configuration errors */ \
73 X(SPI_ERR_INVALID_CONFIGURATION, 22, "Invalid configuration") \
74 X(SPI_ERR_UNSUPPORTED_OPERATION, 23, "Unsupported operation") \
75 X(SPI_ERR_INVALID_CLOCK_SPEED, 24, "Invalid clock speed") \
76 X(SPI_ERR_INVALID_MODE, 25, "Invalid SPI mode") \
77 X(SPI_ERR_PIN_CONFIGURATION_ERROR, 26, "Pin configuration error") \
78 /* System errors */ \
79 X(SPI_ERR_SYSTEM_ERROR, 27, "System error") \
80 X(SPI_ERR_PERMISSION_DENIED, 28, "Permission denied") \
81 X(SPI_ERR_OPERATION_ABORTED, 29, "Operation aborted") \
82 X(SPI_ERR_UNKNOWN, 30, "Unknown error")
83
84enum class hf_spi_err_t : hf_u8_t {
85#define X(NAME, VALUE, DESC) NAME = VALUE,
87#undef X
88};
89
95constexpr std::string_view HfSpiErrToString(hf_spi_err_t err) noexcept {
96 switch (err) {
97#define X(NAME, VALUE, DESC) \
98 case hf_spi_err_t::NAME: \
99 return DESC;
101#undef X
102 default:
104 }
105}
106
128
149
150//--------------------------------------
151// Abstract Base Class
152//--------------------------------------
153
184class BaseSpi {
185public:
189 virtual ~BaseSpi() noexcept = default;
190
191 // Non-copyable, non-movable (can be changed in derived classes if needed)
192 BaseSpi(const BaseSpi&) = delete;
193 BaseSpi& operator=(const BaseSpi&) = delete;
194 BaseSpi(BaseSpi&&) = delete;
195 BaseSpi& operator=(BaseSpi&&) = delete;
196
201 bool EnsureInitialized() noexcept {
202 if (!initialized_) {
204 }
205 return initialized_;
206 }
207
212 bool EnsureDeinitialized() noexcept {
213 if (initialized_) {
215 }
216 return !initialized_;
217 }
218
223 [[nodiscard]] bool IsInitialized() const noexcept {
224 return initialized_;
225 }
226
227 //==============================================//
228 // PURE VIRTUAL FUNCTIONS - MUST BE OVERRIDDEN //
229 //==============================================//
230
236 virtual bool Initialize() noexcept = 0;
237
243 virtual bool Deinitialize() noexcept = 0;
244
255 virtual hf_spi_err_t Transfer(const hf_u8_t* tx_data, hf_u8_t* rx_data, hf_u16_t length,
256 hf_u32_t timeout_ms = 0) noexcept = 0;
257
265 virtual void IdleChipSelect() noexcept {}
266
273 virtual void HoldChipSelectMs(hf_u32_t /*ms*/) noexcept {}
274
280 virtual bool SetTransferMode(hf_u8_t /*mode_0_to_3*/) noexcept { return false; }
281
288 virtual bool SetIoSwap(bool /*enable*/) noexcept { return false; }
289
301 virtual hf_spi_err_t TransferChain(const hf_u8_t* const* tx_frames, hf_u8_t* const* rx_frames,
302 hf_u16_t frame_length, hf_u16_t frame_count,
303 hf_u32_t inter_frame_gap_us,
304 hf_u32_t timeout_ms = 0) noexcept {
305 if (frame_count == 0U || frame_length == 0U) {
307 }
308 if (tx_frames == nullptr && rx_frames == nullptr) {
310 }
311 for (hf_u16_t i = 0; i < frame_count; ++i) {
312 const hf_u8_t* tx = (tx_frames != nullptr) ? tx_frames[i] : nullptr;
313 hf_u8_t* rx = (rx_frames != nullptr) ? rx_frames[i] : nullptr;
314 const hf_spi_err_t err = Transfer(tx, rx, frame_length, timeout_ms);
315 if (err != hf_spi_err_t::SPI_SUCCESS) {
316 return err;
317 }
318 if (inter_frame_gap_us > 0U && (i + 1U) < frame_count) {
319 /* Portable busy-wait; STM32 override uses a tighter spin. */
320 for (hf_u32_t spin = inter_frame_gap_us * 50U; spin > 0U; --spin) {
321 __asm__ volatile("" ::: "memory");
322 }
323 }
324 }
326 }
327
332 virtual const void* GetDeviceConfig() const noexcept = 0;
333
334 //==============================================//
335 // CONVENIENCE METHODS WITH DEFAULT IMPLEMENTATIONS //
336 //==============================================//
337
342 virtual bool Open() noexcept {
343 return EnsureInitialized();
344 }
345
350 virtual bool Close() noexcept {
351 if (initialized_) {
353 return !initialized_;
354 }
355 return true;
356 }
357
365 virtual bool Transfer(const hf_u8_t* tx_data, hf_u8_t* rx_data, hf_u16_t length) noexcept {
366 if (!EnsureInitialized()) {
367 return false;
368 }
369 return Transfer(tx_data, rx_data, length, 0) == hf_spi_err_t::SPI_SUCCESS;
370 }
371
379 virtual hf_spi_err_t Write(const hf_u8_t* data, hf_u16_t length,
380 hf_u32_t timeout_ms = 0) noexcept {
381 return Transfer(data, nullptr, length, timeout_ms);
382 }
383
391 virtual hf_spi_err_t Read(hf_u8_t* data, hf_u16_t length, hf_u32_t timeout_ms = 0) noexcept {
392 return Transfer(nullptr, data, length, timeout_ms);
393 }
394
401 virtual bool Write(const hf_u8_t* data, hf_u16_t length) noexcept {
402 if (!EnsureInitialized()) {
403 return false;
404 }
405 return Write(data, length, 0) == hf_spi_err_t::SPI_SUCCESS;
406 }
407
414 virtual bool Read(hf_u8_t* data, hf_u16_t length) noexcept {
415 if (!EnsureInitialized()) {
416 return false;
417 }
418 return Read(data, length, 0) == hf_spi_err_t::SPI_SUCCESS;
419 }
420
426 virtual bool WriteByte(hf_u8_t data) noexcept {
427 return Write(&data, 1, 0) == hf_spi_err_t::SPI_SUCCESS;
428 }
429
435 virtual bool ReadByte(hf_u8_t& data) noexcept {
436 return Read(&data, 1, 0) == hf_spi_err_t::SPI_SUCCESS;
437 }
438
445 virtual bool TransferByte(hf_u8_t tx_data, hf_u8_t& rx_data) noexcept {
446 return Transfer(&tx_data, &rx_data, 1, 0) == hf_spi_err_t::SPI_SUCCESS;
447 }
448
449 //==============================================//
450 // STATISTICS AND DIAGNOSTICS
451 //==============================================//
452
458 virtual hf_spi_err_t ResetStatistics() noexcept {
459 statistics_ = hf_spi_statistics_t{}; // Reset statistics to default values
461 }
462
468 virtual hf_spi_err_t ResetDiagnostics() noexcept {
469 diagnostics_ = hf_spi_diagnostics_t{}; // Reset diagnostics to default values
471 }
472
478 virtual hf_spi_err_t GetStatistics(hf_spi_statistics_t& statistics) const noexcept {
479 statistics = statistics_; // Return statistics by default
481 }
482
488 virtual hf_spi_err_t GetDiagnostics(hf_spi_diagnostics_t& diagnostics) const noexcept {
489 diagnostics = diagnostics_; // Return diagnostics by default
491 }
492
493protected:
498 BaseSpi() noexcept : initialized_(false), statistics_{}, diagnostics_{} {}
499
503};
hf_spi_err_t
Definition BaseSpi.h:84
@ SPI_ERR_UNSUPPORTED_OPERATION
@ SPI_ERR_INVALID_PARAMETER
constexpr std::string_view HfSpiErrToString(hf_spi_err_t err) noexcept
Convert hf_spi_err_t to human-readable string.
Definition BaseSpi.h:95
#define X(NAME, VALUE, DESC)
Definition BaseSpi.h:85
Platform-agnostic hardware type definitions for the HardFOC system.
uint32_t hf_u32_t
Platform-agnostic 32-bit unsigned integer type.
Definition HardwareTypes.h:52
uint8_t hf_u8_t
Platform-agnostic 8-bit unsigned integer type.
Definition HardwareTypes.h:40
uint64_t hf_u64_t
Platform-agnostic 64-bit unsigned integer type.
Definition HardwareTypes.h:58
uint16_t hf_u16_t
Platform-agnostic 16-bit unsigned integer type.
Definition HardwareTypes.h:46
Abstract base class for SPI device implementations.
Definition BaseSpi.h:184
virtual ~BaseSpi() noexcept=default
Virtual destructor ensures proper cleanup in derived classes.
virtual bool Open() noexcept
Legacy compatibility: Open and initialize the SPI bus.
Definition BaseSpi.h:342
virtual hf_spi_err_t GetStatistics(hf_spi_statistics_t &statistics) const noexcept
Get SPI operation statistics.
Definition BaseSpi.h:478
virtual bool Initialize() noexcept=0
Initialize the SPI bus.
virtual bool Deinitialize() noexcept=0
Deinitialize the SPI bus.
virtual hf_spi_err_t ResetDiagnostics() noexcept
Reset SPI diagnostic information.
Definition BaseSpi.h:468
virtual bool WriteByte(hf_u8_t data) noexcept
Write single byte to SPI bus.
Definition BaseSpi.h:426
virtual bool Write(const hf_u8_t *data, hf_u16_t length) noexcept
Legacy compatibility: Write with boolean return.
Definition BaseSpi.h:401
bool IsInitialized() const noexcept
Checks if the bus is initialized.
Definition BaseSpi.h:223
virtual hf_spi_err_t Read(hf_u8_t *data, hf_u16_t length, hf_u32_t timeout_ms=0) noexcept
Read data from SPI bus.
Definition BaseSpi.h:391
virtual const void * GetDeviceConfig() const noexcept=0
Get the device configuration for this SPI device.
bool EnsureInitialized() noexcept
Ensures that the SPI bus is initialized (lazy initialization).
Definition BaseSpi.h:201
virtual hf_spi_err_t Transfer(const hf_u8_t *tx_data, hf_u8_t *rx_data, hf_u16_t length, hf_u32_t timeout_ms=0) noexcept=0
Perform a full-duplex SPI transfer.
virtual hf_spi_err_t ResetStatistics() noexcept
Reset SPI operation statistics.
Definition BaseSpi.h:458
hf_spi_statistics_t statistics_
SPI operation statistics.
Definition BaseSpi.h:501
virtual bool Close() noexcept
Legacy compatibility: Close and de-initialize the SPI bus.
Definition BaseSpi.h:350
virtual bool Transfer(const hf_u8_t *tx_data, hf_u8_t *rx_data, hf_u16_t length) noexcept
Legacy compatibility: Transfer with boolean return.
Definition BaseSpi.h:365
virtual hf_spi_err_t Write(const hf_u8_t *data, hf_u16_t length, hf_u32_t timeout_ms=0) noexcept
Write data to SPI bus.
Definition BaseSpi.h:379
hf_spi_diagnostics_t diagnostics_
SPI diagnostic information.
Definition BaseSpi.h:502
bool initialized_
Initialization state.
Definition BaseSpi.h:500
virtual bool TransferByte(hf_u8_t tx_data, hf_u8_t &rx_data) noexcept
Write single byte and read response.
Definition BaseSpi.h:445
virtual bool SetIoSwap(bool) noexcept
Swap MOSI↔MISO AF on the next transfer (STM32 SPI CFG2 IOSWP).
Definition BaseSpi.h:288
virtual bool SetTransferMode(hf_u8_t) noexcept
Select CPOL/CPHA mode for the next soft-CS transfer (0..3).
Definition BaseSpi.h:280
bool EnsureDeinitialized() noexcept
Ensures that the SPI bus is deinitialized (lazy deinitialization).
Definition BaseSpi.h:212
virtual void HoldChipSelectMs(hf_u32_t) noexcept
Assert soft-CS for ms milliseconds (logic-analyzer / pad proof).
Definition BaseSpi.h:273
BaseSpi() noexcept
Protected default constructor.
Definition BaseSpi.h:498
virtual void IdleChipSelect() noexcept
Force soft-CS to the idle (deasserted) level without a transfer.
Definition BaseSpi.h:265
virtual hf_spi_err_t TransferChain(const hf_u8_t *const *tx_frames, hf_u8_t *const *rx_frames, hf_u16_t frame_length, hf_u16_t frame_count, hf_u32_t inter_frame_gap_us, hf_u32_t timeout_ms=0) noexcept
Run frame_count soft-CS frames in one ownership window.
Definition BaseSpi.h:301
virtual bool ReadByte(hf_u8_t &data) noexcept
Read single byte from SPI bus.
Definition BaseSpi.h:435
virtual bool Read(hf_u8_t *data, hf_u16_t length) noexcept
Legacy compatibility: Read with boolean return.
Definition BaseSpi.h:414
virtual hf_spi_err_t GetDiagnostics(hf_spi_diagnostics_t &diagnostics) const noexcept
Get SPI diagnostic information.
Definition BaseSpi.h:488
#define HF_SPI_ERR_LIST(X)
HardFOC SPI error codes.
Definition BaseSpi.h:43
SPI diagnostic information.
Definition BaseSpi.h:132
hf_u32_t current_clock_speed
Current clock speed in Hz.
Definition BaseSpi.h:136
hf_u16_t max_transfer_size
Maximum transfer size.
Definition BaseSpi.h:138
hf_u64_t total_transactions
Total transactions performed.
Definition BaseSpi.h:141
hf_u8_t device_count
Number of registered devices.
Definition BaseSpi.h:139
bool is_bus_suspended
Bus suspension state.
Definition BaseSpi.h:134
bool is_initialized
Initialization state.
Definition BaseSpi.h:133
hf_u32_t last_error
Last error code.
Definition BaseSpi.h:140
bool dma_enabled
DMA enabled state.
Definition BaseSpi.h:135
hf_u8_t current_mode
Current SPI mode.
Definition BaseSpi.h:137
hf_spi_diagnostics_t() noexcept
Definition BaseSpi.h:144
hf_u64_t failed_transactions
Failed transactions count.
Definition BaseSpi.h:142
SPI operation statistics.
Definition BaseSpi.h:110
hf_u32_t max_transaction_time_us
Maximum transaction time (microseconds)
Definition BaseSpi.h:117
hf_u32_t min_transaction_time_us
Minimum transaction time (microseconds)
Definition BaseSpi.h:118
hf_u32_t timeout_transactions
Number of timed-out transactions.
Definition BaseSpi.h:114
hf_spi_statistics_t() noexcept
Definition BaseSpi.h:122
hf_u64_t initialization_timestamp
Initialization timestamp.
Definition BaseSpi.h:120
hf_u32_t total_bytes_received
Total bytes received.
Definition BaseSpi.h:116
hf_u32_t failed_transactions
Number of failed transactions.
Definition BaseSpi.h:113
hf_u32_t successful_transactions
Number of successful transactions.
Definition BaseSpi.h:112
hf_u64_t last_activity_timestamp
Last activity timestamp.
Definition BaseSpi.h:119
hf_u32_t total_transactions
Total number of transactions.
Definition BaseSpi.h:111
hf_u32_t total_bytes_sent
Total bytes transmitted.
Definition BaseSpi.h:115