- MyLibs - максимально платформонезависимые библиотеки (кроме разве что RTT) - RTT - STM32_General - библиотеки для периферии stm32
		
			
				
	
	
		
			284 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			284 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** 
 | 
						||
**************************************************************************
 | 
						||
* @file general_spi.c
 | 
						||
* @brief Модуль для инициализации SPI.
 | 
						||
**************************************************************************
 | 
						||
Реализация функций для работы с SPI:
 | 
						||
  - Инициализация SPI и его линий CLK/MISO/MOSI
 | 
						||
  - Настройка GPIO для SPI
 | 
						||
  - Настройка NVIC и тактирования SPI
 | 
						||
**************************************************************************/
 | 
						||
#include "general_spi.h"
 | 
						||
#include "general_gpio.h"
 | 
						||
 | 
						||
//-------------------------------------------------------------------
 | 
						||
//------------------------SPI INIT FUNCTIONS------------------------
 | 
						||
/**  
 | 
						||
  * @brief  Инициализация SPI с помощью структуры SPI_SettingsTypeDef.
 | 
						||
  * @param  sspi Указатель на структуру с настройками SPI.
 | 
						||
  * @return HAL status.
 | 
						||
  * @details  
 | 
						||
  * Инициализирует SPI и его GPIO.
 | 
						||
  * Настройка аналогична HAL_SPI_Init 
 | 
						||
  * @code
 | 
						||
  * suart.hspi.Init...
 | 
						||
  * @endcode 
 | 
						||
  * но дополнительно надо прописать пины CLK/MISO/MOSI @ref SPI_SettingsTypeDef
 | 
						||
  */
 | 
						||
HAL_StatusTypeDef SPI_Base_Init(SPI_SettingsTypeDef *sspi)
 | 
						||
{ // function takes setting structure for init
 | 
						||
  
 | 
						||
  // check is settings are valid
 | 
						||
  if(SPI_Check_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  Инициализация GPIO для SPI.
 | 
						||
  * @param  sspi Указатель на структуру с настройками SPI.
 | 
						||
  */
 | 
						||
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);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
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(STM32F4xx) // 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  Настройка тактирования и прерываний SPI.
 | 
						||
  * @param  hspi Указатель на хендл SPI.
 | 
						||
  * @note   Чтобы не генерировать функцию с иницилизацией неиспользуемых SPI,
 | 
						||
            дефайнами @ref SPI_INIT в @ref 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  Деинициализация тактирования и прерываний SPI.
 | 
						||
  * @param  hspi Указатель на хендл SPI.
 | 
						||
  * @note   Чтобы не генерировать функцию с иницилизацией неиспользуемых SPI,
 | 
						||
            дефайнами @ref SPI_INIT в @ref general_spi.h определяются используемые 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  Проверка корректности структуры инициализации SPI.
 | 
						||
  * @param  sspi Указатель на структуру с настройками SPI.
 | 
						||
  * @return HAL status.
 | 
						||
  */
 | 
						||
HAL_StatusTypeDef SPI_Check_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;
 | 
						||
} |