In my opinion STM32CubeMX code should not be considered as a ready to use code, but some as an example you can start with. With most of the microcontrollers it works, but there are some rare cases when it is not.
If you know it is not working and you have found the solution as well, you do not have to stick to the original code. In your case you can omit the __HAL_RCC_I2C1_CLK_ENABLE()
call after the GPIO initialization, and leave the one before it. If it works, and you have said it works, then use the working way. Even ST's software can have bugs.
You are using an official board so the hardware should be OK, but you can check if the pull-up resistor values are correct. Or if a slave device does something during the initialization.
The best would be to run your code with everything disconnected from the Discovery (apart from the pull-ups), and check if it is still stuck in busy. If yes, it is fine if you replace that line in the generated code. It is not that big modification.
Unfortunately there is not any I2C exapmle in the STM32CubeF1 example package (this is not the code generator), under the STM32Cube_FW_F1_V1.4.0\Projects\STM32VL-Discovery\Examples. But if you check the MspInit
functions of the UART or SPI. The clocks are enabled in both of them before the GPIO init.
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
GPIO_InitTypeDef GPIO_InitStruct;
if (hspi->Instance == SPIx)
{
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
SPIx_SCK_GPIO_CLK_ENABLE();
SPIx_MISO_GPIO_CLK_ENABLE();
SPIx_MOSI_GPIO_CLK_ENABLE();
/* Enable SPI clock */
SPIx_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/
/* SPI SCK GPIO pin configuration */
GPIO_InitStruct.Pin = SPIx_SCK_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct);
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
USARTx_TX_GPIO_CLK_ENABLE();
USARTx_RX_GPIO_CLK_ENABLE();
/* Enable USARTx clock */
USARTx_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/
/* UART TX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTx_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);
So I think your solution is perfectly fine.
Some ideas which might help when debugging a hard fault on a cortex m4, maybe some of them are useful: - the line which causes the hard fault is put on stack at address +0x18, if the interrupt is synchronous, BFARVALID bit set, if not, it can be forced by setting the bit DISDEBUF from ACTLR system register.
Anothe thing, when executing code from flash, things like the wait state configuration, caches, prefetch buffers might sometime cause errors like this.
I currently have a similar issue, which seems to be influenced by a linker option(ignore_debug_references), not sure how yet...
Best Answer
Both the HAL and FreeRTOS use the SysTick - CubeMX does this by calling the FreeRTOS systick handler (vPortSysTickHandler() I think, but might have the name wrong) from its own systick handler. In FreeRTOS you can do the reverse by calling the HAL systick handler from FreeRTOS's tick hook function. Note however that, while FreeRTOS normally runs SysTick at the lowest possible priority, the CubeMX generated code needs the SysTick to run at the highest priority (because its interrupt drivers contains delays that spin on the tick value, and you don't want them to starve out the interrupt they are waiting for).