#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; }