1 /*
2 * Copyright (c) 2006-2025, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-11-15 xckhmf First Verison
9 * 2021-11-27 chenyingchun fix _master_xfer bug
10 * 2023-01-28 Andrew add Nrf5340 support
11 */
12
13 #include <rtdevice.h>
14 #include <nrfx_twi_twim.h>
15 #include <nrfx_twim.h>
16 #include <drv_i2c.h>
17
18
19 #if defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1) || defined(BSP_USING_I2C2) || defined(BSP_USING_I2C3)
20 typedef struct
21 {
22 nrf_twim_frequency_t freq;
23 uint32_t scl_pin;
24 uint32_t sda_pin;
25 nrfx_twim_t twi_instance;
26 }drv_i2c_cfg_t;
27
28 #ifdef BSP_USING_I2C0
29 static drv_i2c_cfg_t drv_i2c_0 =
30 {
31 .freq = NRF_TWIM_FREQ_400K,
32 .scl_pin = BSP_I2C0_SCL_PIN,
33 .sda_pin = BSP_I2C0_SDA_PIN,
34 .twi_instance = NRFX_TWIM_INSTANCE(0)
35 };
36 static struct rt_i2c_bus_device i2c0_bus;
37 #endif
38 #ifdef BSP_USING_I2C1
39 static drv_i2c_cfg_t drv_i2c_1 =
40 {
41 .freq = NRF_TWIM_FREQ_400K,
42 .scl_pin = BSP_I2C1_SCL_PIN,
43 .sda_pin = BSP_I2C1_SDA_PIN,
44 .twi_instance = NRFX_TWIM_INSTANCE(1)
45 };
46 static struct rt_i2c_bus_device i2c1_bus;
47 #endif
48 #ifdef BSP_USING_I2C2
49 static drv_i2c_cfg_t drv_i2c_2 =
50 {
51 .freq = NRF_TWIM_FREQ_400K,
52 .scl_pin = BSP_I2C2_SCL_PIN,
53 .sda_pin = BSP_I2C2_SDA_PIN,
54 .twi_instance = NRFX_TWIM_INSTANCE(2)
55 };
56 static struct rt_i2c_bus_device i2c_bus;
57 #endif
58 #ifdef BSP_USING_I2C3
59 static drv_i2c_cfg_t drv_i2c_3 =
60 {
61 .freq = NRF_TWIM_FREQ_400K,
62 .scl_pin = BSP_I2C3_SCL_PIN,
63 .sda_pin = BSP_I2C3_SDA_PIN,
64 .twi_instance = NRFX_TWIM_INSTANCE(3)
65 };
66 static struct rt_i2c_bus_device i2c3_bus;
67 #endif
68
69
twi_master_init(struct rt_i2c_bus_device * bus)70 static int twi_master_init(struct rt_i2c_bus_device *bus)
71 {
72 nrfx_err_t rtn;
73 nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG(0,0);
74 drv_i2c_cfg_t *p_cfg = bus->priv;
75 nrfx_twim_t const * p_instance = &p_cfg->twi_instance;
76
77 config.frequency = p_cfg->freq;
78 config.scl = p_cfg->scl_pin;
79 config.sda = p_cfg->sda_pin;
80
81 nrfx_twi_twim_bus_recover(config.scl,config.sda);
82
83 rtn = nrfx_twim_init(p_instance,&config,NULL,NULL);
84 if (rtn != NRFX_SUCCESS)
85 {
86 return rtn;
87 }
88 nrfx_twim_enable(p_instance);
89 return 0;
90 }
91
_master_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)92 static rt_ssize_t _master_xfer(struct rt_i2c_bus_device *bus,
93 struct rt_i2c_msg msgs[],
94 rt_uint32_t num)
95 {
96 struct rt_i2c_msg *msg;
97 nrfx_twim_t const *p_instance = &((drv_i2c_cfg_t *)bus->priv)->twi_instance;
98 nrfx_err_t ret = NRFX_ERROR_INTERNAL;
99 uint32_t no_stop_flag = 0;
100 rt_int32_t i = 0;
101
102 for (i = 0; i < num; i++)
103 {
104 msg = &msgs[i];
105 nrfx_twim_xfer_desc_t xfer = NRFX_TWIM_XFER_DESC_TX(msg->addr, msg->buf, msg->len);
106
107 if (msg->flags & RT_I2C_RD)
108 {
109 xfer.type = NRFX_TWIM_XFER_RX;
110 }
111 else
112 {
113 xfer.type = NRFX_TWIM_XFER_TX;
114 if (msg->flags & RT_I2C_NO_READ_ACK)
115 {
116 no_stop_flag = NRFX_TWIM_FLAG_TX_NO_STOP;
117 }
118 }
119
120 ret = nrfx_twim_xfer(p_instance, &xfer, no_stop_flag);
121 if (ret != NRFX_SUCCESS)
122 {
123 goto out;
124 }
125 }
126
127 out:
128 return i;
129 }
130
131
132 static const struct rt_i2c_bus_device_ops _i2c_ops =
133 {
134 _master_xfer,
135 NULL,
136 NULL,
137 };
138
rt_hw_i2c_init(void)139 int rt_hw_i2c_init(void)
140 {
141 #ifdef BSP_USING_I2C0
142 i2c0_bus.ops= &_i2c_ops;
143 i2c0_bus.timeout = 0;
144 i2c0_bus.priv = (void *)&drv_i2c_0;
145 twi_master_init(&i2c0_bus);
146 rt_i2c_bus_device_register(&i2c0_bus, "i2c0");
147 #endif
148 #ifdef BSP_USING_I2C1
149 i2c1_bus.ops= &_i2c_ops;
150 i2c1_bus.timeout = 0;
151 i2c1_bus.priv = (void *)&drv_i2c_1;
152 twi_master_init(&i2c1_bus);
153 rt_i2c_bus_device_register(&i2c1_bus, "i2c1");
154 #endif
155 #ifdef BSP_USING_I2C2
156 i2c_bus.ops= &_i2c_ops;
157 i2c_bus.timeout = 0;
158 i2c_bus.priv = (void *)&drv_i2c_2;
159 twi_master_init(&i2c_bus);
160 rt_i2c_bus_device_register(&i2c_bus, "i2c2");
161 #endif
162 #ifdef BSP_USING_I2C3
163 i2c3_bus.ops= &_i2c_ops;
164 i2c3_bus.timeout = 0;
165 i2c3_bus.priv = (void *)&drv_i2c_3;
166 twi_master_init(&i2c3_bus);
167 rt_i2c_bus_device_register(&i2c3_bus, "i2c3");
168 #endif
169
170
171 return 0;
172 }
173
174 INIT_BOARD_EXPORT(rt_hw_i2c_init);
175 #endif /* defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1) */
176
177