2019-02-28 07:43 AM
I'm using cubemx for stm32f401.
I have to address several SPI devices using a sing spi bus, and different chip selects.
Each SPI device requires a different configuration of CPOL/CPHA.
So when the bus is idle (when all the chip selects are high) I use HAL_SPI_Init () to change the settings SPI settings accordingly. This works fine with the exception of the initial idle clock level.
Apparantly the SPI controller does not set SCK to the correct idle value until after the first message is sent.
The reference manual (RM0368 Rev 5) states on page 564 that:
The idle state of SCK must correspond to the polarity selected in the SPI_CR1 register (by pulling up SCK if CPOL=1 or pulling down SCK if CPOL=0)
It seems that this isn't implemented in the HAL SPI driver?
Solved! Go to Solution.
2019-03-01 02:32 AM
I corrected the issue by adding the code at the bottom of this post to a user section of generated stm32f4xx_hal_msp.c:
This fix is specifically for my situation, and will have to be adapted for other SPI busses / CPUs.
In my opinion the neglection of this part of the SPI configuration is a bug and should not have to be added by the user, but should have been generated by CubeMX, and/or have been part of stm32f4xx_hal_spi.c.
As also mentioned in my comments below with this fix a call to HAL_SPI_DeInit () is required to re-execute this initialization.
This may be a little ineficient in some circumstances, but it is good enough for me.
HAL_SPI_Init () returns no error when it is called while it was already initialized, however it's effect depends on the value hspi->State this may be efficient in some cases, but is not very robust in terms of reproducibility.
/* USER CODE BEGIN SPI1_MspInit 1 */
/* Setup the initial idle level of SCK according to note at botom of
* page 564 of STM32F401 reference manual (RM0368 Rev 5):
*
* The idle state of SCK must correspond to the polarity selected in the
* SPI_CR1 register (by pulling up SCK if CPOL=1 or pulling down SCK if
* CPOL=0).
*
* Warning: For a proper reconfiguration of the SPI bus initial SCK level
* hspi->State has to be HAL_SPI_STATE_RESET, therefore call
* HAL_SPI_DeInit() before the reconfiguring HAL_SPI_Init ().
*/
GPIO_InitStruct.Pin = SPI1_SCLCK_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
if (hspi->Init.CLKPolarity==SPI_POLARITY_HIGH) {
GPIO_InitStruct.Pull = GPIO_PULLUP;
} else {
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
}
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE END SPI1_MspInit 1 */
2019-02-28 09:03 AM
Don't know if it helps: Don't disable the SPI, just change the clock polarity when setting wihen SPI is not BUSY (SR register). Otherwise, push a dummy byte out before NSS goes low if under deadline pressure (and it would still be SPI compliant). More than the clock polarity, the data sampling edge is what really matters.
2019-02-28 12:16 PM
And now I just want to have it work without the dummy write work-around.
2019-03-01 02:32 AM
I corrected the issue by adding the code at the bottom of this post to a user section of generated stm32f4xx_hal_msp.c:
This fix is specifically for my situation, and will have to be adapted for other SPI busses / CPUs.
In my opinion the neglection of this part of the SPI configuration is a bug and should not have to be added by the user, but should have been generated by CubeMX, and/or have been part of stm32f4xx_hal_spi.c.
As also mentioned in my comments below with this fix a call to HAL_SPI_DeInit () is required to re-execute this initialization.
This may be a little ineficient in some circumstances, but it is good enough for me.
HAL_SPI_Init () returns no error when it is called while it was already initialized, however it's effect depends on the value hspi->State this may be efficient in some cases, but is not very robust in terms of reproducibility.
/* USER CODE BEGIN SPI1_MspInit 1 */
/* Setup the initial idle level of SCK according to note at botom of
* page 564 of STM32F401 reference manual (RM0368 Rev 5):
*
* The idle state of SCK must correspond to the polarity selected in the
* SPI_CR1 register (by pulling up SCK if CPOL=1 or pulling down SCK if
* CPOL=0).
*
* Warning: For a proper reconfiguration of the SPI bus initial SCK level
* hspi->State has to be HAL_SPI_STATE_RESET, therefore call
* HAL_SPI_DeInit() before the reconfiguring HAL_SPI_Init ().
*/
GPIO_InitStruct.Pin = SPI1_SCLCK_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
if (hspi->Init.CLKPolarity==SPI_POLARITY_HIGH) {
GPIO_InitStruct.Pull = GPIO_PULLUP;
} else {
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
}
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE END SPI1_MspInit 1 */
2024-04-18 03:59 AM
I am using SPI2 on a STM32L471 device. I've had the same problem and the solution listed above worked brilliantly. Thank you. Although I've had to modify the code slightly since I use SPI2. Also note that I had to put this code block after the HAL_SPI_Init() within MX_SPI2_Init(), that is between /* USER CODE SPI2_Init 2 */ begin and end statements. I did not use HAL_SPI_DeInit ().
/* USER CODE BEGIN SPI2_Init 2 */
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_1; // GPIOD Pin 1 is the SPI2_CLK
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
if (hspi2.Init.CLKPolarity==SPI_POLARITY_HIGH) {
GPIO_InitStruct.Pull = GPIO_PULLUP;
} else {
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
}
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* USER CODE END SPI2_Init 2 */
2024-09-09 06:54 PM
5 years later, and I have the same problem with STM32F765 and STM32CubeIDE 1.15.1. Thanks for the work-around.
I thought about clocking out 0xFF without Chip Select (NSS), but that seemed complicated.
hal_spi code calls __HAL_SPI_DISABLE(hspi); itself on every transaction. That's not the issue. The issue is the initial value of the port pin which seems to come from the output shift register, which is not initialized until a SPI TX.