bs_bcu_app/drv/drv_stm32f4xx/drv_spi.c

351 lines
12 KiB
C
Raw Normal View History

2024-11-07 17:24:19 +08:00
#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)&reg->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)&reg->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仍然为0TXE为02APB时
TXE变为1BSY变为1BSY再变为0
**********************************************************************/
//发送一个字节
2024-11-10 15:28:53 +08:00
2024-11-07 17:24:19 +08:00
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;
}