2021-11-10 01:50 PM
I'm using CubeMX to configure the BSP for an STM32F767. My clock tree has 54MHz going to I2C2, and when I set up I2C2 with "I2C Speed Frequency" of 400KHz, CubeMX outputs a timing register (I2C_TIMINGR) value of 0x6000030D. With a prescaler of 7 and 20 prescaled periods, that comes out to an actual ideal frequency of ~385KHz (which I've confirmed with a scope.)
Problem is, I actually need the full bandwidth of a 400KHz bus. I manually edited the hi2c2.Init.Timing value in the CubeMX-generated main.c to 0x6000030C and compiled and ran it, and this value meets my requirements and works on my hardware. (I am aware this runs the bus at a slightly out-of-spec ~406KHz assuming ideal rise/fall time, but this is acceptable for the application.)
My question is: how can I get CubeMX to either output this value for I2C2's timing register, or edit main.c in such a way that CubeMX won't override it when regenerating? I know about the user code sections, but hi2c2.Init.Timing is set and then consumed in a single auto-generated code section with no user code section in between. I can't edit the timing register after init in a subsequent user code block because this is forbidden by the chip spec.
I can't tell CubeMX to output timing for e.g. 410KHz to get the 406KHz value, it rejects values over 400. And while the "Timing" value is visible on the I2C parameters page, it's grayed out and uneditable and I can't find any option to make it manually editable.
Generated init function in main.c for reference:
static void MX_I2C2_Init(void)
{
/* USER CODE BEGIN I2C2_Init 0 */
/* USER CODE END I2C2_Init 0 */
/* USER CODE BEGIN I2C2_Init 1 */
/* USER CODE END I2C2_Init 1 */
hi2c2.Instance = I2C2;
hi2c2.Init.Timing = 0x6000030D;
hi2c2.Init.OwnAddress1 = 0;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c2) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C2_Init 2 */
/* USER CODE END I2C2_Init 2 */
}
Solved! Go to Solution.
2021-11-11 12:36 AM
Hi @JHugh.3 ,
Please check these two threads I2C Timing configuration tool for STM32H7 ?
How to achieve exact SCL clock timings for I2C master in transmit mode?
Regards,
Sara.
2021-11-10 02:34 PM
> I can't edit the timing register after init in a subsequent user code block because this is forbidden by the chip spec.
What chip spec forbids this?
You can modify the timing register within the user code section, but you must disable the peripheral to do so.
/* USER CODE BEGIN I2C2_Init 2 */
CLEAR_BIT(I2C2->CR1, I2C_CR1_PE);
I2C2->TIMINGR = ...;
HAL_Delay(1); // PE must stay reset for a few clock cycles
SET_BIT(I2C2->CR1, I2C_CR1_PE);
/* USER CODE END I2C2_Init 2 */
2021-11-11 12:36 AM
Hi @JHugh.3 ,
Please check these two threads I2C Timing configuration tool for STM32H7 ?
How to achieve exact SCL clock timings for I2C master in transmit mode?
Regards,
Sara.