Mercurial > public > ostc4
view Small_CPU/Src/spi.c @ 323:b43fa6a6c85a
Merged in Ideenmodellierer/ostc4/O2_SensorSync (pull request #28)
O2 SensorSync
author | heinrichsweikamp <bitbucket@heinrichsweikamp.com> |
---|---|
date | Sun, 30 Jun 2019 19:52:46 +0000 |
parents | 580822b5d3d1 |
children | 2fc08a0d1ec3 |
line wrap: on
line source
/** ****************************************************************************** * @file spi.c * @author heinrichs weikamp gmbh * @version V0.0.1 * @date 16-Sept-2014 * @brief Source code for spi control * @verbatim ============================================================================== ##### How to use ##### ============================================================================== @endverbatim ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2014 heinrichs weikamp</center></h2> * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "global_constants.h" #include "spi.h" #include "dma.h" //#include "gpio.h" /* USER CODE BEGIN 0 */ #include "scheduler.h" #ifdef DEBUG_GPIO extern void GPIO_new_DEBUG_LOW(void); extern void GPIO_new_DEBUG_HIGH(void); #endif uint8_t data_error = 0; uint32_t data_error_time = 0; uint8_t SPIDataRX = 0; /* Flag to signal that SPI RX callback has been triggered */ static void SPI_Error_Handler(void); /* USER CODE END 0 */ static uint8_t SPI_check_header_and_footer_ok(void); static uint8_t DataEX_check_header_and_footer_shifted(void); SPI_HandleTypeDef hspi1; SPI_HandleTypeDef hspi3; DMA_HandleTypeDef hdma_tx; DMA_HandleTypeDef hdma_rx; // SPI3 init function void MX_SPI3_Init(void) { hspi3.Instance = SPI3; hspi3.Init.Mode = SPI_MODE_MASTER; hspi3.Init.Direction = SPI_DIRECTION_2LINES; hspi3.Init.DataSize = SPI_DATASIZE_8BIT; hspi3.Init.CLKPolarity = SPI_POLARITY_HIGH; hspi3.Init.CLKPhase = SPI_PHASE_1EDGE; hspi3.Init.NSS = SPI_NSS_SOFT; hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi3.Init.TIMode = SPI_TIMODE_DISABLED; hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; hspi3.Init.CRCPolynomial = 7; HAL_SPI_Init(&hspi3); } void MX_SPI3_DeInit(void) { HAL_SPI_DeInit(&hspi3); } uint8_t SPI3_ButtonAdjust(uint8_t *arrayInput, uint8_t *arrayOutput) { HAL_StatusTypeDef status; uint8_t answer[10]; uint8_t rework[10]; rework[0] = 0xFF; for (int i = 0; i < 3; i++) { // limiter if (arrayInput[i] == 0xFF) arrayInput[i] = 0xFE; if (arrayInput[i] >= 15) { // copy - ausl�se-schwelle rework[i + 1] = arrayInput[i]; // wieder-scharf-schalte-schwelle rework[i + 3 + 1] = arrayInput[i] - 10; } else if (arrayInput[i] >= 10) { // copy - ausl�se-schwelle rework[i + 1] = arrayInput[i]; // wieder-scharf-schalte-schwelle rework[i + 3 + 1] = arrayInput[i] - 5; } else { // copy - ausl�se-schwelle rework[i + 1] = 7; // wieder-scharf-schalte-schwelle rework[i + 3 + 1] = 6; } } status = HAL_OK; /* = 0 */ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET); for (int i = 0; i < 7; i++) { HAL_Delay(10); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET); HAL_Delay(10); status += HAL_SPI_TransmitReceive(&hspi3, &rework[i], &answer[i], 1, 20); HAL_Delay(10); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET); } if (status == HAL_OK) { for (int i = 0; i < 3; i++) { arrayOutput[i] = answer[i + 2]; // first not, return of 0xFF not } return 1; } else return 0; } // SPI5 init function void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_SLAVE; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_HARD_INPUT; //SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLED; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; //_DISABLED; _ENABLED; hspi1.Init.CRCPolynomial = 7; HAL_SPI_Init(&hspi1); } void MX_SPI_DeInit(void) { HAL_SPI_DeInit(&hspi1); } void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) { GPIO_InitTypeDef GPIO_InitStruct; if (hspi->Instance == SPI1) { SPIDataRX = 0; // Peripheral clock enable __SPI1_CLK_ENABLE(); __GPIOA_CLK_ENABLE(); //SPI1 GPIO Configuration //PA4 ------> SPI1_CS //PA5 ------> SPI1_SCK //PA6 ------> SPI1_MISO //PA7 ------> SPI1_MOSI GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; // GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; /* Decision is based on errata which recommends FAST for GPIO at 90Mhz */ GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); //##-3- Configure the DMA streams ########################################## // Configure the DMA handler for Transmission process hdma_tx.Instance = DMA2_Stream3; hdma_tx.Init.Channel = DMA_CHANNEL_3; hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_tx.Init.Mode = DMA_NORMAL; hdma_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH; hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_tx.Init.MemBurst = DMA_MBURST_INC4; hdma_tx.Init.PeriphBurst = DMA_PBURST_INC4; HAL_DMA_Init(&hdma_tx); // Associate the initialized DMA handle to the the SPI handle __HAL_LINKDMA(hspi, hdmatx, hdma_tx); // Configure the DMA handler for Transmission process hdma_rx.Instance = DMA2_Stream0; hdma_rx.Init.Channel = DMA_CHANNEL_3; 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_NORMAL; hdma_rx.Init.Priority = DMA_PRIORITY_HIGH; hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_rx.Init.MemBurst = DMA_MBURST_INC4; hdma_rx.Init.PeriphBurst = DMA_PBURST_INC4; HAL_DMA_Init(&hdma_rx); // Associate the initialized DMA handle to the the SPI handle __HAL_LINKDMA(hspi, hdmarx, hdma_rx); //##-4- Configure the NVIC for DMA ######################################### //NVIC configuration for DMA transfer complete interrupt (SPI3_RX) HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 1, 0); HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); // NVIC configuration for DMA transfer complete interrupt (SPI1_TX) HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 1, 1); HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); } else if (hspi->Instance == SPI3) { __GPIOC_CLK_ENABLE(); __SPI3_CLK_ENABLE(); //SPI1 GPIO Configuration //PC10 ------> SPI3_SCK //PC11 ------> SPI3_MISO //PC12 ------> SPI3_MOSI //PA15 ------> SPI3_NSS (official) //PC9 ------> SPI3_NSS (hw) GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; GPIO_InitStruct.Alternate = GPIO_AF6_SPI3; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET); } } void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) { if (hspi->Instance == SPI1) { __SPI1_FORCE_RESET(); __SPI1_RELEASE_RESET(); //SPI1 GPIO Configuration //PA5 ------> SPI1_SCK //PA6 ------> SPI1_MISO //PA7 ------> SPI1_MOSI HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7); HAL_DMA_DeInit(&hdma_tx); HAL_DMA_DeInit(&hdma_rx); HAL_NVIC_DisableIRQ(DMA2_Stream3_IRQn); HAL_NVIC_DisableIRQ(DMA2_Stream0_IRQn); } else if (hspi->Instance == SPI3) { __SPI3_FORCE_RESET(); __SPI3_RELEASE_RESET(); //SPI1 GPIO Configuration //PC10 ------> SPI3_SCK //PC11 ------> SPI3_MISO //PC12 ------> SPI3_MOSI //PA15 ------> SPI3_NSS (official) //PC9 ------> SPI3_NSS (hw) HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12); } } void SPI_synchronize_with_Master(void) { #ifdef USE_OLD_SYNC_METHOD GPIO_InitTypeDef GPIO_InitStruct; // __GPIOA_CLK_ENABLE(); /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // HAL_Delay(10); while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == 0); HAL_Delay(10); while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == 1); HAL_Delay(50); #endif } void SPI_Start_single_TxRx_with_Master(void) { uint8_t * pOutput; HAL_StatusTypeDef retval; if (global.dataSendToSlave.getDeviceDataNow) { global.dataSendToSlave.getDeviceDataNow = 0; pOutput = (uint8_t*) &(global.deviceDataSendToMaster); } else { pOutput = (uint8_t*) &(global.dataSendToMaster); } retval = HAL_SPI_TransmitReceive_DMA(&hspi1, pOutput,(uint8_t*) &(global.dataSendToSlave), EXCHANGE_BUFFERSIZE); if ( retval!= HAL_OK) { SPI_Error_Handler(); } } void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { /* restart SPI */ if (hspi == &hspi1) { if(SPI_check_header_and_footer_ok()) /* process timestamp provided by main */ { Scheduler_SyncToSPI(global.dataSendToSlave.header.checkCode[SPI_HEADER_INDEX_TX_TICK]); } else { Scheduler_SyncToSPI(0); /* => no async will be calculated */ } SPIDataRX = 1; /* stop data exchange? */ if (global.mode == MODE_SHUTDOWN) { global.mode = MODE_SLEEP; global.dataSendToSlavePending = 0; global.dataSendToSlaveIsValid = 1; global.dataSendToSlaveIsNotValidCount = 0; } } } uint8_t SPI_Evaluate_RX_Data() { uint8_t resettimeout = 1; uint8_t ret = SPIDataRX; if ((global.mode != MODE_SHUTDOWN) && ( global.mode != MODE_SLEEP) && (SPIDataRX)) { SPIDataRX = 0; /* data consistent? */ if (SPI_check_header_and_footer_ok()) { global.dataSendToMaster.header.checkCode[SPI_HEADER_INDEX_RX_STATE] = SPI_RX_STATE_OK; // GPIO_new_DEBUG_HIGH(); //For debug. global.dataSendToSlaveIsValid = 1; global.dataSendToSlaveIsNotValidCount = 0; /* Master signal a data shift outside of his control => reset own DMA and resync */ if(global.dataSendToSlave.header.checkCode[SPI_HEADER_INDEX_RX_STATE] == SPI_RX_STATE_SHIFTED) { HAL_SPI_Abort_IT(&hspi1); Scheduler_Request_sync_with_SPI(SPI_SYNC_METHOD_HARD); } else { } SPI_Start_single_TxRx_with_Master(); } else { // GPIO_new_DEBUG_LOW(); //For debug. global.dataSendToSlaveIsValid = 0; global.dataSendToSlaveIsNotValidCount++; if(DataEX_check_header_and_footer_shifted()) { /* Reset own DMA */ if ((global.dataSendToSlaveIsNotValidCount % 10) == 1) //% 10 { HAL_SPI_Abort_IT(&hspi1); /* reset DMA only once */ } /* Signal problem to master */ if ((global.dataSendToSlaveIsNotValidCount ) >= 2) { global.dataSendToMaster.header.checkCode[SPI_HEADER_INDEX_RX_STATE] = SPI_RX_STATE_SHIFTED; } } else /* handle received data as if no data would have been received */ { global.dataSendToMaster.header.checkCode[SPI_HEADER_INDEX_RX_STATE] = SPI_RX_STATE_OFFLINE; resettimeout = 0; } HAL_SPI_TransmitReceive_DMA(&hspi1,(uint8_t*) &(global.dataSendToMaster),(uint8_t*) &(global.dataSendToSlave), EXCHANGE_BUFFERSIZE); } global.dataSendToMaster.power_on_reset = 0; global.deviceDataSendToMaster.power_on_reset = 0; scheduleSpecial_Evaluate_DataSendToSlave(); if(resettimeout) { global.check_sync_not_running = 0; } } return ret; } static uint8_t SPI_check_header_and_footer_ok(void) { if (global.dataSendToSlave.header.checkCode[0] != 0xBB) return 0; #ifdef USE_OLD_HEADER_FORMAT if (global.dataSendToSlave.header.checkCode[1] != 0x01) return 0; if (global.dataSendToSlave.header.checkCode[2] != 0x01) return 0; #endif if (global.dataSendToSlave.header.checkCode[3] != 0xBB) return 0; if (global.dataSendToSlave.footer.checkCode[0] != 0xF4) return 0; if (global.dataSendToSlave.footer.checkCode[1] != 0xF3) return 0; if (global.dataSendToSlave.footer.checkCode[2] != 0xF2) return 0; if (global.dataSendToSlave.footer.checkCode[3] != 0xF1) return 0; return 1; } /* Check if there is an empty frame providec by RTE (all 0) or even no data provided by RTE (all 0xFF) * If that is not the case the DMA is somehow not in sync */ uint8_t DataEX_check_header_and_footer_shifted() { uint8_t ret = 1; if((global.dataSendToSlave.footer.checkCode[0] == 0x00) && (global.dataSendToSlave.footer.checkCode[1] == 0x00) && (global.dataSendToSlave.footer.checkCode[2] == 0x00) && (global.dataSendToSlave.footer.checkCode[3] == 0x00)) { ret = 0; } if((global.dataSendToSlave.footer.checkCode[0] == 0xff) && (global.dataSendToSlave.footer.checkCode[1] == 0xff) && (global.dataSendToSlave.footer.checkCode[2] == 0xff) && (global.dataSendToSlave.footer.checkCode[3] == 0xff)) { ret = 0; } return ret; } static void SPI_Error_Handler(void) { //The device is locks. Hard to recover. // while(1) // { // } } /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/