/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : hal_stm32f4_spi.c * @brief : STM32F4 specific SPI HAL implementation ****************************************************************************** */ /* USER CODE END Header */ #include "hal.h" #include "hal_spi.h" #include "hal_stm32f4_spi.h" #include "stm32f4xx_hal.h" #include "stm32f4xx_hal_spi.h" #include /* SPI handles */ static SPI_HandleTypeDef hspi1; static SPI_HandleTypeDef hspi2; static SPI_HandleTypeDef hspi3; static SPI_HandleTypeDef hspi4; static SPI_HandleTypeDef hspi5; static SPI_HandleTypeDef hspi6; /** * @brief Get SPI handle based on instance * @param instance SPI instance identifier * @return Pointer to SPI handle */ static SPI_HandleTypeDef* get_spi_handle(hal_spi_instance_t instance) { switch (instance) { case HAL_SPI_INSTANCE_1: return &hspi1; case HAL_SPI_INSTANCE_2: return &hspi2; case HAL_SPI_INSTANCE_3: return &hspi3; case HAL_SPI_INSTANCE_4: return &hspi4; case HAL_SPI_INSTANCE_5: return &hspi5; case HAL_SPI_INSTANCE_6: return &hspi6; default: return NULL; } } /** * @brief STM32F4 specific SPI initialization * @param instance SPI instance identifier * @param config SPI configuration structure * @return true if initialization is successful, false otherwise */ bool hal_stm32f4_spi_init(hal_spi_instance_t instance, const hal_spi_config_t *config) { if (config == NULL) { return false; } SPI_HandleTypeDef* hspi = get_spi_handle(instance); if (hspi == NULL) { return false; } /* Configure SPI parameters */ hspi->Instance = NULL; hspi->Init.Mode = (config->mode == HAL_SPI_MODE_MASTER) ? SPI_MODE_MASTER : SPI_MODE_SLAVE; hspi->Init.DataSize = (config->databits == HAL_SPI_DATABITS_8) ? SPI_DATASIZE_8BIT : SPI_DATASIZE_16BIT; hspi->Init.CLKPolarity = (config->polarity == HAL_SPI_POLARITY_LOW) ? SPI_POLARITY_LOW : SPI_POLARITY_HIGH; hspi->Init.CLKPhase = (config->phase == HAL_SPI_PHASE_1EDGE) ? SPI_PHASE_1EDGE : SPI_PHASE_2EDGE; hspi->Init.NSS = SPI_NSS_SOFT; /* Use software NSS */ /* Calculate baud rate prescaler based on desired baud rate */ uint32_t apb_clock = HAL_RCC_GetPCLK2Freq(); /* Assume SPI1 is on APB2 */ /* Define prescaler enum values */ const uint32_t prescaler_enums[] = { SPI_BAUDRATEPRESCALER_2, SPI_BAUDRATEPRESCALER_4, SPI_BAUDRATEPRESCALER_8, SPI_BAUDRATEPRESCALER_16, SPI_BAUDRATEPRESCALER_32, SPI_BAUDRATEPRESCALER_64, SPI_BAUDRATEPRESCALER_128, SPI_BAUDRATEPRESCALER_256 }; uint32_t prescaler_index = 0; uint32_t temp_prescaler = 2; /* Find the appropriate prescaler */ while (prescaler_index < sizeof(prescaler_enums)/sizeof(prescaler_enums[0])) { if (apb_clock / temp_prescaler <= config->baudrate) { break; } temp_prescaler <<= 1; prescaler_index++; } /* Use the found prescaler or the maximum available */ if (prescaler_index >= sizeof(prescaler_enums)/sizeof(prescaler_enums[0])) { prescaler_index = sizeof(prescaler_enums)/sizeof(prescaler_enums[0]) - 1; } hspi->Init.BaudRatePrescaler = prescaler_enums[prescaler_index]; hspi->Init.FirstBit = SPI_FIRSTBIT_MSB; /* Default to MSB first */ hspi->Init.TIMode = SPI_TIMODE_DISABLE; hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi->Init.CRCPolynomial = 10; /* Configure GPIO and enable clocks based on instance */ GPIO_InitTypeDef GPIO_InitStruct = {0}; switch (instance) { case HAL_SPI_INSTANCE_1: /* Enable SPI1 clock */ __HAL_RCC_SPI1_CLK_ENABLE(); /* Enable GPIOB clock */ __HAL_RCC_GPIOB_CLK_ENABLE(); /* Configure SPI1 GPIO pins: SCK(PB3), MISO(PB4), MOSI(PB5) */ GPIO_InitStruct.Pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); hspi->Instance = SPI1; break; case HAL_SPI_INSTANCE_2: /* Enable SPI2 clock */ __HAL_RCC_SPI2_CLK_ENABLE(); /* Enable GPIOB clock */ __HAL_RCC_GPIOB_CLK_ENABLE(); /* Configure SPI2 GPIO pins: SCK(PB13), MISO(PB14), MOSI(PB15) */ GPIO_InitStruct.Pin = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); hspi->Instance = SPI2; break; case HAL_SPI_INSTANCE_3: /* Enable SPI3 clock */ __HAL_RCC_SPI3_CLK_ENABLE(); /* Enable GPIOC clock */ __HAL_RCC_GPIOC_CLK_ENABLE(); /* Configure SPI3 GPIO pins: SCK(PC10), MISO(PC11), MOSI(PC12) */ GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF6_SPI3; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); hspi->Instance = SPI3; break; default: return false; } /* Initialize SPI */ if (HAL_SPI_Init(hspi) != HAL_OK) { return false; } return true; } /** * @brief STM32F4 specific SPI deinitialization * @param instance SPI instance identifier * @return true if deinitialization is successful, false otherwise */ bool hal_stm32f4_spi_deinit(hal_spi_instance_t instance) { SPI_HandleTypeDef* hspi = get_spi_handle(instance); if (hspi == NULL || hspi->Instance == NULL) { return false; } if (HAL_SPI_DeInit(hspi) != HAL_OK) { return false; } /* Disable SPI clock */ switch (instance) { case HAL_SPI_INSTANCE_1: __HAL_RCC_SPI1_CLK_DISABLE(); break; case HAL_SPI_INSTANCE_2: __HAL_RCC_SPI2_CLK_DISABLE(); break; case HAL_SPI_INSTANCE_3: __HAL_RCC_SPI3_CLK_DISABLE(); break; default: return false; } return true; } /** * @brief STM32F4 specific SPI transmit implementation * @param instance SPI instance identifier * @param p_data Pointer to data buffer to transmit * @param size Size of data to transmit * @return true if transmission is successful, false otherwise */ bool hal_stm32f4_spi_transmit(hal_spi_instance_t instance, const uint8_t *p_data, uint16_t size) { if (p_data == NULL || size == 0) { return false; } SPI_HandleTypeDef* hspi = get_spi_handle(instance); if (hspi == NULL || hspi->Instance == NULL) { return false; } HAL_StatusTypeDef status = HAL_SPI_Transmit(hspi, (uint8_t*)p_data, size, HAL_MAX_DELAY); return (status == HAL_OK); } /** * @brief STM32F4 specific SPI receive implementation * @param instance SPI instance identifier * @param p_data Pointer to data buffer to receive * @param size Size of data to receive * @return true if reception is successful, false otherwise */ bool hal_stm32f4_spi_receive(hal_spi_instance_t instance, uint8_t *p_data, uint16_t size) { if (p_data == NULL || size == 0) { return false; } SPI_HandleTypeDef* hspi = get_spi_handle(instance); if (hspi == NULL || hspi->Instance == NULL) { return false; } HAL_StatusTypeDef status = HAL_SPI_Receive(hspi, p_data, size, HAL_MAX_DELAY); return (status == HAL_OK); } /** * @brief STM32F4 specific SPI transmit and receive implementation * @param instance SPI instance identifier * @param p_tx_data Pointer to data buffer to transmit * @param p_rx_data Pointer to data buffer to receive * @param size Size of data to transmit/receive * @return true if transmission and reception are successful, false otherwise */ bool hal_stm32f4_spi_transmit_receive(hal_spi_instance_t instance, const uint8_t *p_tx_data, uint8_t *p_rx_data, uint16_t size) { if (p_tx_data == NULL || p_rx_data == NULL || size == 0) { return false; } SPI_HandleTypeDef* hspi = get_spi_handle(instance); if (hspi == NULL || hspi->Instance == NULL) { return false; } HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(hspi, (uint8_t*)p_tx_data, p_rx_data, size, HAL_MAX_DELAY); return (status == HAL_OK); }