351 lines
12 KiB
C
351 lines
12 KiB
C
|
#include "drv_clk.h"
|
|||
|
#include "drv_spi.h"
|
|||
|
#include "drv_dma.h"
|
|||
|
#include "drv_gpio.h"
|
|||
|
|
|||
|
|
|||
|
#include "kit_debug.h"
|
|||
|
|
|||
|
|
|||
|
#define SPI_SYNC_TIMEOUT (2550u)
|
|||
|
#define CR1_SPI_EN ((uint16_t)0x0040)
|
|||
|
#define SPI_NSS_Soft ((uint16_t)0x0200)
|
|||
|
#define SPI_Mode_Master ((uint16_t)0x0104)
|
|||
|
#define SPI_Direction_1Line_Tx ((uint16_t)0xC000)
|
|||
|
#define SPI_I2S_DMAReq_Tx ((uint16_t)0x0002)
|
|||
|
#define SPI_I2S_DMAReq_Rx ((uint16_t)0x0001)
|
|||
|
#define SPI_I2S_FLAG_TXE ((uint16_t)0x0002)
|
|||
|
#define SPI_I2S_FLAG_BSY ((uint16_t)0x0080)
|
|||
|
#define SPI_I2S_FLAG_RXNE ((uint16_t)0x0001)
|
|||
|
|
|||
|
#define GPIO_REMAP_SPI1 ((uint32_t)0x00000001)
|
|||
|
#define GPIO_REMAP_SPI3 ((uint32_t)0x10000000)
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
DmaStream rx_dma_stream;
|
|||
|
DmaStream tx_dma_stream;
|
|||
|
DmaChannel dma_channel;
|
|||
|
|
|||
|
SPI_TypeDef *reg;
|
|||
|
}Stm32SpiProp;
|
|||
|
|
|||
|
static KitResult drv_spi_set_clock_gpio(SpiDev dev, uint16_t sck_idx, uint16_t miso_idx, uint16_t mosi_idx);
|
|||
|
|
|||
|
static const Stm32SpiProp stm32_spi[kSpiDev_End] =
|
|||
|
{
|
|||
|
{kDma2Stream_2, kDma2Stream_3, kDmaChannel_3, SPI1},
|
|||
|
{kDma1Stream_3, kDma1Stream_4, kDmaChannel_0, SPI2},
|
|||
|
{kDma2Stream_0, kDma2Stream_5, kDmaChannel_0, SPI3}
|
|||
|
};
|
|||
|
|
|||
|
/********************************************************************************
|
|||
|
Func SPI1_REMAP = 0 SPI1_REMAP = 1 SPI3_REMAP = 0 SPI3_REMAP = 1
|
|||
|
SPI_SCK PA5 PB3 PB3 PC10
|
|||
|
SPI_MISO PA6 PB4 PB4 PC11
|
|||
|
SPI_MOSI PA7 PB5 PB5 PC12
|
|||
|
|
|||
|
APB1频率 = 168M/4 = 42M
|
|||
|
APB2频率 = 168M/2 = 84M
|
|||
|
********************************************************************************/
|
|||
|
static KitResult drv_spi_set_clock_gpio(SpiDev dev, uint16_t sck_idx, uint16_t miso_idx, uint16_t mosi_idx)
|
|||
|
{
|
|||
|
KitResult res = kKitResult_Ok;
|
|||
|
|
|||
|
uint32_t sck_io = drv_gpio_get_actual_io(sck_idx);
|
|||
|
uint32_t miso_io = drv_gpio_get_actual_io(miso_idx);
|
|||
|
uint32_t mosi_io = drv_gpio_get_actual_io(mosi_idx);
|
|||
|
switch (dev)
|
|||
|
{
|
|||
|
case kSpiDev_1:
|
|||
|
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
|
|||
|
res |= drv_clk_set_status(kBspClk_APB2, RCC_APB2Periph_SPI1);
|
|||
|
if((sck_io == GPIO_PORT_PIN(kGpioPort_A, 5)) && (mosi_io == GPIO_PORT_PIN(kGpioPort_A, 7)))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_A, 5, 5);
|
|||
|
drv_gpio_set_af(kGpioPort_A, 7, 5);
|
|||
|
if(miso_io == GPIO_PORT_PIN(kGpioPort_A, 6))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_A, 6, 5);
|
|||
|
}
|
|||
|
}
|
|||
|
else if((sck_io == GPIO_PORT_PIN(kGpioPort_B, 3)) && (mosi_io == GPIO_PORT_PIN(kGpioPort_B, 5)))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_B, 3, 5);
|
|||
|
drv_gpio_set_af(kGpioPort_B, 5, 5);
|
|||
|
if(miso_io == GPIO_PORT_PIN(kGpioPort_B, 4))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_B, 4, 5);
|
|||
|
}
|
|||
|
}
|
|||
|
else if((sck_io == GPIO_PORT_PIN(kGpioPort_A, 5)) && (mosi_io == GPIO_PORT_PIN(kGpioPort_B, 5)))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_A, 5, 5);
|
|||
|
drv_gpio_set_af(kGpioPort_B, 5, 5);
|
|||
|
if(miso_io == GPIO_PORT_PIN(kGpioPort_A, 6))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_A, 6, 5);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
res |= kKitResult_ParamErr;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case kSpiDev_2:
|
|||
|
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
|
|||
|
if((sck_io == GPIO_PORT_PIN(kGpioPort_B, 13)) || (mosi_io == GPIO_PORT_PIN(kGpioPort_B, 15)))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_B, 13, 5);
|
|||
|
drv_gpio_set_af(kGpioPort_B, 15, 5);
|
|||
|
if(miso_io == GPIO_PORT_PIN(kGpioPort_B, 14))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_B, 14, 5);
|
|||
|
}
|
|||
|
}
|
|||
|
#if defined(STM32F429_439xx)
|
|||
|
else if((sck_io == GPIO_PORT_PIN(kGpioPort_D, 3)) && (mosi_io == GPIO_PORT_PIN(kGpioPort_C, 3)))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_D, 3, 5);
|
|||
|
drv_gpio_set_af(kGpioPort_C, 3, 5);
|
|||
|
if(miso_io == GPIO_PORT_PIN(kGpioPort_C, 2))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_C, 2, 5);
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
else
|
|||
|
{
|
|||
|
res |= kKitResult_ParamErr;
|
|||
|
}
|
|||
|
break;
|
|||
|
case kSpiDev_3:
|
|||
|
RCC->APB1ENR |= RCC_APB1ENR_SPI3EN;
|
|||
|
if((sck_io == GPIO_PORT_PIN(kGpioPort_B, 3)) && (mosi_io == GPIO_PORT_PIN(kGpioPort_B, 5)))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_B, 3, 6);
|
|||
|
drv_gpio_set_af(kGpioPort_B, 5, 6);
|
|||
|
if(miso_io == GPIO_PORT_PIN(kGpioPort_B, 4))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_B, 4, 6);
|
|||
|
}
|
|||
|
}
|
|||
|
else if((sck_io == GPIO_PORT_PIN(kGpioPort_C, 10)) && (mosi_io == GPIO_PORT_PIN(kGpioPort_C, 12)))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_C, 10, 6);
|
|||
|
drv_gpio_set_af(kGpioPort_C, 12, 6);
|
|||
|
if(miso_io == GPIO_PORT_PIN(kGpioPort_C, 11))
|
|||
|
{
|
|||
|
drv_gpio_set_af(kGpioPort_C, 11, 6);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
res = kKitResult_ParamErr;
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
res = kKitResult_ParamErr;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
/*******************重要寄存器默认值*******************
|
|||
|
*SPI_CR1-BIDIMODE(15) 默认“双线双向”模式
|
|||
|
*SPI_CR1-DFF(11) 默认8位数据帧格式
|
|||
|
*SPI_CR1-SSM(9) 默认硬件控制CS
|
|||
|
*SPI_CR1-LSBFIRST(7) 默认先发送MSB
|
|||
|
*spi1 时钟源位APB2 速度= CLOCK_APB2_FREQ/Divx
|
|||
|
*TXE置位表示数据数据从发送缓冲器传输到移位寄存器,并不一定发送完成
|
|||
|
*RXNE置位表示移位寄存器中接收到的数据字被传送到接收缓冲器
|
|||
|
********************************************************/
|
|||
|
#define SPI_CR1_FRF KIT_CREAT_BIT(4)
|
|||
|
KitResult drv_spi_init(SpiDev dev, SpiFreq freq, SpiMode mode, SpiFrame spi_frame, uint16_t sck_idx, uint16_t miso_idx, uint16_t mosi_idx)
|
|||
|
{
|
|||
|
uint16_t cr1;
|
|||
|
KitResult res;
|
|||
|
|
|||
|
KIT_ASSERT_PARAM((dev < kSpiDev_End) && (freq < kSpiFreq_End) && (mode < kSpiMode_End) && (spi_frame < SpiFrame_End));
|
|||
|
|
|||
|
res = drv_spi_set_clock_gpio(dev, sck_idx, miso_idx, mosi_idx);
|
|||
|
if(res == kKitResult_Ok)
|
|||
|
{
|
|||
|
cr1 = stm32_spi[dev].reg->CR1;
|
|||
|
cr1 |= freq << 3;
|
|||
|
cr1 |= (mode | (spi_frame << 7));
|
|||
|
//主机模式 cs软件控制 8位数据
|
|||
|
cr1 |= (SPI_NSS_Soft | SPI_Mode_Master | CR1_SPI_EN);
|
|||
|
if(miso_idx == NULL)
|
|||
|
cr1 |= SPI_Direction_1Line_Tx;
|
|||
|
|
|||
|
stm32_spi[dev].reg->CR1 = cr1;
|
|||
|
}
|
|||
|
|
|||
|
KIT_ASSERT_RES(dev, res);
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
KitResult drv_spi_init1(SpiDev dev, SpiFreq freq, uint32_t spi_config, uint16_t sck_idx, uint16_t miso_idx, uint16_t mosi_idx)
|
|||
|
{
|
|||
|
uint16_t cr1;
|
|||
|
KitResult res;
|
|||
|
|
|||
|
KIT_ASSERT_PARAM((dev < kSpiDev_End) && (freq < kSpiFreq_End));
|
|||
|
|
|||
|
res = drv_spi_set_clock_gpio(dev, sck_idx, miso_idx, mosi_idx);
|
|||
|
if(res == kKitResult_Ok)
|
|||
|
{
|
|||
|
cr1 = freq << 3;
|
|||
|
cr1 |= (uint16_t)spi_config;
|
|||
|
|
|||
|
stm32_spi[dev].reg->CR1 |= cr1;
|
|||
|
stm32_spi[dev].reg->CR2 |= (spi_config >> 16);
|
|||
|
}
|
|||
|
|
|||
|
KIT_ASSERT_RES(dev, res);
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
KitResult drv_spi_set_dma(SpiDev dev, bool is_rx_en, bool is_tx_en)
|
|||
|
{
|
|||
|
uint16_t cr2;
|
|||
|
KitResult res;
|
|||
|
SPI_TypeDef *reg;
|
|||
|
|
|||
|
KIT_ASSERT_PARAM(dev < kSpiDev_End);
|
|||
|
|
|||
|
if(dev < kSpiDev_End)
|
|||
|
{
|
|||
|
reg = stm32_spi[dev].reg;
|
|||
|
cr2 = reg->CR2;
|
|||
|
if(is_rx_en == true)
|
|||
|
{
|
|||
|
drv_dma_init(stm32_spi[dev].rx_dma_stream, stm32_spi[dev].dma_channel, DMA_CFG_DATA_DIR_P2M|DMA_CFG_CYCLE_NONE|DMA_CFG_DATA_M_I|DMA_CFG_DATA_P_N|DMA_CFG_DATA_LEN_1B, (uint32_t)®->DR);
|
|||
|
cr2 |= SPI_I2S_DMAReq_Rx;
|
|||
|
}
|
|||
|
else
|
|||
|
cr2 &= ~SPI_I2S_DMAReq_Rx;
|
|||
|
|
|||
|
if(is_tx_en == true)
|
|||
|
{
|
|||
|
drv_dma_init(stm32_spi[dev].tx_dma_stream, stm32_spi[dev].dma_channel, DMA_CFG_DATA_DIR_M2P|DMA_CFG_CYCLE_NONE|DMA_CFG_DATA_M_I|DMA_CFG_DATA_P_N|DMA_CFG_DATA_LEN_1B, (uint32_t)®->DR);
|
|||
|
cr2 |= SPI_I2S_DMAReq_Tx;
|
|||
|
}
|
|||
|
else
|
|||
|
cr2 &= ~SPI_I2S_DMAReq_Tx;
|
|||
|
|
|||
|
reg->CR2 = cr2;
|
|||
|
res = kKitResult_Ok;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
res = kKitResult_OutRange;
|
|||
|
}
|
|||
|
|
|||
|
return res;
|
|||
|
}
|
|||
|
/********************************************************************
|
|||
|
向DR写数据后SPI并不会立即启动发送此时BSY仍然为0,TXE为0,延迟2个APB时
|
|||
|
钟周期后发送启动TXE变为1,BSY变为1,等到数据发送完成BSY再变为0
|
|||
|
**********************************************************************/
|
|||
|
|
|||
|
//发送一个字节
|
|||
|
//Tan 2023/07/27 超时由--改为++
|
|||
|
KitResult drv_spi_sync_send_receive(SpiDev dev, uint8_t *data)
|
|||
|
{
|
|||
|
KitResult res = kKitResult_Ok;
|
|||
|
SPI_TypeDef *reg;
|
|||
|
int32_t timeout = 0;
|
|||
|
|
|||
|
KIT_ASSERT_PARAM((dev < kSpiDev_End) && (data != NULL));
|
|||
|
|
|||
|
reg = stm32_spi[dev].reg;
|
|||
|
//send data
|
|||
|
while((reg->SR & SPI_I2S_FLAG_TXE) == 0)
|
|||
|
{
|
|||
|
if(timeout++ >= SPI_SYNC_TIMEOUT)
|
|||
|
{
|
|||
|
return kKitResult_TimeOut;
|
|||
|
}
|
|||
|
}
|
|||
|
reg->DR = *data;
|
|||
|
|
|||
|
timeout = 0;
|
|||
|
//recved data
|
|||
|
while((reg->SR & (SPI_I2S_FLAG_RXNE | SPI_I2S_FLAG_BSY)) != SPI_I2S_FLAG_RXNE)
|
|||
|
{
|
|||
|
if(timeout++ >= SPI_SYNC_TIMEOUT)
|
|||
|
{
|
|||
|
res = kKitResult_TimeOut;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
*data = reg->DR;
|
|||
|
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//读写多个字节
|
|||
|
KitResult drv_spi_series_sync_send_receive(SpiDev dev, uint8_t *tx_buf, uint16_t tx_len, uint8_t *rx_buf, uint16_t rx_len)
|
|||
|
{
|
|||
|
uint32_t i;
|
|||
|
KitResult res = kKitResult_Ok;
|
|||
|
|
|||
|
KIT_ASSERT_PARAM(dev < kSpiDev_End);
|
|||
|
KIT_ASSERT_PARAM(((tx_buf == NULL) && (tx_len == 0)) || ((tx_buf != NULL) && (tx_len > 0)));
|
|||
|
KIT_ASSERT_PARAM(((rx_buf == NULL) && (rx_len == 0)) || ((rx_buf != NULL) && (rx_len > 0)));
|
|||
|
|
|||
|
//send
|
|||
|
for(i = 0; i < tx_len; i++)
|
|||
|
res |= drv_spi_sync_send_receive(dev, tx_buf + i);
|
|||
|
|
|||
|
//receive
|
|||
|
for(i = 0; i < rx_len; i++)
|
|||
|
res |= drv_spi_sync_send_receive(dev, rx_buf + i);
|
|||
|
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
KitResult drv_spi_dma_sync_send(SpiDev dev, uint8_t *tx_buf, uint16_t tx_len)
|
|||
|
{
|
|||
|
KitResult res;
|
|||
|
|
|||
|
KIT_ASSERT_PARAM(dev < kSpiDev_End);
|
|||
|
KIT_ASSERT_PARAM(((tx_buf == NULL) && (tx_len == 0)) || ((tx_buf != NULL) && (tx_len > 0)));
|
|||
|
|
|||
|
//接收前读一次SPI2->DR,保证接收缓冲区为空
|
|||
|
stm32_spi[dev].reg->DR;
|
|||
|
res = kit_wait_flag((volatile uint32_t *)&stm32_spi[dev].reg->SR, SPI_I2S_FLAG_TXE, SPI_SYNC_TIMEOUT);
|
|||
|
if(res == kKitResult_Ok)
|
|||
|
{
|
|||
|
res = drv_dma_send(stm32_spi[dev].tx_dma_stream, tx_buf, tx_len);
|
|||
|
}
|
|||
|
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
KitResult drv_spi_dma_sync_receive(SpiDev dev, uint8_t *rx_buf, uint16_t rx_len)
|
|||
|
{
|
|||
|
KitResult res;
|
|||
|
|
|||
|
KIT_ASSERT_PARAM(dev < kSpiDev_End);
|
|||
|
KIT_ASSERT_PARAM(((rx_buf == NULL) && (rx_len == 0)) || ((rx_buf != NULL) && (rx_len > 0)));
|
|||
|
|
|||
|
//接收前读一次SPI2->DR,保证接收缓冲区为空
|
|||
|
stm32_spi[dev].reg->DR;
|
|||
|
res = kit_wait_flag((volatile uint32_t *)&stm32_spi[dev].reg->SR, SPI_I2S_FLAG_TXE, SPI_SYNC_TIMEOUT);
|
|||
|
if(res == kKitResult_Ok)
|
|||
|
{
|
|||
|
res = drv_dma_receive(stm32_spi[dev].rx_dma_stream, stm32_spi[dev].tx_dma_stream, rx_buf, rx_len);
|
|||
|
}
|
|||
|
|
|||
|
return res;
|
|||
|
}
|
|||
|
|