1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8 #include <string.h>
9
10 #include <zephyr/kernel.h>
11 #include <zephyr/linker/devicetree_regions.h>
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/pinctrl.h>
14
15 #include <zephyr/drivers/i2c.h>
16 #include <nrfx_twis.h>
17
18 #include <zephyr/ztest.h>
19
20 #if CONFIG_NRFX_TWIS1
21 #define I2C_S_INSTANCE 1
22 #elif CONFIG_NRFX_TWIS2
23 #define I2C_S_INSTANCE 2
24 #elif CONFIG_NRFX_TWIS22
25 #define I2C_S_INSTANCE 22
26 #elif CONFIG_NRFX_TWIS131
27 #define I2C_S_INSTANCE 131
28 #else
29 #error "TWIS instance not enabled or not supported"
30 #endif
31
32 #define NODE_SENSOR DT_NODELABEL(sensor)
33 #define NODE_TWIS DT_ALIAS(i2c_slave)
34
35 #define TWIS_MEMORY_SECTION \
36 COND_CODE_1(DT_NODE_HAS_PROP(NODE_TWIS, memory_regions), \
37 (__attribute__((__section__( \
38 LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(NODE_TWIS, memory_regions)))))), \
39 ())
40
41 #define TEST_DATA_SIZE 6
42 static const uint8_t msg[TEST_DATA_SIZE] = "Nordic";
43 static const nrfx_twis_t twis = NRFX_TWIS_INSTANCE(I2C_S_INSTANCE);
44
45 static uint8_t i2c_slave_buffer[TEST_DATA_SIZE] TWIS_MEMORY_SECTION;
46 static uint8_t i2c_master_buffer[TEST_DATA_SIZE];
47 struct i2c_api_twis_fixture {
48 const struct device *dev;
49 uint8_t addr;
50 uint8_t *const master_buffer;
51 uint8_t *const slave_buffer;
52 };
53
i2s_slave_handler(nrfx_twis_evt_t const * p_event)54 void i2s_slave_handler(nrfx_twis_evt_t const *p_event)
55 {
56 switch (p_event->type) {
57 case NRFX_TWIS_EVT_READ_REQ:
58 nrfx_twis_tx_prepare(&twis, i2c_slave_buffer, TEST_DATA_SIZE);
59 TC_PRINT("TWIS event: read request\n");
60 break;
61 case NRFX_TWIS_EVT_READ_DONE:
62 TC_PRINT("TWIS event: read done\n");
63 break;
64 case NRFX_TWIS_EVT_WRITE_REQ:
65 nrfx_twis_rx_prepare(&twis, i2c_slave_buffer, TEST_DATA_SIZE);
66 TC_PRINT("TWIS event: write request\n");
67 break;
68 case NRFX_TWIS_EVT_WRITE_DONE:
69 zassert_mem_equal(i2c_slave_buffer, msg, TEST_DATA_SIZE);
70 TC_PRINT("TWIS event: write done\n");
71 break;
72 default:
73 TC_PRINT("TWIS event: %d\n", p_event->type);
74 break;
75 }
76 }
77
test_setup(void)78 static void *test_setup(void)
79 {
80 static struct i2c_api_twis_fixture fixture = {
81 .dev = DEVICE_DT_GET(DT_BUS(NODE_SENSOR)),
82 .addr = DT_REG_ADDR(NODE_SENSOR),
83 .master_buffer = i2c_master_buffer,
84 .slave_buffer = i2c_slave_buffer,
85 };
86 const nrfx_twis_config_t config = {
87 .addr = {fixture.addr, 0},
88 .skip_gpio_cfg = true,
89 .skip_psel_cfg = true,
90 };
91 int ret;
92
93 zassert_equal(NRFX_SUCCESS, nrfx_twis_init(&twis, &config, i2s_slave_handler),
94 "TWIS initialization failed");
95
96 PINCTRL_DT_DEFINE(NODE_TWIS);
97 ret = pinctrl_apply_state(PINCTRL_DT_DEV_CONFIG_GET(NODE_TWIS), PINCTRL_STATE_DEFAULT);
98 zassert_ok(ret);
99
100 IRQ_CONNECT(DT_IRQN(NODE_TWIS), DT_IRQ(NODE_TWIS, priority),
101 NRFX_TWIS_INST_HANDLER_GET(I2C_S_INSTANCE), NULL, 0);
102
103 nrfx_twis_enable(&twis);
104
105 return &fixture;
106 }
107
cleanup_buffers(void * argc)108 static void cleanup_buffers(void *argc)
109 {
110 struct i2c_api_twis_fixture *fixture = (struct i2c_api_twis_fixture *)argc;
111
112 memset(fixture->slave_buffer, 0, TEST_DATA_SIZE);
113 memset(fixture->master_buffer, 0, TEST_DATA_SIZE);
114 }
115
ZTEST_USER_F(i2c_api_twis,test_i2c_read_write)116 ZTEST_USER_F(i2c_api_twis, test_i2c_read_write)
117 {
118 int ret = i2c_write_read(fixture->dev, fixture->addr, msg, TEST_DATA_SIZE,
119 fixture->master_buffer, TEST_DATA_SIZE);
120
121 zassert_ok(ret);
122 zassert_mem_equal(fixture->master_buffer, msg, TEST_DATA_SIZE);
123 }
124
ZTEST_USER_F(i2c_api_twis,test_i2c_read)125 ZTEST_USER_F(i2c_api_twis, test_i2c_read)
126 {
127 /* Prepare slave data */
128 strncpy(fixture->slave_buffer, msg, TEST_DATA_SIZE);
129 zassert_mem_equal(fixture->slave_buffer, msg, TEST_DATA_SIZE);
130
131 int ret = i2c_read(fixture->dev, fixture->master_buffer, TEST_DATA_SIZE, fixture->addr);
132
133 zassert_ok(ret);
134 zassert_mem_equal(fixture->master_buffer, msg, TEST_DATA_SIZE);
135 }
136
ZTEST_USER_F(i2c_api_twis,test_i2c_write)137 ZTEST_USER_F(i2c_api_twis, test_i2c_write)
138 {
139 int ret = i2c_write(fixture->dev, msg, TEST_DATA_SIZE, fixture->addr);
140
141 zassert_ok(ret);
142 zassert_mem_equal(fixture->slave_buffer, msg, TEST_DATA_SIZE);
143 }
144
145 ZTEST_SUITE(i2c_api_twis, NULL, test_setup, NULL, cleanup_buffers, NULL);
146