/** ************************************************************************** * @file general_spi.c * @brief Модуль для инициализации SPI. ************************************************************************** * @details * * Функции: * - SPI_Base_Init Инициализация SPI * * Functions: spi initialize * - SPI_GPIO_Init Инициализация GPIO для SPI * - SPI_DMA_Init Инициализация DMA для SPI * - SPI_MspInit Аналог HAL_MspInit для SPI * - SPI_MspDeInit Аналог HAL_MspDeInit для SPI * *************************************************************************/ #include "general_spi.h" #include "general_gpio.h" //------------------------------------------------------------------- //------------------------SPI INIT FUNCTIONS------------------------ /** * @brief Initialize SPI with SPI_SettingsTypeDef structure. * @param sspi - указатель на структуру с настройками SPI. * @return HAL status. * @note SPI_SettingsTypeDef структура содержит хендл SPI и настройки перефирии (GPIO) */ HAL_StatusTypeDef SPI_Base_Init(SPI_SettingsTypeDef *sspi) { // function takes setting structure for init // check is settings are valid if(Check_SPI_Init_Struct(sspi) != HAL_OK) return HAL_ERROR; SPI_MspInit(&sspi->hspi); if (HAL_SPI_Init(&sspi->hspi) != HAL_OK) { MyLibs_Error_Handler(); return HAL_ERROR; } // init gpio from SPISettings structure SPI_GPIO_Init(sspi); // // init dma from SPISettings structure if need // if (sspi->DMAChannel != 0) // SPI_DMA_Init(&sspi->hspi, sspi->hspi.hdmarx, sspi->DMAChannel, sspi->DMA_CHANNEL_X); return HAL_OK; } /** * @brief Initialize GPIO for SPI. * @param GPIOx - порт для настройки. * @param GPIO_PIN_RX - пин для настройки на прием. * @param GPIO_PIN_TX - пин для настройки на передачу. */ void SPI_GPIO_Init(SPI_SettingsTypeDef *sspi) { GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO INIT GPIO_Clock_Enable(sspi->CLK_GPIOx); GPIO_Clock_Enable(sspi->MISO_GPIOx); GPIO_Clock_Enable(sspi->MOSI_GPIOx); // CLK PIN INIT GPIO_InitStruct.Pin = sspi->CLK_PIN; GPIO_InitStruct.Alternate = sspi->CLK_GPIO_AlternageFunc; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(sspi->CLK_GPIOx, &GPIO_InitStruct); // MISO PIN INIT GPIO_InitStruct.Pin = sspi->MISO_PIN; GPIO_InitStruct.Alternate = sspi->MISO_GPIO_AlternageFunc; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(sspi->MISO_GPIOx, &GPIO_InitStruct); // MOSI PIN INIT GPIO_InitStruct.Pin = sspi->MOSI_PIN; GPIO_InitStruct.Alternate = sspi->MOSI_GPIO_AlternageFunc; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(sspi->MOSI_GPIOx, &GPIO_InitStruct); } /** * @brief Initialize DMA for SPI. * @param hspi - указатель на хендл SPI для настройки DMA. * @param hdma_rx - указатель на хендл DMA для линии приема SPI. * @param DMAChannel - указатель на канал DMA/поток DMA в STM32F407. * @param DMA_CHANNEL_X - канал DMA. */ void SPI_DMA_Init(SPI_HandleTypeDef *hspi, DMA_HandleTypeDef *hdma_rx, DMA_Stream_TypeDef *DMAChannel, uint32_t DMA_CHANNEL_X) { // function takes spi and dma handlers and dmachannel for spi // // for now only dma rx is supported, tx maybe later if needed // // calc defines on boot_project_setup.h // /* SPI3 DMA Init */ // /* SPI3_RX Init */ // // hdma_rx->Instance = DMAChannel; //#if defined(STM32F407xx) // dma channel choose for 407 // hdma_rx->Init.Channel = DMA_CHANNEL_X; //#endif // hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; // hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; // hdma_rx->Init.MemInc = DMA_MINC_ENABLE; // hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; // hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; // hdma_rx->Init.Mode = DMA_CIRCULAR; // hdma_rx->Init.Priority = DMA_PRIORITY_LOW; // if (HAL_DMA_Init(hdma_rx) != HAL_OK) // { // MyLibs_Error_Handler(); // } // __USER_LINKDMA(hspi,hdmarx,hdma_rx); // // // __USER_LINKDMA is need because __HAL_LINKDMA is written for global defined hdma_rx // // so you get error because hal uses . insted of -> } /** * @brief Initialize SPI & DMA clock and interrupt. * @param hspi - указатель на хендл SPI для инициализации. * @note Чтобы не генерировать функцию с иницилизацией неиспользуемых SPI, дефайнами в general_spi.h определяются используемые SPI. */ void SPI_MspInit(SPI_HandleTypeDef *hspi) // analog for hal function { // rcc, dma and interrupt init for SPIs // GPIO init was moved to own functions SPI_GPIO_Init if(0); #ifdef USE_SPI1 else if(hspi->Instance==SPI1) { // /* DMA2 clock enable */ // __HAL_RCC_DMA2_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); /* SPI1 clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); /* SPI1 interrupt Init */ HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(SPI1_IRQn); } #endif // USE_SPI1 #ifdef USE_SPI2 else if(hspi->Instance==SPI2) { // /* DMA1 clock enable */ // __HAL_RCC_DMA1_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); /* SPI2 clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); /* SPI2 interrupt Init */ HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(SPI2_IRQn); } #endif // USE_SPI2 #ifdef USE_SPI3 else if(hspi->Instance==SPI3) { // /* DMA1 clock enable */ // __HAL_RCC_DMA1_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); /* SPI3 clock enable */ __HAL_RCC_SPI3_CLK_ENABLE(); /* SPI3 interrupt Init */ HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(SPI3_IRQn); } #endif // USE_SPI3 } /** * @brief Deinitialize SPI & DMA clock and interrupt. * @param hspi - указатель на хендл SPI для деинициализации. * @note Чтобы не генерировать функцию с деиницилизацией неиспользуемых SPI, дефайнами определяются используемые SPI. */ void SPI_MspDeInit(SPI_HandleTypeDef *hspi) // analog for hal function { // rcc, dma and interrupt init for SPIs // GPIO init was moved to own functions SPI_GPIO_Init if(0); #ifdef USE_SPI1 else if(hspi->Instance==SPI1) { // /* DMA2 clock enable */ // __HAL_RCC_DMA2_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); /* SPI1 clock reset */ __HAL_RCC_SPI1_FORCE_RESET(); __HAL_RCC_SPI1_RELEASE_RESET(); } #endif // USE_SPI1 #ifdef USE_SPI2 else if(hspi->Instance==SPI2) { // /* DMA1 clock enable */ // __HAL_RCC_DMA1_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); /* SPI2 clock reset */ __HAL_RCC_SPI2_FORCE_RESET(); __HAL_RCC_SPI2_RELEASE_RESET(); } #endif // USE_SPI2 #ifdef USE_SPI3 else if(hspi->Instance==SPI3) { // /* DMA1 clock enable */ // __HAL_RCC_DMA1_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); /* SPI3 clock reset */ __HAL_RCC_SPI3_FORCE_RESET(); __HAL_RCC_SPI3_RELEASE_RESET(); } #endif // USE_SPI3 } /** * @brief Check that spi init structure have correct values. * @param sspi - указатель на структуру с настройками SPI. * @return HAL status. */ HAL_StatusTypeDef Check_SPI_Init_Struct(SPI_SettingsTypeDef *sspi) { // check is settings are valid if (!IS_SPI_ALL_INSTANCE(sspi->hspi.Instance)) return HAL_ERROR; // check init settings if (!IS_SPI_MODE(sspi->hspi.Init.Mode)) return HAL_ERROR; if (!IS_SPI_DIRECTION(sspi->hspi.Init.Direction)) return HAL_ERROR; if (!IS_SPI_DATASIZE(sspi->hspi.Init.DataSize)) return HAL_ERROR; if (!IS_SPI_BAUDRATE_PRESCALER(sspi->hspi.Init.BaudRatePrescaler)) return HAL_ERROR; if (!IS_SPI_CPOL(sspi->hspi.Init.CLKPolarity)) return HAL_ERROR; if (!IS_SPI_CPHA(sspi->hspi.Init.CLKPhase)) return HAL_ERROR; if (!IS_SPI_NSS(sspi->hspi.Init.NSS)) return HAL_ERROR; if (!IS_SPI_FIRST_BIT(sspi->hspi.Init.FirstBit)) return HAL_ERROR; if (!IS_SPI_CRC_CALCULATION(sspi->hspi.Init.CRCCalculation)) return HAL_ERROR; if (!IS_SPI_CRC_POLYNOMIAL(sspi->hspi.Init.NSS) && (sspi->hspi.Init.CRCCalculation != SPI_CRCCALCULATION_DISABLE)) return HAL_ERROR; if (!IS_SPI_TIMODE(sspi->hspi.Init.TIMode)) return HAL_ERROR; // check gpio if (!IS_GPIO_ALL_INSTANCE(sspi->CLK_GPIOx) || !IS_GPIO_ALL_INSTANCE(sspi->MISO_GPIOx) || !IS_GPIO_ALL_INSTANCE(sspi->MOSI_GPIOx)) return HAL_ERROR; if (!IS_GPIO_PIN(sspi->CLK_PIN) && !IS_GPIO_PIN(sspi->MISO_PIN) && !IS_GPIO_PIN(sspi->MOSI_PIN)) // if both pins arent set up return HAL_ERROR; return HAL_OK; }