1 /*
2 * Copyright (c) 2024 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * @addtogroup t_i2c_basic
9 * @{
10 * @defgroup t_i2c_read_write test_i2c_read_write
11 * @brief TestPurpose: verify I2C master can read and write
12 * @}
13 */
14
15 #include <zephyr/drivers/i2c.h>
16 #include <zephyr/pm/device_runtime.h>
17 #include <zephyr/kernel.h>
18 #include <zephyr/ztest.h>
19 #include <zephyr/tc_util.h>
20
21 #define RAM_ADDR (0b10100010 >> 1)
22
23 #if DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(i2c_ram))
24 #define I2C_DEV_NODE DT_ALIAS(i2c_ram)
25 #define TX_DATA_OFFSET 2
26 static uint8_t tx_data[9] = {0x00, 0x00, 'Z', 'e', 'p', 'h', 'y', 'r', '\n'};
27 static uint8_t rx_cmd[2] = {0x00, 0x00};
28 #else
29 #error "Please set the correct I2C device and alias for i2c_ram to be status okay"
30 #endif
31
32 uint32_t i2c_cfg = I2C_SPEED_SET(I2C_SPEED_STANDARD) | I2C_MODE_CONTROLLER;
33 struct i2c_msg msgs[2];
34 uint8_t rx_data[7];
35
36 const struct device *i2c_dev = DEVICE_DT_GET(I2C_DEV_NODE);
37
38 /* Address from datasheet is 0b1010xxxr where x bits are additional
39 * memory address bits and r is the r/w i2c bit.
40 *
41 * However... the address needs to be shifted into the lower 7 bits as
42 * Zephyr expects a 7bit device address and shifts this left to set the
43 * i2c r/w bit.
44 */
45
i2c_ram_setup(void)46 static void *i2c_ram_setup(void)
47 {
48 int ret;
49 uint32_t i2c_cfg_tmp;
50
51 zassert_true(device_is_ready(i2c_dev), "I2C device is not read");
52
53 /* 1. Verify i2c_configure() */
54 zassert_ok(i2c_configure(i2c_dev, i2c_cfg), "I2C config failed");
55
56 /* 2. Verify i2c_get_config(), optional API */
57 ret = i2c_get_config(i2c_dev, &i2c_cfg_tmp);
58 if (ret != -ENOSYS) {
59 zassert_equal(i2c_cfg, i2c_cfg_tmp,
60 "I2C get_config returned invalid config");
61 }
62
63 return NULL;
64 }
65
66
67 static uint16_t addr;
68
i2c_ram_before(void * f)69 static void i2c_ram_before(void *f)
70 {
71 tx_data[0] = (addr >> 8) & 0xFF;
72 tx_data[1] = (addr) & 0xFF;
73 rx_cmd[0] = (addr >> 8) & 0xFF;
74 rx_cmd[1] = (addr) & 0xFF;
75 addr += ARRAY_SIZE(tx_data) - TX_DATA_OFFSET;
76 memset(rx_data, 0, ARRAY_SIZE(rx_data));
77
78 #ifdef CONFIG_PM_DEVICE_RUNTIME
79 pm_device_runtime_get(i2c_dev);
80 #endif
81 }
82
i2c_ram_after(void * f)83 static void i2c_ram_after(void *f)
84 {
85 #ifdef CONFIG_PM_DEVICE_RUNTIME
86 pm_device_runtime_put(i2c_dev);
87 #endif
88 }
89
ZTEST(i2c_ram,test_ram_transfer)90 ZTEST(i2c_ram, test_ram_transfer)
91 {
92 TC_PRINT("ram using i2c_transfer from thread %p addr %x\n", k_current_get(), addr);
93
94 msgs[0].buf = tx_data;
95 msgs[0].len = ARRAY_SIZE(tx_data);
96 msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
97
98 zassert_ok(i2c_transfer(i2c_dev, msgs, 1, RAM_ADDR),
99 "I2C write to fram failed");
100
101 /* Write the address and read the data back */
102 msgs[0].buf = rx_cmd;
103 msgs[0].len = ARRAY_SIZE(rx_cmd);
104 msgs[0].flags = I2C_MSG_WRITE;
105 msgs[1].buf = rx_data;
106 msgs[1].len = 7;
107 msgs[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;
108
109 zassert_ok(i2c_transfer(i2c_dev, msgs, 2, RAM_ADDR),
110 "I2C read from fram failed");
111
112 zassert_equal(memcmp(&tx_data[TX_DATA_OFFSET], &rx_data[0], ARRAY_SIZE(rx_data)), 0,
113 "Written and Read data should match");
114 }
115
ZTEST(i2c_ram,test_ram_write_read)116 ZTEST(i2c_ram, test_ram_write_read)
117 {
118 TC_PRINT("ram using i2c_write and i2c_write_read from thread %p addr %x\n",
119 k_current_get(), addr);
120
121 zassert_ok(i2c_write(i2c_dev, tx_data, ARRAY_SIZE(tx_data), RAM_ADDR),
122 "I2C write to fram failed");
123
124 zassert_ok(i2c_write_read(i2c_dev, RAM_ADDR, rx_cmd, ARRAY_SIZE(rx_cmd),
125 rx_data, ARRAY_SIZE(rx_data)),
126 "I2C read from fram failed");
127
128 zassert_equal(memcmp(&tx_data[TX_DATA_OFFSET], &rx_data[0], ARRAY_SIZE(rx_data)), 0,
129 "Written and Read data should match");
130 }
131
132
133 #ifdef CONFIG_I2C_CALLBACK
134 K_SEM_DEFINE(transfer_sem, 0, 1);
135
i2c_ram_transfer_cb(const struct device * dev,int result,void * data)136 static void i2c_ram_transfer_cb(const struct device *dev, int result, void *data)
137 {
138 struct k_sem *s = data;
139
140 k_sem_give(s);
141 }
142
ZTEST(i2c_ram,test_ram_transfer_cb)143 ZTEST(i2c_ram, test_ram_transfer_cb)
144 {
145 msgs[0].buf = tx_data;
146 msgs[0].len = ARRAY_SIZE(tx_data);
147 msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
148
149 zassert_ok(i2c_transfer_cb(i2c_dev, msgs, 1, RAM_ADDR,
150 i2c_ram_transfer_cb,
151 &transfer_sem), "I2C write to fram failed");
152
153 k_sem_take(&transfer_sem, K_FOREVER);
154
155 /* Write the address and read the data back */
156 msgs[0].buf = rx_cmd;
157 msgs[0].len = ARRAY_SIZE(rx_cmd);
158 msgs[0].flags = I2C_MSG_WRITE;
159 msgs[1].buf = rx_data;
160 msgs[1].len = ARRAY_SIZE(rx_data);
161 msgs[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;
162
163 zassert_ok(i2c_transfer_cb(i2c_dev, msgs, 2, RAM_ADDR,
164 i2c_ram_transfer_cb, &transfer_sem),
165 "I2C read from fram failed");
166
167 k_sem_take(&transfer_sem, K_FOREVER);
168
169 zassert_equal(memcmp(&tx_data[TX_DATA_OFFSET], &rx_data[0], ARRAY_SIZE(rx_data)), 0,
170 "Written and Read data should match");
171
172 }
173 #endif /* CONFIG_I2C_CALLBACK */
174
175 #ifdef CONFIG_I2C_RTIO
176 #include <zephyr/rtio/rtio.h>
177
178 I2C_IODEV_DEFINE(i2c_iodev, I2C_DEV_NODE, RAM_ADDR);
179 RTIO_DEFINE(i2c_rtio, 2, 2);
180
ZTEST(i2c_ram,test_ram_rtio)181 ZTEST(i2c_ram, test_ram_rtio)
182 {
183 struct rtio_sqe *wr_sqe, *rd_sqe;
184 struct rtio_cqe *wr_cqe, *rd_cqe;
185
186 TC_PRINT("submitting write from thread %p addr %x\n", k_current_get(), addr);
187 wr_sqe = rtio_sqe_acquire(&i2c_rtio);
188 rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, tx_data, ARRAY_SIZE(tx_data), tx_data);
189 wr_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP;
190 zassert_ok(rtio_submit(&i2c_rtio, 1), "submit should succeed");
191
192 wr_cqe = rtio_cqe_consume(&i2c_rtio);
193 zassert_ok(wr_cqe->result, "i2c write should succeed");
194 rtio_cqe_release(&i2c_rtio, wr_cqe);
195
196 /* Write the address and read the data back */
197 msgs[0].len = ARRAY_SIZE(rx_cmd);
198 msgs[0].flags = I2C_MSG_WRITE;
199 msgs[1].buf = rx_data;
200 msgs[1].len = ARRAY_SIZE(rx_data);
201 msgs[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;
202
203 wr_sqe = rtio_sqe_acquire(&i2c_rtio);
204 rd_sqe = rtio_sqe_acquire(&i2c_rtio);
205 rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, rx_cmd, ARRAY_SIZE(rx_cmd), rx_cmd);
206 rtio_sqe_prep_read(rd_sqe, &i2c_iodev, 0, rx_data, ARRAY_SIZE(rx_data), rx_data);
207 wr_sqe->flags |= RTIO_SQE_TRANSACTION;
208 rd_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
209 zassert_ok(rtio_submit(&i2c_rtio, 2), "submit should succeed");
210
211 wr_cqe = rtio_cqe_consume(&i2c_rtio);
212 rd_cqe = rtio_cqe_consume(&i2c_rtio);
213 zassert_ok(wr_cqe->result, "i2c write should succeed");
214 zassert_ok(rd_cqe->result, "i2c read should succeed");
215 rtio_cqe_release(&i2c_rtio, wr_cqe);
216 rtio_cqe_release(&i2c_rtio, rd_cqe);
217
218 zassert_equal(memcmp(&tx_data[TX_DATA_OFFSET], &rx_data[0], ARRAY_SIZE(rx_data)), 0,
219 "Written and Read data should match");
220 }
221
222 static enum isr_rtio_state {
223 INIT,
224 WRITE_WAIT,
225 READ_CMD_WAIT,
226 READ_DATA_WAIT,
227 DONE
228 } isr_state = INIT;
229
230 K_SEM_DEFINE(ram_rtio_isr_sem, 0, 1);
231
ram_rtio_isr(struct k_timer * tid)232 void ram_rtio_isr(struct k_timer *tid)
233 {
234 struct rtio_sqe *wr_sqe, *rd_sqe;
235 struct rtio_cqe *wr_cqe, *rd_cqe;
236
237 switch (isr_state) {
238 case INIT:
239 TC_PRINT("timer submitting write, addr %x\n", addr);
240 wr_sqe = rtio_sqe_acquire(&i2c_rtio);
241 rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, tx_data, ARRAY_SIZE(tx_data), tx_data);
242 wr_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP;
243 zassert_ok(rtio_submit(&i2c_rtio, 0), "submit should succeed");
244 isr_state += 1;
245 break;
246 case WRITE_WAIT:
247 wr_cqe = rtio_cqe_consume(&i2c_rtio);
248 if (wr_cqe) {
249 TC_PRINT("timer checking write result, submitting read\n");
250 zassert_ok(wr_cqe->result, "i2c write should succeed");
251 rtio_cqe_release(&i2c_rtio, wr_cqe);
252
253 /* Write the address and read the data back */
254 msgs[0].len = ARRAY_SIZE(rx_cmd);
255 msgs[0].flags = I2C_MSG_WRITE;
256 msgs[1].buf = rx_data;
257 msgs[1].len = ARRAY_SIZE(rx_data);
258 msgs[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;
259
260 wr_sqe = rtio_sqe_acquire(&i2c_rtio);
261 rd_sqe = rtio_sqe_acquire(&i2c_rtio);
262 rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, rx_cmd,
263 ARRAY_SIZE(rx_cmd), rx_cmd);
264 rtio_sqe_prep_read(rd_sqe, &i2c_iodev, 0, rx_data,
265 ARRAY_SIZE(rx_data), rx_data);
266 wr_sqe->flags |= RTIO_SQE_TRANSACTION;
267 rd_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
268 zassert_ok(rtio_submit(&i2c_rtio, 0), "submit should succeed");
269 isr_state += 1;
270 }
271 break;
272 case READ_CMD_WAIT:
273 wr_cqe = rtio_cqe_consume(&i2c_rtio);
274 if (wr_cqe) {
275 TC_PRINT("read command complete\n");
276 zassert_ok(wr_cqe->result, "i2c read command should succeed");
277 rtio_cqe_release(&i2c_rtio, wr_cqe);
278 isr_state += 1;
279 }
280 break;
281 case READ_DATA_WAIT:
282 rd_cqe = rtio_cqe_consume(&i2c_rtio);
283 if (rd_cqe) {
284 TC_PRINT("read data complete\n");
285 zassert_ok(rd_cqe->result, "i2c read data should succeed");
286 rtio_cqe_release(&i2c_rtio, rd_cqe);
287 isr_state += 1;
288 k_sem_give(&ram_rtio_isr_sem);
289 k_timer_stop(tid);
290 }
291 break;
292 default:
293
294 zassert_ok(-1, "Should not get here");
295 }
296 }
297
298 K_TIMER_DEFINE(ram_rtio_isr_timer, ram_rtio_isr, NULL);
299
300
ZTEST(i2c_ram,test_ram_rtio_isr)301 ZTEST(i2c_ram, test_ram_rtio_isr)
302 {
303 k_timer_start(&ram_rtio_isr_timer, K_MSEC(1), K_MSEC(1));
304 k_sem_take(&ram_rtio_isr_sem, K_FOREVER);
305 }
306
307 #endif /* CONFIG_I2C_RTIO */
308
309 ZTEST_SUITE(i2c_ram, NULL, i2c_ram_setup, i2c_ram_before, i2c_ram_after, NULL);
310