/* I²C 占用核算的实现。**两个目标编的是同一份**(和 hal_err.c 一样放在组件根下), 所以宿主机上算出来的占用率就是上板会打印的那个数。 */ #include "hal_i2c_acct.h" static uint64_t s_bits; static uint32_t s_txns; static uint32_t s_freq_hz = HAL_I2C_FREQ_HZ_DEFAULT; uint32_t hal_i2c_txn_bits(size_t wr_len, size_t rd_len) { if (wr_len == 0 && rd_len == 0) { return 1u + 9u + 1u; /* 探测:START + 地址字节 + STOP */ } uint32_t bits = 1u; /* START */ if (wr_len > 0) { bits += 9u * (uint32_t)(1u + wr_len); /* 地址 + 载荷 */ } if (rd_len > 0) { if (wr_len > 0) { bits += 1u; /* 重复 START */ } bits += 9u * (uint32_t)(1u + rd_len); } bits += 1u; /* STOP */ return bits; } void hal_i2c_acct_add(size_t wr_len, size_t rd_len) { s_bits += hal_i2c_txn_bits(wr_len, rd_len); s_txns++; } uint64_t hal_i2c_acct_bits(void) { return s_bits; } uint32_t hal_i2c_acct_txns(void) { return s_txns; } void hal_i2c_acct_set_freq(uint32_t hz) { s_freq_hz = (hz == 0) ? HAL_I2C_FREQ_HZ_DEFAULT : hz; } uint32_t hal_i2c_acct_freq(void) { return s_freq_hz; } uint64_t hal_i2c_bits_to_us(uint64_t bits) { /* 先乘后除,别先算「每位多少 µs」—— 400 kHz 下那是 2.5 µs,整数除法会抹平。 */ return (bits * 1000000ull) / (uint64_t)s_freq_hz; } uint32_t hal_i2c_acct_window_us(uint64_t *cursor_bits) { const uint64_t now = s_bits; const uint64_t was = (cursor_bits != NULL) ? *cursor_bits : 0; if (cursor_bits != NULL) { *cursor_bits = now; } return (uint32_t)hal_i2c_bits_to_us(now - was); } void hal_i2c_acct_reset(void) { s_bits = 0; s_txns = 0; s_freq_hz = HAL_I2C_FREQ_HZ_DEFAULT; }