Skip to content

Commit efb3263

Browse files
committed
psoc-edge/machine_i2c: Fix 400kHz issue.
Signed-off-by: zhanglinjing <[email protected]>
1 parent a75130a commit efb3263

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

ports/psoc-edge/machine_i2c.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -152,20 +152,25 @@ static void machine_hw_i2c_init(machine_hw_i2c_obj_t *self, uint32_t freq_hz) {
152152
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2C init failed: 0x%lx"), result);
153153
}
154154

155-
// 4. Configure clock divider for I2C
155+
// 4. Configure clock divider for I2C (balanced performance and power)
156156
// For desired data rate, clk_scb frequency must be in valid range (see TRM I2C Oversampling section)
157-
// For 100kHz: clk_scb range is 1.55 - 3.2 MHz
158-
// - clk_peri = 50 MHz, divider = 32 → clk_scb = 1.563 MHz ✓
159-
// For 400kHz: clk_scb range is 7.82 - 15.38 MHz
160-
// - clk_peri = 50 MHz, divider = 4 → clk_scb = 12.5 MHz ✓
161-
// Note: Cy_SysClk_PeriphSetDivider takes (divider - 1), so divider=4 → value=3
162-
uint32_t divider = (freq_hz <= 100000) ? 31U : 3U;
163-
Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_8_BIT, 0U, divider);
164-
Cy_SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_8_BIT, 0U);
157+
// For 100kHz: clk_scb range is 1.55 - 3.2 MHz (architecture reference manual 002-38331 Rev. P685 table 355)
158+
// - clk_peri = 100 MHz, divider = 42 → clk_scb = 2.38 MHz ✓ (mid-range)
159+
// For 400kHz: clk_scb range is 7.82 - 10 MHz
160+
// - clk_peri = 100 MHz, divider = 11 → clk_scb = 9.09 MHz ✓ (within range)
161+
// Note: Cy_SysClk_PeriphSetDivider takes (divider - 1), so divider=11 → value=10
162+
/* Connect assigned divider to be a clock source for I2C */
163+
Cy_SysClk_PeriphAssignDivider(PCLK_SCB5_CLOCK_SCB_EN, CY_SYSCLK_DIV_8_BIT, 2U);
164+
uint32_t divider = (freq_hz <= 100000) ? 41U : 10U;
165+
Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_8_BIT, 2U, divider);
166+
Cy_SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_8_BIT, 2U);
165167

166168
// 5. Configure master data rate
167-
uint32_t clk_scb_freq = Cy_SysClk_PeriphGetFrequency(CY_SYSCLK_DIV_8_BIT, 0U);
169+
uint32_t clk_scb_freq = Cy_SysClk_PeriphGetFrequency(CY_SYSCLK_DIV_8_BIT, 2U);
170+
mp_printf(&mp_plat_print, "DEBUG: clk_scb_freq=%u Hz\n", clk_scb_freq);
171+
168172
uint32_t actual_rate = Cy_SCB_I2C_SetDataRate(MICROPY_HW_I2C0_SCB, freq_hz, clk_scb_freq);
173+
mp_printf(&mp_plat_print, "DEBUG: actual_rate=%u Hz (requested=%u Hz)\n", actual_rate, freq_hz);
169174

170175
if ((actual_rate > freq_hz) || (actual_rate == 0U)) {
171176
mp_raise_msg_varg(&mp_type_ValueError,

0 commit comments

Comments
 (0)