5#include "sw/device/lib/testing/i2c_testutils.h"
17#include "sw/device/lib/testing/pinmux_testutils.h"
18#include "sw/device/lib/testing/test_framework/check.h"
23#define MODULE_ID MAKE_MODULE_ID('i', 'i', 't')
35 .suppress_nak_irq =
false};
41 pinmux_testutils_peripheral_pin_t sda;
42 pinmux_testutils_peripheral_pin_t scl;
49 pinmux_testutils_mio_pin_t sda;
50 pinmux_testutils_mio_pin_t scl;
57static const i2c_pinmux_pins_t kI2cPinmuxPins[] = {
96static status_t map_platform_to_pins(i2c_pinmux_platform_id_t platform,
98 i2c_platform_pins_t *pins) {
99 TRY_CHECK(pins != NULL);
101 case I2cPinmuxPlatformIdHyper310:
103 (i2c_platform_pins_t){.sda =
113 case I2cPinmuxPlatformIdDvsim:
118 TRY(map_platform_to_pins(I2cPinmuxPlatformIdHyper310, i2c_id, pins));
121 *pins = (i2c_platform_pins_t){
135 TRY(map_platform_to_pins(I2cPinmuxPlatformIdCw310Pmod, i2c_id, pins));
138 TRY_CHECK(
false,
"invalid i2c_id: %0d", i2c_id);
142 case I2cPinmuxPlatformIdCw310Pmod:
143 *pins = (i2c_platform_pins_t){
155 TRY_CHECK(
false,
"invalid platform: %0d", platform);
161status_t i2c_testutils_write(
const dif_i2c_t *i2c, uint8_t addr,
162 size_t byte_count,
const uint8_t *data,
167 TRY_CHECK(byte_count > 0);
171 data_frame = (uint8_t)(addr << 1) | (uint8_t)kI2cWrite;
172 TRY(dif_i2c_write_byte_raw(i2c, data_frame, flags));
175 flags = kDefaultFlags;
176 if (byte_count > 1) {
177 TRY(dif_i2c_write_bytes_raw(i2c, byte_count - 1, data, flags));
180 flags.
stop = !skip_stop;
181 TRY(dif_i2c_write_byte_raw(i2c, data[byte_count - 1], flags));
187status_t i2c_testutils_issue_read(
const dif_i2c_t *i2c, uint8_t addr,
188 uint8_t byte_count) {
195 data_frame = (uint8_t)(addr << 1) | (uint8_t)kI2cRead;
196 TRY(dif_i2c_write_byte_raw(i2c, data_frame, flags));
198 TRY(i2c_testutils_wait_transaction_finish(i2c));
199 dif_i2c_controller_halt_events_t halt_events = {0};
200 TRY(dif_i2c_get_controller_halt_events(i2c, &halt_events));
203 flags = kDefaultFlags;
207 TRY(dif_i2c_write_byte_raw(i2c, byte_count, flags));
210 TRY(dif_i2c_reset_fmt_fifo(i2c));
211 TRY(dif_i2c_clear_controller_halt_events(i2c, halt_events));
219status_t i2c_testutils_read(
const dif_i2c_t *i2c, uint8_t addr,
220 size_t byte_count, uint8_t *data,
size_t timeout) {
221 uint32_t nak_count = 0;
225 dif_i2c_controller_halt_events_t halt_events = {0};
226 TRY(dif_i2c_get_controller_halt_events(i2c, &halt_events));
227 TRY(dif_i2c_clear_controller_halt_events(i2c, halt_events));
228 TRY(dif_i2c_reset_rx_fifo(i2c));
234 I2C_PARAM_FIFO_DEPTH < UINT8_MAX ? I2C_PARAM_FIFO_DEPTH : UINT8_MAX;
235 uint8_t chunk = (uint8_t)(byte_count < max_chunk ? byte_count : max_chunk);
238 while (TRY(i2c_testutils_issue_read(i2c, addr, chunk))) {
240 if (ibex_timeout_check(&timer)) {
241 return DEADLINE_EXCEEDED();
246 TRY(dif_i2c_read_bytes(i2c, chunk, data));
250 }
while (byte_count > 0);
252 TRY(i2c_testutils_wait_transaction_finish(i2c));
253 return OK_STATUS((int32_t)nak_count);
256status_t i2c_testutils_target_check_start(
const dif_i2c_t *i2c, uint8_t *addr) {
258 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
259 TRY_CHECK(acq_fifo_lvl > 1);
263 TRY(dif_i2c_acquire_byte(i2c, &
byte, &signal));
268 return OK_STATUS(
byte & kI2cRead);
271status_t i2c_testutils_target_check_end(
const dif_i2c_t *i2c,
272 uint8_t *cont_byte) {
274 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
275 TRY_CHECK(acq_fifo_lvl >= 1);
279 TRY(dif_i2c_acquire_byte(i2c, &
byte, &signal));
283 return OK_STATUS(
false);
285 TRY_CHECK(cont_byte != NULL);
289 return OK_STATUS(
true);
292status_t i2c_testutils_target_read(
const dif_i2c_t *i2c, uint16_t byte_count,
293 const uint8_t *data) {
295 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, &tx_fifo_lvl, &acq_fifo_lvl));
297 TRY_CHECK(tx_fifo_lvl + byte_count <= I2C_PARAM_FIFO_DEPTH);
298 TRY_CHECK(acq_fifo_lvl + 2 <= I2C_PARAM_FIFO_DEPTH);
300 for (uint16_t i = 0; i < byte_count; ++i) {
301 TRY(dif_i2c_transmit_byte(i2c, data[i]));
307status_t i2c_testutils_target_check_read(
const dif_i2c_t *i2c, uint8_t *addr,
308 uint8_t *cont_byte) {
309 int32_t dir = TRY(i2c_testutils_target_check_start(i2c, addr));
310 TRY_CHECK(dir == kI2cRead);
312 return i2c_testutils_target_check_end(i2c, cont_byte);
315status_t i2c_testutils_target_write(
const dif_i2c_t *i2c, uint16_t byte_count) {
317 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
318 TRY_CHECK(acq_fifo_lvl + 2 + byte_count <= I2C_PARAM_FIFO_DEPTH);
324status_t i2c_testutils_target_check_write(
const dif_i2c_t *i2c,
325 uint16_t byte_count, uint8_t *addr,
326 uint8_t *bytes, uint8_t *cont_byte) {
328 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
329 TRY_CHECK(acq_fifo_lvl >= 2 + byte_count);
331 int32_t dir = TRY(i2c_testutils_target_check_start(i2c, addr));
332 TRY_CHECK(dir == kI2cWrite);
334 for (uint16_t i = 0; i < byte_count; ++i) {
336 TRY(dif_i2c_acquire_byte(i2c, bytes + i, &signal));
342 return i2c_testutils_target_check_end(i2c, cont_byte);
345status_t i2c_testutils_select_pinmux(
const dif_pinmux_t *pinmux, uint8_t i2c_id,
346 i2c_pinmux_platform_id_t platform) {
348 platform < I2cPinmuxPlatformIdCount && i2c_id <
ARRAYSIZE(kI2cPinmuxPins),
349 "Index out of bounds");
350 i2c_platform_pins_t platform_pins;
351 TRY(map_platform_to_pins(platform, i2c_id, &platform_pins));
353 TRY(dif_pinmux_input_select(pinmux, kI2cPinmuxPins[i2c_id].sda.peripheral_in,
354 platform_pins.sda.insel));
355 TRY(dif_pinmux_output_select(pinmux, platform_pins.sda.mio_out,
356 kI2cPinmuxPins[i2c_id].sda.outsel));
359 TRY(dif_pinmux_input_select(pinmux, kI2cPinmuxPins[i2c_id].scl.peripheral_in,
360 platform_pins.scl.insel));
361 TRY(dif_pinmux_output_select(pinmux, platform_pins.scl.mio_out,
362 kI2cPinmuxPins[i2c_id].scl.outsel));
366status_t i2c_testutils_detach_pinmux(
const dif_pinmux_t *pinmux,
369 TRY(dif_pinmux_input_select(pinmux, kI2cPinmuxPins[i2c_id].sda.peripheral_in,
373 TRY(dif_pinmux_input_select(pinmux, kI2cPinmuxPins[i2c_id].scl.peripheral_in,
379 uint32_t speed_khz = 0;
382 LOG_INFO(
"Setting i2c to %s mode.",
"Standard (100kHz)");
386 LOG_INFO(
"Setting i2c to %s mode.",
"Fast (400kHz)");
390 LOG_INFO(
"Setting i2c to %s mode.",
"FastPlus (1000kHz)");
396 .lowest_target_device_speed = speed,
397 .clock_period_nanos =
399 .sda_rise_nanos = 400,
400 .sda_fall_nanos = 110,
401 .scl_period_nanos = 1000000 / speed_khz};
404 TRY(dif_i2c_get_status(i2c, &
status));
409 TRY(dif_i2c_compute_timing(timing_config, &config));
411 LOG_INFO(
"period:%d nanos, cycles={fall=%d, rise=%d, hi=%d, lo=%d}",
413 config.rise_cycles, config.scl_time_high_cycles,
414 config.scl_time_low_cycles);
416 TRY(dif_i2c_configure(i2c, config));
425status_t i2c_testutils_wait_host_idle(
const dif_i2c_t *i2c) {
428 TRY(dif_i2c_get_status(i2c, &
status));
429 }
while (!
status.host_idle);
433status_t i2c_testutils_wait_transaction_finish(
const dif_i2c_t *i2c) {
435 bool controller_halted =
false;
438 &controller_halted));
439 if (controller_halted) {
442 TRY(dif_i2c_get_status(i2c, &
status));
443 }
while (!
status.fmt_fifo_empty);