Software APIs
i2c_host_gas_sensor_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 #include <assert.h>
5 
14 #include "sw/device/lib/testing/i2c_testutils.h"
15 #include "sw/device/lib/testing/rv_core_ibex_testutils.h"
16 #include "sw/device/lib/testing/test_framework/check.h"
18 
20 #include "i2c_regs.h" // Generated.
21 
22 static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
23  "This test assumes the target platform is little endian.");
24 
25 OTTF_DEFINE_TEST_CONFIG();
26 
27 enum {
28  kDeviceAddr = 0x59,
29 
30  // Commands
31  kSerialNumberCmd = 0x3682,
32  kMeasureRawCmd = 0x260F,
33  kExecSelfTestCmd = 0x280E,
34  kTurnHeaterOffCmd = 0x3615,
35  kResetCmd = 0x0006,
36 
37  // Response values
38  kSelfTestPass = 0xD4,
39 };
40 
41 static dif_rv_core_ibex_t rv_core_ibex;
42 static dif_pinmux_t pinmux;
43 static dif_i2c_t i2c;
44 
45 static status_t read_serial_number(void) {
46  uint8_t cmd[2] = {kSerialNumberCmd >> 8, kSerialNumberCmd & 0xFF};
47  uint8_t data[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
48  TRY(i2c_testutils_write(&i2c, kDeviceAddr, sizeof(cmd), cmd, true));
49  TRY(i2c_testutils_read(&i2c, kDeviceAddr, sizeof(data), data, 5000));
50 
51  // Serial numbers are unique per device, so just check it's not 00 or FF.
52  uint8_t all_ff[9] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
53  uint8_t all_00[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
54  LOG_INFO(
55  "Serial number: [0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
56  "0x%02x, 0x%02x]",
57  data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
58  data[8]);
59  TRY_CHECK_ARRAYS_NE(data, all_ff, sizeof(data));
60  TRY_CHECK_ARRAYS_NE(data, all_00, sizeof(data));
61 
62  return OK_STATUS();
63 }
64 
65 static status_t measure_raw(void) {
66  // Write the "measure raw" command with the default arguments, i.e without
67  // humidity compensation.
68  uint8_t cmd[8] = {kMeasureRawCmd >> 8,
69  kMeasureRawCmd & 0xFF,
70  0x80,
71  0x00,
72  0xA2,
73  0x66,
74  0x66,
75  0x93};
76  TRY(i2c_testutils_write(&i2c, kDeviceAddr, sizeof(cmd), cmd, true));
77 
78  // Read back the raw measurement.
79  uint8_t data[3] = {0x00, 0x00, 0x00};
80  TRY(i2c_testutils_read(&i2c, kDeviceAddr, sizeof(data), data, 30000));
81 
82  // AND and OR all the bytes together to check they're not all 0xFF or 0x00.
83  uint8_t all_ff[3] = {0xFF, 0xFF, 0xFF};
84  uint8_t all_00[3] = {0x00, 0x00, 0x00};
85  LOG_INFO("Measured data: [0x%02x, 0x%02x, 0x%02x]", data[0], data[1],
86  data[2]);
87  TRY_CHECK_ARRAYS_NE(data, all_ff, sizeof(data));
88  TRY_CHECK_ARRAYS_NE(data, all_00, sizeof(data));
89 
90  return OK_STATUS();
91 }
92 
93 static status_t self_test(void) {
94  // Write the "measure raw" command with the default arguments, i.e without
95  // humidity compensation.
96  uint8_t cmd[8] = {kExecSelfTestCmd >> 8, kExecSelfTestCmd & 0xFF};
97  TRY(i2c_testutils_write(&i2c, kDeviceAddr, sizeof(cmd), cmd, true));
98 
99  // The device will send back the results of the self test.
100  uint8_t data[3] = {0x00, 0x00, 0x00};
101  TRY(i2c_testutils_read(&i2c, kDeviceAddr, sizeof(data), data, 320000));
102 
103  // Check the first byte for the "pass" pattern (the other two bytes are
104  // ignored and a CRC).
105  TRY_CHECK(data[0] == kSelfTestPass, "Expected self test to pass");
106 
107  return OK_STATUS();
108 }
109 
110 static status_t turn_heater_off(void) {
111  // Turn off the heater, stopping measurements and returning to idle.
112  uint8_t cmd[2] = {kTurnHeaterOffCmd >> 8, kTurnHeaterOffCmd & 0xFF};
113  TRY(i2c_testutils_write(&i2c, kDeviceAddr, sizeof(cmd), cmd, false));
114 
115  busy_spin_micros(1000);
116 
117  return OK_STATUS();
118 }
119 
120 static status_t test_init(void) {
121  mmio_region_t base_addr =
123 
124  TRY(dif_rv_core_ibex_init(base_addr, &rv_core_ibex));
125 
127  TRY(dif_i2c_init(base_addr, &i2c));
128 
130  TRY(dif_pinmux_init(base_addr, &pinmux));
131 
132  TRY(i2c_testutils_select_pinmux(&pinmux, 2, I2cPinmuxPlatformIdCw310Pmod));
133 
135 
136  return OK_STATUS();
137 }
138 
139 bool test_main(void) {
140  status_t test_result;
141  CHECK_STATUS_OK(test_init());
142 
143  // Power up time.
144  busy_spin_micros(1000);
145 
147 
148  test_result = OK_STATUS();
149  for (size_t i = 0; i < ARRAYSIZE(speeds); ++i) {
150  CHECK_STATUS_OK(i2c_testutils_set_speed(&i2c, speeds[i]));
151  EXECUTE_TEST(test_result, read_serial_number);
152  EXECUTE_TEST(test_result, measure_raw);
153  EXECUTE_TEST(test_result, self_test);
154  EXECUTE_TEST(test_result, turn_heater_off);
155  }
156 
157  return status_ok(test_result);
158 }