From 90b9961963b625db0f2aabfe8e5e508b1f4fb7f1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 25 Mar 2018 23:42:48 +1100 Subject: [PATCH] H7_HAL/spi: Prevent strict alias error with 16-bit access of TX/RX regs. Without this modification gcc will warn about violation of strict aliasing rules. It is crucial to be able to compile the HAL with the strict aliasing optimisation (-fstrict-aliasing) because the code can function incorrectly without using this optimisation (at least the SD card driver of the F4 HAL requires this optimisation). And the optimisation also brings noticeable savings in code size along with improved performance. So patching the code as is done here is important to allow the H7 HAL to be compiled with the optimisation enabled (and have no warnings/errors). --- STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_spi.c | 31 ++++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_spi.c b/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_spi.c index cf6d4dd1..0199e454 100644 --- a/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_spi.c +++ b/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_spi.c @@ -110,6 +110,11 @@ */ /* Private macros ------------------------------------------------------------*/ + +// These macros are used to prevent strict aliasing errors +#define SPI_TXDR_STORE_U16(hspi, value) *(__IO uint16_t*)((uintptr_t)(hspi)->Instance + offsetof(SPI_TypeDef, TXDR)) = value +#define SPI_RXDR_LOAD_U16(hspi) (*(__IO uint16_t*)((uintptr_t)(hspi)->Instance + offsetof(SPI_TypeDef, RXDR))) + /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /** @defgroup SPI_Private_Functions SPI Private Functions @@ -590,7 +595,7 @@ HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint } else { - *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr); + SPI_TXDR_STORE_U16(hspi, *((uint16_t *)hspi->pTxBuffPtr)); hspi->pTxBuffPtr += sizeof(uint16_t); hspi->TxXferCount--; } @@ -629,7 +634,7 @@ HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint } else if ((hspi->TxXferCount > 1U) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA)) { - *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr); + SPI_TXDR_STORE_U16(hspi, *((uint16_t *)hspi->pTxBuffPtr)); hspi->pTxBuffPtr += sizeof(uint16_t); hspi->TxXferCount-=2; } @@ -804,7 +809,7 @@ HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint1 } else { - *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR); + *((uint16_t *)hspi->pRxBuffPtr) = SPI_RXDR_LOAD_U16(hspi); hspi->pRxBuffPtr += sizeof(uint16_t); hspi->RxXferCount--; } @@ -844,7 +849,7 @@ HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint1 } else if ((hspi->Instance->SR & SPI_FLAG_FRLVL) > SPI_FRLVL_QUARTER_FULL) { - *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR); + *((uint16_t *)hspi->pRxBuffPtr) = SPI_RXDR_LOAD_U16(hspi); hspi->pRxBuffPtr += sizeof(uint16_t); hspi->RxXferCount-=2; } @@ -1021,7 +1026,7 @@ HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxD } else { - *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr); + SPI_TXDR_STORE_U16(hspi, *((uint16_t *)hspi->pTxBuffPtr)); hspi->pTxBuffPtr += sizeof(uint16_t); hspi->TxXferCount--; } @@ -1038,7 +1043,7 @@ HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxD } else { - *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR); + *((uint16_t *)hspi->pRxBuffPtr) = SPI_RXDR_LOAD_U16(hspi); hspi->pRxBuffPtr += sizeof(uint16_t); hspi->RxXferCount--; } @@ -1074,7 +1079,7 @@ HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxD } else if ((hspi->TxXferCount > 1U) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA)) { - *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr); + SPI_TXDR_STORE_U16(hspi, *((uint16_t *)hspi->pTxBuffPtr)); hspi->pTxBuffPtr += sizeof(uint16_t); hspi->TxXferCount-=2; } @@ -1097,7 +1102,7 @@ HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxD } else if ((hspi->Instance->SR & SPI_FLAG_FRLVL) > SPI_FRLVL_QUARTER_FULL) { - *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR); + *((uint16_t *)hspi->pRxBuffPtr) = SPI_RXDR_LOAD_U16(hspi); hspi->pRxBuffPtr += sizeof(uint16_t); hspi->RxXferCount-=2; } @@ -2183,7 +2188,7 @@ void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi) /* Receive data in 16 Bit mode */ else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) { - *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR); + *((uint16_t *)hspi->pRxBuffPtr) = SPI_RXDR_LOAD_U16(hspi); hspi->pRxBuffPtr += sizeof(uint16_t); } /* Receive data in 8 Bit mode */ @@ -2740,7 +2745,7 @@ static void SPI_2linesRxISR_8BIT(SPI_HandleTypeDef *hspi) static void SPI_2linesRxISR_16BIT(SPI_HandleTypeDef *hspi) { /* Receive data in 16 Bit mode */ - *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR); + *((uint16_t *)hspi->pRxBuffPtr) = SPI_RXDR_LOAD_U16(hspi); hspi->pRxBuffPtr += sizeof(uint16_t); hspi->RxXferCount--; @@ -2806,7 +2811,7 @@ static void SPI_2linesTxISR_8BIT(SPI_HandleTypeDef *hspi) static void SPI_2linesTxISR_16BIT(SPI_HandleTypeDef *hspi) { /* Transmit data in 16 Bit mode */ - *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr); + SPI_TXDR_STORE_U16(hspi, *((uint16_t *)hspi->pTxBuffPtr)); hspi->pTxBuffPtr += sizeof(uint16_t); hspi->TxXferCount--; @@ -2870,7 +2875,7 @@ static void SPI_RxISR_8BIT(SPI_HandleTypeDef *hspi) */ static void SPI_RxISR_16BIT(SPI_HandleTypeDef *hspi) { - *((uint16_t *)hspi->pRxBuffPtr) = (*(__IO uint16_t *)&hspi->Instance->RXDR); + *((uint16_t *)hspi->pRxBuffPtr) = SPI_RXDR_LOAD_U16(hspi); hspi->pRxBuffPtr += sizeof(uint16_t); hspi->RxXferCount--; @@ -2933,7 +2938,7 @@ static void SPI_TxISR_8BIT(SPI_HandleTypeDef *hspi) static void SPI_TxISR_16BIT(SPI_HandleTypeDef *hspi) { /* Transmit data in 16 Bit mode */ - *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr); + SPI_TXDR_STORE_U16(hspi, *((uint16_t *)hspi->pTxBuffPtr)); hspi->pTxBuffPtr += sizeof(uint16_t); hspi->TxXferCount--;