1#include "stm32_spi.hpp"
3#include "libxr_def.hpp"
5#ifdef HAL_SPI_MODULE_ENABLED
9STM32SPI *STM32SPI::map[STM32_SPI_NUMBER] = {
nullptr};
11stm32_spi_id_t STM32_SPI_GetID(SPI_TypeDef *addr)
15 return stm32_spi_id_t::STM32_SPI_ID_ERROR;
18 else if (addr == SPI1)
20 return stm32_spi_id_t::STM32_SPI1;
24 else if (addr == SPI2)
26 return stm32_spi_id_t::STM32_SPI2;
30 else if (addr == SPI3)
32 return stm32_spi_id_t::STM32_SPI3;
36 else if (addr == SPI4)
38 return stm32_spi_id_t::STM32_SPI4;
42 else if (addr == SPI5)
44 return stm32_spi_id_t::STM32_SPI5;
48 else if (addr == SPI6)
50 return stm32_spi_id_t::STM32_SPI6;
54 else if (addr == SPI7)
56 return stm32_spi_id_t::STM32_SPI7;
60 else if (addr == SPI8)
62 return stm32_spi_id_t::STM32_SPI8;
67 return stm32_spi_id_t::STM32_SPI_ID_ERROR;
71STM32SPI::STM32SPI(SPI_HandleTypeDef *spi_handle,
RawData dma_buff_rx,
72 RawData dma_buff_tx, uint32_t dma_enable_min_size)
74 dma_buff_rx_(dma_buff_rx),
75 dma_buff_tx_(dma_buff_tx),
76 spi_handle_(spi_handle),
77 id_(STM32_SPI_GetID(spi_handle_->Instance)),
78 dma_enable_min_size_(dma_enable_min_size)
80 ASSERT(id_ != STM32_SPI_ID_ERROR);
90 if (dma_buff_rx_.
size_ > 0)
92 ASSERT(need_write <= dma_buff_rx_.
size_);
95 if (dma_buff_tx_.
size_ > 0)
97 ASSERT(need_write <= dma_buff_tx_.
size_);
100 if (spi_handle_->State != HAL_SPI_STATE_READY)
102 return ErrorCode::BUSY;
107 if (need_write > dma_enable_min_size_)
111 if (write_data.
size_ > 0)
113 memcpy(dma_buff_tx_.
addr_, write_data.
addr_, need_write);
116 SCB_CleanDCache_by_Addr(
static_cast<uint32_t *
>(dma_buff_tx_.
addr_),
117 static_cast<int32_t
>(write_data.
size_));
120 if (read_data.
size_ > 0)
122 read_buff_ = read_data;
125 if (write_data.
size_ > 0 && read_data.
size_ > 0)
127 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t *
>(dma_buff_tx_.
addr_),
128 static_cast<uint8_t *
>(dma_buff_rx_.
addr_), need_write);
130 else if (write_data.
size_ > 0)
132 HAL_SPI_Transmit_DMA(spi_handle_,
static_cast<uint8_t *
>(dma_buff_tx_.
addr_),
135 else if (read_data.
size_ > 0)
137 HAL_SPI_Receive_DMA(spi_handle_,
static_cast<uint8_t *
>(dma_buff_rx_.
addr_),
142 if (op.
type != OperationRW::OperationType::BLOCK)
146 return ErrorCode::OK;
150 if (op.
type == OperationRW::OperationType::BLOCK)
152 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
154 return ErrorCode::OK;
158 if (write_data.
size_ > 0)
163 ErrorCode ans = ErrorCode::OK;
164 if (read_data.
size_ > 0 && write_data.
size_ > 0)
166 ans = HAL_SPI_TransmitReceive(
167 spi_handle_,
static_cast<uint8_t *
>(dma_buff_tx_.
addr_),
168 static_cast<uint8_t *
>(dma_buff_rx_.
addr_), need_write, 20) == HAL_OK
172 else if (read_data.
size_ > 0)
174 ans = HAL_SPI_Receive(spi_handle_,
static_cast<uint8_t *
>(dma_buff_rx_.
addr_),
175 need_write, 20) == HAL_OK
179 else if (write_data.
size_ > 0)
181 ans = HAL_SPI_Transmit(spi_handle_,
static_cast<uint8_t *
>(dma_buff_tx_.
addr_),
182 need_write, 20) == HAL_OK
188 if (op.
type != OperationRW::OperationType::BLOCK)
192 return ErrorCode::OK;
199 if (op.
type == OperationRW::OperationType::BLOCK)
201 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
213 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
216 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
223 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
226 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
230 return HAL_SPI_Init(spi_handle_) == HAL_OK ? ErrorCode::OK : ErrorCode::BUSY;
235 uint32_t need_read = read_data.
size_;
237 if (spi_handle_->State != HAL_SPI_STATE_READY)
239 return ErrorCode::BUSY;
242 ASSERT(dma_buff_rx_.
size_ >= need_read + 1);
243 ASSERT(dma_buff_tx_.
size_ >= need_read + 1);
245 uint8_t *dma_buffer_rx =
reinterpret_cast<uint8_t *
>(dma_buff_rx_.
addr_);
246 uint8_t *dma_buffer_tx =
reinterpret_cast<uint8_t *
>(dma_buff_tx_.
addr_);
248 if (need_read + 1 > dma_enable_min_size_)
251 memset(dma_buff_tx_.
addr_, 0, need_read + 1);
252 dma_buffer_tx[0] = reg | 0x80;
254 read_buff_ = read_data;
256 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t *
>(dma_buff_tx_.
addr_),
257 static_cast<uint8_t *
>(dma_buff_rx_.
addr_),
261 if (op.
type == OperationRW::OperationType::BLOCK)
263 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
265 return ErrorCode::OK;
270 memset(dma_buff_tx_.
addr_, 0, need_read + 1);
271 dma_buffer_tx[0] = reg | 0x80;
273 HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t *
>(dma_buff_tx_.
addr_),
274 static_cast<uint8_t *
>(dma_buff_rx_.
addr_), need_read + 1,
279 memcpy(read_data.
addr_, dma_buffer_rx + 1, read_data.
size_);
283 if (op.
type == OperationRW::OperationType::BLOCK)
285 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
294 uint32_t need_write = write_data.
size_;
296 if (spi_handle_->State != HAL_SPI_STATE_READY)
298 return ErrorCode::BUSY;
303 ASSERT(dma_buff_tx_.
size_ >= need_write + 1);
305 uint8_t *dma_buffer_tx =
reinterpret_cast<uint8_t *
>(dma_buff_tx_.
addr_);
307 if (need_write + 1 > dma_enable_min_size_)
309 memcpy(dma_buffer_tx + 1, write_data.
addr_, need_write);
310 *dma_buffer_tx = reg & 0x7f;
313 read_buff_ = {
nullptr, 0};
315 HAL_SPI_Transmit_DMA(spi_handle_, dma_buffer_tx, need_write + 1);
318 if (op.
type == OperationRW::OperationType::BLOCK)
320 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
322 return ErrorCode::OK;
326 memcpy(dma_buffer_tx + 1, write_data.
addr_, need_write);
327 *dma_buffer_tx = reg & 0x7f;
329 HAL_SPI_Transmit(spi_handle_, dma_buffer_tx, need_write + 1, 20) == HAL_OK
335 if (op.
type == OperationRW::OperationType::BLOCK)
337 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
344extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
346 STM32SPI *spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
350extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
352 STM32SPI *spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
354 if (spi->read_buff_.
size_ > 0)
357 SCB_InvalidateDCache_by_Addr(spi->dma_buff_rx_.
addr_, spi->read_buff_.
size_);
361 memcpy(spi->read_buff_.
addr_, spi->dma_buff_rx_.
addr_, spi->read_buff_.
size_);
365 uint8_t *rx_dma_buff =
reinterpret_cast<uint8_t *
>(spi->dma_buff_rx_.
addr_);
366 memcpy(spi->read_buff_.
addr_, rx_dma_buff + 1, spi->read_buff_.
size_);
373extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
375 HAL_SPI_RxCpltCallback(hspi);
378extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
380 STM32SPI *spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
常量原始数据封装类。 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 MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
union LibXR::Operation::@4 data
原始数据封装类。 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).
@ EDGE_2
在第二个时钟边沿采样数据。Data sampled on the second clock edge.
@ EDGE_1
在第一个时钟边沿采样数据。Data sampled on the first clock edge.
@ LOW
时钟空闲时为低电平。Clock idle low.
@ HIGH
时钟空闲时为高电平。Clock idle high.
ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op) override
进行 SPI 读写操作。Performs SPI read and write operations.
ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op) override
从 SPI 设备的寄存器读取数据。 Reads data from a specific register of the SPI device.
ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op) override
向 SPI 设备的寄存器写入数据。 Writes data to a specific register of the SPI device.
ErrorCode SetConfig(SPI::Configuration config) override
设置 SPI 配置参数。Sets SPI configuration parameters.
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
constexpr auto max(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最大值
存储 SPI 配置参数的结构体。Structure for storing SPI configuration parameters.
ClockPhase clock_phase
SPI 时钟相位。SPI clock phase.
ClockPolarity clock_polarity
SPI 时钟极性。SPI clock polarity.